commit 28c3d4809bc6d497ac81892bc7eb03b95d8c2b32 (tree)
parent 69e50ad2f54bc446b2258f464f9b09e78e132d45
Author: Andrew Kelley <superjoe30@gmail.com>
Date: Sat, 14 Jul 2018 16:12:41 -0400
rename Module to Compilation
and CompilationUnit to ObjectFile
Diffstat:
10 files changed, 1070 insertions(+), 1072 deletions(-)
diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig
@@ -1,7 +1,5 @@
const std = @import("std");
-// TODO codegen pretends that Module is renamed to Build because I plan to
-// do that refactor at some point
-const Build = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
// we go through llvm instead of c for 2 reasons:
// 1. to avoid accidentally calling the non-thread-safe functions
// 2. patch up some of the types to remove nullability
@@ -11,51 +9,51 @@ const Value = @import("value.zig").Value;
const Type = @import("type.zig").Type;
const event = std.event;
-pub async fn renderToLlvm(build: *Build, fn_val: *Value.Fn, code: *ir.Code) !void {
+pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
fn_val.base.ref();
- defer fn_val.base.deref(build);
- defer code.destroy(build.a());
+ defer fn_val.base.deref(comp);
+ defer code.destroy(comp.a());
- const llvm_handle = try build.event_loop_local.getAnyLlvmContext();
- defer llvm_handle.release(build.event_loop_local);
+ const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
+ defer llvm_handle.release(comp.event_loop_local);
const context = llvm_handle.node.data;
- const module = llvm.ModuleCreateWithNameInContext(build.name.ptr(), context) orelse return error.OutOfMemory;
+ const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
defer llvm.DisposeModule(module);
const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;
defer llvm.DisposeBuilder(builder);
- var cunit = CompilationUnit{
- .build = build,
+ var ofile = ObjectFile{
+ .comp = comp,
.module = module,
.builder = builder,
.context = context,
- .lock = event.Lock.init(build.loop),
+ .lock = event.Lock.init(comp.loop),
};
- try renderToLlvmModule(&cunit, fn_val, code);
+ try renderToLlvmModule(&ofile, fn_val, code);
- if (build.verbose_llvm_ir) {
- llvm.DumpModule(cunit.module);
+ if (comp.verbose_llvm_ir) {
+ llvm.DumpModule(ofile.module);
}
}
-pub const CompilationUnit = struct {
- build: *Build,
+pub const ObjectFile = struct {
+ comp: *Compilation,
module: llvm.ModuleRef,
builder: llvm.BuilderRef,
context: llvm.ContextRef,
lock: event.Lock,
- fn a(self: *CompilationUnit) *std.mem.Allocator {
- return self.build.a();
+ fn a(self: *ObjectFile) *std.mem.Allocator {
+ return self.comp.a();
}
};
-pub fn renderToLlvmModule(cunit: *CompilationUnit, fn_val: *Value.Fn, code: *ir.Code) !void {
+pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void {
// TODO audit more of codegen.cpp:fn_llvm_value and port more logic
- const llvm_fn_type = try fn_val.base.typeof.getLlvmType(cunit);
- const llvm_fn = llvm.AddFunction(cunit.module, fn_val.symbol_name.ptr(), llvm_fn_type);
+ const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);
+ const llvm_fn = llvm.AddFunction(ofile.module, fn_val.symbol_name.ptr(), llvm_fn_type);
}
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
@@ -0,0 +1,747 @@
+const std = @import("std");
+const os = std.os;
+const io = std.io;
+const mem = std.mem;
+const Allocator = mem.Allocator;
+const Buffer = std.Buffer;
+const llvm = @import("llvm.zig");
+const c = @import("c.zig");
+const builtin = @import("builtin");
+const Target = @import("target.zig").Target;
+const warn = std.debug.warn;
+const Token = std.zig.Token;
+const ArrayList = std.ArrayList;
+const errmsg = @import("errmsg.zig");
+const ast = std.zig.ast;
+const event = std.event;
+const assert = std.debug.assert;
+const AtomicRmwOp = builtin.AtomicRmwOp;
+const AtomicOrder = builtin.AtomicOrder;
+const Scope = @import("scope.zig").Scope;
+const Decl = @import("decl.zig").Decl;
+const ir = @import("ir.zig");
+const Visib = @import("visib.zig").Visib;
+const ParsedFile = @import("parsed_file.zig").ParsedFile;
+const Value = @import("value.zig").Value;
+const Type = Value.Type;
+const Span = errmsg.Span;
+const codegen = @import("codegen.zig");
+
+/// Data that is local to the event loop.
+pub const EventLoopLocal = struct {
+ loop: *event.Loop,
+ llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
+
+ fn init(loop: *event.Loop) EventLoopLocal {
+ return EventLoopLocal{
+ .loop = loop,
+ .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
+ };
+ }
+
+ fn deinit(self: *EventLoopLocal) void {
+ while (self.llvm_handle_pool.pop()) |node| {
+ c.LLVMContextDispose(node.data);
+ self.loop.allocator.destroy(node);
+ }
+ }
+
+ /// Gets an exclusive handle on any LlvmContext.
+ /// Caller must release the handle when done.
+ pub fn getAnyLlvmContext(self: *EventLoopLocal) !LlvmHandle {
+ if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
+
+ const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
+ errdefer c.LLVMContextDispose(context_ref);
+
+ const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
+ .next = undefined,
+ .data = context_ref,
+ });
+ errdefer self.loop.allocator.destroy(node);
+
+ return LlvmHandle{ .node = node };
+ }
+};
+
+pub const LlvmHandle = struct {
+ node: *std.atomic.Stack(llvm.ContextRef).Node,
+
+ pub fn release(self: LlvmHandle, event_loop_local: *EventLoopLocal) void {
+ event_loop_local.llvm_handle_pool.push(self.node);
+ }
+};
+
+pub const Compilation = struct {
+ event_loop_local: *EventLoopLocal,
+ loop: *event.Loop,
+ name: Buffer,
+ root_src_path: ?[]const u8,
+ target: Target,
+ build_mode: builtin.Mode,
+ zig_lib_dir: []const u8,
+
+ version_major: u32,
+ version_minor: u32,
+ version_patch: u32,
+
+ linker_script: ?[]const u8,
+ cache_dir: []const u8,
+ libc_lib_dir: ?[]const u8,
+ libc_static_lib_dir: ?[]const u8,
+ libc_include_dir: ?[]const u8,
+ msvc_lib_dir: ?[]const u8,
+ kernel32_lib_dir: ?[]const u8,
+ dynamic_linker: ?[]const u8,
+ out_h_path: ?[]const u8,
+
+ is_test: bool,
+ each_lib_rpath: bool,
+ strip: bool,
+ is_static: bool,
+ linker_rdynamic: bool,
+
+ clang_argv: []const []const u8,
+ llvm_argv: []const []const u8,
+ lib_dirs: []const []const u8,
+ rpath_list: []const []const u8,
+ assembly_files: []const []const u8,
+ link_objects: []const []const u8,
+
+ windows_subsystem_windows: bool,
+ windows_subsystem_console: bool,
+
+ link_libs_list: ArrayList(*LinkLib),
+ libc_link_lib: ?*LinkLib,
+
+ err_color: errmsg.Color,
+
+ verbose_tokenize: bool,
+ verbose_ast_tree: bool,
+ verbose_ast_fmt: bool,
+ verbose_cimport: bool,
+ verbose_ir: bool,
+ verbose_llvm_ir: bool,
+ verbose_link: bool,
+
+ darwin_frameworks: []const []const u8,
+ darwin_version_min: DarwinVersionMin,
+
+ test_filters: []const []const u8,
+ test_name_prefix: ?[]const u8,
+
+ emit_file_type: Emit,
+
+ kind: Kind,
+
+ link_out_file: ?[]const u8,
+ events: *event.Channel(Event),
+
+ exported_symbol_names: event.Locked(Decl.Table),
+
+ /// Before code generation starts, must wait on this group to make sure
+ /// the build is complete.
+ build_group: event.Group(BuildError!void),
+
+ compile_errors: event.Locked(CompileErrList),
+
+ meta_type: *Type.MetaType,
+ void_type: *Type.Void,
+ bool_type: *Type.Bool,
+ noreturn_type: *Type.NoReturn,
+
+ void_value: *Value.Void,
+ true_value: *Value.Bool,
+ false_value: *Value.Bool,
+ noreturn_value: *Value.NoReturn,
+
+ const CompileErrList = std.ArrayList(*errmsg.Msg);
+
+ // TODO handle some of these earlier and report them in a way other than error codes
+ pub const BuildError = error{
+ OutOfMemory,
+ EndOfStream,
+ BadFd,
+ Io,
+ IsDir,
+ Unexpected,
+ SystemResources,
+ SharingViolation,
+ PathAlreadyExists,
+ FileNotFound,
+ AccessDenied,
+ PipeBusy,
+ FileTooBig,
+ SymLinkLoop,
+ ProcessFdQuotaExceeded,
+ NameTooLong,
+ SystemFdQuotaExceeded,
+ NoDevice,
+ PathNotFound,
+ NoSpaceLeft,
+ NotDir,
+ FileSystem,
+ OperationAborted,
+ IoPending,
+ BrokenPipe,
+ WouldBlock,
+ FileClosed,
+ DestinationAddressRequired,
+ DiskQuota,
+ InputOutput,
+ NoStdHandles,
+ Overflow,
+ NotSupported,
+ BufferTooSmall,
+ Unimplemented, // TODO remove this one
+ SemanticAnalysisFailed, // TODO remove this one
+ };
+
+ pub const Event = union(enum) {
+ Ok,
+ Error: BuildError,
+ Fail: []*errmsg.Msg,
+ };
+
+ pub const DarwinVersionMin = union(enum) {
+ None,
+ MacOS: []const u8,
+ Ios: []const u8,
+ };
+
+ pub const Kind = enum {
+ Exe,
+ Lib,
+ Obj,
+ };
+
+ pub const LinkLib = struct {
+ name: []const u8,
+ path: ?[]const u8,
+
+ /// the list of symbols we depend on from this lib
+ symbols: ArrayList([]u8),
+ provided_explicitly: bool,
+ };
+
+ pub const Emit = enum {
+ Binary,
+ Assembly,
+ LlvmIr,
+ };
+
+ pub fn create(
+ event_loop_local: *EventLoopLocal,
+ name: []const u8,
+ root_src_path: ?[]const u8,
+ target: *const Target,
+ kind: Kind,
+ build_mode: builtin.Mode,
+ zig_lib_dir: []const u8,
+ cache_dir: []const u8,
+ ) !*Compilation {
+ const loop = event_loop_local.loop;
+
+ var name_buffer = try Buffer.init(loop.allocator, name);
+ errdefer name_buffer.deinit();
+
+ const events = try event.Channel(Event).create(loop, 0);
+ errdefer events.destroy();
+
+ const comp = try loop.allocator.create(Compilation{
+ .loop = loop,
+ .event_loop_local = event_loop_local,
+ .events = events,
+ .name = name_buffer,
+ .root_src_path = root_src_path,
+ .target = target.*,
+ .kind = kind,
+ .build_mode = build_mode,
+ .zig_lib_dir = zig_lib_dir,
+ .cache_dir = cache_dir,
+
+ .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,
+ .libc_lib_dir = null,
+ .libc_static_lib_dir = null,
+ .libc_include_dir = null,
+ .msvc_lib_dir = null,
+ .kernel32_lib_dir = null,
+ .dynamic_linker = null,
+ .out_h_path = null,
+ .is_test = false,
+ .each_lib_rpath = false,
+ .strip = false,
+ .is_static = false,
+ .linker_rdynamic = false,
+ .clang_argv = [][]const u8{},
+ .llvm_argv = [][]const u8{},
+ .lib_dirs = [][]const u8{},
+ .rpath_list = [][]const u8{},
+ .assembly_files = [][]const u8{},
+ .link_objects = [][]const u8{},
+ .windows_subsystem_windows = false,
+ .windows_subsystem_console = false,
+ .link_libs_list = ArrayList(*LinkLib).init(loop.allocator),
+ .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(loop, Decl.Table.init(loop.allocator)),
+ .build_group = event.Group(BuildError!void).init(loop),
+ .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
+
+ .meta_type = undefined,
+ .void_type = undefined,
+ .void_value = undefined,
+ .bool_type = undefined,
+ .true_value = undefined,
+ .false_value = undefined,
+ .noreturn_type = undefined,
+ .noreturn_value = undefined,
+ });
+ try comp.initTypes();
+ return comp;
+ }
+
+ fn initTypes(comp: *Compilation) !void {
+ comp.meta_type = try comp.a().create(Type.MetaType{
+ .base = Type{
+ .base = Value{
+ .id = Value.Id.Type,
+ .typeof = undefined,
+ .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
+ },
+ .id = builtin.TypeId.Type,
+ },
+ .value = undefined,
+ });
+ comp.meta_type.value = &comp.meta_type.base;
+ comp.meta_type.base.base.typeof = &comp.meta_type.base;
+ errdefer comp.a().destroy(comp.meta_type);
+
+ comp.void_type = try comp.a().create(Type.Void{
+ .base = Type{
+ .base = Value{
+ .id = Value.Id.Type,
+ .typeof = &Type.MetaType.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .id = builtin.TypeId.Void,
+ },
+ });
+ errdefer comp.a().destroy(comp.void_type);
+
+ comp.noreturn_type = try comp.a().create(Type.NoReturn{
+ .base = Type{
+ .base = Value{
+ .id = Value.Id.Type,
+ .typeof = &Type.MetaType.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .id = builtin.TypeId.NoReturn,
+ },
+ });
+ errdefer comp.a().destroy(comp.noreturn_type);
+
+ comp.bool_type = try comp.a().create(Type.Bool{
+ .base = Type{
+ .base = Value{
+ .id = Value.Id.Type,
+ .typeof = &Type.MetaType.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .id = builtin.TypeId.Bool,
+ },
+ });
+ errdefer comp.a().destroy(comp.bool_type);
+
+ comp.void_value = try comp.a().create(Value.Void{
+ .base = Value{
+ .id = Value.Id.Void,
+ .typeof = &Type.Void.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ });
+ errdefer comp.a().destroy(comp.void_value);
+
+ comp.true_value = try comp.a().create(Value.Bool{
+ .base = Value{
+ .id = Value.Id.Bool,
+ .typeof = &Type.Bool.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .x = true,
+ });
+ errdefer comp.a().destroy(comp.true_value);
+
+ comp.false_value = try comp.a().create(Value.Bool{
+ .base = Value{
+ .id = Value.Id.Bool,
+ .typeof = &Type.Bool.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ .x = false,
+ });
+ errdefer comp.a().destroy(comp.false_value);
+
+ comp.noreturn_value = try comp.a().create(Value.NoReturn{
+ .base = Value{
+ .id = Value.Id.NoReturn,
+ .typeof = &Type.NoReturn.get(comp).base,
+ .ref_count = std.atomic.Int(usize).init(1),
+ },
+ });
+ errdefer comp.a().destroy(comp.noreturn_value);
+ }
+
+ pub fn destroy(self: *Compilation) void {
+ self.noreturn_value.base.deref(self);
+ self.void_value.base.deref(self);
+ self.false_value.base.deref(self);
+ self.true_value.base.deref(self);
+ self.noreturn_type.base.base.deref(self);
+ self.void_type.base.base.deref(self);
+ self.meta_type.base.base.deref(self);
+
+ self.events.destroy();
+ self.name.deinit();
+
+ self.a().destroy(self);
+ }
+
+ pub fn build(self: *Compilation) !void {
+ if (self.llvm_argv.len != 0) {
+ var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.a(), [][]const []const u8{
+ [][]const u8{"zig (LLVM option parsing)"},
+ self.llvm_argv,
+ });
+ defer c_compatible_args.deinit();
+ // TODO this sets global state
+ c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
+ }
+
+ _ = try async<self.a()> self.buildAsync();
+ }
+
+ async fn buildAsync(self: *Compilation) void {
+ while (true) {
+ // TODO directly awaiting async should guarantee memory allocation elision
+ // TODO also async before suspending should guarantee memory allocation elision
+ const build_result = await (async self.addRootSrc() catch unreachable);
+
+ // this makes a handy error return trace and stack trace in debug mode
+ if (std.debug.runtime_safety) {
+ build_result catch unreachable;
+ }
+
+ const compile_errors = blk: {
+ const held = await (async self.compile_errors.acquire() catch unreachable);
+ defer held.release();
+ break :blk held.value.toOwnedSlice();
+ };
+
+ if (build_result) |_| {
+ if (compile_errors.len == 0) {
+ await (async self.events.put(Event.Ok) catch unreachable);
+ } else {
+ await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
+ }
+ } else |err| {
+ // if there's an error then the compile errors have dangling references
+ self.a().free(compile_errors);
+
+ await (async self.events.put(Event{ .Error = err }) catch unreachable);
+ }
+
+ // for now we stop after 1
+ return;
+ }
+ }
+
+ async fn addRootSrc(self: *Compilation) !void {
+ const root_src_path = self.root_src_path orelse @panic("TODO handle null root src path");
+ // TODO async/await os.path.real
+ const root_src_real_path = os.path.real(self.a(), root_src_path) catch |err| {
+ try printError("unable to get real path '{}': {}", root_src_path, err);
+ return err;
+ };
+ errdefer self.a().free(root_src_real_path);
+
+ // TODO async/await readFileAlloc()
+ const source_code = io.readFileAlloc(self.a(), root_src_real_path) catch |err| {
+ try printError("unable to open '{}': {}", root_src_real_path, err);
+ return err;
+ };
+ errdefer self.a().free(source_code);
+
+ const parsed_file = try self.a().create(ParsedFile{
+ .tree = undefined,
+ .realpath = root_src_real_path,
+ });
+ errdefer self.a().destroy(parsed_file);
+
+ parsed_file.tree = try std.zig.parse(self.a(), source_code);
+ errdefer parsed_file.tree.deinit();
+
+ const tree = &parsed_file.tree;
+
+ // create empty struct for it
+ const decls = try Scope.Decls.create(self, null);
+ defer decls.base.deref(self);
+
+ var decl_group = event.Group(BuildError!void).init(self.loop);
+ errdefer decl_group.cancelAll();
+
+ var it = tree.root_node.decls.iterator(0);
+ while (it.next()) |decl_ptr| {
+ const decl = decl_ptr.*;
+ switch (decl.id) {
+ ast.Node.Id.Comptime => @panic("TODO"),
+ ast.Node.Id.VarDecl => @panic("TODO"),
+ ast.Node.Id.FnProto => {
+ const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
+
+ const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
+ try self.addCompileError(parsed_file, Span{
+ .first = fn_proto.fn_token,
+ .last = fn_proto.fn_token + 1,
+ }, "missing function name");
+ continue;
+ };
+
+ const fn_decl = try self.a().create(Decl.Fn{
+ .base = Decl{
+ .id = Decl.Id.Fn,
+ .name = name,
+ .visib = parseVisibToken(tree, fn_proto.visib_token),
+ .resolution = event.Future(BuildError!void).init(self.loop),
+ .resolution_in_progress = 0,
+ .parsed_file = parsed_file,
+ .parent_scope = &decls.base,
+ },
+ .value = Decl.Fn.Val{ .Unresolved = {} },
+ .fn_proto = fn_proto,
+ });
+ errdefer self.a().destroy(fn_decl);
+
+ try decl_group.call(addTopLevelDecl, self, &fn_decl.base);
+ },
+ ast.Node.Id.TestDecl => @panic("TODO"),
+ else => unreachable,
+ }
+ }
+ try await (async decl_group.wait() catch unreachable);
+ try await (async self.build_group.wait() catch unreachable);
+ }
+
+ async fn addTopLevelDecl(self: *Compilation, decl: *Decl) !void {
+ const is_export = decl.isExported(&decl.parsed_file.tree);
+
+ if (is_export) {
+ try self.build_group.call(verifyUniqueSymbol, self, decl);
+ try self.build_group.call(resolveDecl, self, decl);
+ }
+ }
+
+ fn addCompileError(self: *Compilation, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
+ const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
+ errdefer self.loop.allocator.free(text);
+
+ try self.build_group.call(addCompileErrorAsync, self, parsed_file, span, text);
+ }
+
+ async fn addCompileErrorAsync(
+ self: *Compilation,
+ parsed_file: *ParsedFile,
+ span: Span,
+ text: []u8,
+ ) !void {
+ const msg = try self.loop.allocator.create(errmsg.Msg{
+ .path = parsed_file.realpath,
+ .text = text,
+ .span = span,
+ .tree = &parsed_file.tree,
+ });
+ errdefer self.loop.allocator.destroy(msg);
+
+ const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
+ defer compile_errors.release();
+
+ try compile_errors.value.append(msg);
+ }
+
+ async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void {
+ const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
+ defer exported_symbol_names.release();
+
+ if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
+ try self.addCompileError(
+ decl.parsed_file,
+ decl.getSpan(),
+ "exported symbol collision: '{}'",
+ decl.name,
+ );
+ // TODO add error note showing location of other symbol
+ }
+ }
+
+ pub fn link(self: *Compilation, out_file: ?[]const u8) !void {
+ warn("TODO link");
+ return error.Todo;
+ }
+
+ pub fn addLinkLib(self: *Compilation, name: []const u8, provided_explicitly: bool) !*LinkLib {
+ const is_libc = mem.eql(u8, name, "c");
+
+ if (is_libc) {
+ if (self.libc_link_lib) |libc_link_lib| {
+ return libc_link_lib;
+ }
+ }
+
+ for (self.link_libs_list.toSliceConst()) |existing_lib| {
+ if (mem.eql(u8, name, existing_lib.name)) {
+ return existing_lib;
+ }
+ }
+
+ const link_lib = try self.a().create(LinkLib{
+ .name = name,
+ .path = null,
+ .provided_explicitly = provided_explicitly,
+ .symbols = ArrayList([]u8).init(self.a()),
+ });
+ try self.link_libs_list.append(link_lib);
+ if (is_libc) {
+ self.libc_link_lib = link_lib;
+ }
+ return link_lib;
+ }
+
+ fn a(self: Compilation) *mem.Allocator {
+ return self.loop.allocator;
+ }
+};
+
+fn printError(comptime format: []const u8, args: ...) !void {
+ var stderr_file = try std.io.getStdErr();
+ var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
+ const out_stream = &stderr_file_out_stream.stream;
+ try out_stream.print(format, args);
+}
+
+fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib {
+ if (optional_token_index) |token_index| {
+ const token = tree.tokens.at(token_index);
+ assert(token.id == Token.Id.Keyword_pub);
+ return Visib.Pub;
+ } else {
+ return Visib.Private;
+ }
+}
+
+/// This declaration has been blessed as going into the final code generation.
+pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void {
+ if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
+ decl.resolution.data = await (async generateDecl(comp, decl) catch unreachable);
+ decl.resolution.resolve();
+ return decl.resolution.data;
+ } else {
+ return (await (async decl.resolution.get() catch unreachable)).*;
+ }
+}
+
+/// The function that actually does the generation.
+async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
+ switch (decl.id) {
+ Decl.Id.Var => @panic("TODO"),
+ Decl.Id.Fn => {
+ const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
+ return await (async generateDeclFn(comp, fn_decl) catch unreachable);
+ },
+ Decl.Id.CompTime => @panic("TODO"),
+ }
+}
+
+async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
+ const body_node = fn_decl.fn_proto.body_node orelse @panic("TODO extern fn proto decl");
+
+ const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);
+ defer fndef_scope.base.deref(comp);
+
+ // TODO actually look at the return type of the AST
+ const return_type = &Type.Void.get(comp).base;
+ defer return_type.base.deref(comp);
+
+ const is_var_args = false;
+ const params = ([*]Type.Fn.Param)(undefined)[0..0];
+ const fn_type = try Type.Fn.create(comp, return_type, params, is_var_args);
+ defer fn_type.base.base.deref(comp);
+
+ var symbol_name = try std.Buffer.init(comp.a(), fn_decl.base.name);
+ errdefer symbol_name.deinit();
+
+ const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
+ defer fn_val.base.deref(comp);
+
+ fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
+
+ const unanalyzed_code = (await (async ir.gen(
+ comp,
+ body_node,
+ &fndef_scope.base,
+ Span.token(body_node.lastToken()),
+ fn_decl.base.parsed_file,
+ ) catch unreachable)) catch |err| switch (err) {
+ // This poison value should not cause the errdefers to run. It simply means
+ // that self.compile_errors is populated.
+ // TODO https://github.com/ziglang/zig/issues/769
+ error.SemanticAnalysisFailed => return {},
+ else => return err,
+ };
+ defer unanalyzed_code.destroy(comp.a());
+
+ if (comp.verbose_ir) {
+ std.debug.warn("unanalyzed:\n");
+ unanalyzed_code.dump();
+ }
+
+ const analyzed_code = (await (async ir.analyze(
+ comp,
+ fn_decl.base.parsed_file,
+ unanalyzed_code,
+ null,
+ ) catch unreachable)) catch |err| switch (err) {
+ // This poison value should not cause the errdefers to run. It simply means
+ // that self.compile_errors is populated.
+ // TODO https://github.com/ziglang/zig/issues/769
+ error.SemanticAnalysisFailed => return {},
+ else => return err,
+ };
+ errdefer analyzed_code.destroy(comp.a());
+
+ if (comp.verbose_ir) {
+ std.debug.warn("analyzed:\n");
+ analyzed_code.dump();
+ }
+
+ // Kick off rendering to LLVM comp, but it doesn't block the fn decl
+ // analysis from being complete.
+ try comp.build_group.call(codegen.renderToLlvm, comp, fn_val, analyzed_code);
+}
diff --git a/src-self-hosted/decl.zig b/src-self-hosted/decl.zig
@@ -9,13 +9,13 @@ const Value = @import("value.zig").Value;
const Token = std.zig.Token;
const errmsg = @import("errmsg.zig");
const Scope = @import("scope.zig").Scope;
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
pub const Decl = struct {
id: Id,
name: []const u8,
visib: Visib,
- resolution: event.Future(Module.BuildError!void),
+ resolution: event.Future(Compilation.BuildError!void),
resolution_in_progress: u8,
parsed_file: *ParsedFile,
parent_scope: *Scope,
diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
const Scope = @import("scope.zig").Scope;
const ast = std.zig.ast;
const Allocator = std.mem.Allocator;
@@ -243,7 +243,7 @@ pub const Instruction = struct {
Value.Ptr.Mut.CompTimeConst,
self.params.mut,
self.params.volatility,
- val.typeof.getAbiAlignment(ira.irb.module),
+ val.typeof.getAbiAlignment(ira.irb.comp),
);
}
@@ -254,12 +254,12 @@ pub const Instruction = struct {
});
const elem_type = target.getKnownType();
const ptr_type = Type.Pointer.get(
- ira.irb.module,
+ ira.irb.comp,
elem_type,
self.params.mut,
self.params.volatility,
Type.Pointer.Size.One,
- elem_type.getAbiAlignment(ira.irb.module),
+ elem_type.getAbiAlignment(ira.irb.comp),
);
// TODO: potentially set the hint that this is a stack pointer. But it might not be - this
// could be a ref of a global, for example
@@ -417,7 +417,7 @@ pub const Code = struct {
arena: std.heap.ArenaAllocator,
return_type: ?*Type,
- /// allocator is module.a()
+ /// allocator is comp.a()
pub fn destroy(self: *Code, allocator: *Allocator) void {
self.arena.deinit();
allocator.destroy(self);
@@ -437,7 +437,7 @@ pub const Code = struct {
};
pub const Builder = struct {
- module: *Module,
+ comp: *Compilation,
code: *Code,
current_basic_block: *BasicBlock,
next_debug_id: usize,
@@ -446,17 +446,17 @@ pub const Builder = struct {
pub const Error = Analyze.Error;
- pub fn init(module: *Module, parsed_file: *ParsedFile) !Builder {
- const code = try module.a().create(Code{
+ pub fn init(comp: *Compilation, parsed_file: *ParsedFile) !Builder {
+ const code = try comp.a().create(Code{
.basic_block_list = undefined,
- .arena = std.heap.ArenaAllocator.init(module.a()),
+ .arena = std.heap.ArenaAllocator.init(comp.a()),
.return_type = null,
});
code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
- errdefer code.destroy(module.a());
+ errdefer code.destroy(comp.a());
return Builder{
- .module = module,
+ .comp = comp,
.parsed_file = parsed_file,
.current_basic_block = undefined,
.code = code,
@@ -466,7 +466,7 @@ pub const Builder = struct {
}
pub fn abort(self: *Builder) void {
- self.code.destroy(self.module.a());
+ self.code.destroy(self.comp.a());
}
/// Call code.destroy() when done
@@ -581,7 +581,7 @@ pub const Builder = struct {
}
pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Instruction {
- const block_scope = try Scope.Block.create(irb.module, parent_scope);
+ const block_scope = try Scope.Block.create(irb.comp, parent_scope);
const outer_block_scope = &block_scope.base;
var child_scope = outer_block_scope;
@@ -623,8 +623,8 @@ pub const Builder = struct {
Token.Id.Keyword_errdefer => Scope.Defer.Kind.ErrorExit,
else => unreachable,
};
- const defer_expr_scope = try Scope.DeferExpr.create(irb.module, parent_scope, defer_node.expr);
- const defer_child_scope = try Scope.Defer.create(irb.module, parent_scope, kind, defer_expr_scope);
+ const defer_expr_scope = try Scope.DeferExpr.create(irb.comp, parent_scope, defer_node.expr);
+ const defer_child_scope = try Scope.Defer.create(irb.comp, parent_scope, kind, defer_expr_scope);
child_scope = &defer_child_scope.base;
continue;
}
@@ -770,8 +770,8 @@ pub const Builder = struct {
.debug_id = self.next_debug_id,
.val = switch (I.ir_val_init) {
IrVal.Init.Unknown => IrVal.Unknown,
- IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.module).base },
- IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.module).base },
+ IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
+ IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
},
.ref_count = 0,
.span = span,
@@ -819,13 +819,13 @@ pub const Builder = struct {
fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Instruction {
const inst = try self.build(Instruction.Const, scope, span, Instruction.Const.Params{});
- inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.module, x).base };
+ inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.comp, x).base };
return inst;
}
fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Instruction {
const inst = try self.buildExtra(Instruction.Const, scope, span, Instruction.Const.Params{}, is_generated);
- inst.val = IrVal{ .KnownValue = &Value.Void.get(self.module).base };
+ inst.val = IrVal{ .KnownValue = &Value.Void.get(self.comp).base };
return inst;
}
};
@@ -850,8 +850,8 @@ const Analyze = struct {
OutOfMemory,
};
- pub fn init(module: *Module, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
- var irb = try Builder.init(module, parsed_file);
+ pub fn init(comp: *Compilation, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
+ var irb = try Builder.init(comp, parsed_file);
errdefer irb.abort();
return Analyze{
@@ -929,12 +929,12 @@ const Analyze = struct {
}
fn addCompileError(self: *Analyze, span: Span, comptime fmt: []const u8, args: ...) !void {
- return self.irb.module.addCompileError(self.irb.parsed_file, span, fmt, args);
+ return self.irb.comp.addCompileError(self.irb.parsed_file, span, fmt, args);
}
fn resolvePeerTypes(self: *Analyze, expected_type: ?*Type, peers: []const *Instruction) Analyze.Error!*Type {
// TODO actual implementation
- return &Type.Void.get(self.irb.module).base;
+ return &Type.Void.get(self.irb.comp).base;
}
fn implicitCast(self: *Analyze, target: *Instruction, optional_dest_type: ?*Type) Analyze.Error!*Instruction {
@@ -959,13 +959,13 @@ const Analyze = struct {
};
pub async fn gen(
- module: *Module,
+ comp: *Compilation,
body_node: *ast.Node,
scope: *Scope,
end_span: Span,
parsed_file: *ParsedFile,
) !*Code {
- var irb = try Builder.init(module, parsed_file);
+ var irb = try Builder.init(comp, parsed_file);
errdefer irb.abort();
const entry_block = try irb.createBasicBlock(scope, "Entry");
@@ -991,8 +991,8 @@ pub async fn gen(
return irb.finish();
}
-pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
- var ira = try Analyze.init(module, parsed_file, expected_type);
+pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
+ var ira = try Analyze.init(comp, parsed_file, expected_type);
errdefer ira.abort();
const old_entry_bb = old_code.basic_block_list.at(0);
@@ -1025,7 +1025,7 @@ pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code,
}
if (ira.src_implicit_return_type_list.len == 0) {
- ira.irb.code.return_type = &Type.NoReturn.get(module).base;
+ ira.irb.code.return_type = &Type.NoReturn.get(comp).base;
return ira.irb.finish();
}
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
@@ -14,8 +14,8 @@ const c = @import("c.zig");
const introspect = @import("introspect.zig");
const Args = arg.Args;
const Flag = arg.Flag;
-const EventLoopLocal = @import("module.zig").EventLoopLocal;
-const Module = @import("module.zig").Module;
+const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
+const Compilation = @import("compilation.zig").Compilation;
const Target = @import("target.zig").Target;
const errmsg = @import("errmsg.zig");
@@ -258,7 +258,7 @@ const args_build_generic = []Flag{
Flag.Arg1("--ver-patch"),
};
-fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Module.Kind) !void {
+fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
var flags = try Args.parse(allocator, args_build_generic, args);
defer flags.deinit();
@@ -300,14 +300,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
const emit_type = blk: {
if (flags.single("emit")) |emit_flag| {
if (mem.eql(u8, emit_flag, "asm")) {
- break :blk Module.Emit.Assembly;
+ break :blk Compilation.Emit.Assembly;
} else if (mem.eql(u8, emit_flag, "bin")) {
- break :blk Module.Emit.Binary;
+ break :blk Compilation.Emit.Binary;
} else if (mem.eql(u8, emit_flag, "llvm-ir")) {
- break :blk Module.Emit.LlvmIr;
+ break :blk Compilation.Emit.LlvmIr;
} else unreachable;
} else {
- break :blk Module.Emit.Binary;
+ break :blk Compilation.Emit.Binary;
}
};
@@ -370,7 +370,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
os.exit(1);
}
- if (out_type == Module.Kind.Obj and link_objects.len != 0) {
+ if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
try stderr.write("When building an object file, --object arguments are invalid\n");
os.exit(1);
}
@@ -392,7 +392,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
var event_loop_local = EventLoopLocal.init(&loop);
defer event_loop_local.deinit();
- var module = try Module.create(
+ var comp = try Compilation.create(
&event_loop_local,
root_name,
root_source_file,
@@ -402,16 +402,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
zig_lib_dir,
full_cache_dir,
);
- defer module.destroy();
+ defer comp.destroy();
- module.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
- module.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
- module.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
+ comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
+ comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
+ comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
- module.is_test = false;
+ comp.is_test = false;
- module.linker_script = flags.single("linker-script");
- module.each_lib_rpath = flags.present("each-lib-rpath");
+ comp.linker_script = flags.single("linker-script");
+ comp.each_lib_rpath = flags.present("each-lib-rpath");
var clang_argv_buf = ArrayList([]const u8).init(allocator);
defer clang_argv_buf.deinit();
@@ -422,51 +422,51 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
try clang_argv_buf.append(mllvm);
}
- module.llvm_argv = mllvm_flags;
- module.clang_argv = clang_argv_buf.toSliceConst();
+ comp.llvm_argv = mllvm_flags;
+ comp.clang_argv = clang_argv_buf.toSliceConst();
- module.strip = flags.present("strip");
- module.is_static = flags.present("static");
+ comp.strip = flags.present("strip");
+ comp.is_static = flags.present("static");
if (flags.single("libc-lib-dir")) |libc_lib_dir| {
- module.libc_lib_dir = libc_lib_dir;
+ comp.libc_lib_dir = libc_lib_dir;
}
if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| {
- module.libc_static_lib_dir = libc_static_lib_dir;
+ comp.libc_static_lib_dir = libc_static_lib_dir;
}
if (flags.single("libc-include-dir")) |libc_include_dir| {
- module.libc_include_dir = libc_include_dir;
+ comp.libc_include_dir = libc_include_dir;
}
if (flags.single("msvc-lib-dir")) |msvc_lib_dir| {
- module.msvc_lib_dir = msvc_lib_dir;
+ comp.msvc_lib_dir = msvc_lib_dir;
}
if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| {
- module.kernel32_lib_dir = kernel32_lib_dir;
+ comp.kernel32_lib_dir = kernel32_lib_dir;
}
if (flags.single("dynamic-linker")) |dynamic_linker| {
- module.dynamic_linker = dynamic_linker;
+ comp.dynamic_linker = dynamic_linker;
}
- module.verbose_tokenize = flags.present("verbose-tokenize");
- module.verbose_ast_tree = flags.present("verbose-ast-tree");
- module.verbose_ast_fmt = flags.present("verbose-ast-fmt");
- module.verbose_link = flags.present("verbose-link");
- module.verbose_ir = flags.present("verbose-ir");
- module.verbose_llvm_ir = flags.present("verbose-llvm-ir");
- module.verbose_cimport = flags.present("verbose-cimport");
+ comp.verbose_tokenize = flags.present("verbose-tokenize");
+ comp.verbose_ast_tree = flags.present("verbose-ast-tree");
+ comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
+ comp.verbose_link = flags.present("verbose-link");
+ comp.verbose_ir = flags.present("verbose-ir");
+ comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
+ comp.verbose_cimport = flags.present("verbose-cimport");
- module.err_color = color;
- module.lib_dirs = flags.many("library-path");
- module.darwin_frameworks = flags.many("framework");
- module.rpath_list = flags.many("rpath");
+ comp.err_color = color;
+ comp.lib_dirs = flags.many("library-path");
+ comp.darwin_frameworks = flags.many("framework");
+ comp.rpath_list = flags.many("rpath");
if (flags.single("output-h")) |output_h| {
- module.out_h_path = output_h;
+ comp.out_h_path = output_h;
}
- module.windows_subsystem_windows = flags.present("mwindows");
- module.windows_subsystem_console = flags.present("mconsole");
- module.linker_rdynamic = flags.present("rdynamic");
+ comp.windows_subsystem_windows = flags.present("mwindows");
+ comp.windows_subsystem_console = flags.present("mconsole");
+ comp.linker_rdynamic = flags.present("rdynamic");
if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {
try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
@@ -474,37 +474,37 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
}
if (flags.single("mmacosx-version-min")) |ver| {
- module.darwin_version_min = Module.DarwinVersionMin{ .MacOS = ver };
+ comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
}
if (flags.single("mios-version-min")) |ver| {
- module.darwin_version_min = Module.DarwinVersionMin{ .Ios = ver };
+ comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
}
- module.emit_file_type = emit_type;
- module.link_objects = link_objects;
- module.assembly_files = assembly_files;
- module.link_out_file = flags.single("out-file");
+ comp.emit_file_type = emit_type;
+ comp.link_objects = link_objects;
+ comp.assembly_files = assembly_files;
+ comp.link_out_file = flags.single("out-file");
- try module.build();
- const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color);
+ try comp.build();
+ const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
defer cancel process_build_events_handle;
loop.run();
}
-async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
+async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
// TODO directly awaiting async should guarantee memory allocation elision
- const build_event = await (async module.events.get() catch unreachable);
+ const build_event = await (async comp.events.get() catch unreachable);
switch (build_event) {
- Module.Event.Ok => {
+ Compilation.Event.Ok => {
std.debug.warn("Build succeeded\n");
return;
},
- Module.Event.Error => |err| {
+ Compilation.Event.Error => |err| {
std.debug.warn("build failed: {}\n", @errorName(err));
os.exit(1);
},
- Module.Event.Fail => |msgs| {
+ Compilation.Event.Fail => |msgs| {
for (msgs) |msg| {
errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);
}
@@ -513,15 +513,15 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
}
fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {
- return buildOutputType(allocator, args, Module.Kind.Exe);
+ return buildOutputType(allocator, args, Compilation.Kind.Exe);
}
fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {
- return buildOutputType(allocator, args, Module.Kind.Lib);
+ return buildOutputType(allocator, args, Compilation.Kind.Lib);
}
fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
- return buildOutputType(allocator, args, Module.Kind.Obj);
+ return buildOutputType(allocator, args, Compilation.Kind.Obj);
}
const usage_fmt =
diff --git a/src-self-hosted/module.zig b/src-self-hosted/module.zig
@@ -1,747 +0,0 @@
-const std = @import("std");
-const os = std.os;
-const io = std.io;
-const mem = std.mem;
-const Allocator = mem.Allocator;
-const Buffer = std.Buffer;
-const llvm = @import("llvm.zig");
-const c = @import("c.zig");
-const builtin = @import("builtin");
-const Target = @import("target.zig").Target;
-const warn = std.debug.warn;
-const Token = std.zig.Token;
-const ArrayList = std.ArrayList;
-const errmsg = @import("errmsg.zig");
-const ast = std.zig.ast;
-const event = std.event;
-const assert = std.debug.assert;
-const AtomicRmwOp = builtin.AtomicRmwOp;
-const AtomicOrder = builtin.AtomicOrder;
-const Scope = @import("scope.zig").Scope;
-const Decl = @import("decl.zig").Decl;
-const ir = @import("ir.zig");
-const Visib = @import("visib.zig").Visib;
-const ParsedFile = @import("parsed_file.zig").ParsedFile;
-const Value = @import("value.zig").Value;
-const Type = Value.Type;
-const Span = errmsg.Span;
-const codegen = @import("codegen.zig");
-
-/// Data that is local to the event loop.
-pub const EventLoopLocal = struct {
- loop: *event.Loop,
- llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
-
- fn init(loop: *event.Loop) EventLoopLocal {
- return EventLoopLocal{
- .loop = loop,
- .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
- };
- }
-
- fn deinit(self: *EventLoopLocal) void {
- while (self.llvm_handle_pool.pop()) |node| {
- c.LLVMContextDispose(node.data);
- self.loop.allocator.destroy(node);
- }
- }
-
- /// Gets an exclusive handle on any LlvmContext.
- /// Caller must release the handle when done.
- pub fn getAnyLlvmContext(self: *EventLoopLocal) !LlvmHandle {
- if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
-
- const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
- errdefer c.LLVMContextDispose(context_ref);
-
- const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
- .next = undefined,
- .data = context_ref,
- });
- errdefer self.loop.allocator.destroy(node);
-
- return LlvmHandle{ .node = node };
- }
-};
-
-pub const LlvmHandle = struct {
- node: *std.atomic.Stack(llvm.ContextRef).Node,
-
- pub fn release(self: LlvmHandle, event_loop_local: *EventLoopLocal) void {
- event_loop_local.llvm_handle_pool.push(self.node);
- }
-};
-
-pub const Module = struct {
- event_loop_local: *EventLoopLocal,
- loop: *event.Loop,
- name: Buffer,
- root_src_path: ?[]const u8,
- target: Target,
- build_mode: builtin.Mode,
- zig_lib_dir: []const u8,
-
- version_major: u32,
- version_minor: u32,
- version_patch: u32,
-
- linker_script: ?[]const u8,
- cache_dir: []const u8,
- libc_lib_dir: ?[]const u8,
- libc_static_lib_dir: ?[]const u8,
- libc_include_dir: ?[]const u8,
- msvc_lib_dir: ?[]const u8,
- kernel32_lib_dir: ?[]const u8,
- dynamic_linker: ?[]const u8,
- out_h_path: ?[]const u8,
-
- is_test: bool,
- each_lib_rpath: bool,
- strip: bool,
- is_static: bool,
- linker_rdynamic: bool,
-
- clang_argv: []const []const u8,
- llvm_argv: []const []const u8,
- lib_dirs: []const []const u8,
- rpath_list: []const []const u8,
- assembly_files: []const []const u8,
- link_objects: []const []const u8,
-
- windows_subsystem_windows: bool,
- windows_subsystem_console: bool,
-
- link_libs_list: ArrayList(*LinkLib),
- libc_link_lib: ?*LinkLib,
-
- err_color: errmsg.Color,
-
- verbose_tokenize: bool,
- verbose_ast_tree: bool,
- verbose_ast_fmt: bool,
- verbose_cimport: bool,
- verbose_ir: bool,
- verbose_llvm_ir: bool,
- verbose_link: bool,
-
- darwin_frameworks: []const []const u8,
- darwin_version_min: DarwinVersionMin,
-
- test_filters: []const []const u8,
- test_name_prefix: ?[]const u8,
-
- emit_file_type: Emit,
-
- kind: Kind,
-
- link_out_file: ?[]const u8,
- events: *event.Channel(Event),
-
- exported_symbol_names: event.Locked(Decl.Table),
-
- /// Before code generation starts, must wait on this group to make sure
- /// the build is complete.
- build_group: event.Group(BuildError!void),
-
- compile_errors: event.Locked(CompileErrList),
-
- meta_type: *Type.MetaType,
- void_type: *Type.Void,
- bool_type: *Type.Bool,
- noreturn_type: *Type.NoReturn,
-
- void_value: *Value.Void,
- true_value: *Value.Bool,
- false_value: *Value.Bool,
- noreturn_value: *Value.NoReturn,
-
- const CompileErrList = std.ArrayList(*errmsg.Msg);
-
- // TODO handle some of these earlier and report them in a way other than error codes
- pub const BuildError = error{
- OutOfMemory,
- EndOfStream,
- BadFd,
- Io,
- IsDir,
- Unexpected,
- SystemResources,
- SharingViolation,
- PathAlreadyExists,
- FileNotFound,
- AccessDenied,
- PipeBusy,
- FileTooBig,
- SymLinkLoop,
- ProcessFdQuotaExceeded,
- NameTooLong,
- SystemFdQuotaExceeded,
- NoDevice,
- PathNotFound,
- NoSpaceLeft,
- NotDir,
- FileSystem,
- OperationAborted,
- IoPending,
- BrokenPipe,
- WouldBlock,
- FileClosed,
- DestinationAddressRequired,
- DiskQuota,
- InputOutput,
- NoStdHandles,
- Overflow,
- NotSupported,
- BufferTooSmall,
- Unimplemented, // TODO remove this one
- SemanticAnalysisFailed, // TODO remove this one
- };
-
- pub const Event = union(enum) {
- Ok,
- Error: BuildError,
- Fail: []*errmsg.Msg,
- };
-
- pub const DarwinVersionMin = union(enum) {
- None,
- MacOS: []const u8,
- Ios: []const u8,
- };
-
- pub const Kind = enum {
- Exe,
- Lib,
- Obj,
- };
-
- pub const LinkLib = struct {
- name: []const u8,
- path: ?[]const u8,
-
- /// the list of symbols we depend on from this lib
- symbols: ArrayList([]u8),
- provided_explicitly: bool,
- };
-
- pub const Emit = enum {
- Binary,
- Assembly,
- LlvmIr,
- };
-
- pub fn create(
- event_loop_local: *EventLoopLocal,
- name: []const u8,
- root_src_path: ?[]const u8,
- target: *const Target,
- kind: Kind,
- build_mode: builtin.Mode,
- zig_lib_dir: []const u8,
- cache_dir: []const u8,
- ) !*Module {
- const loop = event_loop_local.loop;
-
- var name_buffer = try Buffer.init(loop.allocator, name);
- errdefer name_buffer.deinit();
-
- const events = try event.Channel(Event).create(loop, 0);
- errdefer events.destroy();
-
- const module = try loop.allocator.create(Module{
- .loop = loop,
- .event_loop_local = event_loop_local,
- .events = events,
- .name = name_buffer,
- .root_src_path = root_src_path,
- .target = target.*,
- .kind = kind,
- .build_mode = build_mode,
- .zig_lib_dir = zig_lib_dir,
- .cache_dir = cache_dir,
-
- .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,
- .libc_lib_dir = null,
- .libc_static_lib_dir = null,
- .libc_include_dir = null,
- .msvc_lib_dir = null,
- .kernel32_lib_dir = null,
- .dynamic_linker = null,
- .out_h_path = null,
- .is_test = false,
- .each_lib_rpath = false,
- .strip = false,
- .is_static = false,
- .linker_rdynamic = false,
- .clang_argv = [][]const u8{},
- .llvm_argv = [][]const u8{},
- .lib_dirs = [][]const u8{},
- .rpath_list = [][]const u8{},
- .assembly_files = [][]const u8{},
- .link_objects = [][]const u8{},
- .windows_subsystem_windows = false,
- .windows_subsystem_console = false,
- .link_libs_list = ArrayList(*LinkLib).init(loop.allocator),
- .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(loop, Decl.Table.init(loop.allocator)),
- .build_group = event.Group(BuildError!void).init(loop),
- .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
-
- .meta_type = undefined,
- .void_type = undefined,
- .void_value = undefined,
- .bool_type = undefined,
- .true_value = undefined,
- .false_value = undefined,
- .noreturn_type = undefined,
- .noreturn_value = undefined,
- });
- try module.initTypes();
- return module;
- }
-
- fn initTypes(module: *Module) !void {
- module.meta_type = try module.a().create(Type.MetaType{
- .base = Type{
- .base = Value{
- .id = Value.Id.Type,
- .typeof = undefined,
- .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
- },
- .id = builtin.TypeId.Type,
- },
- .value = undefined,
- });
- module.meta_type.value = &module.meta_type.base;
- module.meta_type.base.base.typeof = &module.meta_type.base;
- errdefer module.a().destroy(module.meta_type);
-
- module.void_type = try module.a().create(Type.Void{
- .base = Type{
- .base = Value{
- .id = Value.Id.Type,
- .typeof = &Type.MetaType.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- .id = builtin.TypeId.Void,
- },
- });
- errdefer module.a().destroy(module.void_type);
-
- module.noreturn_type = try module.a().create(Type.NoReturn{
- .base = Type{
- .base = Value{
- .id = Value.Id.Type,
- .typeof = &Type.MetaType.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- .id = builtin.TypeId.NoReturn,
- },
- });
- errdefer module.a().destroy(module.noreturn_type);
-
- module.bool_type = try module.a().create(Type.Bool{
- .base = Type{
- .base = Value{
- .id = Value.Id.Type,
- .typeof = &Type.MetaType.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- .id = builtin.TypeId.Bool,
- },
- });
- errdefer module.a().destroy(module.bool_type);
-
- module.void_value = try module.a().create(Value.Void{
- .base = Value{
- .id = Value.Id.Void,
- .typeof = &Type.Void.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- });
- errdefer module.a().destroy(module.void_value);
-
- module.true_value = try module.a().create(Value.Bool{
- .base = Value{
- .id = Value.Id.Bool,
- .typeof = &Type.Bool.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- .x = true,
- });
- errdefer module.a().destroy(module.true_value);
-
- module.false_value = try module.a().create(Value.Bool{
- .base = Value{
- .id = Value.Id.Bool,
- .typeof = &Type.Bool.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- .x = false,
- });
- errdefer module.a().destroy(module.false_value);
-
- module.noreturn_value = try module.a().create(Value.NoReturn{
- .base = Value{
- .id = Value.Id.NoReturn,
- .typeof = &Type.NoReturn.get(module).base,
- .ref_count = std.atomic.Int(usize).init(1),
- },
- });
- errdefer module.a().destroy(module.noreturn_value);
- }
-
- pub fn destroy(self: *Module) void {
- self.noreturn_value.base.deref(self);
- self.void_value.base.deref(self);
- self.false_value.base.deref(self);
- self.true_value.base.deref(self);
- self.noreturn_type.base.base.deref(self);
- self.void_type.base.base.deref(self);
- self.meta_type.base.base.deref(self);
-
- self.events.destroy();
- self.name.deinit();
-
- self.a().destroy(self);
- }
-
- pub fn build(self: *Module) !void {
- if (self.llvm_argv.len != 0) {
- var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.a(), [][]const []const u8{
- [][]const u8{"zig (LLVM option parsing)"},
- self.llvm_argv,
- });
- defer c_compatible_args.deinit();
- // TODO this sets global state
- c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
- }
-
- _ = try async<self.a()> self.buildAsync();
- }
-
- async fn buildAsync(self: *Module) void {
- while (true) {
- // TODO directly awaiting async should guarantee memory allocation elision
- // TODO also async before suspending should guarantee memory allocation elision
- const build_result = await (async self.addRootSrc() catch unreachable);
-
- // this makes a handy error return trace and stack trace in debug mode
- if (std.debug.runtime_safety) {
- build_result catch unreachable;
- }
-
- const compile_errors = blk: {
- const held = await (async self.compile_errors.acquire() catch unreachable);
- defer held.release();
- break :blk held.value.toOwnedSlice();
- };
-
- if (build_result) |_| {
- if (compile_errors.len == 0) {
- await (async self.events.put(Event.Ok) catch unreachable);
- } else {
- await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
- }
- } else |err| {
- // if there's an error then the compile errors have dangling references
- self.a().free(compile_errors);
-
- await (async self.events.put(Event{ .Error = err }) catch unreachable);
- }
-
- // for now we stop after 1
- return;
- }
- }
-
- async fn addRootSrc(self: *Module) !void {
- const root_src_path = self.root_src_path orelse @panic("TODO handle null root src path");
- // TODO async/await os.path.real
- const root_src_real_path = os.path.real(self.a(), root_src_path) catch |err| {
- try printError("unable to get real path '{}': {}", root_src_path, err);
- return err;
- };
- errdefer self.a().free(root_src_real_path);
-
- // TODO async/await readFileAlloc()
- const source_code = io.readFileAlloc(self.a(), root_src_real_path) catch |err| {
- try printError("unable to open '{}': {}", root_src_real_path, err);
- return err;
- };
- errdefer self.a().free(source_code);
-
- const parsed_file = try self.a().create(ParsedFile{
- .tree = undefined,
- .realpath = root_src_real_path,
- });
- errdefer self.a().destroy(parsed_file);
-
- parsed_file.tree = try std.zig.parse(self.a(), source_code);
- errdefer parsed_file.tree.deinit();
-
- const tree = &parsed_file.tree;
-
- // create empty struct for it
- const decls = try Scope.Decls.create(self, null);
- defer decls.base.deref(self);
-
- var decl_group = event.Group(BuildError!void).init(self.loop);
- errdefer decl_group.cancelAll();
-
- var it = tree.root_node.decls.iterator(0);
- while (it.next()) |decl_ptr| {
- const decl = decl_ptr.*;
- switch (decl.id) {
- ast.Node.Id.Comptime => @panic("TODO"),
- ast.Node.Id.VarDecl => @panic("TODO"),
- ast.Node.Id.FnProto => {
- const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
-
- const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
- try self.addCompileError(parsed_file, Span{
- .first = fn_proto.fn_token,
- .last = fn_proto.fn_token + 1,
- }, "missing function name");
- continue;
- };
-
- const fn_decl = try self.a().create(Decl.Fn{
- .base = Decl{
- .id = Decl.Id.Fn,
- .name = name,
- .visib = parseVisibToken(tree, fn_proto.visib_token),
- .resolution = event.Future(BuildError!void).init(self.loop),
- .resolution_in_progress = 0,
- .parsed_file = parsed_file,
- .parent_scope = &decls.base,
- },
- .value = Decl.Fn.Val{ .Unresolved = {} },
- .fn_proto = fn_proto,
- });
- errdefer self.a().destroy(fn_decl);
-
- try decl_group.call(addTopLevelDecl, self, &fn_decl.base);
- },
- ast.Node.Id.TestDecl => @panic("TODO"),
- else => unreachable,
- }
- }
- try await (async decl_group.wait() catch unreachable);
- try await (async self.build_group.wait() catch unreachable);
- }
-
- async fn addTopLevelDecl(self: *Module, decl: *Decl) !void {
- const is_export = decl.isExported(&decl.parsed_file.tree);
-
- if (is_export) {
- try self.build_group.call(verifyUniqueSymbol, self, decl);
- try self.build_group.call(resolveDecl, self, decl);
- }
- }
-
- fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
- const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
- errdefer self.loop.allocator.free(text);
-
- try self.build_group.call(addCompileErrorAsync, self, parsed_file, span, text);
- }
-
- async fn addCompileErrorAsync(
- self: *Module,
- parsed_file: *ParsedFile,
- span: Span,
- text: []u8,
- ) !void {
- const msg = try self.loop.allocator.create(errmsg.Msg{
- .path = parsed_file.realpath,
- .text = text,
- .span = span,
- .tree = &parsed_file.tree,
- });
- errdefer self.loop.allocator.destroy(msg);
-
- const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
- defer compile_errors.release();
-
- try compile_errors.value.append(msg);
- }
-
- async fn verifyUniqueSymbol(self: *Module, decl: *Decl) !void {
- const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
- defer exported_symbol_names.release();
-
- if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
- try self.addCompileError(
- decl.parsed_file,
- decl.getSpan(),
- "exported symbol collision: '{}'",
- decl.name,
- );
- // TODO add error note showing location of other symbol
- }
- }
-
- pub fn link(self: *Module, out_file: ?[]const u8) !void {
- warn("TODO link");
- return error.Todo;
- }
-
- pub fn addLinkLib(self: *Module, name: []const u8, provided_explicitly: bool) !*LinkLib {
- const is_libc = mem.eql(u8, name, "c");
-
- if (is_libc) {
- if (self.libc_link_lib) |libc_link_lib| {
- return libc_link_lib;
- }
- }
-
- for (self.link_libs_list.toSliceConst()) |existing_lib| {
- if (mem.eql(u8, name, existing_lib.name)) {
- return existing_lib;
- }
- }
-
- const link_lib = try self.a().create(LinkLib{
- .name = name,
- .path = null,
- .provided_explicitly = provided_explicitly,
- .symbols = ArrayList([]u8).init(self.a()),
- });
- try self.link_libs_list.append(link_lib);
- if (is_libc) {
- self.libc_link_lib = link_lib;
- }
- return link_lib;
- }
-
- fn a(self: Module) *mem.Allocator {
- return self.loop.allocator;
- }
-};
-
-fn printError(comptime format: []const u8, args: ...) !void {
- var stderr_file = try std.io.getStdErr();
- var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
- const out_stream = &stderr_file_out_stream.stream;
- try out_stream.print(format, args);
-}
-
-fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib {
- if (optional_token_index) |token_index| {
- const token = tree.tokens.at(token_index);
- assert(token.id == Token.Id.Keyword_pub);
- return Visib.Pub;
- } else {
- return Visib.Private;
- }
-}
-
-/// This declaration has been blessed as going into the final code generation.
-pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
- if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
- decl.resolution.data = await (async generateDecl(module, decl) catch unreachable);
- decl.resolution.resolve();
- return decl.resolution.data;
- } else {
- return (await (async decl.resolution.get() catch unreachable)).*;
- }
-}
-
-/// The function that actually does the generation.
-async fn generateDecl(module: *Module, decl: *Decl) !void {
- switch (decl.id) {
- Decl.Id.Var => @panic("TODO"),
- Decl.Id.Fn => {
- const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
- return await (async generateDeclFn(module, fn_decl) catch unreachable);
- },
- Decl.Id.CompTime => @panic("TODO"),
- }
-}
-
-async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
- const body_node = fn_decl.fn_proto.body_node orelse @panic("TODO extern fn proto decl");
-
- const fndef_scope = try Scope.FnDef.create(module, fn_decl.base.parent_scope);
- defer fndef_scope.base.deref(module);
-
- // TODO actually look at the return type of the AST
- const return_type = &Type.Void.get(module).base;
- defer return_type.base.deref(module);
-
- const is_var_args = false;
- const params = ([*]Type.Fn.Param)(undefined)[0..0];
- const fn_type = try Type.Fn.create(module, return_type, params, is_var_args);
- defer fn_type.base.base.deref(module);
-
- var symbol_name = try std.Buffer.init(module.a(), fn_decl.base.name);
- errdefer symbol_name.deinit();
-
- const fn_val = try Value.Fn.create(module, fn_type, fndef_scope, symbol_name);
- defer fn_val.base.deref(module);
-
- fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
-
- const unanalyzed_code = (await (async ir.gen(
- module,
- body_node,
- &fndef_scope.base,
- Span.token(body_node.lastToken()),
- fn_decl.base.parsed_file,
- ) catch unreachable)) catch |err| switch (err) {
- // This poison value should not cause the errdefers to run. It simply means
- // that self.compile_errors is populated.
- // TODO https://github.com/ziglang/zig/issues/769
- error.SemanticAnalysisFailed => return {},
- else => return err,
- };
- defer unanalyzed_code.destroy(module.a());
-
- if (module.verbose_ir) {
- std.debug.warn("unanalyzed:\n");
- unanalyzed_code.dump();
- }
-
- const analyzed_code = (await (async ir.analyze(
- module,
- fn_decl.base.parsed_file,
- unanalyzed_code,
- null,
- ) catch unreachable)) catch |err| switch (err) {
- // This poison value should not cause the errdefers to run. It simply means
- // that self.compile_errors is populated.
- // TODO https://github.com/ziglang/zig/issues/769
- error.SemanticAnalysisFailed => return {},
- else => return err,
- };
- errdefer analyzed_code.destroy(module.a());
-
- if (module.verbose_ir) {
- std.debug.warn("analyzed:\n");
- analyzed_code.dump();
- }
-
- // Kick off rendering to LLVM module, but it doesn't block the fn decl
- // analysis from being complete.
- try module.build_group.call(codegen.renderToLlvm, module, fn_val, analyzed_code);
-}
diff --git a/src-self-hosted/scope.zig b/src-self-hosted/scope.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const Allocator = mem.Allocator;
const Decl = @import("decl.zig").Decl;
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
const mem = std.mem;
const ast = std.zig.ast;
const Value = @import("value.zig").Value;
@@ -16,17 +16,17 @@ pub const Scope = struct {
base.ref_count += 1;
}
- pub fn deref(base: *Scope, module: *Module) void {
+ pub fn deref(base: *Scope, comp: *Compilation) void {
base.ref_count -= 1;
if (base.ref_count == 0) {
- if (base.parent) |parent| parent.deref(module);
+ if (base.parent) |parent| parent.deref(comp);
switch (base.id) {
Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(),
- Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
- Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(module),
- Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(module),
- Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(module),
- Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(module),
+ Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
+ Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
+ Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
+ Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
+ Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
}
}
}
@@ -61,8 +61,8 @@ pub const Scope = struct {
table: Decl.Table,
/// Creates a Decls scope with 1 reference
- pub fn create(module: *Module, parent: ?*Scope) !*Decls {
- const self = try module.a().create(Decls{
+ pub fn create(comp: *Compilation, parent: ?*Scope) !*Decls {
+ const self = try comp.a().create(Decls{
.base = Scope{
.id = Id.Decls,
.parent = parent,
@@ -70,9 +70,9 @@ pub const Scope = struct {
},
.table = undefined,
});
- errdefer module.a().destroy(self);
+ errdefer comp.a().destroy(self);
- self.table = Decl.Table.init(module.a());
+ self.table = Decl.Table.init(comp.a());
errdefer self.table.deinit();
if (parent) |p| p.ref();
@@ -94,8 +94,8 @@ pub const Scope = struct {
is_comptime: *ir.Instruction,
/// Creates a Block scope with 1 reference
- pub fn create(module: *Module, parent: ?*Scope) !*Block {
- const self = try module.a().create(Block{
+ pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {
+ const self = try comp.a().create(Block{
.base = Scope{
.id = Id.Block,
.parent = parent,
@@ -106,14 +106,14 @@ pub const Scope = struct {
.end_block = undefined,
.is_comptime = undefined,
});
- errdefer module.a().destroy(self);
+ errdefer comp.a().destroy(self);
if (parent) |p| p.ref();
return self;
}
- pub fn destroy(self: *Block, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Block, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -125,8 +125,8 @@ pub const Scope = struct {
/// Creates a FnDef scope with 1 reference
/// Must set the fn_val later
- pub fn create(module: *Module, parent: ?*Scope) !*FnDef {
- const self = try module.a().create(FnDef{
+ pub fn create(comp: *Compilation, parent: ?*Scope) !*FnDef {
+ const self = try comp.a().create(FnDef{
.base = Scope{
.id = Id.FnDef,
.parent = parent,
@@ -140,8 +140,8 @@ pub const Scope = struct {
return self;
}
- pub fn destroy(self: *FnDef, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *FnDef, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -149,8 +149,8 @@ pub const Scope = struct {
base: Scope,
/// Creates a CompTime scope with 1 reference
- pub fn create(module: *Module, parent: ?*Scope) !*CompTime {
- const self = try module.a().create(CompTime{
+ pub fn create(comp: *Compilation, parent: ?*Scope) !*CompTime {
+ const self = try comp.a().create(CompTime{
.base = Scope{
.id = Id.CompTime,
.parent = parent,
@@ -162,8 +162,8 @@ pub const Scope = struct {
return self;
}
- pub fn destroy(self: *CompTime, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *CompTime, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -179,12 +179,12 @@ pub const Scope = struct {
/// Creates a Defer scope with 1 reference
pub fn create(
- module: *Module,
+ comp: *Compilation,
parent: ?*Scope,
kind: Kind,
defer_expr_scope: *DeferExpr,
) !*Defer {
- const self = try module.a().create(Defer{
+ const self = try comp.a().create(Defer{
.base = Scope{
.id = Id.Defer,
.parent = parent,
@@ -193,7 +193,7 @@ pub const Scope = struct {
.defer_expr_scope = defer_expr_scope,
.kind = kind,
});
- errdefer module.a().destroy(self);
+ errdefer comp.a().destroy(self);
defer_expr_scope.base.ref();
@@ -201,9 +201,9 @@ pub const Scope = struct {
return self;
}
- pub fn destroy(self: *Defer, module: *Module) void {
- self.defer_expr_scope.base.deref(module);
- module.a().destroy(self);
+ pub fn destroy(self: *Defer, comp: *Compilation) void {
+ self.defer_expr_scope.base.deref(comp);
+ comp.a().destroy(self);
}
};
@@ -212,8 +212,8 @@ pub const Scope = struct {
expr_node: *ast.Node,
/// Creates a DeferExpr scope with 1 reference
- pub fn create(module: *Module, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
- const self = try module.a().create(DeferExpr{
+ pub fn create(comp: *Compilation, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
+ const self = try comp.a().create(DeferExpr{
.base = Scope{
.id = Id.DeferExpr,
.parent = parent,
@@ -221,14 +221,14 @@ pub const Scope = struct {
},
.expr_node = expr_node,
});
- errdefer module.a().destroy(self);
+ errdefer comp.a().destroy(self);
if (parent) |p| p.ref();
return self;
}
- pub fn destroy(self: *DeferExpr, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *DeferExpr, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
};
diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig
@@ -2,11 +2,11 @@ const std = @import("std");
const mem = std.mem;
const builtin = @import("builtin");
const Target = @import("target.zig").Target;
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
const introspect = @import("introspect.zig");
const assertOrPanic = std.debug.assertOrPanic;
const errmsg = @import("errmsg.zig");
-const EventLoopLocal = @import("module.zig").EventLoopLocal;
+const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
test "compile errors" {
var ctx: TestContext = undefined;
@@ -100,42 +100,42 @@ pub const TestContext = struct {
// TODO async I/O
try std.io.writeFile(allocator, file1_path, source);
- var module = try Module.create(
+ var comp = try Compilation.create(
&self.event_loop_local,
"test",
file1_path,
Target.Native,
- Module.Kind.Obj,
+ Compilation.Kind.Obj,
builtin.Mode.Debug,
self.zig_lib_dir,
self.zig_cache_dir,
);
- errdefer module.destroy();
+ errdefer comp.destroy();
- try module.build();
+ try comp.build();
- try self.group.call(getModuleEvent, module, source, path, line, column, msg);
+ try self.group.call(getModuleEvent, comp, source, path, line, column, msg);
}
async fn getModuleEvent(
- module: *Module,
+ comp: *Compilation,
source: []const u8,
path: []const u8,
line: usize,
column: usize,
text: []const u8,
) !void {
- defer module.destroy();
- const build_event = await (async module.events.get() catch unreachable);
+ defer comp.destroy();
+ const build_event = await (async comp.events.get() catch unreachable);
switch (build_event) {
- Module.Event.Ok => {
+ Compilation.Event.Ok => {
@panic("build incorrectly succeeded");
},
- Module.Event.Error => |err| {
+ Compilation.Event.Error => |err| {
@panic("build incorrectly failed");
},
- Module.Event.Fail => |msgs| {
+ Compilation.Event.Fail => |msgs| {
assertOrPanic(msgs.len != 0);
for (msgs) |msg| {
if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) {
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
@@ -1,10 +1,10 @@
const std = @import("std");
const builtin = @import("builtin");
const Scope = @import("scope.zig").Scope;
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
const Value = @import("value.zig").Value;
const llvm = @import("llvm.zig");
-const CompilationUnit = @import("codegen.zig").CompilationUnit;
+const ObjectFile = @import("codegen.zig").ObjectFile;
pub const Type = struct {
base: Value,
@@ -12,63 +12,63 @@ pub const Type = struct {
pub const Id = builtin.TypeId;
- pub fn destroy(base: *Type, module: *Module) void {
+ pub fn destroy(base: *Type, comp: *Compilation) void {
switch (base.id) {
- Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(module),
- Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
- Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(module),
- Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
- Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
- Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
- Id.Int => @fieldParentPtr(Int, "base", base).destroy(module),
- Id.Float => @fieldParentPtr(Float, "base", base).destroy(module),
- Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(module),
- Id.Array => @fieldParentPtr(Array, "base", base).destroy(module),
- Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(module),
- Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(module),
- Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(module),
- Id.Null => @fieldParentPtr(Null, "base", base).destroy(module),
- Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(module),
- Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(module),
- Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(module),
- Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(module),
- Id.Union => @fieldParentPtr(Union, "base", base).destroy(module),
- Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(module),
- Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
- Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(module),
- Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(module),
- Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(module),
- Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(module),
+ Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
+ Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
+ Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
+ Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
+ Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
+ Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
+ Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
+ Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),
+ Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
+ Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
+ Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
+ Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
+ Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
+ Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),
+ Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
+ Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
+ Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
+ Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
+ Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
+ Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
+ Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
+ Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
+ Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
+ Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
+ Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
}
}
- pub fn getLlvmType(base: *Type, cunit: *CompilationUnit) (error{OutOfMemory}!llvm.TypeRef) {
+ pub fn getLlvmType(base: *Type, ofile: *ObjectFile) (error{OutOfMemory}!llvm.TypeRef) {
switch (base.id) {
- Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(cunit),
- Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(cunit),
+ Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(ofile),
+ Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(ofile),
Id.Type => unreachable,
Id.Void => unreachable,
- Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(cunit),
+ Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(ofile),
Id.NoReturn => unreachable,
- Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(cunit),
- Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(cunit),
- Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(cunit),
- Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(cunit),
+ Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(ofile),
+ Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(ofile),
+ Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(ofile),
+ Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(ofile),
Id.ComptimeFloat => unreachable,
Id.ComptimeInt => unreachable,
Id.Undefined => unreachable,
Id.Null => unreachable,
- Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(cunit),
- Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(cunit),
- Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(cunit),
- Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(cunit),
- Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(cunit),
+ Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(ofile),
+ Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(ofile),
+ Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(ofile),
+ Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(ofile),
+ Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(ofile),
Id.Namespace => unreachable,
Id.Block => unreachable,
- Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(cunit),
+ Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(ofile),
Id.ArgTuple => unreachable,
- Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(cunit),
- Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(cunit),
+ Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(ofile),
+ Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(ofile),
}
}
@@ -76,7 +76,7 @@ pub const Type = struct {
std.debug.warn("{}", @tagName(base.id));
}
- pub fn getAbiAlignment(base: *Type, module: *Module) u32 {
+ pub fn getAbiAlignment(base: *Type, comp: *Compilation) u32 {
@panic("TODO getAbiAlignment");
}
@@ -84,11 +84,11 @@ pub const Type = struct {
base: Type,
decls: *Scope.Decls,
- pub fn destroy(self: *Struct, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Struct, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Struct, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Struct, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -104,12 +104,12 @@ pub const Type = struct {
typeof: *Type,
};
- pub fn create(module: *Module, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
- const result = try module.a().create(Fn{
+ pub fn create(comp: *Compilation, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
+ const result = try comp.a().create(Fn{
.base = Type{
.base = Value{
.id = Value.Id.Type,
- .typeof = &MetaType.get(module).base,
+ .typeof = &MetaType.get(comp).base,
.ref_count = std.atomic.Int(usize).init(1),
},
.id = builtin.TypeId.Fn,
@@ -118,7 +118,7 @@ pub const Type = struct {
.params = params,
.is_var_args = is_var_args,
});
- errdefer module.a().destroy(result);
+ errdefer comp.a().destroy(result);
result.return_type.base.ref();
for (result.params) |param| {
@@ -127,23 +127,23 @@ pub const Type = struct {
return result;
}
- pub fn destroy(self: *Fn, module: *Module) void {
- self.return_type.base.deref(module);
+ pub fn destroy(self: *Fn, comp: *Compilation) void {
+ self.return_type.base.deref(comp);
for (self.params) |param| {
- param.typeof.base.deref(module);
+ param.typeof.base.deref(comp);
}
- module.a().destroy(self);
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Fn, cunit: *CompilationUnit) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Fn, ofile: *ObjectFile) !llvm.TypeRef {
const llvm_return_type = switch (self.return_type.id) {
- Type.Id.Void => llvm.VoidTypeInContext(cunit.context) orelse return error.OutOfMemory,
- else => try self.return_type.getLlvmType(cunit),
+ Type.Id.Void => llvm.VoidTypeInContext(ofile.context) orelse return error.OutOfMemory,
+ else => try self.return_type.getLlvmType(ofile),
};
- const llvm_param_types = try cunit.a().alloc(llvm.TypeRef, self.params.len);
- defer cunit.a().free(llvm_param_types);
+ const llvm_param_types = try ofile.a().alloc(llvm.TypeRef, self.params.len);
+ defer ofile.a().free(llvm_param_types);
for (llvm_param_types) |*llvm_param_type, i| {
- llvm_param_type.* = try self.params[i].typeof.getLlvmType(cunit);
+ llvm_param_type.* = try self.params[i].typeof.getLlvmType(ofile);
}
return llvm.FunctionType(
@@ -160,13 +160,13 @@ pub const Type = struct {
value: *Type,
/// Adds 1 reference to the resulting type
- pub fn get(module: *Module) *MetaType {
- module.meta_type.base.base.ref();
- return module.meta_type;
+ pub fn get(comp: *Compilation) *MetaType {
+ comp.meta_type.base.base.ref();
+ return comp.meta_type;
}
- pub fn destroy(self: *MetaType, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *MetaType, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -174,13 +174,13 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
- pub fn get(module: *Module) *Void {
- module.void_type.base.base.ref();
- return module.void_type;
+ pub fn get(comp: *Compilation) *Void {
+ comp.void_type.base.base.ref();
+ return comp.void_type;
}
- pub fn destroy(self: *Void, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Void, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -188,16 +188,16 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
- pub fn get(module: *Module) *Bool {
- module.bool_type.base.base.ref();
- return module.bool_type;
+ pub fn get(comp: *Compilation) *Bool {
+ comp.bool_type.base.base.ref();
+ return comp.bool_type;
}
- pub fn destroy(self: *Bool, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Bool, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Bool, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Bool, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -206,24 +206,24 @@ pub const Type = struct {
base: Type,
/// Adds 1 reference to the resulting type
- pub fn get(module: *Module) *NoReturn {
- module.noreturn_type.base.base.ref();
- return module.noreturn_type;
+ pub fn get(comp: *Compilation) *NoReturn {
+ comp.noreturn_type.base.base.ref();
+ return comp.noreturn_type;
}
- pub fn destroy(self: *NoReturn, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *NoReturn, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Int = struct {
base: Type,
- pub fn destroy(self: *Int, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Int, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Int, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Int, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -231,11 +231,11 @@ pub const Type = struct {
pub const Float = struct {
base: Type,
- pub fn destroy(self: *Float, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Float, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Float, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Float, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -256,12 +256,12 @@ pub const Type = struct {
};
pub const Size = builtin.TypeInfo.Pointer.Size;
- pub fn destroy(self: *Pointer, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Pointer, comp: *Compilation) void {
+ comp.a().destroy(self);
}
pub fn get(
- module: *Module,
+ comp: *Compilation,
elem_type: *Type,
mut: Mut,
vol: Vol,
@@ -271,7 +271,7 @@ pub const Type = struct {
@panic("TODO get pointer");
}
- pub fn getLlvmType(self: *Pointer, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Pointer, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -279,11 +279,11 @@ pub const Type = struct {
pub const Array = struct {
base: Type,
- pub fn destroy(self: *Array, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Array, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Array, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Array, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -291,43 +291,43 @@ pub const Type = struct {
pub const ComptimeFloat = struct {
base: Type,
- pub fn destroy(self: *ComptimeFloat, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *ComptimeFloat, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const ComptimeInt = struct {
base: Type,
- pub fn destroy(self: *ComptimeInt, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *ComptimeInt, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Undefined = struct {
base: Type,
- pub fn destroy(self: *Undefined, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Undefined, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Null = struct {
base: Type,
- pub fn destroy(self: *Null, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Null, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Optional = struct {
base: Type,
- pub fn destroy(self: *Optional, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Optional, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Optional, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Optional, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -335,11 +335,11 @@ pub const Type = struct {
pub const ErrorUnion = struct {
base: Type,
- pub fn destroy(self: *ErrorUnion, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *ErrorUnion, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *ErrorUnion, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorUnion, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -347,11 +347,11 @@ pub const Type = struct {
pub const ErrorSet = struct {
base: Type,
- pub fn destroy(self: *ErrorSet, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *ErrorSet, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *ErrorSet, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorSet, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -359,11 +359,11 @@ pub const Type = struct {
pub const Enum = struct {
base: Type,
- pub fn destroy(self: *Enum, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Enum, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Enum, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Enum, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -371,11 +371,11 @@ pub const Type = struct {
pub const Union = struct {
base: Type,
- pub fn destroy(self: *Union, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Union, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Union, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Union, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -383,27 +383,27 @@ pub const Type = struct {
pub const Namespace = struct {
base: Type,
- pub fn destroy(self: *Namespace, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Namespace, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Block = struct {
base: Type,
- pub fn destroy(self: *Block, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Block, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const BoundFn = struct {
base: Type,
- pub fn destroy(self: *BoundFn, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *BoundFn, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *BoundFn, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *BoundFn, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -411,19 +411,19 @@ pub const Type = struct {
pub const ArgTuple = struct {
base: Type,
- pub fn destroy(self: *ArgTuple, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *ArgTuple, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const Opaque = struct {
base: Type,
- pub fn destroy(self: *Opaque, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Opaque, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Opaque, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Opaque, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
@@ -431,11 +431,11 @@ pub const Type = struct {
pub const Promise = struct {
base: Type,
- pub fn destroy(self: *Promise, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Promise, comp: *Compilation) void {
+ comp.a().destroy(self);
}
- pub fn getLlvmType(self: *Promise, cunit: *CompilationUnit) llvm.TypeRef {
+ pub fn getLlvmType(self: *Promise, ofile: *ObjectFile) llvm.TypeRef {
@panic("TODO");
}
};
diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const builtin = @import("builtin");
const Scope = @import("scope.zig").Scope;
-const Module = @import("module.zig").Module;
+const Compilation = @import("compilation.zig").Compilation;
/// Values are ref-counted, heap-allocated, and copy-on-write
/// If there is only 1 ref then write need not copy
@@ -16,16 +16,16 @@ pub const Value = struct {
}
/// Thread-safe
- pub fn deref(base: *Value, module: *Module) void {
+ pub fn deref(base: *Value, comp: *Compilation) void {
if (base.ref_count.decr() == 1) {
- base.typeof.base.deref(module);
+ base.typeof.base.deref(comp);
switch (base.id) {
- Id.Type => @fieldParentPtr(Type, "base", base).destroy(module),
- Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
- Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
- Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
- Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
- Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(module),
+ Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
+ Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
+ Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
+ Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
+ Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
+ Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
}
}
}
@@ -68,8 +68,8 @@ pub const Value = struct {
/// Creates a Fn value with 1 ref
/// Takes ownership of symbol_name
- pub fn create(module: *Module, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
- const self = try module.a().create(Fn{
+ pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
+ const self = try comp.a().create(Fn{
.base = Value{
.id = Value.Id.Fn,
.typeof = &fn_type.base,
@@ -86,23 +86,23 @@ pub const Value = struct {
return self;
}
- pub fn destroy(self: *Fn, module: *Module) void {
- self.fndef_scope.base.deref(module);
+ pub fn destroy(self: *Fn, comp: *Compilation) void {
+ self.fndef_scope.base.deref(comp);
self.symbol_name.deinit();
- module.a().destroy(self);
+ comp.a().destroy(self);
}
};
pub const Void = struct {
base: Value,
- pub fn get(module: *Module) *Void {
- module.void_value.base.ref();
- return module.void_value;
+ pub fn get(comp: *Compilation) *Void {
+ comp.void_value.base.ref();
+ return comp.void_value;
}
- pub fn destroy(self: *Void, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Void, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -110,31 +110,31 @@ pub const Value = struct {
base: Value,
x: bool,
- pub fn get(module: *Module, x: bool) *Bool {
+ pub fn get(comp: *Compilation, x: bool) *Bool {
if (x) {
- module.true_value.base.ref();
- return module.true_value;
+ comp.true_value.base.ref();
+ return comp.true_value;
} else {
- module.false_value.base.ref();
- return module.false_value;
+ comp.false_value.base.ref();
+ return comp.false_value;
}
}
- pub fn destroy(self: *Bool, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Bool, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
pub const NoReturn = struct {
base: Value,
- pub fn get(module: *Module) *NoReturn {
- module.noreturn_value.base.ref();
- return module.noreturn_value;
+ pub fn get(comp: *Compilation) *NoReturn {
+ comp.noreturn_value.base.ref();
+ return comp.noreturn_value;
}
- pub fn destroy(self: *NoReturn, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *NoReturn, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
@@ -147,8 +147,8 @@ pub const Value = struct {
RunTime,
};
- pub fn destroy(self: *Ptr, module: *Module) void {
- module.a().destroy(self);
+ pub fn destroy(self: *Ptr, comp: *Compilation) void {
+ comp.a().destroy(self);
}
};
};