diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2018-07-14 18:27:51 -0400 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-07-14 18:27:51 -0400 |
| commit | 4d920cee6e8be2f2ae2cfd9067358c65b977568a (patch) | |
| tree | 2c04de6151b7448dec9958d0a91234ea0ba9a15d /src-self-hosted/module.zig | |
| parent | da3acacc14331a6be33445c3bfd204e2cccabddd (diff) | |
| parent | 28c3d4809bc6d497ac81892bc7eb03b95d8c2b32 (diff) | |
| download | zig-4d920cee6e8be2f2ae2cfd9067358c65b977568a.tar.gz zig-4d920cee6e8be2f2ae2cfd9067358c65b977568a.zip | |
Merge remote-tracking branch 'origin/master' into llvm7
Diffstat (limited to 'src-self-hosted/module.zig')
| -rw-r--r-- | src-self-hosted/module.zig | 579 |
1 files changed, 0 insertions, 579 deletions
diff --git a/src-self-hosted/module.zig b/src-self-hosted/module.zig deleted file mode 100644 index 5ce1a7965a..0000000000 --- a/src-self-hosted/module.zig +++ /dev/null @@ -1,579 +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; - -pub const Module = struct { - loop: *event.Loop, - name: Buffer, - root_src_path: ?[]const u8, - module: llvm.ModuleRef, - context: llvm.ContextRef, - builder: llvm.BuilderRef, - 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), - - // 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, - }; - - pub const Event = union(enum) { - Ok, - Fail: []errmsg.Msg, - Error: BuildError, - }; - - 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( - loop: *event.Loop, - 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 { - var name_buffer = try Buffer.init(loop.allocator, name); - errdefer name_buffer.deinit(); - - const context = c.LLVMContextCreate() orelse return error.OutOfMemory; - errdefer c.LLVMContextDispose(context); - - const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) orelse return error.OutOfMemory; - errdefer c.LLVMDisposeModule(module); - - const builder = c.LLVMCreateBuilderInContext(context) orelse return error.OutOfMemory; - errdefer c.LLVMDisposeBuilder(builder); - - const events = try event.Channel(Event).create(loop, 0); - errdefer events.destroy(); - - return loop.allocator.create(Module{ - .loop = loop, - .events = events, - .name = name_buffer, - .root_src_path = root_src_path, - .module = module, - .context = context, - .builder = builder, - .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)), - }); - } - - fn dump(self: *Module) void { - c.LLVMDumpModule(self.module); - } - - pub fn destroy(self: *Module) void { - self.events.destroy(); - c.LLVMDisposeBuilder(self.builder); - c.LLVMDisposeModule(self.module); - c.LLVMContextDispose(self.context); - 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 - (await (async self.addRootSrc() catch unreachable)) catch |err| { - await (async self.events.put(Event{ .Error = err }) catch unreachable); - return; - }; - await (async self.events.put(Event.Ok) 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); - - var parsed_file = ParsedFile{ - .tree = try std.zig.parse(self.a(), source_code), - .realpath = root_src_real_path, - }; - errdefer parsed_file.tree.deinit(); - - const tree = &parsed_file.tree; - - // create empty struct for it - const decls = try Scope.Decls.create(self.a(), null); - errdefer decls.destroy(); - - 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 { - @panic("TODO add compile error"); - //try self.addCompileError( - // &parsed_file, - // fn_proto.fn_token, - // 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 = Decl.Resolution.Unresolved, - }, - .value = Decl.Fn.Val{ .Unresolved = {} }, - .fn_proto = fn_proto, - }); - errdefer self.a().destroy(fn_decl); - - // TODO make this parallel - try await try async self.addTopLevelDecl(tree, &fn_decl.base); - }, - ast.Node.Id.TestDecl => @panic("TODO"), - else => unreachable, - } - } - } - - async fn addTopLevelDecl(self: *Module, tree: *ast.Tree, decl: *Decl) !void { - const is_export = decl.isExported(tree); - - { - const exported_symbol_names = await try async self.exported_symbol_names.acquire(); - defer exported_symbol_names.release(); - - if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| { - @panic("TODO report compile error"); - } - } - } - - 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; - } -} - -pub const Scope = struct { - id: Id, - parent: ?*Scope, - - pub const Id = enum { - Decls, - Block, - }; - - pub const Decls = struct { - base: Scope, - table: Decl.Table, - - pub fn create(a: *Allocator, parent: ?*Scope) !*Decls { - const self = try a.create(Decls{ - .base = Scope{ - .id = Id.Decls, - .parent = parent, - }, - .table = undefined, - }); - errdefer a.destroy(self); - - self.table = Decl.Table.init(a); - errdefer self.table.deinit(); - - return self; - } - - pub fn destroy(self: *Decls) void { - self.table.deinit(); - self.table.allocator.destroy(self); - self.* = undefined; - } - }; - - pub const Block = struct { - base: Scope, - }; -}; - -pub const Visib = enum { - Private, - Pub, -}; - -pub const Decl = struct { - id: Id, - name: []const u8, - visib: Visib, - resolution: Resolution, - - pub const Table = std.HashMap([]const u8, *Decl, mem.hash_slice_u8, mem.eql_slice_u8); - - pub fn isExported(base: *const Decl, tree: *ast.Tree) bool { - switch (base.id) { - Id.Fn => { - const fn_decl = @fieldParentPtr(Fn, "base", base); - return fn_decl.isExported(tree); - }, - else => return false, - } - } - - pub const Resolution = enum { - Unresolved, - InProgress, - Invalid, - Ok, - }; - - pub const Id = enum { - Var, - Fn, - CompTime, - }; - - pub const Var = struct { - base: Decl, - }; - - pub const Fn = struct { - base: Decl, - value: Val, - fn_proto: *const ast.Node.FnProto, - - // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous - pub const Val = union { - Unresolved: void, - Ok: *Value.Fn, - }; - - pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 { - return if (self.fn_proto.extern_export_inline_token) |tok_index| x: { - const token = tree.tokens.at(tok_index); - break :x switch (token.id) { - Token.Id.Extern => tree.tokenSlicePtr(token), - else => null, - }; - } else null; - } - - pub fn isExported(self: Fn, tree: *ast.Tree) bool { - if (self.fn_proto.extern_export_inline_token) |tok_index| { - const token = tree.tokens.at(tok_index); - return token.id == Token.Id.Keyword_export; - } else { - return false; - } - } - }; - - pub const CompTime = struct { - base: Decl, - }; -}; - -pub const Value = struct { - pub const Fn = struct {}; -}; - -pub const Type = struct { - id: Id, - - pub const Id = enum { - Type, - Void, - Bool, - NoReturn, - Int, - Float, - Pointer, - Array, - Struct, - ComptimeFloat, - ComptimeInt, - Undefined, - Null, - Optional, - ErrorUnion, - ErrorSet, - Enum, - Union, - Fn, - Opaque, - Promise, - }; - - pub const Struct = struct { - base: Type, - decls: *Scope.Decls, - }; -}; - -pub const ParsedFile = struct { - tree: ast.Tree, - realpath: []const u8, -}; |
