mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge pull request #17328 from ziglang/simplify-cbe-deps
C backend: remove unneeded ordering mechanism
This commit is contained in:
commit
937e8cb705
@ -3495,7 +3495,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
|
||||
.module = module,
|
||||
.error_msg = null,
|
||||
.decl_index = decl_index.toOptional(),
|
||||
.decl = decl,
|
||||
.is_naked_fn = false,
|
||||
.fwd_decl = fwd_decl.toManaged(gpa),
|
||||
.ctypes = .{},
|
||||
};
|
||||
|
||||
@ -522,8 +522,8 @@ pub const Object = struct {
|
||||
pub const DeclGen = struct {
|
||||
gpa: mem.Allocator,
|
||||
module: *Module,
|
||||
decl: ?*Decl,
|
||||
decl_index: Decl.OptionalIndex,
|
||||
is_naked_fn: bool,
|
||||
/// This is a borrowed reference from `link.C`.
|
||||
fwd_decl: std.ArrayList(u8),
|
||||
error_msg: ?*Module.ErrorMsg,
|
||||
@ -532,8 +532,10 @@ pub const DeclGen = struct {
|
||||
fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
|
||||
@setCold(true);
|
||||
const mod = dg.module;
|
||||
const decl_index = dg.decl_index.unwrap().?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const src = LazySrcLoc.nodeOffset(0);
|
||||
const src_loc = src.toSrcLoc(dg.decl.?, mod);
|
||||
const src_loc = src.toSrcLoc(decl, mod);
|
||||
dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
|
||||
return error.AnalysisFail;
|
||||
}
|
||||
@ -2493,8 +2495,8 @@ fn genExports(o: *Object) !void {
|
||||
|
||||
const mod = o.dg.module;
|
||||
const ip = &mod.intern_pool;
|
||||
const decl = o.dg.decl.?;
|
||||
const decl_index = o.dg.decl_index.unwrap().?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
|
||||
const fwd = o.dg.fwd_decl.writer();
|
||||
|
||||
@ -2634,9 +2636,10 @@ pub fn genFunc(f: *Function) !void {
|
||||
const mod = o.dg.module;
|
||||
const gpa = o.dg.gpa;
|
||||
const decl_index = o.dg.decl_index.unwrap().?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const tv: TypedValue = .{
|
||||
.ty = o.dg.decl.?.ty,
|
||||
.val = o.dg.decl.?.val,
|
||||
.ty = decl.ty,
|
||||
.val = decl.val,
|
||||
};
|
||||
|
||||
o.code_header = std.ArrayList(u8).init(gpa);
|
||||
@ -2719,19 +2722,20 @@ pub fn genDecl(o: *Object) !void {
|
||||
defer tracy.end();
|
||||
|
||||
const mod = o.dg.module;
|
||||
const decl = o.dg.decl.?;
|
||||
const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? };
|
||||
const decl_index = o.dg.decl_index.unwrap().?;
|
||||
const decl_c_value = .{ .decl = decl_index };
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
|
||||
|
||||
if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
|
||||
if (tv.val.getExternFunc(mod)) |_| {
|
||||
const fwd_decl_writer = o.dg.fwd_decl.writer();
|
||||
try fwd_decl_writer.writeAll("zig_extern ");
|
||||
try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });
|
||||
try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });
|
||||
try fwd_decl_writer.writeAll(";\n");
|
||||
try genExports(o);
|
||||
} else if (tv.val.getVariable(mod)) |variable| {
|
||||
try o.dg.renderFwdDecl(decl_c_value.decl, variable);
|
||||
try o.dg.renderFwdDecl(decl_index, variable);
|
||||
try genExports(o);
|
||||
|
||||
if (variable.is_extern) return;
|
||||
@ -2750,7 +2754,7 @@ pub fn genDecl(o: *Object) !void {
|
||||
try w.writeByte(';');
|
||||
try o.indent_writer.insertNewline();
|
||||
} else {
|
||||
const is_global = o.dg.module.decl_exports.contains(decl_c_value.decl);
|
||||
const is_global = o.dg.module.decl_exports.contains(decl_index);
|
||||
const fwd_decl_writer = o.dg.fwd_decl.writer();
|
||||
|
||||
try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
|
||||
@ -2773,12 +2777,14 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const mod = dg.module;
|
||||
const decl_index = dg.decl_index.unwrap().?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const tv: TypedValue = .{
|
||||
.ty = dg.decl.?.ty,
|
||||
.val = dg.decl.?.val,
|
||||
.ty = decl.ty,
|
||||
.val = decl.val,
|
||||
};
|
||||
const writer = dg.fwd_decl.writer();
|
||||
const mod = dg.module;
|
||||
|
||||
switch (tv.ty.zigTypeTag(mod)) {
|
||||
.Fn => {
|
||||
@ -3504,8 +3510,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
|
||||
} else {
|
||||
try reap(f, inst, &.{un_op});
|
||||
// Not even allowed to return void in a naked function.
|
||||
if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention(mod) != .Naked else true)
|
||||
try writer.writeAll("return;\n");
|
||||
if (!f.object.dg.is_naked_fn) try writer.writeAll("return;\n");
|
||||
}
|
||||
return .none;
|
||||
}
|
||||
@ -4144,7 +4149,7 @@ fn airCall(
|
||||
) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
// Not even allowed to call panic in a naked function.
|
||||
if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
|
||||
if (f.object.dg.is_naked_fn) return .none;
|
||||
|
||||
const gpa = f.object.dg.gpa;
|
||||
const writer = f.object.writer();
|
||||
@ -4637,9 +4642,8 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
|
||||
}
|
||||
|
||||
fn airTrap(f: *Function, writer: anytype) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
// Not even allowed to call trap in a naked function.
|
||||
if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
|
||||
if (f.object.dg.is_naked_fn) return .none;
|
||||
|
||||
try writer.writeAll("zig_trap();\n");
|
||||
return .none;
|
||||
@ -4682,9 +4686,8 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
}
|
||||
|
||||
fn airUnreach(f: *Function) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
// Not even allowed to call unreachable in a naked function.
|
||||
if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
|
||||
if (f.object.dg.is_naked_fn) return .none;
|
||||
|
||||
try f.object.writer().writeAll("zig_unreachable();\n");
|
||||
return .none;
|
||||
@ -7194,8 +7197,11 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
}
|
||||
|
||||
fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const mod = f.object.dg.module;
|
||||
const inst_ty = f.typeOfIndex(inst);
|
||||
const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
|
||||
const decl_index = f.object.dg.decl_index.unwrap().?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const fn_cty = try f.typeToCType(decl.ty, .complete);
|
||||
const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
|
||||
|
||||
const writer = f.object.writer();
|
||||
|
||||
@ -139,6 +139,7 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:
|
||||
|
||||
const func = module.funcInfo(func_index);
|
||||
const decl_index = func.owner_decl;
|
||||
const decl = module.declPtr(decl_index);
|
||||
const gop = try self.decl_table.getOrPut(gpa, decl_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
@ -163,7 +164,7 @@ pub fn updateFunc(self: *C, module: *Module, func_index: InternPool.Index, air:
|
||||
.module = module,
|
||||
.error_msg = null,
|
||||
.decl_index = decl_index.toOptional(),
|
||||
.decl = module.declPtr(decl_index),
|
||||
.is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked,
|
||||
.fwd_decl = fwd_decl.toManaged(gpa),
|
||||
.ctypes = ctypes.*,
|
||||
},
|
||||
@ -216,15 +217,13 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
|
||||
fwd_decl.clearRetainingCapacity();
|
||||
code.clearRetainingCapacity();
|
||||
|
||||
const decl = module.declPtr(decl_index);
|
||||
|
||||
var object: codegen.Object = .{
|
||||
.dg = .{
|
||||
.gpa = gpa,
|
||||
.module = module,
|
||||
.error_msg = null,
|
||||
.decl_index = decl_index.toOptional(),
|
||||
.decl = decl,
|
||||
.is_naked_fn = false,
|
||||
.fwd_decl = fwd_decl.toManaged(gpa),
|
||||
.ctypes = ctypes.*,
|
||||
},
|
||||
@ -322,29 +321,19 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
|
||||
self.lazy_code_buf.clearRetainingCapacity();
|
||||
try self.flushErrDecls(&f.lazy_ctypes);
|
||||
|
||||
// Unlike other backends, the .c code we are emitting has order-dependent decls.
|
||||
// `CType`s, forward decls, and non-functions first.
|
||||
// Unlike other backends, the .c code we are emitting is order-dependent. Therefore
|
||||
// we must traverse the set of Decls that we are emitting according to their dependencies.
|
||||
// Our strategy is to populate a set of remaining decls, pop Decls one by one,
|
||||
// recursively chasing their dependencies.
|
||||
try f.remaining_decls.ensureUnusedCapacity(gpa, self.decl_table.count());
|
||||
|
||||
const decl_keys = self.decl_table.keys();
|
||||
const decl_values = self.decl_table.values();
|
||||
for (decl_keys) |decl_index| {
|
||||
assert(module.declPtr(decl_index).has_tv);
|
||||
f.remaining_decls.putAssumeCapacityNoClobber(decl_index, {});
|
||||
}
|
||||
|
||||
{
|
||||
var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
|
||||
defer export_names.deinit(gpa);
|
||||
try export_names.ensureTotalCapacity(gpa, @as(u32, @intCast(module.decl_exports.entries.len)));
|
||||
try export_names.ensureTotalCapacity(gpa, @intCast(module.decl_exports.entries.len));
|
||||
for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
|
||||
try export_names.put(gpa, @"export".opts.name, {});
|
||||
|
||||
while (f.remaining_decls.popOrNull()) |kv| {
|
||||
const decl_index = kv.key;
|
||||
const decl_keys = self.decl_table.keys();
|
||||
for (decl_keys) |decl_index| {
|
||||
assert(module.declPtr(decl_index).has_tv);
|
||||
try self.flushDecl(&f, decl_index, export_names);
|
||||
}
|
||||
}
|
||||
@ -355,9 +344,9 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
|
||||
assert(f.ctypes.count() == 0);
|
||||
try self.flushCTypes(&f, .none, f.lazy_ctypes);
|
||||
|
||||
var it = self.decl_table.iterator();
|
||||
while (it.next()) |entry|
|
||||
try self.flushCTypes(&f, entry.key_ptr.toOptional(), entry.value_ptr.ctypes);
|
||||
for (self.decl_table.keys(), self.decl_table.values()) |decl_index, db| {
|
||||
try self.flushCTypes(&f, decl_index.toOptional(), db.ctypes);
|
||||
}
|
||||
}
|
||||
|
||||
f.all_buffers.items[ctypes_index] = .{
|
||||
@ -374,6 +363,7 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
|
||||
f.file_size += lazy_fwd_decl_len;
|
||||
|
||||
// Now the code.
|
||||
const decl_values = self.decl_table.values();
|
||||
try f.all_buffers.ensureUnusedCapacity(gpa, 1 + decl_values.len);
|
||||
f.appendBufAssumeCapacity(self.lazy_code_buf.items);
|
||||
for (decl_values) |decl| f.appendBufAssumeCapacity(self.getString(decl.code));
|
||||
@ -384,8 +374,6 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
|
||||
}
|
||||
|
||||
const Flush = struct {
|
||||
remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
|
||||
|
||||
ctypes: codegen.CType.Store = .{},
|
||||
ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{},
|
||||
ctypes_buf: std.ArrayListUnmanaged(u8) = .{},
|
||||
@ -416,7 +404,6 @@ const Flush = struct {
|
||||
f.ctypes_buf.deinit(gpa);
|
||||
f.ctypes_map.deinit(gpa);
|
||||
f.ctypes.deinit(gpa);
|
||||
f.remaining_decls.deinit(gpa);
|
||||
}
|
||||
};
|
||||
|
||||
@ -522,7 +509,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
|
||||
.module = self.base.options.module.?,
|
||||
.error_msg = null,
|
||||
.decl_index = .none,
|
||||
.decl = null,
|
||||
.is_naked_fn = false,
|
||||
.fwd_decl = fwd_decl.toManaged(gpa),
|
||||
.ctypes = ctypes.*,
|
||||
},
|
||||
@ -556,7 +543,7 @@ fn flushLazyFn(self: *C, ctypes: *codegen.CType.Store, lazy_fn: codegen.LazyFnMa
|
||||
.module = self.base.options.module.?,
|
||||
.error_msg = null,
|
||||
.decl_index = .none,
|
||||
.decl = null,
|
||||
.is_naked_fn = false,
|
||||
.fwd_decl = fwd_decl.toManaged(gpa),
|
||||
.ctypes = ctypes.*,
|
||||
},
|
||||
@ -591,7 +578,6 @@ fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError
|
||||
}
|
||||
}
|
||||
|
||||
/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
|
||||
fn flushDecl(
|
||||
self: *C,
|
||||
f: *Flush,
|
||||
@ -601,14 +587,6 @@ fn flushDecl(
|
||||
const gpa = self.base.allocator;
|
||||
const mod = self.base.options.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
// Before flushing any particular Decl we must ensure its
|
||||
// dependencies are already flushed, so that the order in the .c
|
||||
// file comes out correctly.
|
||||
for (decl.dependencies.keys()) |dep| {
|
||||
if (f.remaining_decls.swapRemove(dep)) {
|
||||
try flushDecl(self, f, dep, export_names);
|
||||
}
|
||||
}
|
||||
|
||||
const decl_block = self.decl_table.getPtr(decl_index).?;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user