solve recursion in self hosted

master
Vexu 2019-11-26 10:34:38 +02:00
parent 36849d8a7b
commit 128034481a
No known key found for this signature in database
GPG Key ID: 5AEABFCAFF5CD8D6
8 changed files with 75 additions and 54 deletions

View File

@ -735,24 +735,26 @@ pub fn Watch(comptime V: type) type {
allocator: *Allocator,
const OsData = switch (builtin.os) {
.macosx, .freebsd, .netbsd, .dragonfly => struct {
file_table: FileTable,
table_lock: event.Lock,
const FileTable = std.StringHashMap(*Put);
const Put = struct {
putter_frame: @Frame(kqPutEvents),
cancelled: bool = false,
value: V,
};
},
// TODO https://github.com/ziglang/zig/issues/3778
.macosx, .freebsd, .netbsd, .dragonfly => KqOsData,
.linux => LinuxOsData,
.windows => WindowsOsData,
else => @compileError("Unsupported OS"),
};
const KqOsData = struct {
file_table: FileTable,
table_lock: event.Lock,
const FileTable = std.StringHashMap(*Put);
const Put = struct {
putter_frame: @Frame(kqPutEvents),
cancelled: bool = false,
value: V,
};
};
const WindowsOsData = struct {
table_lock: event.Lock,
dir_table: DirTable,

View File

@ -133,7 +133,7 @@ pub const Compilation = struct {
zig_std_dir: []const u8,
/// lazily created when we need it
tmp_dir: event.Future(BuildError![]u8),
tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),
version_major: u32 = 0,
version_minor: u32 = 0,
@ -158,7 +158,7 @@ pub const Compilation = struct {
/// functions that have their own objects that we need to link
/// it uses an optional pointer so that tombstone removals are possible
fn_link_set: event.Locked(FnLinkSet),
fn_link_set: event.Locked(FnLinkSet) = event.Locked(FnLinkSet).init(FnLinkSet.init()),
pub const FnLinkSet = std.TailQueue(?*Value.Fn);
@ -227,9 +227,9 @@ pub const Compilation = struct {
/// need to wait on this group before deinitializing
deinit_group: event.Group(void),
// destroy_frame: @Frame(createAsync),
// main_loop_frame: @Frame(Compilation.mainLoop),
main_loop_future: event.Future(void),
destroy_frame: *@Frame(createAsync),
main_loop_frame: *@Frame(Compilation.mainLoop),
main_loop_future: event.Future(void) = event.Future(void).init(),
have_err_ret_tracing: bool = false,
@ -245,6 +245,8 @@ pub const Compilation = struct {
fs_watch: *fs.Watch(*Scope.Root),
cancelled: bool = false,
const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);
const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);
const PtrTypeTable = std.HashMap(*const Type.Pointer.Key, *Type.Pointer, Type.Pointer.Key.hash, Type.Pointer.Key.eql);
@ -348,7 +350,9 @@ pub const Compilation = struct {
zig_lib_dir: []const u8,
) !*Compilation {
var optional_comp: ?*Compilation = null;
var frame = async createAsync(
var frame = try zig_compiler.allocator.create(@Frame(createAsync));
errdefer zig_compiler.allocator.destroy(frame);
frame.* = async createAsync(
&optional_comp,
zig_compiler,
name,
@ -385,15 +389,12 @@ pub const Compilation = struct {
.build_mode = build_mode,
.zig_lib_dir = zig_lib_dir,
.zig_std_dir = undefined,
.tmp_dir = event.Future(BuildError![]u8).init(),
// .destroy_frame = @frame(),
// .main_loop_frame = undefined,
.main_loop_future = event.Future(void).init(),
.destroy_frame = @frame(),
.main_loop_frame = undefined,
.name = undefined,
.llvm_triple = undefined,
.is_static = is_static,
.fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()),
.link_libs_list = undefined,
.exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),
@ -505,7 +506,10 @@ pub const Compilation = struct {
try comp.initTypes();
defer comp.primitive_type_table.deinit();
// comp.main_loop_frame = async comp.mainLoop();
comp.main_loop_frame = try allocator.create(@Frame(mainLoop));
defer allocator.destroy(comp.main_loop_frame);
comp.main_loop_frame.* = async comp.mainLoop();
// Set this to indicate that initialization completed successfully.
// from here on out we must not return an error.
// This must occur before the first suspend/await.
@ -718,8 +722,11 @@ pub const Compilation = struct {
}
pub fn destroy(self: *Compilation) void {
// await self.main_loop_frame;
// resume self.destroy_frame;
const allocator = self.gpa();
self.cancelled = true;
await self.main_loop_frame;
resume self.destroy_frame;
allocator.destroy(self.destroy_frame);
}
fn start(self: *Compilation) void {
@ -732,7 +739,7 @@ pub const Compilation = struct {
var build_result = self.initialCompile();
while (true) {
while (!self.cancelled) {
const link_result = if (build_result) blk: {
break :blk self.maybeLink();
} else |err| err;
@ -1130,11 +1137,10 @@ pub const Compilation = struct {
return link_lib;
}
/// cancels itself so no need to await or cancel the promise.
async fn startFindingNativeLibC(self: *Compilation) void {
std.event.Loop.instance.?.yield();
event.Loop.startCpuBoundOperation();
// we don't care if it fails, we're just trying to kick off the future resolution
_ = (self.zig_compiler.getNativeLibC()) catch return;
_ = self.zig_compiler.getNativeLibC() catch return;
}
/// General Purpose Allocator. Must free when done.
@ -1215,7 +1221,10 @@ pub const Compilation = struct {
node: *ast.Node,
expected_type: *Type,
) !*Value {
const analyzed_code = try comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type);
var frame = try comp.gpa().create(@Frame(genAndAnalyzeCode));
defer comp.gpa().destroy(frame);
frame.* = async comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type);
const analyzed_code = try await frame;
defer analyzed_code.destroy(comp.gpa());
return analyzed_code.getCompTimeResult(comp);
@ -1315,12 +1324,15 @@ fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
try fn_type.non_key.Normal.variable_list.append(var_scope);
}
const analyzed_code = try comp.genAndAnalyzeCode(
var frame = try comp.gpa().create(@Frame(Compilation.genAndAnalyzeCode));
defer comp.gpa().destroy(frame);
frame.* = async comp.genAndAnalyzeCode(
tree_scope,
fn_val.child_scope,
body_node,
fn_type.key.data.Normal.return_type,
);
const analyzed_code = try await frame;
errdefer analyzed_code.destroy(comp.gpa());
assert(fn_val.block_scope != null);

View File

@ -658,7 +658,7 @@ pub const Inst = struct {
const amt = try align_inst.getAsConstAlign(ira);
break :blk Type.Pointer.Align{ .Override = amt };
} else blk: {
break :blk Type.Pointer.Align{ .Abi = {} };
break :blk .Abi;
};
const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
.child_type = child_type,
@ -1078,6 +1078,14 @@ pub const Builder = struct {
self.current_basic_block = basic_block;
}
pub fn genNodeRecursive(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
const alloc = irb.comp.gpa();
var frame = try alloc.create(@Frame(genNode));
defer alloc.destroy(frame);
frame.* = async irb.genNode(node, scope, lval);
return await frame;
}
pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
switch (node.id) {
.Root => unreachable,
@ -1157,7 +1165,7 @@ pub const Builder = struct {
},
.GroupedExpression => {
const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);
return irb.genNode(grouped_expr.expr, scope, lval);
return irb.genNodeRecursive(grouped_expr.expr, scope, lval);
},
.BuiltinCall => return error.Unimplemented,
.ErrorSetDecl => return error.Unimplemented,
@ -1187,14 +1195,13 @@ pub const Builder = struct {
}
fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None);
const fn_ref = try irb.genNodeRecursive(suffix_op.lhs.node, scope, .None);
const args = try irb.arena().alloc(*Inst, call.params.len);
var it = call.params.iterator(0);
var i: usize = 0;
while (it.next()) |arg_node_ptr| : (i += 1) {
args[i] = try irb.genNode(arg_node_ptr.*, scope, .None);
args[i] = try irb.genNodeRecursive(arg_node_ptr.*, scope, .None);
}
//bool is_async = node->data.fn_call_expr.is_async;
@ -1239,7 +1246,7 @@ pub const Builder = struct {
//} else {
// align_value = nullptr;
//}
const child_type = try irb.genNode(prefix_op.rhs, scope, .None);
const child_type = try irb.genNodeRecursive(prefix_op.rhs, scope, .None);
//uint32_t bit_offset_start = 0;
//if (node->data.pointer_type.bit_offset_start != nullptr) {
@ -1438,7 +1445,7 @@ pub const Builder = struct {
child_scope = &defer_child_scope.base;
continue;
}
const statement_value = try irb.genNode(statement_node, child_scope, .None);
const statement_value = try irb.genNodeRecursive(statement_node, child_scope, .None);
is_continuation_unreachable = statement_value.isNoReturn();
if (is_continuation_unreachable) {
@ -1534,7 +1541,7 @@ pub const Builder = struct {
const outer_scope = irb.begin_scope.?;
const return_value = if (control_flow_expr.rhs) |rhs| blk: {
break :blk try irb.genNode(rhs, scope, .None);
break :blk try irb.genNodeRecursive(rhs, scope, .None);
} else blk: {
break :blk try irb.buildConstVoid(scope, src_span, true);
};
@ -1713,7 +1720,7 @@ pub const Builder = struct {
};
if (generate) {
const defer_expr_scope = defer_scope.defer_expr_scope;
const instruction = try irb.genNode(
const instruction = try irb.genNodeRecursive(
defer_expr_scope.expr_node,
&defer_expr_scope.base,
.None,

View File

@ -400,7 +400,7 @@ fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool
const argv = [_][]const u8{ cc_exe, arg1 };
// TODO This simulates evented I/O for the child process exec
std.event.Loop.instance.?.yield();
event.Loop.startCpuBoundOperation();
const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
const exec_result = if (std.debug.runtime_safety) blk: {
break :blk errorable_result catch unreachable;

View File

@ -623,16 +623,15 @@ fn constructLinkerArgsWasm(ctx: *Context) void {
}
fn addFnObjects(ctx: *Context) !void {
// at this point it's guaranteed nobody else has this lock, so we circumvent it
// and avoid having to be an async function
const fn_link_set = &ctx.comp.fn_link_set.private_data;
const held = ctx.comp.fn_link_set.acquire();
defer held.release();
var it = fn_link_set.first;
var it = held.value.first;
while (it) |node| {
const fn_val = node.data orelse {
// handle the tombstone. See Value.Fn.destroy.
it = node.next;
fn_link_set.remove(node);
held.value.remove(node);
ctx.comp.gpa().destroy(node);
continue;
};

View File

@ -127,7 +127,7 @@ pub fn main() !void {
try stderr.print("unknown command: {}\n\n", args[1]);
try stderr.write(usage);
process.argsFree(allocator, args);
defer process.exit(1);
process.exit(1);
}
const usage_build_generic =
@ -467,7 +467,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
var count: usize = 0;
while (true) { // TODO(Vexu)
while (!comp.cancelled) {
const build_event = comp.events.get();
count += 1;
@ -545,7 +545,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil
"Try running `zig libc` to see an example for the native target.\n",
libc_paths_file,
@errorName(err),
) catch process.exit(1);
) catch {};
process.exit(1);
};
}
@ -568,7 +568,7 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
defer zig_compiler.deinit();
const libc = zig_compiler.getNativeLibC() catch |err| {
stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);
stderr.print("unable to find libc: {}\n", @errorName(err)) catch {};
process.exit(1);
};
libc.render(stdout) catch process.exit(1);
@ -706,7 +706,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
while (try it.next()) |entry| {
if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
try group.call(fmtPath, fmt, full_path, check_mode);
@panic("TODO https://github.com/ziglang/zig/issues/3777");
// try group.call(fmtPath, fmt, full_path, check_mode);
}
}
return group.wait();

View File

@ -167,7 +167,7 @@ pub fn getDarwinArchString(self: Target) [:0]const u8 {
.powerpc64 => return "ppc64",
.powerpc64le => return "ppc64le",
// @tagName should be able to return sentinel terminated slice
else => @panic("TODO"), //return @tagName(arch),
else => @panic("TODO https://github.com/ziglang/zig/issues/3779"), //return @tagName(arch),
}
}

View File

@ -350,7 +350,7 @@ pub const Value = struct {
.mut = mut,
.vol = Type.Pointer.Vol.Non,
.size = size,
.alignment = Type.Pointer.Align.Abi,
.alignment = .Abi,
});
var ptr_type_consumed = false;
errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);