aro: update

This is f5fb720a5399ee98e45f36337b2f68a4d23a783c plus ehaas's nonnull
attribute pull request currently at 4b26cb3ac610a0a070fc43e43da8b4cdf0e9101b
with zig patches intact.
This commit is contained in:
Andrew Kelley 2025-08-21 15:05:28 -07:00
parent 01132e0cf8
commit 8cba6b1df8
31 changed files with 1483 additions and 1240 deletions

View File

@ -345,6 +345,7 @@ fn diagnoseField(
pub fn diagnose(attr: Tag, arguments: *Arguments, arg_idx: u32, res: Parser.Result, arg_start: TokenIndex, node: Tree.Node, p: *Parser) !bool {
switch (attr) {
.nonnull => return false,
inline else => |tag| {
const decl = @typeInfo(attributes).@"struct".decls[@intFromEnum(tag)];
const max_arg_count = comptime maxArgCount(tag);
@ -532,10 +533,7 @@ const attributes = struct {
pub const @"noinline" = struct {};
pub const noipa = struct {};
// TODO: arbitrary number of arguments
// const nonnull = struct {
// // arg_index: []const u32,
// };
// };
pub const nonnull = struct {};
pub const nonstring = struct {};
pub const noplt = struct {};
pub const @"noreturn" = struct {};
@ -802,8 +800,16 @@ fn ignoredAttrErr(p: *Parser, tok: TokenIndex, attr: Attribute.Tag, context: []c
try p.errStr(.ignored_attribute, tok, str);
}
pub const applyParameterAttributes = applyVariableAttributes;
pub fn applyParameterAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diagnostic: ?Parser.Diagnostic) !QualType {
return applyVariableOrParameterAttributes(p, qt, attr_buf_start, diagnostic, .parameter);
}
pub fn applyVariableAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diagnostic: ?Parser.Diagnostic) !QualType {
return applyVariableOrParameterAttributes(p, qt, attr_buf_start, diagnostic, .variable);
}
fn applyVariableOrParameterAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diagnostic: ?Parser.Diagnostic, context: enum { parameter, variable }) !QualType {
const gpa = p.comp.gpa;
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
@ -814,27 +820,33 @@ pub fn applyVariableAttributes(p: *Parser, qt: QualType, attr_buf_start: usize,
// zig fmt: off
.alias, .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .weak, .used,
.noinit, .retain, .persistent, .section, .mode, .asm_label, .nullability, .unaligned,
=> try p.attr_application_buf.append(p.gpa, attr),
=> try p.attr_application_buf.append(gpa, attr),
// zig fmt: on
.common => if (nocommon) {
try p.err(tok, .ignore_common, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
common = true;
},
.nocommon => if (common) {
try p.err(tok, .ignore_nocommon, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
nocommon = true;
},
.vector_size => try attr.applyVectorSize(p, tok, &base_qt),
.aligned => try attr.applyAligned(p, base_qt, diagnostic),
.nonnull => {
switch (context) {
.parameter => try p.err(tok, .attribute_todo, .{ "nonnull", "parameters" }),
.variable => try p.err(tok, .nonnull_not_applicable, .{}),
}
},
.nonstring => {
if (base_qt.get(p.comp, .array)) |array_ty| {
if (array_ty.elem.get(p.comp, .int)) |int_ty| switch (int_ty) {
.char, .uchar, .schar => {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
continue;
},
else => {},
@ -845,12 +857,12 @@ pub fn applyVariableAttributes(p: *Parser, qt: QualType, attr_buf_start: usize,
.uninitialized => if (p.func.qt == null) {
try p.err(tok, .local_variable_attribute, .{"uninitialized"});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
},
.cleanup => if (p.func.qt == null) {
try p.err(tok, .local_variable_attribute, .{"cleanup"});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
},
.calling_convention => try applyCallingConvention(attr, p, tok, base_qt),
.alloc_size,
@ -873,7 +885,7 @@ pub fn applyFieldAttributes(p: *Parser, field_qt: *QualType, attr_buf_start: usi
// zig fmt: off
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned,
.mode, .warn_unused_result, .nodiscard, .nullability, .unaligned,
=> try p.attr_application_buf.append(p.gpa, attr),
=> try p.attr_application_buf.append(p.comp.gpa, attr),
// zig fmt: on
.vector_size => try attr.applyVectorSize(p, tok, field_qt),
.aligned => try attr.applyAligned(p, field_qt.*, null),
@ -884,6 +896,7 @@ pub fn applyFieldAttributes(p: *Parser, field_qt: *QualType, attr_buf_start: usi
}
pub fn applyTypeAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diagnostic: ?Parser.Diagnostic) !QualType {
const gpa = p.comp.gpa;
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
@ -891,13 +904,13 @@ pub fn applyTypeAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diag
for (attrs, toks) |attr, tok| switch (attr.tag) {
// zig fmt: off
.@"packed", .may_alias, .deprecated, .unavailable, .unused, .warn_if_not_aligned, .mode, .nullability, .unaligned,
=> try p.attr_application_buf.append(p.gpa, attr),
=> try p.attr_application_buf.append(gpa, attr),
// zig fmt: on
.transparent_union => try attr.applyTransparentUnion(p, tok, base_qt),
.vector_size => try attr.applyVectorSize(p, tok, &base_qt),
.aligned => try attr.applyAligned(p, base_qt, diagnostic),
.designated_init => if (base_qt.is(p.comp, .@"struct")) {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
} else {
try p.err(tok, .designated_init_invalid, .{});
},
@ -913,6 +926,7 @@ pub fn applyTypeAttributes(p: *Parser, qt: QualType, attr_buf_start: usize, diag
}
pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize) !QualType {
const gpa = p.comp.gpa;
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
@ -927,37 +941,37 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
.@"const", .warn_unused_result, .section, .returns_nonnull, .returns_twice, .@"error",
.externally_visible, .retain, .flatten, .gnu_inline, .alias, .asm_label, .nodiscard,
.reproducible, .unsequenced, .nothrow, .nullability, .unaligned,
=> try p.attr_application_buf.append(p.gpa, attr),
=> try p.attr_application_buf.append(gpa, attr),
// zig fmt: on
.hot => if (cold) {
try p.err(tok, .ignore_hot, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
hot = true;
},
.cold => if (hot) {
try p.err(tok, .ignore_cold, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
cold = true;
},
.always_inline => if (@"noinline") {
try p.err(tok, .ignore_always_inline, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
always_inline = true;
},
.@"noinline" => if (always_inline) {
try p.err(tok, .ignore_noinline, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
@"noinline" = true;
},
.aligned => try attr.applyAligned(p, base_qt, null),
.format => try attr.applyFormat(p, base_qt),
.calling_convention => try applyCallingConvention(attr, p, tok, base_qt),
.fastcall => if (p.comp.target.cpu.arch == .x86) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .fastcall } },
.syntax = attr.syntax,
@ -966,7 +980,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"fastcall"});
},
.stdcall => if (p.comp.target.cpu.arch == .x86) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .stdcall } },
.syntax = attr.syntax,
@ -975,7 +989,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"stdcall"});
},
.thiscall => if (p.comp.target.cpu.arch == .x86) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .thiscall } },
.syntax = attr.syntax,
@ -984,7 +998,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"thiscall"});
},
.vectorcall => if (p.comp.target.cpu.arch == .x86 or p.comp.target.cpu.arch.isAARCH64()) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .vectorcall } },
.syntax = attr.syntax,
@ -994,7 +1008,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
},
.cdecl => {},
.pcs => if (p.comp.target.cpu.arch.isArm()) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = switch (attr.args.pcs.kind) {
.aapcs => .arm_aapcs,
@ -1006,7 +1020,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"pcs"});
},
.riscv_vector_cc => if (p.comp.target.cpu.arch.isRISCV()) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .riscv_vector } },
.syntax = attr.syntax,
@ -1015,7 +1029,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"pcs"});
},
.aarch64_sve_pcs => if (p.comp.target.cpu.arch.isAARCH64()) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .aarch64_sve_pcs } },
.syntax = attr.syntax,
@ -1024,7 +1038,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"pcs"});
},
.aarch64_vector_pcs => if (p.comp.target.cpu.arch.isAARCH64()) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .aarch64_vector_pcs } },
.syntax = attr.syntax,
@ -1033,14 +1047,14 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
try p.err(tok, .callconv_not_supported, .{"pcs"});
},
.sysv_abi => if (p.comp.target.cpu.arch == .x86_64 and p.comp.target.os.tag == .windows) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .x86_64_sysv } },
.syntax = attr.syntax,
});
},
.ms_abi => if (p.comp.target.cpu.arch == .x86_64 and p.comp.target.os.tag != .windows) {
try p.attr_application_buf.append(p.gpa, .{
try p.attr_application_buf.append(gpa, .{
.tag = .calling_convention,
.args = .{ .calling_convention = .{ .cc = .x86_64_win } },
.syntax = attr.syntax,
@ -1048,7 +1062,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
},
.malloc => {
if (base_qt.get(p.comp, .func).?.return_type.isPointer(p.comp)) {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
} else {
try ignoredAttrErr(p, tok, attr.tag, "functions that do not return pointers");
}
@ -1065,7 +1079,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
if (!arg_sk.isInt() or !arg_sk.isReal()) {
try p.err(tok, .alloc_align_required_int_param, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
}
}
} else {
@ -1098,7 +1112,7 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
.no_stack_protector,
.noclone,
.noipa,
// .nonnull,
.nonnull,
.noplt,
// .optimize,
.patchable_function_entry,
@ -1118,23 +1132,24 @@ pub fn applyFunctionAttributes(p: *Parser, qt: QualType, attr_buf_start: usize)
}
pub fn applyLabelAttributes(p: *Parser, attr_buf_start: usize) !QualType {
const gpa = p.comp.gpa;
const attrs = p.attr_buf.items(.attr)[attr_buf_start..];
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
var hot = false;
var cold = false;
for (attrs, toks) |attr, tok| switch (attr.tag) {
.unused => try p.attr_application_buf.append(p.gpa, attr),
.unused => try p.attr_application_buf.append(gpa, attr),
.hot => if (cold) {
try p.err(tok, .ignore_hot, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
hot = true;
},
.cold => if (hot) {
try p.err(tok, .ignore_cold, .{});
} else {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(gpa, attr);
cold = true;
},
else => try ignoredAttrErr(p, tok, attr.tag, "labels"),
@ -1151,7 +1166,7 @@ pub fn applyStatementAttributes(p: *Parser, expr_start: TokenIndex, attr_buf_sta
for (p.tok_ids[p.tok_i..]) |tok_id| {
switch (tok_id) {
.keyword_case, .keyword_default, .eof => {
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(p.comp.gpa, attr);
break;
},
.r_brace => {},
@ -1172,7 +1187,7 @@ pub fn applyEnumeratorAttributes(p: *Parser, qt: QualType, attr_buf_start: usize
const toks = p.attr_buf.items(.tok)[attr_buf_start..];
p.attr_application_buf.items.len = 0;
for (attrs, toks) |attr, tok| switch (attr.tag) {
.deprecated, .unavailable => try p.attr_application_buf.append(p.gpa, attr),
.deprecated, .unavailable => try p.attr_application_buf.append(p.comp.gpa, attr),
else => try ignoredAttrErr(p, tok, attr.tag, "enums"),
};
return applySelected(qt, p);
@ -1193,7 +1208,7 @@ fn applyAligned(attr: Attribute, p: *Parser, qt: QualType, diagnostic: ?Parser.D
try p.err(align_tok, .minimum_alignment, .{default_align});
}
}
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(p.comp.gpa, attr);
}
fn applyTransparentUnion(attr: Attribute, p: *Parser, tok: TokenIndex, qt: QualType) !void {
@ -1214,7 +1229,7 @@ fn applyTransparentUnion(attr: Attribute, p: *Parser, tok: TokenIndex, qt: QualT
return p.err(union_ty.fields[0].name_tok, .transparent_union_size_note, .{first_field_size});
}
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(p.comp.gpa, attr);
}
fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, qt: *QualType) !void {
@ -1245,7 +1260,7 @@ fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, qt: *QualType)
return p.err(tok, .vec_size_not_multiple, .{});
}
qt.* = try p.comp.type_store.put(p.gpa, .{ .vector = .{
qt.* = try p.comp.type_store.put(p.comp.gpa, .{ .vector = .{
.elem = qt.*,
.len = @intCast(vec_bytes / elem_size),
} });
@ -1254,7 +1269,7 @@ fn applyVectorSize(attr: Attribute, p: *Parser, tok: TokenIndex, qt: *QualType)
fn applyFormat(attr: Attribute, p: *Parser, qt: QualType) !void {
// TODO validate
_ = qt;
try p.attr_application_buf.append(p.gpa, attr);
try p.attr_application_buf.append(p.comp.gpa, attr);
}
fn applyCallingConvention(attr: Attribute, p: *Parser, tok: TokenIndex, qt: QualType) !void {
@ -1264,11 +1279,11 @@ fn applyCallingConvention(attr: Attribute, p: *Parser, tok: TokenIndex, qt: Qual
switch (attr.args.calling_convention.cc) {
.c => {},
.stdcall, .thiscall, .fastcall, .regcall => switch (p.comp.target.cpu.arch) {
.x86 => try p.attr_application_buf.append(p.gpa, attr),
.x86 => try p.attr_application_buf.append(p.comp.gpa, attr),
else => try p.err(tok, .callconv_not_supported, .{p.tok_ids[tok].symbol()}),
},
.vectorcall => switch (p.comp.target.cpu.arch) {
.x86, .aarch64, .aarch64_be => try p.attr_application_buf.append(p.gpa, attr),
.x86, .aarch64, .aarch64_be => try p.attr_application_buf.append(p.comp.gpa, attr),
else => try p.err(tok, .callconv_not_supported, .{p.tok_ids[tok].symbol()}),
},
.riscv_vector,
@ -1285,7 +1300,7 @@ fn applyCallingConvention(attr: Attribute, p: *Parser, tok: TokenIndex, qt: Qual
fn applySelected(qt: QualType, p: *Parser) !QualType {
if (p.attr_application_buf.items.len == 0) return qt;
if (qt.isInvalid()) return qt;
return (try p.comp.type_store.put(p.gpa, .{ .attributed = .{
return (try p.comp.type_store.put(p.comp.gpa, .{ .attributed = .{
.base = qt,
.attributes = p.attr_application_buf.items,
} })).withQualifiers(qt);

File diff suppressed because it is too large Load Diff

View File

@ -312,12 +312,13 @@ pub const Iterator = struct {
};
test Iterator {
const gpa = std.testing.allocator;
var it = Iterator{};
var seen = std.StringHashMap(Builtin).init(std.testing.allocator);
defer seen.deinit();
var seen: std.StringHashMapUnmanaged(Builtin) = .empty;
defer seen.deinit(gpa);
var arena_state = std.heap.ArenaAllocator.init(std.testing.allocator);
var arena_state = std.heap.ArenaAllocator.init(gpa);
defer arena_state.deinit();
const arena = arena_state.allocator();
@ -333,7 +334,7 @@ test Iterator {
std.debug.print("previous data: {}\n", .{seen.get(entry.name).?});
return error.TestExpectedUniqueEntries;
}
try seen.put(try arena.dupe(u8, entry.name), entry.builtin);
try seen.put(gpa, try arena.dupe(u8, entry.name), entry.builtin);
}
try std.testing.expectEqual(@as(usize, Builtin.data.len), seen.count());
}

View File

@ -40,11 +40,11 @@ tree: *const Tree,
comp: *Compilation,
builder: Builder,
wip_switch: *WipSwitch = undefined,
symbols: std.ArrayListUnmanaged(Symbol) = .{},
ret_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{},
phi_nodes: std.ArrayListUnmanaged(Ir.Inst.Phi.Input) = .{},
record_elem_buf: std.ArrayListUnmanaged(Interner.Ref) = .{},
record_cache: std.AutoHashMapUnmanaged(QualType, Interner.Ref) = .{},
symbols: std.ArrayList(Symbol) = .empty,
ret_nodes: std.ArrayList(Ir.Inst.Phi.Input) = .empty,
phi_nodes: std.ArrayList(Ir.Inst.Phi.Input) = .empty,
record_elem_buf: std.ArrayList(Interner.Ref) = .empty,
record_cache: std.AutoHashMapUnmanaged(QualType, Interner.Ref) = .empty,
cond_dummy_ty: ?Interner.Ref = null,
bool_invert: bool = false,
bool_end_label: Ir.Ref = .none,
@ -56,10 +56,11 @@ compound_assign_dummy: ?Ir.Ref = null,
fn fail(c: *CodeGen, comptime fmt: []const u8, args: anytype) error{ FatalError, OutOfMemory } {
var sf = std.heap.stackFallback(1024, c.comp.gpa);
var buf = std.ArrayList(u8).init(sf.get());
defer buf.deinit();
const allocator = sf.get();
var buf: std.ArrayList(u8) = .empty;
defer buf.deinit(allocator);
try buf.print(fmt, args);
try buf.print(allocator, fmt, args);
try c.comp.diagnostics.add(.{ .text = buf.items, .kind = .@"fatal error", .location = null });
return error.FatalError;
}

View File

@ -4,8 +4,9 @@ const EpochSeconds = std.time.epoch.EpochSeconds;
const mem = std.mem;
const Allocator = mem.Allocator;
const Interner = @import("../backend.zig").Interner;
const CodeGenOptions = @import("../backend.zig").CodeGenOptions;
const backend = @import("../backend.zig");
const Interner = backend.Interner;
const CodeGenOptions = backend.CodeGenOptions;
const Builtins = @import("Builtins.zig");
const Builtin = Builtins.Builtin;
@ -127,24 +128,24 @@ diagnostics: *Diagnostics,
code_gen_options: CodeGenOptions = .default,
environment: Environment = .{},
sources: std.StringArrayHashMapUnmanaged(Source) = .{},
sources: std.StringArrayHashMapUnmanaged(Source) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
include_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
include_dirs: std.ArrayList([]const u8) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
system_include_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
system_include_dirs: std.ArrayList([]const u8) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
after_include_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
after_include_dirs: std.ArrayList([]const u8) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
framework_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
framework_dirs: std.ArrayList([]const u8) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
system_framework_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
system_framework_dirs: std.ArrayList([]const u8) = .empty,
/// Allocated into `gpa`, but keys are externally managed.
embed_dirs: std.ArrayListUnmanaged([]const u8) = .empty,
embed_dirs: std.ArrayList([]const u8) = .empty,
target: std.Target = @import("builtin").target,
cmodel: std.builtin.CodeModel = .default,
pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .{},
pragma_handlers: std.StringArrayHashMapUnmanaged(*Pragma) = .empty,
langopts: LangOpts = .{},
generated_buf: std.ArrayListUnmanaged(u8) = .{},
generated_buf: std.ArrayList(u8) = .empty,
builtins: Builtins = .{},
string_interner: StringInterner = .{},
interner: Interner = .{},
@ -245,6 +246,13 @@ fn generateSystemDefines(comp: *Compilation, w: *std.Io.Writer) !void {
try w.print("#define __GNUC_PATCHLEVEL__ {d}\n", .{comp.langopts.gnuc_version % 100});
}
if (comp.code_gen_options.optimization_level.hasAnyOptimizations()) {
try define(w, "__OPTIMIZE__");
}
if (comp.code_gen_options.optimization_level.isSizeOptimized()) {
try define(w, "__OPTIMIZE_SIZE__");
}
// os macros
switch (comp.target.os.tag) {
.linux => try defineStd(w, "linux", is_gnu),
@ -1379,8 +1387,8 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
const duped_path = try comp.gpa.dupe(u8, path);
errdefer comp.gpa.free(duped_path);
var splice_list = std.array_list.Managed(u32).init(comp.gpa);
defer splice_list.deinit();
var splice_list: std.ArrayList(u32) = .empty;
defer splice_list.deinit(comp.gpa);
const source_id: Source.Id = @enumFromInt(comp.sources.count() + 2);
@ -1413,9 +1421,9 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
},
.back_slash, .trailing_ws, .back_slash_cr => {
i = backslash_loc;
try splice_list.append(i);
try splice_list.append(comp.gpa, i);
if (state == .trailing_ws) {
try comp.addNewlineEscapeError(path, buf, splice_list.items, i, line);
try comp.addNewlineEscapeError(path, buf, splice_list.items, i, line, kind);
}
state = if (state == .back_slash_cr) .cr else .back_slash_cr;
},
@ -1433,10 +1441,10 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
.back_slash, .trailing_ws => {
i = backslash_loc;
if (state == .back_slash or state == .trailing_ws) {
try splice_list.append(i);
try splice_list.append(comp.gpa, i);
}
if (state == .trailing_ws) {
try comp.addNewlineEscapeError(path, buf, splice_list.items, i, line);
try comp.addNewlineEscapeError(path, buf, splice_list.items, i, line, kind);
}
},
.bom1, .bom2 => break,
@ -1486,11 +1494,11 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
}
}
const splice_locs = try splice_list.toOwnedSlice();
const splice_locs = try splice_list.toOwnedSlice(comp.gpa);
errdefer comp.gpa.free(splice_locs);
if (i != contents.len) {
var list: std.ArrayListUnmanaged(u8) = .{
var list: std.ArrayList(u8) = .{
.items = contents[0..i],
.capacity = contents.len,
};
@ -1510,13 +1518,21 @@ pub fn addSourceFromOwnedBuffer(comp: *Compilation, path: []const u8, buf: []u8,
return source;
}
fn addNewlineEscapeError(comp: *Compilation, path: []const u8, buf: []const u8, splice_locs: []const u32, byte_offset: u32, line: u32) !void {
fn addNewlineEscapeError(
comp: *Compilation,
path: []const u8,
buf: []const u8,
splice_locs: []const u32,
byte_offset: u32,
line: u32,
kind: Source.Kind,
) !void {
// Temporary source for getting the location for errors.
var tmp_source: Source = .{
.path = path,
.buf = buf,
.id = undefined,
.kind = undefined,
.kind = kind,
.splice_locs = splice_locs,
};
@ -1566,17 +1582,7 @@ fn addSourceFromPathExtra(comp: *Compilation, path: []const u8, kind: Source.Kin
}
pub fn addSourceFromFile(comp: *Compilation, file: std.fs.File, path: []const u8, kind: Source.Kind) !Source {
var file_buf: [4096]u8 = undefined;
var file_reader = file.reader(&file_buf);
if (try file_reader.getSize() > std.math.maxInt(u32)) return error.FileTooBig;
var allocating: std.Io.Writer.Allocating = .init(comp.gpa);
_ = allocating.writer.sendFileAll(&file_reader, .limited(std.math.maxInt(u32))) catch |e| switch (e) {
error.WriteFailed => return error.OutOfMemory,
error.ReadFailed => return file_reader.err.?,
};
const contents = try allocating.toOwnedSlice();
const contents = try comp.getFileContents(file, .unlimited);
errdefer comp.gpa.free(contents);
return comp.addSourceFromOwnedBuffer(path, contents, kind);
}
@ -1671,7 +1677,7 @@ const FindInclude = struct {
if (try find.checkFrameworkDir(dir, .system)) |res| return res;
}
for (comp.after_include_dirs.items) |dir| {
if (try find.checkIncludeDir(dir, .user)) |res| return res;
if (try find.checkIncludeDir(dir, .system)) |res| return res;
}
if (comp.ms_cwd_source_id) |source_id| {
if (try find.checkMsCwdIncludeDir(source_id)) |res| return res;
@ -1766,26 +1772,38 @@ pub const IncludeType = enum {
angle_brackets,
};
fn getFileContents(comp: *Compilation, path: []const u8, limit: std.Io.Limit) ![]const u8 {
fn getPathContents(comp: *Compilation, path: []const u8, limit: std.Io.Limit) ![]u8 {
if (mem.indexOfScalar(u8, path, 0) != null) {
return error.FileNotFound;
}
const file = try comp.cwd.openFile(path, .{});
defer file.close();
return comp.getFileContents(file, limit);
}
fn getFileContents(comp: *Compilation, file: std.fs.File, limit: std.Io.Limit) ![]u8 {
var file_buf: [4096]u8 = undefined;
var file_reader = file.reader(&file_buf);
var allocating: std.Io.Writer.Allocating = .init(comp.gpa);
defer allocating.deinit();
if (file_reader.getSize()) |size| {
const limited_size = limit.minInt64(size);
if (limited_size > std.math.maxInt(u32)) return error.FileTooBig;
try allocating.ensureUnusedCapacity(limited_size);
} else |_| {}
var file_buf: [4096]u8 = undefined;
var file_reader = file.reader(&file_buf);
if (limit.minInt64(try file_reader.getSize()) > std.math.maxInt(u32)) return error.FileTooBig;
_ = allocating.writer.sendFileAll(&file_reader, limit) catch |err| switch (err) {
error.WriteFailed => return error.OutOfMemory,
error.ReadFailed => return file_reader.err.?,
};
var remaining = limit.min(.limited(std.math.maxInt(u32)));
while (remaining.nonzero()) {
const n = file_reader.interface.stream(&allocating.writer, remaining) catch |err| switch (err) {
error.EndOfStream => return allocating.toOwnedSlice(),
error.WriteFailed => return error.OutOfMemory,
error.ReadFailed => return file_reader.err.?,
};
remaining = remaining.subtract(n).?;
}
if (limit == .unlimited) return error.FileTooBig;
return allocating.toOwnedSlice();
}
@ -1797,9 +1815,10 @@ pub fn findEmbed(
include_type: IncludeType,
limit: std.Io.Limit,
opt_dep_file: ?*DepFile,
) !?[]const u8 {
) !?[]u8 {
if (std.fs.path.isAbsolute(filename)) {
if (comp.getFileContents(filename, limit)) |some| {
if (comp.getPathContents(filename, limit)) |some| {
errdefer comp.gpa.free(some);
if (opt_dep_file) |dep_file| try dep_file.addDependencyDupe(comp.gpa, comp.arena, filename);
return some;
} else |err| switch (err) {
@ -1819,7 +1838,8 @@ pub fn findEmbed(
if (comp.langopts.ms_extensions) {
std.mem.replaceScalar(u8, path, '\\', '/');
}
if (comp.getFileContents(path, limit)) |some| {
if (comp.getPathContents(path, limit)) |some| {
errdefer comp.gpa.free(some);
if (opt_dep_file) |dep_file| try dep_file.addDependencyDupe(comp.gpa, comp.arena, filename);
return some;
} else |err| switch (err) {
@ -1835,7 +1855,8 @@ pub fn findEmbed(
if (comp.langopts.ms_extensions) {
std.mem.replaceScalar(u8, path, '\\', '/');
}
if (comp.getFileContents(path, limit)) |some| {
if (comp.getPathContents(path, limit)) |some| {
errdefer comp.gpa.free(some);
if (opt_dep_file) |dep_file| try dep_file.addDependencyDupe(comp.gpa, comp.arena, filename);
return some;
} else |err| switch (err) {

View File

@ -28,7 +28,7 @@ pub fn write(d: *const DepFile, w: *std.Io.Writer) std.Io.Writer.Error!void {
const max_columns = 75;
var columns: usize = 0;
try w.writeAll(d.target);
try writeTarget(d.target, w);
columns += d.target.len;
try w.writeByte(':');
columns += 1;
@ -48,6 +48,26 @@ pub fn write(d: *const DepFile, w: *std.Io.Writer) std.Io.Writer.Error!void {
try w.flush();
}
fn writeTarget(path: []const u8, w: *std.Io.Writer) !void {
for (path, 0..) |c, i| {
switch (c) {
' ', '\t' => {
try w.writeByte('\\');
var j = i;
while (j != 0) {
j -= 1;
if (path[j] != '\\') break;
try w.writeByte('\\');
}
},
'$' => try w.writeByte('$'),
'#' => try w.writeByte('\\'),
else => {},
}
try w.writeByte(c);
}
}
fn writePath(d: *const DepFile, path: []const u8, w: *std.Io.Writer) !void {
switch (d.format) {
.nmake => {
@ -58,18 +78,19 @@ fn writePath(d: *const DepFile, path: []const u8, w: *std.Io.Writer) !void {
},
.make => {
for (path, 0..) |c, i| {
if (c == '#') {
try w.writeByte('\\');
} else if (c == '$') {
try w.writeByte('$');
} else if (c == ' ') {
try w.writeByte('\\');
var j = i;
while (j != 0) {
j -= 1;
if (path[j] != '\\') break;
switch (c) {
' ' => {
try w.writeByte('\\');
}
var j = i;
while (j != 0) {
j -= 1;
if (path[j] != '\\') break;
try w.writeByte('\\');
}
},
'$' => try w.writeByte('$'),
'#' => try w.writeByte('\\'),
else => {},
}
try w.writeByte(c);
}

View File

@ -193,6 +193,8 @@ pub const Option = enum {
@"microsoft-flexible-array",
@"microsoft-anon-tag",
@"out-of-scope-function",
@"date-time",
@"attribute-todo",
/// GNU extensions
pub const gnu = [_]Option{
@ -278,6 +280,8 @@ pub const State = struct {
extensions: Message.Kind = .off,
/// How to treat individual options, set by -W<name>
options: std.EnumMap(Option, Message.Kind) = .{},
/// Should warnings be suppressed in system headers, set by -Wsystem-headers
suppress_system_headers: bool = true,
};
const Diagnostics = @This();
@ -288,7 +292,7 @@ output: union(enum) {
color: std.Io.tty.Config,
},
to_list: struct {
messages: std.ArrayListUnmanaged(Message) = .empty,
messages: std.ArrayList(Message) = .empty,
arena: std.heap.ArenaAllocator,
},
ignore,
@ -373,6 +377,16 @@ pub fn effectiveKind(d: *Diagnostics, message: anytype) Message.Kind {
return .off;
}
if (@hasField(@TypeOf(message), "location")) {
if (message.location) |location| {
if (location.kind != .user and d.state.suppress_system_headers and
(message.kind == .warning or message.kind == .off))
{
return .off;
}
}
}
var kind = message.kind;
// Get explicit kind set by -W<name>=
@ -418,9 +432,9 @@ pub fn addWithLocation(
note_msg_loc: bool,
) Compilation.Error!void {
var copy = msg;
copy.effective_kind = d.effectiveKind(msg);
if (copy.effective_kind == .off) return;
if (expansion_locs.len != 0) copy.location = expansion_locs[expansion_locs.len - 1].expand(comp);
copy.effective_kind = d.effectiveKind(copy);
if (copy.effective_kind == .off) return;
try d.addMessage(copy);
if (expansion_locs.len != 0) {

View File

@ -45,8 +45,8 @@ const Driver = @This();
comp: *Compilation,
diagnostics: *Diagnostics,
inputs: std.ArrayListUnmanaged(Source) = .{},
link_objects: std.ArrayListUnmanaged([]const u8) = .{},
inputs: std.ArrayList(Source) = .empty,
link_objects: std.ArrayList([]const u8) = .empty,
output_name: ?[]const u8 = null,
sysroot: ?[]const u8 = null,
resource_dir: ?[]const u8 = null,
@ -107,7 +107,6 @@ raw_cpu: ?[]const u8 = null,
use_assembly_backend: bool = false,
// linker options
use_linker: ?[]const u8 = null,
linker_path: ?[]const u8 = null,
nodefaultlibs: bool = false,
nolibc: bool = false,
@ -270,7 +269,7 @@ pub const usage =
pub fn parseArgs(
d: *Driver,
stdout: *std.Io.Writer,
macro_buf: *std.ArrayListUnmanaged(u8),
macro_buf: *std.ArrayList(u8),
args: []const []const u8,
) (Compilation.Error || std.Io.Writer.Error)!bool {
var i: usize = 1;
@ -322,7 +321,7 @@ pub fn parseArgs(
}
try macro_buf.print(d.comp.gpa, "#undef {s}\n", .{macro});
} else if (mem.eql(u8, arg, "-O")) {
d.comp.code_gen_options.optimization_level = .@"0";
d.comp.code_gen_options.optimization_level = .@"1";
} else if (mem.startsWith(u8, arg, "-O")) {
d.comp.code_gen_options.optimization_level = backend.CodeGenOptions.OptimizationLevel.fromString(arg["-O".len..]) orelse {
try d.err("invalid optimization level '{s}'", .{arg});
@ -600,6 +599,10 @@ pub fn parseArgs(
d.diagnostics.state.enable_all_warnings = false;
} else if (mem.eql(u8, arg, "-Weverything")) {
d.diagnostics.state.enable_all_warnings = true;
} else if (mem.eql(u8, arg, "-Wno-system-headers")) {
d.diagnostics.state.suppress_system_headers = true;
} else if (mem.eql(u8, arg, "-Wsystem-headers")) {
d.diagnostics.state.suppress_system_headers = false;
} else if (mem.eql(u8, arg, "-Werror")) {
d.diagnostics.state.error_warnings = true;
} else if (mem.eql(u8, arg, "-Wno-error")) {
@ -644,10 +647,6 @@ pub fn parseArgs(
d.comp.langopts.preserve_comments = true;
d.comp.langopts.preserve_comments_in_macros = true;
comment_arg = arg;
} else if (option(arg, "-fuse-ld=")) |linker_name| {
d.use_linker = linker_name;
} else if (mem.eql(u8, arg, "-fuse-ld=")) {
d.use_linker = null;
} else if (option(arg, "--ld-path=")) |linker_path| {
d.linker_path = linker_path;
} else if (mem.eql(u8, arg, "-r")) {
@ -917,13 +916,11 @@ pub fn errorDescription(e: anyerror) []const u8 {
};
}
var stdout_buffer: [4096]u8 = undefined;
/// The entry point of the Aro compiler.
/// **MAY call `exit` if `fast_exit` is set.**
pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_exit: bool, asm_gen_fn: ?AsmCodeGenFn) Compilation.Error!void {
const user_macros = macros: {
var macro_buf: std.ArrayListUnmanaged(u8) = .empty;
var macro_buf: std.ArrayList(u8) = .empty;
defer macro_buf.deinit(d.comp.gpa);
var stdout_buf: [256]u8 = undefined;
@ -1107,7 +1104,7 @@ fn processSource(
var name_buf: [std.fs.max_name_bytes]u8 = undefined;
var opt_dep_file = try d.initDepFile(source, &name_buf, false);
defer if (opt_dep_file) |*dep_file| dep_file.deinit(pp.gpa);
defer if (opt_dep_file) |*dep_file| dep_file.deinit(d.comp.gpa);
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;
@ -1164,14 +1161,11 @@ fn processSource(
else
std.fs.File.stdout();
defer if (d.output_name != null) file.close();
var file_buffer: [1024]u8 = undefined;
var file_writer = file.writer(&file_buffer);
pp.prettyPrintTokens(&file_writer.interface, dump_mode) catch |er|
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
var file_writer = file.writer(&writer_buf);
pp.prettyPrintTokens(&file_writer.interface, dump_mode) catch
return d.fatal("unable to write result: {s}", .{errorDescription(file_writer.err.?)});
file_writer.interface.flush() catch |er|
return d.fatal("unable to write result: {s}", .{errorDescription(er)});
if (fast_exit) std.process.exit(0); // Not linking, no need for cleanup.
return;
}
@ -1180,9 +1174,8 @@ fn processSource(
defer tree.deinit();
if (d.verbose_ast) {
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
tree.dump(d.detectConfig(.stdout()), &stdout_writer.interface) catch {};
stdout_writer.interface.flush() catch {};
var stdout = std.fs.File.stdout().writer(&writer_buf);
tree.dump(d.detectConfig(stdout.file), &stdout.interface) catch {};
}
d.printDiagnosticsStats();
@ -1299,12 +1292,13 @@ fn dumpLinkerArgs(w: *std.Io.Writer, items: []const []const u8) !void {
/// The entry point of the Aro compiler.
/// **MAY call `exit` if `fast_exit` is set.**
pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) Compilation.Error!void {
var argv = std.array_list.Managed([]const u8).init(d.comp.gpa);
defer argv.deinit();
const gpa = d.comp.gpa;
var argv: std.ArrayList([]const u8) = .empty;
defer argv.deinit(gpa);
var linker_path_buf: [std.fs.max_path_bytes]u8 = undefined;
const linker_path = try tc.getLinkerPath(&linker_path_buf);
try argv.append(linker_path);
try argv.append(gpa, linker_path);
try tc.buildLinkerArgs(&argv);

View File

@ -1,47 +1,50 @@
const std = @import("std");
const Filesystem = @import("Filesystem.zig").Filesystem;
pub const Flags = std.ArrayListUnmanaged([]const u8);
/// Large enough for GCCDetector for Linux; may need to be increased to support other toolchains.
const max_multilibs = 4;
const MultilibArray = std.ArrayListUnmanaged(Multilib);
pub const Detected = struct {
multilibs: MultilibArray = .{},
multilib_buf: [max_multilibs]Multilib = undefined,
multilib_count: u8 = 0,
selected: Multilib = .{},
biarch_sibling: ?Multilib = null,
pub fn filter(self: *Detected, multilib_filter: Filter, fs: Filesystem) void {
var found_count: usize = 0;
for (self.multilibs.items) |multilib| {
pub fn filter(d: *Detected, multilib_filter: Filter, fs: Filesystem) void {
var found_count: u8 = 0;
for (d.multilibs()) |multilib| {
if (multilib_filter.exists(multilib, fs)) {
self.multilibs.items[found_count] = multilib;
d.multilib_buf[found_count] = multilib;
found_count += 1;
}
}
self.multilibs.resize(found_count) catch unreachable;
d.multilib_count = found_count;
}
pub fn select(self: *Detected, flags: []const []const Flags) !bool {
var filtered: MultilibArray = .{};
for (self.multilibs.items) |multilib| {
for (flags) |multilib_flag| {
const matched = for (flags) |arg_flag| {
pub fn select(d: *Detected, check_flags: []const []const u8) !bool {
var selected: ?Multilib = null;
for (d.multilibs()) |multilib| {
for (multilib.flags()) |multilib_flag| {
const matched = for (check_flags) |arg_flag| {
if (std.mem.eql(u8, arg_flag[1..], multilib_flag[1..])) break arg_flag;
} else multilib_flag;
if (matched[0] != multilib_flag[0]) break;
} else if (selected != null) {
return error.TooManyMultilibs;
} else {
filtered.appendAssumeCapacity(multilib);
selected = multilib;
}
}
if (filtered.len == 0) return false;
if (filtered.len == 1) {
self.selected = filtered.get(0);
if (selected) |multilib| {
d.selected = multilib;
return true;
}
return error.TooManyMultilibs;
return false;
}
pub fn multilibs(d: *const Detected) []const Multilib {
return d.multilib_buf[0..d.multilib_count];
}
};
@ -58,14 +61,20 @@ const Multilib = @This();
gcc_suffix: []const u8 = "",
os_suffix: []const u8 = "",
include_suffix: []const u8 = "",
flags: Flags = .{},
flag_buf: [6][]const u8 = undefined,
flag_count: u8 = 0,
priority: u32 = 0,
pub fn init(gcc_suffix: []const u8, os_suffix: []const u8, flags: []const []const u8) Multilib {
pub fn init(gcc_suffix: []const u8, os_suffix: []const u8, init_flags: []const []const u8) Multilib {
var self: Multilib = .{
.gcc_suffix = gcc_suffix,
.os_suffix = os_suffix,
.flag_count = @intCast(init_flags.len),
};
self.flags.appendSliceAssumeCapacity(flags);
@memcpy(self.flag_buf[0..init_flags.len], init_flags);
return self;
}
pub fn flags(m: *const Multilib) []const []const u8 {
return m.flag_buf[0..m.flag_count];
}

View File

@ -22,7 +22,7 @@ const Item = struct {
const InitList = @This();
list: std.ArrayListUnmanaged(Item) = .empty,
list: std.ArrayList(Item) = .empty,
node: Node.OptIndex = .null,
tok: TokenIndex = 0,

File diff suppressed because it is too large Load Diff

View File

@ -2304,6 +2304,7 @@ pub const overflow_result_requires_ptr: Diagnostic = .{
pub const attribute_todo: Diagnostic = .{
.fmt = "TODO: implement '{s}' attribute for {s}",
.kind = .warning,
.opt = .@"attribute-todo",
};
pub const invalid_type_underlying_enum: Diagnostic = .{
@ -2395,3 +2396,29 @@ pub const invalid_nullability: Diagnostic = .{
.fmt = "nullability specifier cannot be applied to non-pointer type {qt}",
.kind = .@"error",
};
pub const array_not_assignable: Diagnostic = .{
.fmt = "array type {qt} is not assignable",
.kind = .@"error",
};
pub const non_object_not_assignable: Diagnostic = .{
.fmt = "non-object type {qt} is not assignable",
.kind = .@"error",
};
pub const const_var_assignment: Diagnostic = .{
.fmt = "cannot assign to variable '{s}' with const-qualified type {qt}",
.kind = .@"error",
};
pub const declared_const_here: Diagnostic = .{
.fmt = "variable '{s}' declared const here",
.kind = .note,
};
pub const nonnull_not_applicable: Diagnostic = .{
.fmt = "'nonnull' attribute only applies to functions, methods, and parameters",
.kind = .warning,
.opt = .@"ignored-attributes",
};

View File

@ -60,7 +60,7 @@ pub fn pasteTokens(pp: *Preprocessor, start_idx: TokenIndex) ![]const u8 {
.string_literal => {
if (rparen_count != 0) return error.ExpectedStringLiteral;
const str = pp.expandedSlice(tok);
try pp.char_buf.appendSlice(str[1 .. str.len - 1]);
try pp.char_buf.appendSlice(pp.comp.gpa, str[1 .. str.len - 1]);
},
else => return error.ExpectedStringLiteral,
}
@ -194,7 +194,7 @@ pub const Diagnostic = struct {
};
pub fn err(pp: *Preprocessor, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) Compilation.Error!void {
var sf = std.heap.stackFallback(1024, pp.gpa);
var sf = std.heap.stackFallback(1024, pp.comp.gpa);
var allocating: std.Io.Writer.Allocating = .init(sf.get());
defer allocating.deinit();

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@ fmt: []const u8,
kind: Diagnostics.Message.Kind,
opt: ?Diagnostics.Option = null,
extension: bool = false,
show_in_system_headers: bool = false,
pub const elif_without_if: Diagnostic = .{
.fmt = "#elif without #if",
@ -91,6 +92,7 @@ pub const warning_directive: Diagnostic = .{
.fmt = "{s}",
.opt = .@"#warnings",
.kind = .warning,
.show_in_system_headers = true,
};
pub const macro_name_missing: Diagnostic = .{
@ -440,3 +442,10 @@ pub const invalid_source_epoch: Diagnostic = .{
.fmt = "environment variable SOURCE_DATE_EPOCH must expand to a non-negative integer less than or equal to 253402300799",
.kind = .@"error",
};
pub const date_time: Diagnostic = .{
.fmt = "expansion of date or time macro is not reproducible",
.kind = .off,
.opt = .@"date-time",
.show_in_system_headers = true,
};

View File

@ -38,6 +38,7 @@ pub const ExpandedLocation = struct {
col: u32,
width: u32,
end_with_splice: bool,
kind: Kind,
};
const Source = @This();
@ -120,6 +121,7 @@ pub fn lineCol(source: Source, loc: Location) ExpandedLocation {
.col = col,
.width = width,
.end_with_splice = end_with_splice,
.kind = source.kind,
};
}

View File

@ -35,14 +35,14 @@ pub const Kind = enum {
constexpr,
};
scopes: std.ArrayListUnmanaged(Scope) = .{},
scopes: std.ArrayList(Scope) = .empty,
/// allocations from nested scopes are retained after popping; `active_len` is the number
/// of currently-active items in `scopes`.
active_len: usize = 0,
const Scope = struct {
vars: std.AutoHashMapUnmanaged(StringId, Symbol) = .{},
tags: std.AutoHashMapUnmanaged(StringId, Symbol) = .{},
vars: std.AutoHashMapUnmanaged(StringId, Symbol) = .empty,
tags: std.AutoHashMapUnmanaged(StringId, Symbol) = .empty,
fn deinit(self: *Scope, allocator: Allocator) void {
self.vars.deinit(allocator);
@ -66,7 +66,7 @@ pub fn deinit(s: *SymbolStack, gpa: Allocator) void {
pub fn pushScope(s: *SymbolStack, p: *Parser) !void {
if (s.active_len + 1 > s.scopes.items.len) {
try s.scopes.append(p.gpa, .{});
try s.scopes.append(p.comp.gpa, .{});
s.active_len = s.scopes.items.len;
} else {
s.scopes.items[s.active_len].clearRetainingCapacity();
@ -195,7 +195,7 @@ pub fn defineTypedef(
else => unreachable,
}
}
try s.define(p.gpa, .{
try s.define(p.comp.gpa, .{
.kind = .typedef,
.name = name,
.tok = tok,
@ -245,7 +245,7 @@ pub fn defineSymbol(
}
}
try s.define(p.gpa, .{
try s.define(p.comp.gpa, .{
.kind = if (constexpr) .constexpr else .def,
.name = name,
.tok = tok,
@ -306,7 +306,7 @@ pub fn declareSymbol(
else => unreachable,
}
}
try s.define(p.gpa, .{
try s.define(p.comp.gpa, .{
.kind = .decl,
.name = name,
.tok = tok,
@ -317,7 +317,7 @@ pub fn declareSymbol(
// Declare out of scope symbol for functions declared in functions.
if (s.active_len > 1 and !p.comp.langopts.standard.atLeast(.c23) and qt.is(p.comp, .func)) {
try s.scopes.items[0].vars.put(p.gpa, name, .{
try s.scopes.items[0].vars.put(p.comp.gpa, name, .{
.kind = .decl,
.name = name,
.tok = tok,
@ -352,7 +352,7 @@ pub fn defineParam(
else => unreachable,
}
}
try s.define(p.gpa, .{
try s.define(p.comp.gpa, .{
.kind = .def,
.name = name,
.tok = tok,
@ -424,7 +424,7 @@ pub fn defineEnumeration(
else => unreachable,
}
}
try s.define(p.gpa, .{
try s.define(p.comp.gpa, .{
.kind = .enumeration,
.name = name,
.tok = tok,

View File

@ -9,7 +9,7 @@ const Filesystem = @import("Driver/Filesystem.zig").Filesystem;
const Multilib = @import("Driver/Multilib.zig");
const target_util = @import("target.zig");
pub const PathList = std.ArrayListUnmanaged([]const u8);
pub const PathList = std.ArrayList([]const u8);
pub const RuntimeLibKind = enum {
compiler_rt,
@ -64,7 +64,6 @@ pub fn getTarget(tc: *const Toolchain) std.Target {
fn getDefaultLinker(tc: *const Toolchain) []const u8 {
return switch (tc.inner) {
.uninitialized => unreachable,
.linux => |linux| linux.getDefaultLinker(tc.getTarget()),
.unknown => "ld",
};
}
@ -72,6 +71,7 @@ fn getDefaultLinker(tc: *const Toolchain) []const u8 {
/// Call this after driver has finished parsing command line arguments to find the toolchain
pub fn discover(tc: *Toolchain) !void {
if (tc.inner != .uninitialized) return;
tc.inner = .unknown;
return switch (tc.inner) {
.uninitialized => unreachable,
@ -143,8 +143,11 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
return use_linker;
}
} else {
var linker_name = try std.array_list.Managed(u8).initCapacity(tc.driver.comp.gpa, 5 + use_linker.len); // "ld64." ++ use_linker
defer linker_name.deinit();
const gpa = tc.driver.comp.gpa;
var linker_name: std.ArrayList(u8) = .empty;
defer linker_name.deinit(gpa);
try linker_name.ensureUnusedCapacity(tc.driver.comp.gpa, 5 + use_linker.len); // "ld64." ++ use_linker
if (tc.getTarget().os.tag.isDarwin()) {
linker_name.appendSliceAssumeCapacity("ld64.");
} else {
@ -171,20 +174,27 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 {
/// TODO: this isn't exactly right since our target names don't necessarily match up
/// with GCC's.
/// For example the Zig target `arm-freestanding-eabi` would need the `arm-none-eabi` tools
fn possibleProgramNames(raw_triple: ?[]const u8, name: []const u8, buf: *[64]u8, possible_names: *std.ArrayListUnmanaged([]const u8)) void {
fn possibleProgramNames(
raw_triple: ?[]const u8,
name: []const u8,
buf: *[64]u8,
possible_name_buf: *[2][]const u8,
) []const []const u8 {
var i: u32 = 0;
if (raw_triple) |triple| {
if (std.fmt.bufPrint(buf, "{s}-{s}", .{ triple, name })) |res| {
possible_names.appendAssumeCapacity(res);
possible_name_buf[i] = res;
i += 1;
} else |_| {}
}
possible_names.appendAssumeCapacity(name);
possible_name_buf[i] = name;
return possible_names;
return possible_name_buf[0..i];
}
/// Add toolchain `file_paths` to argv as `-L` arguments
pub fn addFilePathLibArgs(tc: *const Toolchain, argv: *std.array_list.Managed([]const u8)) !void {
try argv.ensureUnusedCapacity(tc.file_paths.items.len);
pub fn addFilePathLibArgs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void {
try argv.ensureUnusedCapacity(tc.driver.comp.gpa, tc.file_paths.items.len);
var bytes_needed: usize = 0;
for (tc.file_paths.items) |path| {
@ -208,11 +218,10 @@ fn getProgramPath(tc: *const Toolchain, name: []const u8, buf: []u8) []const u8
var fib = std.heap.FixedBufferAllocator.init(&path_buf);
var tool_specific_buf: [64]u8 = undefined;
var possible_names_buffer: [2][]const u8 = undefined;
var possible_names = std.ArrayListUnmanaged.initBuffer(&possible_names_buffer);
possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_buf, &possible_names);
var possible_name_buf: [2][]const u8 = undefined;
const possible_names = possibleProgramNames(tc.driver.raw_target_triple, name, &tool_specific_buf, &possible_name_buf);
for (possible_names.items) |tool_name| {
for (possible_names) |tool_name| {
for (tc.program_paths.items) |program_path| {
defer fib.reset();
@ -318,16 +327,6 @@ pub fn addPathFromComponents(tc: *Toolchain, components: []const []const u8, des
try dest.append(tc.driver.comp.gpa, full_path);
}
/// Add linker args to `argv`. Does not add path to linker executable as first item; that must be handled separately
/// Items added to `argv` will be string literals or owned by `tc.driver.comp.arena` so they must not be individually freed
pub fn buildLinkerArgs(tc: *Toolchain, argv: *std.array_list.Managed([]const u8)) !void {
return switch (tc.inner) {
.uninitialized => unreachable,
.linux => |*linux| linux.buildLinkerArgs(tc, argv),
.unknown => @panic("This toolchain does not support linking yet"),
};
}
fn getDefaultRuntimeLibKind(tc: *const Toolchain) RuntimeLibKind {
if (tc.getTarget().abi.isAndroid()) {
return .compiler_rt;
@ -400,7 +399,7 @@ fn getAsNeededOption(is_solaris: bool, needed: bool) []const u8 {
}
}
fn addUnwindLibrary(tc: *const Toolchain, argv: *std.array_list.Managed([]const u8)) !void {
fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void {
const unw = try tc.getUnwindLibKind();
const target = tc.getTarget();
if ((target.abi.isAndroid() and unw == .libgcc) or
@ -410,46 +409,49 @@ fn addUnwindLibrary(tc: *const Toolchain, argv: *std.array_list.Managed([]const
const lgk = tc.getLibGCCKind();
const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target_util.isCygwinMinGW(target) and target.os.tag != .aix;
try argv.ensureUnusedCapacity(tc.driver.comp.gpa, 3);
if (as_needed) {
try argv.append(getAsNeededOption(target.os.tag == .solaris, true));
argv.appendAssumeCapacity(getAsNeededOption(target.os.tag == .solaris, true));
}
switch (unw) {
.none => return,
.libgcc => if (lgk == .static) try argv.append("-lgcc_eh") else try argv.append("-lgcc_s"),
.libgcc => argv.appendAssumeCapacity(if (lgk == .static) "-lgcc_eh" else "-lgcc_s"),
.compiler_rt => if (target.os.tag == .aix) {
if (lgk != .static) {
try argv.append("-lunwind");
argv.appendAssumeCapacity("-lunwind");
}
} else if (lgk == .static) {
try argv.append("-l:libunwind.a");
argv.appendAssumeCapacity("-l:libunwind.a");
} else if (lgk == .shared) {
if (target_util.isCygwinMinGW(target)) {
try argv.append("-l:libunwind.dll.a");
argv.appendAssumeCapacity("-l:libunwind.dll.a");
} else {
try argv.append("-l:libunwind.so");
argv.appendAssumeCapacity("-l:libunwind.so");
}
} else {
try argv.append("-lunwind");
argv.appendAssumeCapacity("-lunwind");
},
}
if (as_needed) {
try argv.append(getAsNeededOption(target.os.tag == .solaris, false));
argv.appendAssumeCapacity(getAsNeededOption(target.os.tag == .solaris, false));
}
}
fn addLibGCC(tc: *const Toolchain, argv: *std.array_list.Managed([]const u8)) !void {
fn addLibGCC(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void {
const gpa = tc.driver.comp.gpa;
const libgcc_kind = tc.getLibGCCKind();
if (libgcc_kind == .static or libgcc_kind == .unspecified) {
try argv.append("-lgcc");
try argv.append(gpa, "-lgcc");
}
try tc.addUnwindLibrary(argv);
if (libgcc_kind == .shared) {
try argv.append("-lgcc");
try argv.append(gpa, "-lgcc");
}
}
pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.array_list.Managed([]const u8)) !void {
pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void {
const target = tc.getTarget();
const rlt = tc.getRuntimeLibKind();
switch (rlt) {
@ -469,7 +471,7 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.array_list.Managed([]cons
}
if (target.abi.isAndroid() and !tc.driver.static and !tc.driver.static_pie) {
try argv.append("-ldl");
try argv.append(tc.driver.comp.gpa, "-ldl");
}
}

View File

@ -42,7 +42,7 @@ pub const TokenWithExpansionLocs = struct {
pub fn addExpansionLocation(tok: *TokenWithExpansionLocs, gpa: std.mem.Allocator, new: []const Source.Location) !void {
if (new.len == 0 or tok.id == .whitespace or tok.id == .macro_ws or tok.id == .placemarker) return;
var list = std.array_list.Managed(Source.Location).init(gpa);
var list: std.ArrayList(Source.Location) = .empty;
defer {
@memset(list.items.ptr[list.items.len..list.capacity], .{});
// Add a sentinel to indicate the end of the list since
@ -65,7 +65,7 @@ pub const TokenWithExpansionLocs = struct {
const min_len = @max(list.items.len + new.len + 1, 4);
const wanted_len = std.math.ceilPowerOfTwo(usize, min_len) catch
return error.OutOfMemory;
try list.ensureTotalCapacity(wanted_len);
try list.ensureTotalCapacity(gpa, wanted_len);
for (new) |new_loc| {
if (new_loc.id == .generated) continue;
@ -119,8 +119,8 @@ tokens: Token.List.Slice,
// Values owned by this Tree
nodes: std.MultiArrayList(Node.Repr) = .empty,
extra: std.ArrayListUnmanaged(u32) = .empty,
root_decls: std.ArrayListUnmanaged(Node.Index) = .empty,
extra: std.ArrayList(u32) = .empty,
root_decls: std.ArrayList(Node.Index) = .empty,
value_map: ValueMap = .empty,
pub const genIr = CodeGen.genIr;

View File

@ -1216,6 +1216,13 @@ pub const QualType = packed struct(u32) {
return false;
},
.array => |array| {
if (qt.@"const") {
try w.writeAll("const ");
}
if (qt.@"volatile") {
try w.writeAll("volatile");
}
const simple = try array.elem.printPrologue(comp, desugar, w);
if (simple) try w.writeByte(' ');
return false;
@ -1341,14 +1348,6 @@ pub const QualType = packed struct(u32) {
const static = array.len == .static;
if (static) try w.writeAll("static");
if (qt.@"const") {
if (static) try w.writeByte(' ');
try w.writeAll("const");
}
if (qt.@"volatile") {
if (static or qt.@"const") try w.writeByte(' ');
try w.writeAll("volatile");
}
if (qt.restrict) {
if (static or qt.@"const" or qt.@"volatile") try w.writeByte(' ');
try w.writeAll("restrict");
@ -1694,8 +1693,8 @@ pub const Type = union(enum) {
};
types: std.MultiArrayList(Repr) = .empty,
extra: std.ArrayListUnmanaged(u32) = .empty,
attributes: std.ArrayListUnmanaged(Attribute) = .empty,
extra: std.ArrayList(u32) = .empty,
attributes: std.ArrayList(Attribute) = .empty,
anon_name_arena: std.heap.ArenaAllocator.State = .{},
wchar: QualType = .invalid,
@ -2435,7 +2434,7 @@ pub const Builder = struct {
}
if (b.complex_tok) |tok| try b.parser.err(tok, .complex_int, .{});
const qt = try b.parser.comp.type_store.put(b.parser.gpa, .{ .bit_int = .{
const qt = try b.parser.comp.type_store.put(b.parser.comp.gpa, .{ .bit_int = .{
.signedness = if (unsigned) .unsigned else .signed,
.bits = @intCast(bits),
} });
@ -2476,6 +2475,7 @@ pub const Builder = struct {
pub fn finishQuals(b: Builder, qt: QualType) !QualType {
if (qt.isInvalid()) return .invalid;
const gpa = b.parser.comp.gpa;
var result_qt = qt;
if (b.atomic_type orelse b.atomic) |atomic_tok| {
if (result_qt.isAutoType()) return b.parser.todo("_Atomic __auto_type");
@ -2505,7 +2505,7 @@ pub const Builder = struct {
return .invalid;
},
else => {
result_qt = try b.parser.comp.type_store.put(b.parser.gpa, .{ .atomic = result_qt });
result_qt = try b.parser.comp.type_store.put(gpa, .{ .atomic = result_qt });
},
}
}
@ -2514,7 +2514,7 @@ pub const Builder = struct {
const is_pointer = qt.isAutoType() or qt.isC23Auto() or qt.base(b.parser.comp).type == .pointer;
if (b.unaligned != null and !is_pointer) {
result_qt = (try b.parser.comp.type_store.put(b.parser.gpa, .{ .attributed = .{
result_qt = (try b.parser.comp.type_store.put(gpa, .{ .attributed = .{
.base = result_qt,
.attributes = &.{.{ .tag = .unaligned, .args = .{ .unaligned = .{} }, .syntax = .keyword }},
} })).withQualifiers(result_qt);

View File

@ -20,7 +20,7 @@ pragma: Pragma = .{
.preserveTokens = preserveTokens,
},
original_state: Diagnostics.State = .{},
state_stack: std.ArrayListUnmanaged(Diagnostics.State) = .{},
state_stack: std.ArrayList(Diagnostics.State) = .empty,
const Directive = enum {
warning,
@ -138,7 +138,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
if (pp.defines.get(str) != null) {
try Pragma.err(pp, start_idx + i, .pragma_poison_macro, .{});
}
try pp.poisoned_identifiers.put(str, {});
try pp.poisoned_identifiers.put(pp.comp.gpa, str, {});
}
return;
},

View File

@ -44,7 +44,7 @@ fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pra
const diagnostic: Pragma.Diagnostic = .pragma_message;
var sf = std.heap.stackFallback(1024, pp.gpa);
var sf = std.heap.stackFallback(1024, pp.comp.gpa);
var allocating: std.Io.Writer.Allocating = .init(sf.get());
defer allocating.deinit();

View File

@ -17,14 +17,12 @@ pragma: Pragma = .{
.preprocessorHandler = preprocessorHandler,
.preserveTokens = preserveTokens,
},
pragma_once: std.AutoHashMap(Source.Id, void),
pragma_once: std.AutoHashMapUnmanaged(Source.Id, void) = .empty,
preprocess_count: u32 = 0,
pub fn init(allocator: mem.Allocator) !*Pragma {
var once = try allocator.create(Once);
once.* = .{
.pragma_once = std.AutoHashMap(Source.Id, void).init(allocator),
};
once.* = .{};
return &once.pragma;
}
@ -35,8 +33,9 @@ fn afterParse(pragma: *Pragma, _: *Compilation) void {
fn deinit(pragma: *Pragma, comp: *Compilation) void {
var self: *Once = @fieldParentPtr("pragma", pragma);
self.pragma_once.deinit();
self.pragma_once.deinit(comp.gpa);
comp.gpa.destroy(self);
pragma.* = undefined;
}
fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pragma.Error!void {
@ -53,7 +52,7 @@ fn preprocessorHandler(pragma: *Pragma, pp: *Preprocessor, start_idx: TokenIndex
}, pp.expansionSlice(start_idx + 1), true);
}
const seen = self.preprocess_count == pp.preprocess_count;
const prev = try self.pragma_once.fetchPut(name_tok.loc.id, {});
const prev = try self.pragma_once.fetchPut(pp.comp.gpa, name_tok.loc.id, {});
if (prev != null and !seen) {
return error.StopPreprocessing;
}

View File

@ -15,7 +15,7 @@ pragma: Pragma = .{
.deinit = deinit,
.parserHandler = parserHandler,
},
stack: std.ArrayListUnmanaged(struct { label: []const u8, val: u8 }) = .{},
stack: std.ArrayList(struct { label: []const u8, val: u8 }) = .empty,
pub fn init(allocator: mem.Allocator) !*Pragma {
var pack = try allocator.create(Pack);
@ -82,7 +82,7 @@ fn parserHandler(pragma: *Pragma, p: *Parser, start_idx: TokenIndex) Compilation
}
}
if (action == .push) {
try pack.stack.append(p.gpa, .{ .label = label orelse "", .val = p.pragma_pack orelse 8 });
try pack.stack.append(p.comp.gpa, .{ .label = label orelse "", .val = p.pragma_pack orelse 8 });
} else {
pack.pop(p, label);
if (new_val != null) {

View File

@ -70,10 +70,11 @@ pub fn todo(c: *AsmCodeGen, msg: []const u8, tok: Tree.TokenIndex) Error {
const loc: Source.Location = c.tree.tokens.items(.loc)[tok];
var sf = std.heap.stackFallback(1024, c.comp.gpa);
var buf = std.ArrayList(u8).init(sf.get());
defer buf.deinit();
const allocator = sf.get();
var buf: std.ArrayList(u8) = .empty;
defer buf.deinit(allocator);
try buf.print("TODO: {s}", .{msg});
try buf.print(allocator, "TODO: {s}", .{msg});
try c.comp.diagnostics.add(.{
.text = buf.items,
.kind = .@"error",
@ -163,7 +164,7 @@ pub fn genAsm(tree: *const Tree) Error!Assembly {
}
fn genDecls(c: *AsmCodeGen) !void {
if (c.tree.comp.code_gen_options.debug) {
if (c.tree.comp.code_gen_options.debug != .strip) {
const sources = c.tree.comp.sources.values();
for (sources) |source| {
try c.data.print(" .file {d} \"{s}\"\n", .{ @intFromEnum(source.id) - 1, source.path });

View File

@ -66,6 +66,20 @@ pub const OptimizationLevel = enum {
pub fn fromString(str: []const u8) ?OptimizationLevel {
return level_map.get(str);
}
pub fn isSizeOptimized(self: OptimizationLevel) bool {
return switch (self) {
.s, .z => true,
.@"0", .@"1", .@"2", .@"3", .fast, .g => false,
};
}
pub fn hasAnyOptimizations(self: OptimizationLevel) bool {
return switch (self) {
.@"0" => false,
.@"1", .@"2", .@"3", .s, .fast, .g, .z => true,
};
}
};
pub const default: @This() = .{

View File

@ -8,14 +8,14 @@ const Limb = std.math.big.Limb;
const Interner = @This();
map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
map: std.AutoArrayHashMapUnmanaged(void, void) = .empty,
items: std.MultiArrayList(struct {
tag: Tag,
data: u32,
}) = .{},
extra: std.ArrayListUnmanaged(u32) = .{},
limbs: std.ArrayListUnmanaged(Limb) = .{},
strings: std.ArrayListUnmanaged(u8) = .{},
}) = .empty,
extra: std.ArrayList(u32) = .empty,
limbs: std.ArrayList(Limb) = .empty,
strings: std.ArrayList(u8) = .empty,
const KeyAdapter = struct {
interner: *const Interner,

View File

@ -11,7 +11,7 @@ decls: std.StringArrayHashMapUnmanaged(Decl),
pub const Decl = struct {
instructions: std.MultiArrayList(Inst),
body: std.ArrayListUnmanaged(Ref),
body: std.ArrayList(Ref),
arena: std.heap.ArenaAllocator.State,
pub fn deinit(decl: *Decl, gpa: Allocator) void {
@ -26,9 +26,9 @@ pub const Builder = struct {
arena: std.heap.ArenaAllocator,
interner: *Interner,
decls: std.StringArrayHashMapUnmanaged(Decl) = .{},
instructions: std.MultiArrayList(Ir.Inst) = .{},
body: std.ArrayListUnmanaged(Ref) = .{},
decls: std.StringArrayHashMapUnmanaged(Decl) = .empty,
instructions: std.MultiArrayList(Ir.Inst) = .empty,
body: std.ArrayList(Ref) = .empty,
alloc_count: u32 = 0,
arg_count: u32 = 0,
current_label: Ref = undefined,
@ -380,7 +380,7 @@ const REF = std.Io.tty.Color.bright_blue;
const LITERAL = std.Io.tty.Color.bright_green;
const ATTRIBUTE = std.Io.tty.Color.bright_yellow;
const RefMap = std.AutoArrayHashMap(Ref, void);
const RefMap = std.AutoArrayHashMapUnmanaged(Ref, void);
pub fn dump(ir: *const Ir, gpa: Allocator, config: std.Io.tty.Config, w: *std.Io.Writer) !void {
for (ir.decls.keys(), ir.decls.values()) |name, *decl| {
@ -393,11 +393,11 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
const tags = decl.instructions.items(.tag);
const data = decl.instructions.items(.data);
var ref_map = RefMap.init(gpa);
defer ref_map.deinit();
var ref_map: RefMap = .empty;
defer ref_map.deinit(gpa);
var label_map = RefMap.init(gpa);
defer label_map.deinit();
var label_map: RefMap = .empty;
defer label_map.deinit(gpa);
const ret_inst = decl.body.items[decl.body.items.len - 1];
const ret_operand = data[@intFromEnum(ret_inst)].un;
@ -413,14 +413,14 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
const ref = decl.body.items[arg_count];
if (tags[@intFromEnum(ref)] != .arg) break;
if (arg_count != 0) try w.writeAll(", ");
try ref_map.put(ref, {});
try ref_map.put(gpa, ref, {});
try ir.writeRef(decl, &ref_map, ref, config, w);
try config.setColor(w, .reset);
}
try w.writeAll(") {\n");
for (decl.body.items[arg_count..]) |ref| {
switch (tags[@intFromEnum(ref)]) {
.label => try label_map.put(ref, {}),
.label => try label_map.put(gpa, ref, {}),
else => {},
}
}
@ -461,7 +461,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
},
.select => {
const br = data[i].branch;
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.writeAll("select ");
try ir.writeRef(decl, &ref_map, br.cond, config, w);
try config.setColor(w, .reset);
@ -501,7 +501,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
},
.call => {
const call = data[i].call;
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.writeAll("call ");
try ir.writeRef(decl, &ref_map, call.func, config, w);
try config.setColor(w, .reset);
@ -515,7 +515,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
},
.alloc => {
const alloc = data[i].alloc;
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.writeAll("alloc ");
try config.setColor(w, ATTRIBUTE);
try w.writeAll("size ");
@ -528,7 +528,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
try w.writeByte('\n');
},
.phi => {
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.writeAll("phi");
try config.setColor(w, .reset);
try w.writeAll(" {");
@ -560,7 +560,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
try w.writeByte('\n');
},
.load => {
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.writeAll("load ");
try ir.writeRef(decl, &ref_map, data[i].un, config, w);
try w.writeByte('\n');
@ -583,7 +583,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
.mod,
=> {
const bin = data[i].bin;
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.print("{s} ", .{@tagName(tag)});
try ir.writeRef(decl, &ref_map, bin.lhs, config, w);
try config.setColor(w, .reset);
@ -598,7 +598,7 @@ fn dumpDecl(ir: *const Ir, decl: *const Decl, gpa: Allocator, name: []const u8,
.sext,
=> {
const un = data[i].un;
try ir.writeNewRef(decl, &ref_map, ref, config, w);
try ir.writeNewRef(gpa, decl, &ref_map, ref, config, w);
try w.print("{s} ", .{@tagName(tag)});
try ir.writeRef(decl, &ref_map, un, config, w);
try w.writeByte('\n');
@ -679,8 +679,8 @@ fn writeRef(ir: Ir, decl: *const Decl, ref_map: *RefMap, ref: Ref, config: std.I
try w.print(" %{d}", .{ref_index});
}
fn writeNewRef(ir: Ir, decl: *const Decl, ref_map: *RefMap, ref: Ref, config: std.Io.tty.Config, w: *std.Io.Writer) !void {
try ref_map.put(ref, {});
fn writeNewRef(ir: Ir, gpa: Allocator, decl: *const Decl, ref_map: *RefMap, ref: Ref, config: std.Io.tty.Config, w: *std.Io.Writer) !void {
try ref_map.put(gpa, ref, {});
try w.writeAll(" ");
try ir.writeRef(decl, ref_map, ref, config, w);
try config.setColor(w, .reset);

View File

@ -30,7 +30,7 @@ pub const Section = union(enum) {
custom: []const u8,
};
pub fn getSection(obj: *Object, section: Section) !*std.array_list.Managed(u8) {
pub fn getSection(obj: *Object, section: Section) !*std.ArrayList(u8) {
switch (obj.format) {
.elf => return @as(*Elf, @alignCast(@fieldParentPtr("obj", obj))).getSection(section),
else => unreachable,

View File

@ -4,8 +4,8 @@ const Target = std.Target;
const Object = @import("../Object.zig");
const Section = struct {
data: std.array_list.Managed(u8),
relocations: std.ArrayListUnmanaged(Relocation) = .{},
data: std.ArrayList(u8) = .empty,
relocations: std.ArrayList(Relocation) = .empty,
flags: u64,
type: u32,
index: u16 = undefined,
@ -37,9 +37,9 @@ const Elf = @This();
obj: Object,
/// The keys are owned by the Codegen.tree
sections: std.StringHashMapUnmanaged(*Section) = .{},
local_symbols: std.StringHashMapUnmanaged(*Symbol) = .{},
global_symbols: std.StringHashMapUnmanaged(*Symbol) = .{},
sections: std.StringHashMapUnmanaged(*Section) = .empty,
local_symbols: std.StringHashMapUnmanaged(*Symbol) = .empty,
global_symbols: std.StringHashMapUnmanaged(*Symbol) = .empty,
unnamed_symbol_mangle: u32 = 0,
strtab_len: u64 = strtab_default.len,
arena: std.heap.ArenaAllocator,
@ -58,7 +58,7 @@ pub fn deinit(elf: *Elf) void {
{
var it = elf.sections.valueIterator();
while (it.next()) |sect| {
sect.*.data.deinit();
sect.*.data.deinit(gpa);
sect.*.relocations.deinit(gpa);
}
}
@ -80,12 +80,12 @@ fn sectionString(sec: Object.Section) []const u8 {
};
}
pub fn getSection(elf: *Elf, section_kind: Object.Section) !*std.array_list.Managed(u8) {
pub fn getSection(elf: *Elf, section_kind: Object.Section) !*std.ArrayList(u8) {
const section_name = sectionString(section_kind);
const section = elf.sections.get(section_name) orelse blk: {
const section = try elf.arena.allocator().create(Section);
section.* = .{
.data = std.array_list.Managed(u8).init(elf.arena.child_allocator),
.data = std.ArrayList(u8).init(elf.arena.child_allocator),
.type = std.elf.SHT_PROGBITS,
.flags = switch (section_kind) {
.func, .custom => std.elf.SHF_ALLOC + std.elf.SHF_EXECINSTR,

View File

@ -150,7 +150,7 @@ fn translate(d: *aro.Driver, tc: *aro.Toolchain, args: [][:0]u8) !void {
// be written to a tmp file then renamed into place, meaning the path will be
// wrong as soon as the work is done.
var opt_dep_file = try d.initDepFile(source, &name_buf, true);
defer if (opt_dep_file) |*dep_file| dep_file.deinit(pp.gpa);
defer if (opt_dep_file) |*dep_file| dep_file.deinit(gpa);
if (opt_dep_file) |*dep_file| pp.dep_file = dep_file;