mirror of
https://github.com/ziglang/zig.git
synced 2026-01-22 15:25:23 +00:00
Merge pull request #3780 from Vexu/stage2-async-review
Update use of async functions in self hosted compiler
This commit is contained in:
commit
83c664eaa0
@ -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,
|
||||
@ -1291,7 +1293,7 @@ pub fn Watch(comptime V: type) type {
|
||||
os.linux.EINVAL => unreachable,
|
||||
os.linux.EFAULT => unreachable,
|
||||
os.linux.EAGAIN => {
|
||||
global_event_loop.linuxWaitFd(self.os_data.inotify_fd, os.linux.EPOLLET | os.linux.EPOLLIN);
|
||||
global_event_loop.linuxWaitFd(self.os_data.inotify_fd, os.linux.EPOLLET | os.linux.EPOLLIN | os.EPOLLONESHOT);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
@ -25,10 +25,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
||||
|
||||
const context = llvm_handle.node.data;
|
||||
|
||||
const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
|
||||
const module = llvm.ModuleCreateWithNameInContext(comp.name.toSliceConst(), context) orelse return error.OutOfMemory;
|
||||
defer llvm.DisposeModule(module);
|
||||
|
||||
llvm.SetTarget(module, comp.llvm_triple.ptr());
|
||||
llvm.SetTarget(module, comp.llvm_triple.toSliceConst());
|
||||
llvm.SetDataLayout(module, comp.target_layout_str);
|
||||
|
||||
if (util.getObjectFormat(comp.target) == .coff) {
|
||||
@ -48,23 +48,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
||||
const producer = try std.Buffer.allocPrint(
|
||||
&code.arena.allocator,
|
||||
"zig {}.{}.{}",
|
||||
u32(c.ZIG_VERSION_MAJOR),
|
||||
u32(c.ZIG_VERSION_MINOR),
|
||||
u32(c.ZIG_VERSION_PATCH),
|
||||
@as(u32, c.ZIG_VERSION_MAJOR),
|
||||
@as(u32, c.ZIG_VERSION_MINOR),
|
||||
@as(u32, c.ZIG_VERSION_PATCH),
|
||||
);
|
||||
const flags = "";
|
||||
const runtime_version = 0;
|
||||
const compile_unit_file = llvm.CreateFile(
|
||||
dibuilder,
|
||||
comp.name.ptr(),
|
||||
comp.root_package.root_src_dir.ptr(),
|
||||
comp.name.toSliceConst(),
|
||||
comp.root_package.root_src_dir.toSliceConst(),
|
||||
) orelse return error.OutOfMemory;
|
||||
const is_optimized = comp.build_mode != .Debug;
|
||||
const compile_unit = llvm.CreateCompileUnit(
|
||||
dibuilder,
|
||||
DW.LANG_C99,
|
||||
compile_unit_file,
|
||||
producer.ptr(),
|
||||
producer.toSliceConst(),
|
||||
is_optimized,
|
||||
flags,
|
||||
runtime_version,
|
||||
@ -99,7 +99,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
||||
|
||||
// verify the llvm module when safety is on
|
||||
if (std.debug.runtime_safety) {
|
||||
var error_ptr: ?[*]u8 = null;
|
||||
var error_ptr: ?[*:0]u8 = null;
|
||||
_ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
|
||||
}
|
||||
|
||||
@ -108,12 +108,12 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
||||
const is_small = comp.build_mode == .ReleaseSmall;
|
||||
const is_debug = comp.build_mode == .Debug;
|
||||
|
||||
var err_msg: [*]u8 = undefined;
|
||||
var err_msg: [*:0]u8 = undefined;
|
||||
// TODO integrate this with evented I/O
|
||||
if (llvm.TargetMachineEmitToFile(
|
||||
comp.target_machine,
|
||||
module,
|
||||
output_path.ptr(),
|
||||
output_path.toSliceConst(),
|
||||
llvm.EmitBinary,
|
||||
&err_msg,
|
||||
is_debug,
|
||||
@ -154,7 +154,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
|
||||
const llvm_fn_type = try fn_val.base.typ.getLlvmType(ofile.arena, ofile.context);
|
||||
const llvm_fn = llvm.AddFunction(
|
||||
ofile.module,
|
||||
fn_val.symbol_name.ptr(),
|
||||
fn_val.symbol_name.toSliceConst(),
|
||||
llvm_fn_type,
|
||||
) orelse return error.OutOfMemory;
|
||||
|
||||
@ -379,7 +379,7 @@ fn renderLoadUntyped(
|
||||
ptr: *llvm.Value,
|
||||
alignment: Type.Pointer.Align,
|
||||
vol: Type.Pointer.Vol,
|
||||
name: [*]const u8,
|
||||
name: [*:0]const u8,
|
||||
) !*llvm.Value {
|
||||
const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
|
||||
switch (vol) {
|
||||
@ -390,7 +390,7 @@ fn renderLoadUntyped(
|
||||
return result;
|
||||
}
|
||||
|
||||
fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
|
||||
fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*:0]const u8) !*llvm.Value {
|
||||
return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
|
||||
}
|
||||
|
||||
@ -438,7 +438,7 @@ pub fn renderAlloca(
|
||||
) !*llvm.Value {
|
||||
const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
|
||||
const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
|
||||
const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
|
||||
const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, @ptrCast([*:0]const u8, name_with_null.ptr)) orelse return error.OutOfMemory;
|
||||
llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm_var_type));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ pub const ZigCompiler = struct {
|
||||
return LlvmHandle{ .node = node };
|
||||
}
|
||||
|
||||
pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
|
||||
pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
|
||||
if (self.native_libc.start()) |ptr| return ptr;
|
||||
try self.native_libc.data.findNative(self.allocator);
|
||||
self.native_libc.resolve();
|
||||
@ -133,62 +133,62 @@ 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,
|
||||
version_minor: u32,
|
||||
version_patch: u32,
|
||||
version_major: u32 = 0,
|
||||
version_minor: u32 = 0,
|
||||
version_patch: u32 = 0,
|
||||
|
||||
linker_script: ?[]const u8,
|
||||
out_h_path: ?[]const u8,
|
||||
linker_script: ?[]const u8 = null,
|
||||
out_h_path: ?[]const u8 = null,
|
||||
|
||||
is_test: bool,
|
||||
each_lib_rpath: bool,
|
||||
strip: bool,
|
||||
is_test: bool = false,
|
||||
each_lib_rpath: bool = false,
|
||||
strip: bool = false,
|
||||
is_static: bool,
|
||||
linker_rdynamic: bool,
|
||||
linker_rdynamic: bool = false,
|
||||
|
||||
clang_argv: []const []const u8,
|
||||
lib_dirs: []const []const u8,
|
||||
rpath_list: []const []const u8,
|
||||
assembly_files: []const []const u8,
|
||||
clang_argv: []const []const u8 = [_][]const u8{},
|
||||
lib_dirs: []const []const u8 = [_][]const u8{},
|
||||
rpath_list: []const []const u8 = [_][]const u8{},
|
||||
assembly_files: []const []const u8 = [_][]const u8{},
|
||||
|
||||
/// paths that are explicitly provided by the user to link against
|
||||
link_objects: []const []const u8,
|
||||
link_objects: []const []const u8 = [_][]const u8{},
|
||||
|
||||
/// 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);
|
||||
|
||||
windows_subsystem_windows: bool,
|
||||
windows_subsystem_console: bool,
|
||||
windows_subsystem_windows: bool = false,
|
||||
windows_subsystem_console: bool = false,
|
||||
|
||||
link_libs_list: ArrayList(*LinkLib),
|
||||
libc_link_lib: ?*LinkLib,
|
||||
libc_link_lib: ?*LinkLib = null,
|
||||
|
||||
err_color: errmsg.Color,
|
||||
err_color: errmsg.Color = .Auto,
|
||||
|
||||
verbose_tokenize: bool,
|
||||
verbose_ast_tree: bool,
|
||||
verbose_ast_fmt: bool,
|
||||
verbose_cimport: bool,
|
||||
verbose_ir: bool,
|
||||
verbose_llvm_ir: bool,
|
||||
verbose_link: bool,
|
||||
verbose_tokenize: bool = false,
|
||||
verbose_ast_tree: bool = false,
|
||||
verbose_ast_fmt: bool = false,
|
||||
verbose_cimport: bool = false,
|
||||
verbose_ir: bool = false,
|
||||
verbose_llvm_ir: bool = false,
|
||||
verbose_link: bool = false,
|
||||
|
||||
darwin_frameworks: []const []const u8,
|
||||
darwin_version_min: DarwinVersionMin,
|
||||
darwin_frameworks: []const []const u8 = [_][]const u8{},
|
||||
darwin_version_min: DarwinVersionMin = .None,
|
||||
|
||||
test_filters: []const []const u8,
|
||||
test_name_prefix: ?[]const u8,
|
||||
test_filters: []const []const u8 = [_][]const u8{},
|
||||
test_name_prefix: ?[]const u8 = null,
|
||||
|
||||
emit_file_type: Emit,
|
||||
emit_file_type: Emit = .Binary,
|
||||
|
||||
kind: Kind,
|
||||
|
||||
link_out_file: ?[]const u8,
|
||||
link_out_file: ?[]const u8 = null,
|
||||
events: *event.Channel(Event),
|
||||
|
||||
exported_symbol_names: event.Locked(Decl.Table),
|
||||
@ -213,7 +213,7 @@ pub const Compilation = struct {
|
||||
|
||||
target_machine: *llvm.TargetMachine,
|
||||
target_data_ref: *llvm.TargetData,
|
||||
target_layout_str: [*]u8,
|
||||
target_layout_str: [*:0]u8,
|
||||
target_ptr_bits: u32,
|
||||
|
||||
/// for allocating things which have the same lifetime as this Compilation
|
||||
@ -222,16 +222,16 @@ pub const Compilation = struct {
|
||||
root_package: *Package,
|
||||
std_package: *Package,
|
||||
|
||||
override_libc: ?*LibCInstallation,
|
||||
override_libc: ?*LibCInstallation = null,
|
||||
|
||||
/// 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,
|
||||
have_err_ret_tracing: bool = false,
|
||||
|
||||
/// not locked because it is read-only
|
||||
primitive_type_table: TypeTable,
|
||||
@ -243,7 +243,9 @@ pub const Compilation = struct {
|
||||
|
||||
c_int_types: [CInt.list.len]*Type.Int,
|
||||
|
||||
// fs_watch: *fs.Watch(*Scope.Root),
|
||||
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);
|
||||
@ -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,
|
||||
@ -359,7 +363,11 @@ pub const Compilation = struct {
|
||||
is_static,
|
||||
zig_lib_dir,
|
||||
);
|
||||
return optional_comp orelse if (await frame) |_| unreachable else |err| err;
|
||||
// TODO causes segfault
|
||||
// return optional_comp orelse if (await frame) |_| unreachable else |err| err;
|
||||
if (optional_comp) |comp| {
|
||||
return comp;
|
||||
} else if (await frame) |_| unreachable else |err| return err;
|
||||
}
|
||||
|
||||
async fn createAsync(
|
||||
@ -385,50 +393,14 @@ 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,
|
||||
|
||||
.version_major = 0,
|
||||
.version_minor = 0,
|
||||
.version_patch = 0,
|
||||
|
||||
.verbose_tokenize = false,
|
||||
.verbose_ast_tree = false,
|
||||
.verbose_ast_fmt = false,
|
||||
.verbose_cimport = false,
|
||||
.verbose_ir = false,
|
||||
.verbose_llvm_ir = false,
|
||||
.verbose_link = false,
|
||||
|
||||
.linker_script = null,
|
||||
.out_h_path = null,
|
||||
.is_test = false,
|
||||
.each_lib_rpath = false,
|
||||
.strip = false,
|
||||
.is_static = is_static,
|
||||
.linker_rdynamic = false,
|
||||
.clang_argv = [_][]const u8{},
|
||||
.lib_dirs = [_][]const u8{},
|
||||
.rpath_list = [_][]const u8{},
|
||||
.assembly_files = [_][]const u8{},
|
||||
.link_objects = [_][]const u8{},
|
||||
.fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()),
|
||||
.windows_subsystem_windows = false,
|
||||
.windows_subsystem_console = false,
|
||||
.link_libs_list = undefined,
|
||||
.libc_link_lib = null,
|
||||
.err_color = errmsg.Color.Auto,
|
||||
.darwin_frameworks = [_][]const u8{},
|
||||
.darwin_version_min = DarwinVersionMin.None,
|
||||
.test_filters = [_][]const u8{},
|
||||
.test_name_prefix = null,
|
||||
.emit_file_type = Emit.Binary,
|
||||
.link_out_file = null,
|
||||
|
||||
.exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),
|
||||
.prelink_group = event.Group(BuildError!void).init(allocator),
|
||||
.deinit_group = event.Group(void).init(allocator),
|
||||
@ -458,11 +430,9 @@ pub const Compilation = struct {
|
||||
.root_package = undefined,
|
||||
.std_package = undefined,
|
||||
|
||||
.override_libc = null,
|
||||
.have_err_ret_tracing = false,
|
||||
.primitive_type_table = undefined,
|
||||
|
||||
// .fs_watch = undefined,
|
||||
.fs_watch = undefined,
|
||||
};
|
||||
comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());
|
||||
comp.primitive_type_table = TypeTable.init(comp.arena());
|
||||
@ -534,13 +504,16 @@ pub const Compilation = struct {
|
||||
comp.root_package = try Package.create(comp.arena(), ".", "");
|
||||
}
|
||||
|
||||
// comp.fs_watch = try fs.Watch(*Scope.Root).create(16);
|
||||
// defer comp.fs_watch.destroy();
|
||||
comp.fs_watch = try fs.Watch(*Scope.Root).init(allocator, 16);
|
||||
defer comp.fs_watch.deinit();
|
||||
|
||||
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.
|
||||
@ -559,7 +532,7 @@ pub const Compilation = struct {
|
||||
}
|
||||
|
||||
/// it does ref the result because it could be an arbitrary integer size
|
||||
pub async fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {
|
||||
pub fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {
|
||||
if (name.len >= 2) {
|
||||
switch (name[0]) {
|
||||
'i', 'u' => blk: {
|
||||
@ -753,8 +726,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 {
|
||||
@ -767,7 +743,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;
|
||||
@ -795,47 +771,47 @@ pub const Compilation = struct {
|
||||
self.events.put(Event{ .Error = err });
|
||||
}
|
||||
|
||||
// // First, get an item from the watch channel, waiting on the channel.
|
||||
// var group = event.Group(BuildError!void).init(self.gpa());
|
||||
// {
|
||||
// const ev = (self.fs_watch.channel.get()) catch |err| {
|
||||
// build_result = err;
|
||||
// continue;
|
||||
// };
|
||||
// const root_scope = ev.data;
|
||||
// group.call(rebuildFile, self, root_scope) catch |err| {
|
||||
// build_result = err;
|
||||
// continue;
|
||||
// };
|
||||
// }
|
||||
// // Next, get all the items from the channel that are buffered up.
|
||||
// while (self.fs_watch.channel.getOrNull()) |ev_or_err| {
|
||||
// if (ev_or_err) |ev| {
|
||||
// const root_scope = ev.data;
|
||||
// group.call(rebuildFile, self, root_scope) catch |err| {
|
||||
// build_result = err;
|
||||
// continue;
|
||||
// };
|
||||
// } else |err| {
|
||||
// build_result = err;
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
// build_result = group.wait();
|
||||
// First, get an item from the watch channel, waiting on the channel.
|
||||
var group = event.Group(BuildError!void).init(self.gpa());
|
||||
{
|
||||
const ev = (self.fs_watch.channel.get()) catch |err| {
|
||||
build_result = err;
|
||||
continue;
|
||||
};
|
||||
const root_scope = ev.data;
|
||||
group.call(rebuildFile, self, root_scope) catch |err| {
|
||||
build_result = err;
|
||||
continue;
|
||||
};
|
||||
}
|
||||
// Next, get all the items from the channel that are buffered up.
|
||||
while (self.fs_watch.channel.getOrNull()) |ev_or_err| {
|
||||
if (ev_or_err) |ev| {
|
||||
const root_scope = ev.data;
|
||||
group.call(rebuildFile, self, root_scope) catch |err| {
|
||||
build_result = err;
|
||||
continue;
|
||||
};
|
||||
} else |err| {
|
||||
build_result = err;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
build_result = group.wait();
|
||||
}
|
||||
}
|
||||
|
||||
async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {
|
||||
async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) BuildError!void {
|
||||
const tree_scope = blk: {
|
||||
const source_code = "";
|
||||
// const source_code = fs.readFile(
|
||||
// root_scope.realpath,
|
||||
// max_src_size,
|
||||
// ) catch |err| {
|
||||
// try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
|
||||
// return;
|
||||
// };
|
||||
// errdefer self.gpa().free(source_code);
|
||||
const source_code = fs.readFile(
|
||||
self.gpa(),
|
||||
root_scope.realpath,
|
||||
max_src_size,
|
||||
) catch |err| {
|
||||
try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
|
||||
return;
|
||||
};
|
||||
errdefer self.gpa().free(source_code);
|
||||
|
||||
const tree = try std.zig.parse(self.gpa(), source_code);
|
||||
errdefer {
|
||||
@ -873,7 +849,7 @@ pub const Compilation = struct {
|
||||
try decl_group.wait();
|
||||
}
|
||||
|
||||
async fn rebuildChangedDecls(
|
||||
fn rebuildChangedDecls(
|
||||
self: *Compilation,
|
||||
group: *event.Group(BuildError!void),
|
||||
locked_table: *Decl.Table,
|
||||
@ -962,7 +938,7 @@ pub const Compilation = struct {
|
||||
}
|
||||
}
|
||||
|
||||
async fn initialCompile(self: *Compilation) !void {
|
||||
fn initialCompile(self: *Compilation) !void {
|
||||
if (self.root_src_path) |root_src_path| {
|
||||
const root_scope = blk: {
|
||||
// TODO async/await std.fs.realpath
|
||||
@ -981,7 +957,7 @@ pub const Compilation = struct {
|
||||
}
|
||||
}
|
||||
|
||||
async fn maybeLink(self: *Compilation) !void {
|
||||
fn maybeLink(self: *Compilation) !void {
|
||||
(self.prelink_group.wait()) catch |err| switch (err) {
|
||||
error.SemanticAnalysisFailed => {},
|
||||
else => return err,
|
||||
@ -1165,11 +1141,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.
|
||||
@ -1184,7 +1159,7 @@ pub const Compilation = struct {
|
||||
|
||||
/// If the temporary directory for this compilation has not been created, it creates it.
|
||||
/// Then it creates a random file name in that dir and returns it.
|
||||
pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
|
||||
pub fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
|
||||
const tmp_dir = try self.getTmpDir();
|
||||
const file_prefix = self.getRandomFileName();
|
||||
|
||||
@ -1200,14 +1175,14 @@ pub const Compilation = struct {
|
||||
/// If the temporary directory for this Compilation has not been created, creates it.
|
||||
/// Then returns it. The directory is unique to this Compilation and cleaned up when
|
||||
/// the Compilation deinitializes.
|
||||
async fn getTmpDir(self: *Compilation) ![]const u8 {
|
||||
fn getTmpDir(self: *Compilation) ![]const u8 {
|
||||
if (self.tmp_dir.start()) |ptr| return ptr.*;
|
||||
self.tmp_dir.data = self.getTmpDirImpl();
|
||||
self.tmp_dir.resolve();
|
||||
return self.tmp_dir.data;
|
||||
}
|
||||
|
||||
async fn getTmpDirImpl(self: *Compilation) ![]u8 {
|
||||
fn getTmpDirImpl(self: *Compilation) ![]u8 {
|
||||
const comp_dir_name = self.getRandomFileName();
|
||||
const zig_dir_path = try getZigDir(self.gpa());
|
||||
defer self.gpa().free(zig_dir_path);
|
||||
@ -1217,7 +1192,7 @@ pub const Compilation = struct {
|
||||
return tmp_dir;
|
||||
}
|
||||
|
||||
async fn getRandomFileName(self: *Compilation) [12]u8 {
|
||||
fn getRandomFileName(self: *Compilation) [12]u8 {
|
||||
// here we replace the standard +/ with -_ so that it can be used in a file name
|
||||
const b64_fs_encoder = std.base64.Base64Encoder.init(
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
||||
@ -1243,20 +1218,23 @@ pub const Compilation = struct {
|
||||
}
|
||||
|
||||
/// Returns a value which has been ref()'d once
|
||||
async fn analyzeConstValue(
|
||||
fn analyzeConstValue(
|
||||
comp: *Compilation,
|
||||
tree_scope: *Scope.AstTree,
|
||||
scope: *Scope,
|
||||
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);
|
||||
}
|
||||
|
||||
async fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {
|
||||
fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {
|
||||
const meta_type = &Type.MetaType.get(comp).base;
|
||||
defer meta_type.base.deref(comp);
|
||||
|
||||
@ -1287,7 +1265,7 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
|
||||
}
|
||||
|
||||
/// The function that actually does the generation.
|
||||
async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
|
||||
fn generateDecl(comp: *Compilation, decl: *Decl) !void {
|
||||
switch (decl.id) {
|
||||
.Var => @panic("TODO"),
|
||||
.Fn => {
|
||||
@ -1298,7 +1276,7 @@ async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
|
||||
}
|
||||
}
|
||||
|
||||
async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
const tree_scope = fn_decl.base.tree_scope;
|
||||
|
||||
const body_node = fn_decl.fn_proto.body_node orelse return generateDeclFnProto(comp, fn_decl);
|
||||
@ -1315,7 +1293,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
|
||||
// The Decl.Fn owns the initial 1 reference count
|
||||
const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
|
||||
fn_decl.value = Decl.Fn.Val{ .Fn = fn_val };
|
||||
fn_decl.value = .{ .Fn = fn_val };
|
||||
symbol_name_consumed = true;
|
||||
|
||||
// Define local parameter variables
|
||||
@ -1350,12 +1328,15 @@ async 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);
|
||||
@ -1382,7 +1363,7 @@ fn getZigDir(allocator: *mem.Allocator) ![]u8 {
|
||||
return std.fs.getAppDataDir(allocator, "zig");
|
||||
}
|
||||
|
||||
async fn analyzeFnType(
|
||||
fn analyzeFnType(
|
||||
comp: *Compilation,
|
||||
tree_scope: *Scope.AstTree,
|
||||
scope: *Scope,
|
||||
@ -1444,7 +1425,7 @@ async fn analyzeFnType(
|
||||
return fn_type;
|
||||
}
|
||||
|
||||
async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
const fn_type = try analyzeFnType(
|
||||
comp,
|
||||
fn_decl.base.tree_scope,
|
||||
@ -1459,6 +1440,6 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
|
||||
|
||||
// The Decl.Fn owns the initial 1 reference count
|
||||
const fn_proto_val = try Value.FnProto.create(comp, fn_type, symbol_name);
|
||||
fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };
|
||||
fn_decl.value = .{ .FnProto = fn_proto_val };
|
||||
symbol_name_consumed = true;
|
||||
}
|
||||
|
||||
@ -69,15 +69,12 @@ pub const Decl = struct {
|
||||
|
||||
pub const Fn = struct {
|
||||
base: Decl,
|
||||
value: Val,
|
||||
fn_proto: *ast.Node.FnProto,
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
|
||||
pub const Val = union(enum) {
|
||||
value: union(enum) {
|
||||
Unresolved,
|
||||
Fn: *Value.Fn,
|
||||
FnProto: *Value.FnProto,
|
||||
};
|
||||
},
|
||||
fn_proto: *ast.Node.FnProto,
|
||||
|
||||
pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 {
|
||||
return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
|
||||
|
||||
@ -110,7 +110,7 @@ pub const Inst = struct {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
|
||||
pub fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
|
||||
switch (base.id) {
|
||||
.Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
|
||||
.Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
|
||||
@ -422,7 +422,7 @@ pub const Inst = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub async fn analyze(self: *const Ref, ira: *Analyze) !*Inst {
|
||||
pub fn analyze(self: *const Ref, ira: *Analyze) !*Inst {
|
||||
const target = try self.params.target.getAsParam();
|
||||
|
||||
if (ira.getCompTimeValOrNullUndefOk(target)) |val| {
|
||||
@ -472,7 +472,7 @@ pub const Inst = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
|
||||
pub fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
|
||||
(ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => return error.SemanticAnalysisFailed,
|
||||
@ -516,7 +516,7 @@ pub const Inst = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
|
||||
pub fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
|
||||
switch (self.params.var_scope.data) {
|
||||
.Const => @panic("TODO"),
|
||||
.Param => |param| {
|
||||
@ -563,7 +563,7 @@ pub const Inst = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
|
||||
pub fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
|
||||
const target = try self.params.target.getAsParam();
|
||||
const target_type = target.getKnownType();
|
||||
if (target_type.id != .Pointer) {
|
||||
@ -645,7 +645,7 @@ pub const Inst = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub async fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {
|
||||
pub fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {
|
||||
const child_type = try self.params.child_type.getAsConstType(ira);
|
||||
// if (child_type->id == TypeTableEntryIdUnreachable) {
|
||||
// ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
|
||||
@ -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,
|
||||
@ -927,7 +927,7 @@ pub const Variable = struct {
|
||||
|
||||
pub const BasicBlock = struct {
|
||||
ref_count: usize,
|
||||
name_hint: [*]const u8, // must be a C string literal
|
||||
name_hint: [*:0]const u8,
|
||||
debug_id: usize,
|
||||
scope: *Scope,
|
||||
instruction_list: std.ArrayList(*Inst),
|
||||
@ -1051,7 +1051,7 @@ pub const Builder = struct {
|
||||
}
|
||||
|
||||
/// No need to clean up resources thanks to the arena allocator.
|
||||
pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
|
||||
pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*:0]const u8) !*BasicBlock {
|
||||
const basic_block = try self.arena().create(BasicBlock);
|
||||
basic_block.* = BasicBlock{
|
||||
.ref_count = 0,
|
||||
@ -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,
|
||||
@ -1186,14 +1194,14 @@ pub const Builder = struct {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
|
||||
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;
|
||||
@ -1214,7 +1222,7 @@ pub const Builder = struct {
|
||||
//return ir_lval_wrap(irb, scope, fn_call, lval);
|
||||
}
|
||||
|
||||
async fn genPtrType(
|
||||
fn genPtrType(
|
||||
irb: *Builder,
|
||||
prefix_op: *ast.Node.PrefixOp,
|
||||
ptr_info: ast.Node.PrefixOp.PtrInfo,
|
||||
@ -1238,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) {
|
||||
@ -1307,9 +1315,9 @@ pub const Builder = struct {
|
||||
var rest: []const u8 = undefined;
|
||||
if (int_token.len >= 3 and int_token[0] == '0') {
|
||||
base = switch (int_token[1]) {
|
||||
'b' => u8(2),
|
||||
'o' => u8(8),
|
||||
'x' => u8(16),
|
||||
'b' => 2,
|
||||
'o' => 8,
|
||||
'x' => 16,
|
||||
else => unreachable,
|
||||
};
|
||||
rest = int_token[2..];
|
||||
@ -1339,7 +1347,7 @@ pub const Builder = struct {
|
||||
return inst;
|
||||
}
|
||||
|
||||
pub async fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {
|
||||
pub fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {
|
||||
const str_token = irb.code.tree_scope.tree.tokenSlice(str_lit.token);
|
||||
const src_span = Span.token(str_lit.token);
|
||||
|
||||
@ -1389,7 +1397,7 @@ pub const Builder = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
|
||||
pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
|
||||
const block_scope = try Scope.Block.create(irb.comp, parent_scope);
|
||||
|
||||
const outer_block_scope = &block_scope.base;
|
||||
@ -1437,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) {
|
||||
@ -1499,7 +1507,7 @@ pub const Builder = struct {
|
||||
return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
|
||||
}
|
||||
|
||||
pub async fn genControlFlowExpr(
|
||||
pub fn genControlFlowExpr(
|
||||
irb: *Builder,
|
||||
control_flow_expr: *ast.Node.ControlFlowExpression,
|
||||
scope: *Scope,
|
||||
@ -1533,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);
|
||||
};
|
||||
@ -1596,7 +1604,7 @@ pub const Builder = struct {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {
|
||||
pub fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {
|
||||
const src_span = Span.token(identifier.token);
|
||||
const name = irb.code.tree_scope.tree.tokenSlice(identifier.token);
|
||||
|
||||
@ -1694,7 +1702,7 @@ pub const Builder = struct {
|
||||
return result;
|
||||
}
|
||||
|
||||
async fn genDefersForBlock(
|
||||
fn genDefersForBlock(
|
||||
irb: *Builder,
|
||||
inner_scope: *Scope,
|
||||
outer_scope: *Scope,
|
||||
@ -1712,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,
|
||||
@ -1797,7 +1805,7 @@ pub const Builder = struct {
|
||||
// Look at the params and ref() other instructions
|
||||
comptime var i = 0;
|
||||
inline while (i < @memberCount(I.Params)) : (i += 1) {
|
||||
const FieldType = comptime @typeOf(@field(I.Params(undefined), @memberName(I.Params, i)));
|
||||
const FieldType = comptime @typeOf(@field(@as(I.Params, undefined), @memberName(I.Params, i)));
|
||||
switch (FieldType) {
|
||||
*Inst => @field(inst.params, @memberName(I.Params, i)).ref(self),
|
||||
*BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self),
|
||||
@ -1909,7 +1917,7 @@ pub const Builder = struct {
|
||||
VarScope: *Scope.Var,
|
||||
};
|
||||
|
||||
async fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {
|
||||
fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {
|
||||
var s = scope;
|
||||
while (true) {
|
||||
switch (s.id) {
|
||||
@ -2519,7 +2527,7 @@ const Analyze = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub async fn gen(
|
||||
pub fn gen(
|
||||
comp: *Compilation,
|
||||
body_node: *ast.Node,
|
||||
tree_scope: *Scope.AstTree,
|
||||
@ -2541,7 +2549,7 @@ pub async fn gen(
|
||||
return irb.finish();
|
||||
}
|
||||
|
||||
pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {
|
||||
pub fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {
|
||||
const old_entry_bb = old_code.basic_block_list.at(0);
|
||||
|
||||
var ira = try Analyze.init(comp, old_code.tree_scope, expected_type);
|
||||
|
||||
@ -143,7 +143,7 @@ pub const LibCInstallation = struct {
|
||||
}
|
||||
|
||||
/// Finds the default, native libc.
|
||||
pub async fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
|
||||
pub fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
|
||||
self.initEmpty();
|
||||
var group = event.Group(FindError!void).init(allocator);
|
||||
errdefer group.wait() catch {};
|
||||
@ -393,14 +393,14 @@ pub const LibCInstallation = struct {
|
||||
};
|
||||
|
||||
/// caller owns returned memory
|
||||
async fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
|
||||
fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
|
||||
const cc_exe = std.os.getenv("CC") orelse "cc";
|
||||
const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file);
|
||||
defer allocator.free(arg1);
|
||||
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;
|
||||
|
||||
@ -11,7 +11,7 @@ const util = @import("util.zig");
|
||||
const Context = struct {
|
||||
comp: *Compilation,
|
||||
arena: std.heap.ArenaAllocator,
|
||||
args: std.ArrayList([*]const u8),
|
||||
args: std.ArrayList([*:0]const u8),
|
||||
link_in_crt: bool,
|
||||
|
||||
link_err: error{OutOfMemory}!void,
|
||||
@ -21,7 +21,7 @@ const Context = struct {
|
||||
out_file_path: std.Buffer,
|
||||
};
|
||||
|
||||
pub async fn link(comp: *Compilation) !void {
|
||||
pub fn link(comp: *Compilation) !void {
|
||||
var ctx = Context{
|
||||
.comp = comp,
|
||||
.arena = std.heap.ArenaAllocator.init(comp.gpa()),
|
||||
@ -33,7 +33,7 @@ pub async fn link(comp: *Compilation) !void {
|
||||
.out_file_path = undefined,
|
||||
};
|
||||
defer ctx.arena.deinit();
|
||||
ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);
|
||||
ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
|
||||
ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
|
||||
|
||||
if (comp.link_out_file) |out_file| {
|
||||
@ -58,7 +58,8 @@ pub async fn link(comp: *Compilation) !void {
|
||||
try ctx.args.append("lld");
|
||||
|
||||
if (comp.haveLibC()) {
|
||||
ctx.libc = ctx.comp.override_libc orelse blk: {
|
||||
// TODO https://github.com/ziglang/zig/issues/3190
|
||||
var libc = ctx.comp.override_libc orelse blk: {
|
||||
switch (comp.target) {
|
||||
Target.Native => {
|
||||
break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
|
||||
@ -66,6 +67,7 @@ pub async fn link(comp: *Compilation) !void {
|
||||
else => return error.LibCRequiredButNotProvidedOrFound,
|
||||
}
|
||||
};
|
||||
ctx.libc = libc;
|
||||
}
|
||||
|
||||
try constructLinkerArgs(&ctx);
|
||||
@ -171,7 +173,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
//}
|
||||
|
||||
try ctx.args.append("-o");
|
||||
try ctx.args.append(ctx.out_file_path.ptr());
|
||||
try ctx.args.append(ctx.out_file_path.toSliceConst());
|
||||
|
||||
if (ctx.link_in_crt) {
|
||||
const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
|
||||
@ -214,10 +216,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
|
||||
if (ctx.comp.haveLibC()) {
|
||||
try ctx.args.append("-L");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
|
||||
// TODO addNullByte should probably return [:0]u8
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr));
|
||||
|
||||
try ctx.args.append("-L");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr));
|
||||
|
||||
if (!ctx.comp.is_static) {
|
||||
const dl = blk: {
|
||||
@ -226,7 +229,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
return error.LibCMissingDynamicLinker;
|
||||
};
|
||||
try ctx.args.append("-dynamic-linker");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -238,7 +241,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
// .o files
|
||||
for (ctx.comp.link_objects) |link_object| {
|
||||
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
||||
try ctx.args.append(link_obj_with_null.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
||||
}
|
||||
try addFnObjects(ctx);
|
||||
|
||||
@ -313,7 +316,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
|
||||
const full_path = try std.fs.path.join(&ctx.arena.allocator, [_][]const u8{ dirname, basename });
|
||||
const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
|
||||
try ctx.args.append(full_path_with_null.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, full_path_with_null.ptr));
|
||||
}
|
||||
|
||||
fn constructLinkerArgsCoff(ctx: *Context) !void {
|
||||
@ -339,12 +342,12 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
||||
const is_library = ctx.comp.kind == .Lib;
|
||||
|
||||
const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());
|
||||
try ctx.args.append(out_arg.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
|
||||
|
||||
if (ctx.comp.haveLibC()) {
|
||||
try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr);
|
||||
try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr);
|
||||
try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr));
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr));
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr));
|
||||
}
|
||||
|
||||
if (ctx.link_in_crt) {
|
||||
@ -353,17 +356,17 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
||||
|
||||
if (ctx.comp.is_static) {
|
||||
const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);
|
||||
try ctx.args.append(cmt_lib_name.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
|
||||
} else {
|
||||
const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", d_str);
|
||||
try ctx.args.append(msvcrt_lib_name.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
|
||||
}
|
||||
|
||||
const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", lib_str, d_str);
|
||||
try ctx.args.append(vcruntime_lib_name.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
|
||||
|
||||
const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", lib_str, d_str);
|
||||
try ctx.args.append(crt_lib_name.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
|
||||
|
||||
// Visual C++ 2015 Conformance Changes
|
||||
// https://msdn.microsoft.com/en-us/library/bb531344.aspx
|
||||
@ -395,7 +398,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
||||
|
||||
for (ctx.comp.link_objects) |link_object| {
|
||||
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
||||
try ctx.args.append(link_obj_with_null.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
||||
}
|
||||
try addFnObjects(ctx);
|
||||
|
||||
@ -504,11 +507,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||
//}
|
||||
|
||||
try ctx.args.append("-arch");
|
||||
const darwin_arch_str = try std.cstr.addNullByte(
|
||||
&ctx.arena.allocator,
|
||||
ctx.comp.target.getDarwinArchString(),
|
||||
);
|
||||
try ctx.args.append(darwin_arch_str.ptr);
|
||||
try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
|
||||
|
||||
const platform = try DarwinPlatform.get(ctx.comp);
|
||||
switch (platform.kind) {
|
||||
@ -517,7 +516,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||
.IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
|
||||
}
|
||||
const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
|
||||
try ctx.args.append(ver_str.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, ver_str.ptr));
|
||||
|
||||
if (ctx.comp.kind == .Exe) {
|
||||
if (ctx.comp.is_static) {
|
||||
@ -528,7 +527,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||
}
|
||||
|
||||
try ctx.args.append("-o");
|
||||
try ctx.args.append(ctx.out_file_path.ptr());
|
||||
try ctx.args.append(ctx.out_file_path.toSliceConst());
|
||||
|
||||
//for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
||||
// Buf *rpath = g->rpath_list.at(i);
|
||||
@ -572,7 +571,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||
|
||||
for (ctx.comp.link_objects) |link_object| {
|
||||
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
||||
try ctx.args.append(link_obj_with_null.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
||||
}
|
||||
try addFnObjects(ctx);
|
||||
|
||||
@ -593,10 +592,10 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||
} else {
|
||||
if (mem.indexOfScalar(u8, lib.name, '/') == null) {
|
||||
const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
|
||||
try ctx.args.append(arg.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
|
||||
} else {
|
||||
const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
|
||||
try ctx.args.append(arg.ptr);
|
||||
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -626,20 +625,19 @@ 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;
|
||||
};
|
||||
try ctx.args.append(fn_val.containing_object.ptr());
|
||||
try ctx.args.append(fn_val.containing_object.toSliceConst());
|
||||
it = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,7 +86,7 @@ pub const AddGlobal = LLVMAddGlobal;
|
||||
extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value;
|
||||
|
||||
pub const ConstStringInContext = LLVMConstStringInContext;
|
||||
extern fn LLVMConstStringInContext(C: *Context, Str: [*:0]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
|
||||
extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
|
||||
|
||||
pub const ConstInt = LLVMConstInt;
|
||||
extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
|
||||
|
||||
@ -49,14 +49,15 @@ const usage =
|
||||
|
||||
const Command = struct {
|
||||
name: []const u8,
|
||||
exec: fn (*Allocator, []const []const u8) anyerror!void,
|
||||
exec: async fn (*Allocator, []const []const u8) anyerror!void,
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
// This allocator needs to be thread-safe because we use it for the event.Loop
|
||||
// which multiplexes async functions onto kernel threads.
|
||||
// libc allocator is guaranteed to have this property.
|
||||
const allocator = std.heap.c_allocator;
|
||||
// TODO https://github.com/ziglang/zig/issues/3783
|
||||
const allocator = std.heap.page_allocator;
|
||||
|
||||
stdout = &std.io.getStdOut().outStream().stream;
|
||||
|
||||
@ -118,14 +119,18 @@ pub fn main() !void {
|
||||
},
|
||||
};
|
||||
|
||||
for (commands) |command| {
|
||||
inline for (commands) |command| {
|
||||
if (mem.eql(u8, command.name, args[1])) {
|
||||
return command.exec(allocator, args[2..]);
|
||||
var frame = try allocator.create(@Frame(command.exec));
|
||||
defer allocator.destroy(frame);
|
||||
frame.* = async command.exec(allocator, args[2..]);
|
||||
return await frame;
|
||||
}
|
||||
}
|
||||
|
||||
try stderr.print("unknown command: {}\n\n", args[1]);
|
||||
try stderr.write(usage);
|
||||
process.argsFree(allocator, args);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@ -461,13 +466,12 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
||||
comp.link_objects = link_objects;
|
||||
|
||||
comp.start();
|
||||
const frame = async processBuildEvents(comp, color);
|
||||
processBuildEvents(comp, color);
|
||||
}
|
||||
|
||||
async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
|
||||
fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
|
||||
var count: usize = 0;
|
||||
while (true) {
|
||||
// TODO directly awaiting async should guarantee memory allocation elision
|
||||
while (!comp.cancelled) {
|
||||
const build_event = comp.events.get();
|
||||
count += 1;
|
||||
|
||||
@ -545,7 +549,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);
|
||||
};
|
||||
}
|
||||
@ -567,12 +571,8 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
|
||||
var zig_compiler = try ZigCompiler.init(allocator);
|
||||
defer zig_compiler.deinit();
|
||||
|
||||
const frame = async findLibCAsync(&zig_compiler);
|
||||
}
|
||||
|
||||
async fn findLibCAsync(zig_compiler: *ZigCompiler) void {
|
||||
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);
|
||||
@ -644,11 +644,23 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return asyncFmtMain(
|
||||
allocator,
|
||||
&flags,
|
||||
color,
|
||||
);
|
||||
var fmt = Fmt{
|
||||
.allocator = allocator,
|
||||
.seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
|
||||
.any_error = false,
|
||||
.color = color,
|
||||
};
|
||||
|
||||
const check_mode = flags.present("check");
|
||||
|
||||
var group = event.Group(FmtError!void).init(allocator);
|
||||
for (flags.positionals.toSliceConst()) |file_path| {
|
||||
try group.call(fmtPath, &fmt, file_path, check_mode);
|
||||
}
|
||||
try group.wait();
|
||||
if (fmt.any_error) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const FmtError = error{
|
||||
@ -673,30 +685,6 @@ const FmtError = error{
|
||||
CurrentWorkingDirectoryUnlinked,
|
||||
} || fs.File.OpenError;
|
||||
|
||||
async fn asyncFmtMain(
|
||||
allocator: *Allocator,
|
||||
flags: *const Args,
|
||||
color: errmsg.Color,
|
||||
) FmtError!void {
|
||||
var fmt = Fmt{
|
||||
.allocator = allocator,
|
||||
.seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
|
||||
.any_error = false,
|
||||
.color = color,
|
||||
};
|
||||
|
||||
const check_mode = flags.present("check");
|
||||
|
||||
var group = event.Group(FmtError!void).init(allocator);
|
||||
for (flags.positionals.toSliceConst()) |file_path| {
|
||||
try group.call(fmtPath, &fmt, file_path, check_mode);
|
||||
}
|
||||
try group.wait();
|
||||
if (fmt.any_error) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
|
||||
const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
|
||||
defer fmt.allocator.free(file_path);
|
||||
@ -708,33 +696,34 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
|
||||
if (try held.value.put(file_path, {})) |_| return;
|
||||
}
|
||||
|
||||
const source_code = "";
|
||||
// const source_code = event.fs.readFile(
|
||||
// file_path,
|
||||
// max_src_size,
|
||||
// ) catch |err| switch (err) {
|
||||
// error.IsDir, error.AccessDenied => {
|
||||
// // TODO make event based (and dir.next())
|
||||
// var dir = try fs.Dir.cwd().openDirList(file_path);
|
||||
// defer dir.close();
|
||||
const source_code = event.fs.readFile(
|
||||
fmt.allocator,
|
||||
file_path,
|
||||
max_src_size,
|
||||
) catch |err| switch (err) {
|
||||
error.IsDir, error.AccessDenied => {
|
||||
var dir = try fs.Dir.cwd().openDirList(file_path);
|
||||
defer dir.close();
|
||||
|
||||
// var group = event.Group(FmtError!void).init(fmt.allocator);
|
||||
// while (try dir.next()) |entry| {
|
||||
// if (entry.kind == fs.Dir.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);
|
||||
// }
|
||||
// }
|
||||
// return group.wait();
|
||||
// },
|
||||
// else => {
|
||||
// // TODO lock stderr printing
|
||||
// try stderr.print("unable to open '{}': {}\n", file_path, err);
|
||||
// fmt.any_error = true;
|
||||
// return;
|
||||
// },
|
||||
// };
|
||||
// defer fmt.allocator.free(source_code);
|
||||
var group = event.Group(FmtError!void).init(fmt.allocator);
|
||||
var it = dir.iterate();
|
||||
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 });
|
||||
@panic("TODO https://github.com/ziglang/zig/issues/3777");
|
||||
// try group.call(fmtPath, fmt, full_path, check_mode);
|
||||
}
|
||||
}
|
||||
return group.wait();
|
||||
},
|
||||
else => {
|
||||
// TODO lock stderr printing
|
||||
try stderr.print("unable to open '{}': {}\n", file_path, err);
|
||||
fmt.any_error = true;
|
||||
return;
|
||||
},
|
||||
};
|
||||
defer fmt.allocator.free(source_code);
|
||||
|
||||
const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
|
||||
try stderr.print("error parsing file '{}': {}\n", file_path, err);
|
||||
@ -867,10 +856,12 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
|
||||
.exec = cmdInternalBuildInfo,
|
||||
}};
|
||||
|
||||
for (sub_commands) |sub_command| {
|
||||
inline for (sub_commands) |sub_command| {
|
||||
if (mem.eql(u8, sub_command.name, args[0])) {
|
||||
try sub_command.exec(allocator, args[1..]);
|
||||
return;
|
||||
var frame = try allocator.create(@Frame(sub_command.exec));
|
||||
defer allocator.destroy(frame);
|
||||
frame.* = async sub_command.exec(allocator, args[1..]);
|
||||
return await frame;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,8 @@ test "stage2" {
|
||||
}
|
||||
|
||||
const file1 = "1.zig";
|
||||
const allocator = std.heap.c_allocator;
|
||||
// TODO https://github.com/ziglang/zig/issues/3783
|
||||
const allocator = std.heap.page_allocator;
|
||||
|
||||
pub const TestContext = struct {
|
||||
zig_compiler: ZigCompiler,
|
||||
@ -94,8 +95,8 @@ pub const TestContext = struct {
|
||||
&self.zig_compiler,
|
||||
"test",
|
||||
file1_path,
|
||||
Target.Native,
|
||||
Compilation.Kind.Obj,
|
||||
.Native,
|
||||
.Obj,
|
||||
.Debug,
|
||||
true, // is_static
|
||||
self.zig_lib_dir,
|
||||
@ -116,7 +117,7 @@ pub const TestContext = struct {
|
||||
const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
|
||||
const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
|
||||
|
||||
const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{.Native = {}}).exeFileExt());
|
||||
const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{ .Native = {} }).exeFileExt());
|
||||
if (std.fs.path.dirname(file1_path)) |dirname| {
|
||||
try std.fs.makePath(allocator, dirname);
|
||||
}
|
||||
@ -128,8 +129,8 @@ pub const TestContext = struct {
|
||||
&self.zig_compiler,
|
||||
"test",
|
||||
file1_path,
|
||||
Target.Native,
|
||||
Compilation.Kind.Exe,
|
||||
.Native,
|
||||
.Exe,
|
||||
.Debug,
|
||||
false,
|
||||
self.zig_lib_dir,
|
||||
@ -148,15 +149,12 @@ pub const TestContext = struct {
|
||||
exe_file: []const u8,
|
||||
expected_output: []const u8,
|
||||
) anyerror!void {
|
||||
// TODO this should not be necessary
|
||||
const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);
|
||||
|
||||
defer comp.destroy();
|
||||
const build_event = comp.events.get();
|
||||
|
||||
switch (build_event) {
|
||||
.Ok => {
|
||||
const argv = [_][]const u8{exe_file_2};
|
||||
const argv = [_][]const u8{exe_file};
|
||||
// TODO use event loop
|
||||
const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
|
||||
switch (child.term) {
|
||||
@ -173,13 +171,13 @@ pub const TestContext = struct {
|
||||
return error.OutputMismatch;
|
||||
}
|
||||
},
|
||||
Compilation.Event.Error => |err| return err,
|
||||
Compilation.Event.Fail => |msgs| {
|
||||
.Error => @panic("Cannot return error: https://github.com/ziglang/zig/issues/3190"), // |err| return err,
|
||||
.Fail => |msgs| {
|
||||
const stderr = std.io.getStdErr();
|
||||
try stderr.write("build incorrectly failed:\n");
|
||||
for (msgs) |msg| {
|
||||
defer msg.destroy();
|
||||
try msg.printToFile(stderr, errmsg.Color.Auto);
|
||||
try msg.printToFile(stderr, .Auto);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ pub const Type = struct {
|
||||
base: *Type,
|
||||
allocator: *Allocator,
|
||||
llvm_context: *llvm.Context,
|
||||
) (error{OutOfMemory}!*llvm.Type) {
|
||||
) error{OutOfMemory}!*llvm.Type {
|
||||
switch (base.id) {
|
||||
.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
|
||||
.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
|
||||
@ -184,7 +184,7 @@ pub const Type = struct {
|
||||
|
||||
/// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.
|
||||
/// Otherwise, this one will grab one from the pool and then release it.
|
||||
pub async fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {
|
||||
pub fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {
|
||||
if (base.abi_alignment.start()) |ptr| return ptr.*;
|
||||
|
||||
{
|
||||
@ -200,7 +200,7 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
/// If you have an llvm conext handy, you can use it here.
|
||||
pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
|
||||
pub fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
|
||||
if (base.abi_alignment.start()) |ptr| return ptr.*;
|
||||
|
||||
base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);
|
||||
@ -209,7 +209,7 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
/// Lower level function that does the work. See getAbiAlignment.
|
||||
async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
|
||||
fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
|
||||
const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
|
||||
return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
|
||||
}
|
||||
@ -367,7 +367,7 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
/// takes ownership of key.Normal.params on success
|
||||
pub async fn get(comp: *Compilation, key: Key) !*Fn {
|
||||
pub fn get(comp: *Compilation, key: Key) !*Fn {
|
||||
{
|
||||
const held = comp.fn_type_table.acquire();
|
||||
defer held.release();
|
||||
@ -564,7 +564,7 @@ pub const Type = struct {
|
||||
return comp.u8_type;
|
||||
}
|
||||
|
||||
pub async fn get(comp: *Compilation, key: Key) !*Int {
|
||||
pub fn get(comp: *Compilation, key: Key) !*Int {
|
||||
{
|
||||
const held = comp.int_type_table.acquire();
|
||||
defer held.release();
|
||||
@ -606,7 +606,7 @@ pub const Type = struct {
|
||||
comp.registerGarbage(Int, &self.garbage_node);
|
||||
}
|
||||
|
||||
pub async fn gcDestroy(self: *Int, comp: *Compilation) void {
|
||||
pub fn gcDestroy(self: *Int, comp: *Compilation) void {
|
||||
{
|
||||
const held = comp.int_type_table.acquire();
|
||||
defer held.release();
|
||||
@ -700,7 +700,7 @@ pub const Type = struct {
|
||||
comp.registerGarbage(Pointer, &self.garbage_node);
|
||||
}
|
||||
|
||||
pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {
|
||||
pub fn gcDestroy(self: *Pointer, comp: *Compilation) void {
|
||||
{
|
||||
const held = comp.ptr_type_table.acquire();
|
||||
defer held.release();
|
||||
@ -711,14 +711,14 @@ pub const Type = struct {
|
||||
comp.gpa().destroy(self);
|
||||
}
|
||||
|
||||
pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
|
||||
pub fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
|
||||
switch (self.key.alignment) {
|
||||
.Abi => return self.key.child_type.getAbiAlignment(comp),
|
||||
.Override => |alignment| return alignment,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
pub fn get(
|
||||
comp: *Compilation,
|
||||
key: Key,
|
||||
) !*Pointer {
|
||||
@ -726,8 +726,10 @@ pub const Type = struct {
|
||||
switch (key.alignment) {
|
||||
.Abi => {},
|
||||
.Override => |alignment| {
|
||||
// TODO https://github.com/ziglang/zig/issues/3190
|
||||
var align_spill = alignment;
|
||||
const abi_align = try key.child_type.getAbiAlignment(comp);
|
||||
if (abi_align == alignment) {
|
||||
if (abi_align == align_spill) {
|
||||
normal_key.alignment = .Abi;
|
||||
}
|
||||
},
|
||||
@ -828,7 +830,7 @@ pub const Type = struct {
|
||||
comp.gpa().destroy(self);
|
||||
}
|
||||
|
||||
pub async fn get(comp: *Compilation, key: Key) !*Array {
|
||||
pub fn get(comp: *Compilation, key: Key) !*Array {
|
||||
key.elem_type.base.ref();
|
||||
errdefer key.elem_type.base.deref(comp);
|
||||
|
||||
|
||||
@ -32,21 +32,21 @@ pub fn getFloatAbi(self: Target) FloatAbi {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getObjectFormat(self: Target) Target.ObjectFormat {
|
||||
return switch (self) {
|
||||
.Native => @import("builtin").object_format,
|
||||
.Cross => {
|
||||
pub fn getObjectFormat(target: Target) Target.ObjectFormat {
|
||||
switch (target) {
|
||||
.Native => return @import("builtin").object_format,
|
||||
.Cross => blk: {
|
||||
if (target.isWindows() or target.isUefi()) {
|
||||
break .coff;
|
||||
return .coff;
|
||||
} else if (target.isDarwin()) {
|
||||
break .macho;
|
||||
return .macho;
|
||||
}
|
||||
if (target.isWasm()) {
|
||||
break .wasm;
|
||||
return .wasm;
|
||||
}
|
||||
break .elf;
|
||||
return .elf;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
|
||||
@ -156,7 +156,7 @@ pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getDarwinArchString(self: Target) []const u8 {
|
||||
pub fn getDarwinArchString(self: Target) [:0]const u8 {
|
||||
const arch = self.getArch();
|
||||
switch (arch) {
|
||||
.aarch64 => return "arm64",
|
||||
@ -166,7 +166,8 @@ pub fn getDarwinArchString(self: Target) []const u8 {
|
||||
.powerpc => return "ppc",
|
||||
.powerpc64 => return "ppc64",
|
||||
.powerpc64le => return "ppc64le",
|
||||
else => return @tagName(arch),
|
||||
// @tagName should be able to return sentinel terminated slice
|
||||
else => @panic("TODO https://github.com/ziglang/zig/issues/3779"), //return @tagName(arch),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -156,7 +156,7 @@ pub const Value = struct {
|
||||
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
|
||||
const llvm_fn = llvm.AddFunction(
|
||||
ofile.module,
|
||||
self.symbol_name.ptr(),
|
||||
self.symbol_name.toSliceConst(),
|
||||
llvm_fn_type,
|
||||
) orelse return error.OutOfMemory;
|
||||
|
||||
@ -241,7 +241,7 @@ pub const Value = struct {
|
||||
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
|
||||
const llvm_fn = llvm.AddFunction(
|
||||
ofile.module,
|
||||
self.symbol_name.ptr(),
|
||||
self.symbol_name.toSliceConst(),
|
||||
llvm_fn_type,
|
||||
) orelse return error.OutOfMemory;
|
||||
|
||||
@ -334,7 +334,7 @@ pub const Value = struct {
|
||||
field_index: usize,
|
||||
};
|
||||
|
||||
pub async fn createArrayElemPtr(
|
||||
pub fn createArrayElemPtr(
|
||||
comp: *Compilation,
|
||||
array_val: *Array,
|
||||
mut: Type.Pointer.Mut,
|
||||
@ -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);
|
||||
@ -390,13 +390,13 @@ pub const Value = struct {
|
||||
const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
|
||||
const ptr_bit_count = ofile.comp.target_ptr_bits;
|
||||
const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
|
||||
const indices = [_]*llvm.Value{
|
||||
var indices = [_]*llvm.Value{
|
||||
llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
|
||||
llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
|
||||
};
|
||||
return llvm.ConstInBoundsGEP(
|
||||
array_llvm_value,
|
||||
&indices,
|
||||
@ptrCast([*]*llvm.Value, &indices),
|
||||
@intCast(c_uint, indices.len),
|
||||
) orelse return error.OutOfMemory;
|
||||
},
|
||||
@ -423,7 +423,7 @@ pub const Value = struct {
|
||||
};
|
||||
|
||||
/// Takes ownership of buffer
|
||||
pub async fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {
|
||||
pub fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {
|
||||
const u8_type = Type.Int.get_u8(comp);
|
||||
defer u8_type.base.base.deref(comp);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user