authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-14 16:12:41-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-14 16:31:17-04:00
log28c3d4809bc6d497ac81892bc7eb03b95d8c2b32
tree1461827a130befdb2eb0938eb490588b350d845a
parent69e50ad2f54bc446b2258f464f9b09e78e132d45

rename Module to Compilation

and CompilationUnit to ObjectFile

10 files changed, 1070 insertions(+), 1072 deletions(-)

src-self-hosted/codegen.zig+20-22
...@@ -1,7 +1,5 @@...@@ -1,7 +1,5 @@
1const std = @import("std");1const std = @import("std");
2// TODO codegen pretends that Module is renamed to Build because I plan to2const Compilation = @import("compilation.zig").Compilation;
3// do that refactor at some point
4const Build = @import("module.zig").Module;
5// we go through llvm instead of c for 2 reasons:3// we go through llvm instead of c for 2 reasons:
6// 1. to avoid accidentally calling the non-thread-safe functions4// 1. to avoid accidentally calling the non-thread-safe functions
7// 2. patch up some of the types to remove nullability5// 2. patch up some of the types to remove nullability
...@@ -11,51 +9,51 @@ const Value = @import("value.zig").Value;...@@ -11,51 +9,51 @@ const Value = @import("value.zig").Value;
11const Type = @import("type.zig").Type;9const Type = @import("type.zig").Type;
12const event = std.event;10const event = std.event;
1311
14pub async fn renderToLlvm(build: *Build, fn_val: *Value.Fn, code: *ir.Code) !void {12pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
15 fn_val.base.ref();13 fn_val.base.ref();
16 defer fn_val.base.deref(build);14 defer fn_val.base.deref(comp);
17 defer code.destroy(build.a());15 defer code.destroy(comp.a());
1816
19 const llvm_handle = try build.event_loop_local.getAnyLlvmContext();17 const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
20 defer llvm_handle.release(build.event_loop_local);18 defer llvm_handle.release(comp.event_loop_local);
2119
22 const context = llvm_handle.node.data;20 const context = llvm_handle.node.data;
2321
24 const module = llvm.ModuleCreateWithNameInContext(build.name.ptr(), context) orelse return error.OutOfMemory;22 const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
25 defer llvm.DisposeModule(module);23 defer llvm.DisposeModule(module);
2624
27 const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;25 const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;
28 defer llvm.DisposeBuilder(builder);26 defer llvm.DisposeBuilder(builder);
2927
30 var cunit = CompilationUnit{28 var ofile = ObjectFile{
31 .build = build,29 .comp = comp,
32 .module = module,30 .module = module,
33 .builder = builder,31 .builder = builder,
34 .context = context,32 .context = context,
35 .lock = event.Lock.init(build.loop),33 .lock = event.Lock.init(comp.loop),
36 };34 };
3735
38 try renderToLlvmModule(&cunit, fn_val, code);36 try renderToLlvmModule(&ofile, fn_val, code);
3937
40 if (build.verbose_llvm_ir) {38 if (comp.verbose_llvm_ir) {
41 llvm.DumpModule(cunit.module);39 llvm.DumpModule(ofile.module);
42 }40 }
43}41}
4442
45pub const CompilationUnit = struct {43pub const ObjectFile = struct {
46 build: *Build,44 comp: *Compilation,
47 module: llvm.ModuleRef,45 module: llvm.ModuleRef,
48 builder: llvm.BuilderRef,46 builder: llvm.BuilderRef,
49 context: llvm.ContextRef,47 context: llvm.ContextRef,
50 lock: event.Lock,48 lock: event.Lock,
5149
52 fn a(self: *CompilationUnit) *std.mem.Allocator {50 fn a(self: *ObjectFile) *std.mem.Allocator {
53 return self.build.a();51 return self.comp.a();
54 }52 }
55};53};
5654
57pub fn renderToLlvmModule(cunit: *CompilationUnit, fn_val: *Value.Fn, code: *ir.Code) !void {55pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) !void {
58 // TODO audit more of codegen.cpp:fn_llvm_value and port more logic56 // TODO audit more of codegen.cpp:fn_llvm_value and port more logic
59 const llvm_fn_type = try fn_val.base.typeof.getLlvmType(cunit);57 const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);
60 const llvm_fn = llvm.AddFunction(cunit.module, fn_val.symbol_name.ptr(), llvm_fn_type);58 const llvm_fn = llvm.AddFunction(ofile.module, fn_val.symbol_name.ptr(), llvm_fn_type);
61}59}
src-self-hosted/compilation.zig created+747
...@@ -0,0 +1,747 @@
1const std = @import("std");
2const os = std.os;
3const io = std.io;
4const mem = std.mem;
5const Allocator = mem.Allocator;
6const Buffer = std.Buffer;
7const llvm = @import("llvm.zig");
8const c = @import("c.zig");
9const builtin = @import("builtin");
10const Target = @import("target.zig").Target;
11const warn = std.debug.warn;
12const Token = std.zig.Token;
13const ArrayList = std.ArrayList;
14const errmsg = @import("errmsg.zig");
15const ast = std.zig.ast;
16const event = std.event;
17const assert = std.debug.assert;
18const AtomicRmwOp = builtin.AtomicRmwOp;
19const AtomicOrder = builtin.AtomicOrder;
20const Scope = @import("scope.zig").Scope;
21const Decl = @import("decl.zig").Decl;
22const ir = @import("ir.zig");
23const Visib = @import("visib.zig").Visib;
24const ParsedFile = @import("parsed_file.zig").ParsedFile;
25const Value = @import("value.zig").Value;
26const Type = Value.Type;
27const Span = errmsg.Span;
28const codegen = @import("codegen.zig");
29
30/// Data that is local to the event loop.
31pub const EventLoopLocal = struct {
32 loop: *event.Loop,
33 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
34
35 fn init(loop: *event.Loop) EventLoopLocal {
36 return EventLoopLocal{
37 .loop = loop,
38 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
39 };
40 }
41
42 fn deinit(self: *EventLoopLocal) void {
43 while (self.llvm_handle_pool.pop()) |node| {
44 c.LLVMContextDispose(node.data);
45 self.loop.allocator.destroy(node);
46 }
47 }
48
49 /// Gets an exclusive handle on any LlvmContext.
50 /// Caller must release the handle when done.
51 pub fn getAnyLlvmContext(self: *EventLoopLocal) !LlvmHandle {
52 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
53
54 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
55 errdefer c.LLVMContextDispose(context_ref);
56
57 const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
58 .next = undefined,
59 .data = context_ref,
60 });
61 errdefer self.loop.allocator.destroy(node);
62
63 return LlvmHandle{ .node = node };
64 }
65};
66
67pub const LlvmHandle = struct {
68 node: *std.atomic.Stack(llvm.ContextRef).Node,
69
70 pub fn release(self: LlvmHandle, event_loop_local: *EventLoopLocal) void {
71 event_loop_local.llvm_handle_pool.push(self.node);
72 }
73};
74
75pub const Compilation = struct {
76 event_loop_local: *EventLoopLocal,
77 loop: *event.Loop,
78 name: Buffer,
79 root_src_path: ?[]const u8,
80 target: Target,
81 build_mode: builtin.Mode,
82 zig_lib_dir: []const u8,
83
84 version_major: u32,
85 version_minor: u32,
86 version_patch: u32,
87
88 linker_script: ?[]const u8,
89 cache_dir: []const u8,
90 libc_lib_dir: ?[]const u8,
91 libc_static_lib_dir: ?[]const u8,
92 libc_include_dir: ?[]const u8,
93 msvc_lib_dir: ?[]const u8,
94 kernel32_lib_dir: ?[]const u8,
95 dynamic_linker: ?[]const u8,
96 out_h_path: ?[]const u8,
97
98 is_test: bool,
99 each_lib_rpath: bool,
100 strip: bool,
101 is_static: bool,
102 linker_rdynamic: bool,
103
104 clang_argv: []const []const u8,
105 llvm_argv: []const []const u8,
106 lib_dirs: []const []const u8,
107 rpath_list: []const []const u8,
108 assembly_files: []const []const u8,
109 link_objects: []const []const u8,
110
111 windows_subsystem_windows: bool,
112 windows_subsystem_console: bool,
113
114 link_libs_list: ArrayList(*LinkLib),
115 libc_link_lib: ?*LinkLib,
116
117 err_color: errmsg.Color,
118
119 verbose_tokenize: bool,
120 verbose_ast_tree: bool,
121 verbose_ast_fmt: bool,
122 verbose_cimport: bool,
123 verbose_ir: bool,
124 verbose_llvm_ir: bool,
125 verbose_link: bool,
126
127 darwin_frameworks: []const []const u8,
128 darwin_version_min: DarwinVersionMin,
129
130 test_filters: []const []const u8,
131 test_name_prefix: ?[]const u8,
132
133 emit_file_type: Emit,
134
135 kind: Kind,
136
137 link_out_file: ?[]const u8,
138 events: *event.Channel(Event),
139
140 exported_symbol_names: event.Locked(Decl.Table),
141
142 /// Before code generation starts, must wait on this group to make sure
143 /// the build is complete.
144 build_group: event.Group(BuildError!void),
145
146 compile_errors: event.Locked(CompileErrList),
147
148 meta_type: *Type.MetaType,
149 void_type: *Type.Void,
150 bool_type: *Type.Bool,
151 noreturn_type: *Type.NoReturn,
152
153 void_value: *Value.Void,
154 true_value: *Value.Bool,
155 false_value: *Value.Bool,
156 noreturn_value: *Value.NoReturn,
157
158 const CompileErrList = std.ArrayList(*errmsg.Msg);
159
160 // TODO handle some of these earlier and report them in a way other than error codes
161 pub const BuildError = error{
162 OutOfMemory,
163 EndOfStream,
164 BadFd,
165 Io,
166 IsDir,
167 Unexpected,
168 SystemResources,
169 SharingViolation,
170 PathAlreadyExists,
171 FileNotFound,
172 AccessDenied,
173 PipeBusy,
174 FileTooBig,
175 SymLinkLoop,
176 ProcessFdQuotaExceeded,
177 NameTooLong,
178 SystemFdQuotaExceeded,
179 NoDevice,
180 PathNotFound,
181 NoSpaceLeft,
182 NotDir,
183 FileSystem,
184 OperationAborted,
185 IoPending,
186 BrokenPipe,
187 WouldBlock,
188 FileClosed,
189 DestinationAddressRequired,
190 DiskQuota,
191 InputOutput,
192 NoStdHandles,
193 Overflow,
194 NotSupported,
195 BufferTooSmall,
196 Unimplemented, // TODO remove this one
197 SemanticAnalysisFailed, // TODO remove this one
198 };
199
200 pub const Event = union(enum) {
201 Ok,
202 Error: BuildError,
203 Fail: []*errmsg.Msg,
204 };
205
206 pub const DarwinVersionMin = union(enum) {
207 None,
208 MacOS: []const u8,
209 Ios: []const u8,
210 };
211
212 pub const Kind = enum {
213 Exe,
214 Lib,
215 Obj,
216 };
217
218 pub const LinkLib = struct {
219 name: []const u8,
220 path: ?[]const u8,
221
222 /// the list of symbols we depend on from this lib
223 symbols: ArrayList([]u8),
224 provided_explicitly: bool,
225 };
226
227 pub const Emit = enum {
228 Binary,
229 Assembly,
230 LlvmIr,
231 };
232
233 pub fn create(
234 event_loop_local: *EventLoopLocal,
235 name: []const u8,
236 root_src_path: ?[]const u8,
237 target: *const Target,
238 kind: Kind,
239 build_mode: builtin.Mode,
240 zig_lib_dir: []const u8,
241 cache_dir: []const u8,
242 ) !*Compilation {
243 const loop = event_loop_local.loop;
244
245 var name_buffer = try Buffer.init(loop.allocator, name);
246 errdefer name_buffer.deinit();
247
248 const events = try event.Channel(Event).create(loop, 0);
249 errdefer events.destroy();
250
251 const comp = try loop.allocator.create(Compilation{
252 .loop = loop,
253 .event_loop_local = event_loop_local,
254 .events = events,
255 .name = name_buffer,
256 .root_src_path = root_src_path,
257 .target = target.*,
258 .kind = kind,
259 .build_mode = build_mode,
260 .zig_lib_dir = zig_lib_dir,
261 .cache_dir = cache_dir,
262
263 .version_major = 0,
264 .version_minor = 0,
265 .version_patch = 0,
266
267 .verbose_tokenize = false,
268 .verbose_ast_tree = false,
269 .verbose_ast_fmt = false,
270 .verbose_cimport = false,
271 .verbose_ir = false,
272 .verbose_llvm_ir = false,
273 .verbose_link = false,
274
275 .linker_script = null,
276 .libc_lib_dir = null,
277 .libc_static_lib_dir = null,
278 .libc_include_dir = null,
279 .msvc_lib_dir = null,
280 .kernel32_lib_dir = null,
281 .dynamic_linker = null,
282 .out_h_path = null,
283 .is_test = false,
284 .each_lib_rpath = false,
285 .strip = false,
286 .is_static = false,
287 .linker_rdynamic = false,
288 .clang_argv = [][]const u8{},
289 .llvm_argv = [][]const u8{},
290 .lib_dirs = [][]const u8{},
291 .rpath_list = [][]const u8{},
292 .assembly_files = [][]const u8{},
293 .link_objects = [][]const u8{},
294 .windows_subsystem_windows = false,
295 .windows_subsystem_console = false,
296 .link_libs_list = ArrayList(*LinkLib).init(loop.allocator),
297 .libc_link_lib = null,
298 .err_color = errmsg.Color.Auto,
299 .darwin_frameworks = [][]const u8{},
300 .darwin_version_min = DarwinVersionMin.None,
301 .test_filters = [][]const u8{},
302 .test_name_prefix = null,
303 .emit_file_type = Emit.Binary,
304 .link_out_file = null,
305 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
306 .build_group = event.Group(BuildError!void).init(loop),
307 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
308
309 .meta_type = undefined,
310 .void_type = undefined,
311 .void_value = undefined,
312 .bool_type = undefined,
313 .true_value = undefined,
314 .false_value = undefined,
315 .noreturn_type = undefined,
316 .noreturn_value = undefined,
317 });
318 try comp.initTypes();
319 return comp;
320 }
321
322 fn initTypes(comp: *Compilation) !void {
323 comp.meta_type = try comp.a().create(Type.MetaType{
324 .base = Type{
325 .base = Value{
326 .id = Value.Id.Type,
327 .typeof = undefined,
328 .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
329 },
330 .id = builtin.TypeId.Type,
331 },
332 .value = undefined,
333 });
334 comp.meta_type.value = &comp.meta_type.base;
335 comp.meta_type.base.base.typeof = &comp.meta_type.base;
336 errdefer comp.a().destroy(comp.meta_type);
337
338 comp.void_type = try comp.a().create(Type.Void{
339 .base = Type{
340 .base = Value{
341 .id = Value.Id.Type,
342 .typeof = &Type.MetaType.get(comp).base,
343 .ref_count = std.atomic.Int(usize).init(1),
344 },
345 .id = builtin.TypeId.Void,
346 },
347 });
348 errdefer comp.a().destroy(comp.void_type);
349
350 comp.noreturn_type = try comp.a().create(Type.NoReturn{
351 .base = Type{
352 .base = Value{
353 .id = Value.Id.Type,
354 .typeof = &Type.MetaType.get(comp).base,
355 .ref_count = std.atomic.Int(usize).init(1),
356 },
357 .id = builtin.TypeId.NoReturn,
358 },
359 });
360 errdefer comp.a().destroy(comp.noreturn_type);
361
362 comp.bool_type = try comp.a().create(Type.Bool{
363 .base = Type{
364 .base = Value{
365 .id = Value.Id.Type,
366 .typeof = &Type.MetaType.get(comp).base,
367 .ref_count = std.atomic.Int(usize).init(1),
368 },
369 .id = builtin.TypeId.Bool,
370 },
371 });
372 errdefer comp.a().destroy(comp.bool_type);
373
374 comp.void_value = try comp.a().create(Value.Void{
375 .base = Value{
376 .id = Value.Id.Void,
377 .typeof = &Type.Void.get(comp).base,
378 .ref_count = std.atomic.Int(usize).init(1),
379 },
380 });
381 errdefer comp.a().destroy(comp.void_value);
382
383 comp.true_value = try comp.a().create(Value.Bool{
384 .base = Value{
385 .id = Value.Id.Bool,
386 .typeof = &Type.Bool.get(comp).base,
387 .ref_count = std.atomic.Int(usize).init(1),
388 },
389 .x = true,
390 });
391 errdefer comp.a().destroy(comp.true_value);
392
393 comp.false_value = try comp.a().create(Value.Bool{
394 .base = Value{
395 .id = Value.Id.Bool,
396 .typeof = &Type.Bool.get(comp).base,
397 .ref_count = std.atomic.Int(usize).init(1),
398 },
399 .x = false,
400 });
401 errdefer comp.a().destroy(comp.false_value);
402
403 comp.noreturn_value = try comp.a().create(Value.NoReturn{
404 .base = Value{
405 .id = Value.Id.NoReturn,
406 .typeof = &Type.NoReturn.get(comp).base,
407 .ref_count = std.atomic.Int(usize).init(1),
408 },
409 });
410 errdefer comp.a().destroy(comp.noreturn_value);
411 }
412
413 pub fn destroy(self: *Compilation) void {
414 self.noreturn_value.base.deref(self);
415 self.void_value.base.deref(self);
416 self.false_value.base.deref(self);
417 self.true_value.base.deref(self);
418 self.noreturn_type.base.base.deref(self);
419 self.void_type.base.base.deref(self);
420 self.meta_type.base.base.deref(self);
421
422 self.events.destroy();
423 self.name.deinit();
424
425 self.a().destroy(self);
426 }
427
428 pub fn build(self: *Compilation) !void {
429 if (self.llvm_argv.len != 0) {
430 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.a(), [][]const []const u8{
431 [][]const u8{"zig (LLVM option parsing)"},
432 self.llvm_argv,
433 });
434 defer c_compatible_args.deinit();
435 // TODO this sets global state
436 c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
437 }
438
439 _ = try async<self.a()> self.buildAsync();
440 }
441
442 async fn buildAsync(self: *Compilation) void {
443 while (true) {
444 // TODO directly awaiting async should guarantee memory allocation elision
445 // TODO also async before suspending should guarantee memory allocation elision
446 const build_result = await (async self.addRootSrc() catch unreachable);
447
448 // this makes a handy error return trace and stack trace in debug mode
449 if (std.debug.runtime_safety) {
450 build_result catch unreachable;
451 }
452
453 const compile_errors = blk: {
454 const held = await (async self.compile_errors.acquire() catch unreachable);
455 defer held.release();
456 break :blk held.value.toOwnedSlice();
457 };
458
459 if (build_result) |_| {
460 if (compile_errors.len == 0) {
461 await (async self.events.put(Event.Ok) catch unreachable);
462 } else {
463 await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
464 }
465 } else |err| {
466 // if there's an error then the compile errors have dangling references
467 self.a().free(compile_errors);
468
469 await (async self.events.put(Event{ .Error = err }) catch unreachable);
470 }
471
472 // for now we stop after 1
473 return;
474 }
475 }
476
477 async fn addRootSrc(self: *Compilation) !void {
478 const root_src_path = self.root_src_path orelse @panic("TODO handle null root src path");
479 // TODO async/await os.path.real
480 const root_src_real_path = os.path.real(self.a(), root_src_path) catch |err| {
481 try printError("unable to get real path '{}': {}", root_src_path, err);
482 return err;
483 };
484 errdefer self.a().free(root_src_real_path);
485
486 // TODO async/await readFileAlloc()
487 const source_code = io.readFileAlloc(self.a(), root_src_real_path) catch |err| {
488 try printError("unable to open '{}': {}", root_src_real_path, err);
489 return err;
490 };
491 errdefer self.a().free(source_code);
492
493 const parsed_file = try self.a().create(ParsedFile{
494 .tree = undefined,
495 .realpath = root_src_real_path,
496 });
497 errdefer self.a().destroy(parsed_file);
498
499 parsed_file.tree = try std.zig.parse(self.a(), source_code);
500 errdefer parsed_file.tree.deinit();
501
502 const tree = &parsed_file.tree;
503
504 // create empty struct for it
505 const decls = try Scope.Decls.create(self, null);
506 defer decls.base.deref(self);
507
508 var decl_group = event.Group(BuildError!void).init(self.loop);
509 errdefer decl_group.cancelAll();
510
511 var it = tree.root_node.decls.iterator(0);
512 while (it.next()) |decl_ptr| {
513 const decl = decl_ptr.*;
514 switch (decl.id) {
515 ast.Node.Id.Comptime => @panic("TODO"),
516 ast.Node.Id.VarDecl => @panic("TODO"),
517 ast.Node.Id.FnProto => {
518 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
519
520 const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
521 try self.addCompileError(parsed_file, Span{
522 .first = fn_proto.fn_token,
523 .last = fn_proto.fn_token + 1,
524 }, "missing function name");
525 continue;
526 };
527
528 const fn_decl = try self.a().create(Decl.Fn{
529 .base = Decl{
530 .id = Decl.Id.Fn,
531 .name = name,
532 .visib = parseVisibToken(tree, fn_proto.visib_token),
533 .resolution = event.Future(BuildError!void).init(self.loop),
534 .resolution_in_progress = 0,
535 .parsed_file = parsed_file,
536 .parent_scope = &decls.base,
537 },
538 .value = Decl.Fn.Val{ .Unresolved = {} },
539 .fn_proto = fn_proto,
540 });
541 errdefer self.a().destroy(fn_decl);
542
543 try decl_group.call(addTopLevelDecl, self, &fn_decl.base);
544 },
545 ast.Node.Id.TestDecl => @panic("TODO"),
546 else => unreachable,
547 }
548 }
549 try await (async decl_group.wait() catch unreachable);
550 try await (async self.build_group.wait() catch unreachable);
551 }
552
553 async fn addTopLevelDecl(self: *Compilation, decl: *Decl) !void {
554 const is_export = decl.isExported(&decl.parsed_file.tree);
555
556 if (is_export) {
557 try self.build_group.call(verifyUniqueSymbol, self, decl);
558 try self.build_group.call(resolveDecl, self, decl);
559 }
560 }
561
562 fn addCompileError(self: *Compilation, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
563 const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
564 errdefer self.loop.allocator.free(text);
565
566 try self.build_group.call(addCompileErrorAsync, self, parsed_file, span, text);
567 }
568
569 async fn addCompileErrorAsync(
570 self: *Compilation,
571 parsed_file: *ParsedFile,
572 span: Span,
573 text: []u8,
574 ) !void {
575 const msg = try self.loop.allocator.create(errmsg.Msg{
576 .path = parsed_file.realpath,
577 .text = text,
578 .span = span,
579 .tree = &parsed_file.tree,
580 });
581 errdefer self.loop.allocator.destroy(msg);
582
583 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
584 defer compile_errors.release();
585
586 try compile_errors.value.append(msg);
587 }
588
589 async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void {
590 const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
591 defer exported_symbol_names.release();
592
593 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
594 try self.addCompileError(
595 decl.parsed_file,
596 decl.getSpan(),
597 "exported symbol collision: '{}'",
598 decl.name,
599 );
600 // TODO add error note showing location of other symbol
601 }
602 }
603
604 pub fn link(self: *Compilation, out_file: ?[]const u8) !void {
605 warn("TODO link");
606 return error.Todo;
607 }
608
609 pub fn addLinkLib(self: *Compilation, name: []const u8, provided_explicitly: bool) !*LinkLib {
610 const is_libc = mem.eql(u8, name, "c");
611
612 if (is_libc) {
613 if (self.libc_link_lib) |libc_link_lib| {
614 return libc_link_lib;
615 }
616 }
617
618 for (self.link_libs_list.toSliceConst()) |existing_lib| {
619 if (mem.eql(u8, name, existing_lib.name)) {
620 return existing_lib;
621 }
622 }
623
624 const link_lib = try self.a().create(LinkLib{
625 .name = name,
626 .path = null,
627 .provided_explicitly = provided_explicitly,
628 .symbols = ArrayList([]u8).init(self.a()),
629 });
630 try self.link_libs_list.append(link_lib);
631 if (is_libc) {
632 self.libc_link_lib = link_lib;
633 }
634 return link_lib;
635 }
636
637 fn a(self: Compilation) *mem.Allocator {
638 return self.loop.allocator;
639 }
640};
641
642fn printError(comptime format: []const u8, args: ...) !void {
643 var stderr_file = try std.io.getStdErr();
644 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
645 const out_stream = &stderr_file_out_stream.stream;
646 try out_stream.print(format, args);
647}
648
649fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib {
650 if (optional_token_index) |token_index| {
651 const token = tree.tokens.at(token_index);
652 assert(token.id == Token.Id.Keyword_pub);
653 return Visib.Pub;
654 } else {
655 return Visib.Private;
656 }
657}
658
659/// This declaration has been blessed as going into the final code generation.
660pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void {
661 if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
662 decl.resolution.data = await (async generateDecl(comp, decl) catch unreachable);
663 decl.resolution.resolve();
664 return decl.resolution.data;
665 } else {
666 return (await (async decl.resolution.get() catch unreachable)).*;
667 }
668}
669
670/// The function that actually does the generation.
671async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
672 switch (decl.id) {
673 Decl.Id.Var => @panic("TODO"),
674 Decl.Id.Fn => {
675 const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
676 return await (async generateDeclFn(comp, fn_decl) catch unreachable);
677 },
678 Decl.Id.CompTime => @panic("TODO"),
679 }
680}
681
682async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
683 const body_node = fn_decl.fn_proto.body_node orelse @panic("TODO extern fn proto decl");
684
685 const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);
686 defer fndef_scope.base.deref(comp);
687
688 // TODO actually look at the return type of the AST
689 const return_type = &Type.Void.get(comp).base;
690 defer return_type.base.deref(comp);
691
692 const is_var_args = false;
693 const params = ([*]Type.Fn.Param)(undefined)[0..0];
694 const fn_type = try Type.Fn.create(comp, return_type, params, is_var_args);
695 defer fn_type.base.base.deref(comp);
696
697 var symbol_name = try std.Buffer.init(comp.a(), fn_decl.base.name);
698 errdefer symbol_name.deinit();
699
700 const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
701 defer fn_val.base.deref(comp);
702
703 fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
704
705 const unanalyzed_code = (await (async ir.gen(
706 comp,
707 body_node,
708 &fndef_scope.base,
709 Span.token(body_node.lastToken()),
710 fn_decl.base.parsed_file,
711 ) catch unreachable)) catch |err| switch (err) {
712 // This poison value should not cause the errdefers to run. It simply means
713 // that self.compile_errors is populated.
714 // TODO https://github.com/ziglang/zig/issues/769
715 error.SemanticAnalysisFailed => return {},
716 else => return err,
717 };
718 defer unanalyzed_code.destroy(comp.a());
719
720 if (comp.verbose_ir) {
721 std.debug.warn("unanalyzed:\n");
722 unanalyzed_code.dump();
723 }
724
725 const analyzed_code = (await (async ir.analyze(
726 comp,
727 fn_decl.base.parsed_file,
728 unanalyzed_code,
729 null,
730 ) catch unreachable)) catch |err| switch (err) {
731 // This poison value should not cause the errdefers to run. It simply means
732 // that self.compile_errors is populated.
733 // TODO https://github.com/ziglang/zig/issues/769
734 error.SemanticAnalysisFailed => return {},
735 else => return err,
736 };
737 errdefer analyzed_code.destroy(comp.a());
738
739 if (comp.verbose_ir) {
740 std.debug.warn("analyzed:\n");
741 analyzed_code.dump();
742 }
743
744 // Kick off rendering to LLVM comp, but it doesn't block the fn decl
745 // analysis from being complete.
746 try comp.build_group.call(codegen.renderToLlvm, comp, fn_val, analyzed_code);
747}
src-self-hosted/decl.zig+2-2
...@@ -9,13 +9,13 @@ const Value = @import("value.zig").Value;...@@ -9,13 +9,13 @@ const Value = @import("value.zig").Value;
9const Token = std.zig.Token;9const Token = std.zig.Token;
10const errmsg = @import("errmsg.zig");10const errmsg = @import("errmsg.zig");
11const Scope = @import("scope.zig").Scope;11const Scope = @import("scope.zig").Scope;
12const Module = @import("module.zig").Module;12const Compilation = @import("compilation.zig").Compilation;
1313
14pub const Decl = struct {14pub const Decl = struct {
15 id: Id,15 id: Id,
16 name: []const u8,16 name: []const u8,
17 visib: Visib,17 visib: Visib,
18 resolution: event.Future(Module.BuildError!void),18 resolution: event.Future(Compilation.BuildError!void),
19 resolution_in_progress: u8,19 resolution_in_progress: u8,
20 parsed_file: *ParsedFile,20 parsed_file: *ParsedFile,
21 parent_scope: *Scope,21 parent_scope: *Scope,
src-self-hosted/ir.zig+28-28
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Module = @import("module.zig").Module;3const Compilation = @import("compilation.zig").Compilation;
4const Scope = @import("scope.zig").Scope;4const Scope = @import("scope.zig").Scope;
5const ast = std.zig.ast;5const ast = std.zig.ast;
6const Allocator = std.mem.Allocator;6const Allocator = std.mem.Allocator;
...@@ -243,7 +243,7 @@ pub const Instruction = struct {...@@ -243,7 +243,7 @@ pub const Instruction = struct {
243 Value.Ptr.Mut.CompTimeConst,243 Value.Ptr.Mut.CompTimeConst,
244 self.params.mut,244 self.params.mut,
245 self.params.volatility,245 self.params.volatility,
246 val.typeof.getAbiAlignment(ira.irb.module),246 val.typeof.getAbiAlignment(ira.irb.comp),
247 );247 );
248 }248 }
249249
...@@ -254,12 +254,12 @@ pub const Instruction = struct {...@@ -254,12 +254,12 @@ pub const Instruction = struct {
254 });254 });
255 const elem_type = target.getKnownType();255 const elem_type = target.getKnownType();
256 const ptr_type = Type.Pointer.get(256 const ptr_type = Type.Pointer.get(
257 ira.irb.module,257 ira.irb.comp,
258 elem_type,258 elem_type,
259 self.params.mut,259 self.params.mut,
260 self.params.volatility,260 self.params.volatility,
261 Type.Pointer.Size.One,261 Type.Pointer.Size.One,
262 elem_type.getAbiAlignment(ira.irb.module),262 elem_type.getAbiAlignment(ira.irb.comp),
263 );263 );
264 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this264 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this
265 // could be a ref of a global, for example265 // could be a ref of a global, for example
...@@ -417,7 +417,7 @@ pub const Code = struct {...@@ -417,7 +417,7 @@ pub const Code = struct {
417 arena: std.heap.ArenaAllocator,417 arena: std.heap.ArenaAllocator,
418 return_type: ?*Type,418 return_type: ?*Type,
419419
420 /// allocator is module.a()420 /// allocator is comp.a()
421 pub fn destroy(self: *Code, allocator: *Allocator) void {421 pub fn destroy(self: *Code, allocator: *Allocator) void {
422 self.arena.deinit();422 self.arena.deinit();
423 allocator.destroy(self);423 allocator.destroy(self);
...@@ -437,7 +437,7 @@ pub const Code = struct {...@@ -437,7 +437,7 @@ pub const Code = struct {
437};437};
438438
439pub const Builder = struct {439pub const Builder = struct {
440 module: *Module,440 comp: *Compilation,
441 code: *Code,441 code: *Code,
442 current_basic_block: *BasicBlock,442 current_basic_block: *BasicBlock,
443 next_debug_id: usize,443 next_debug_id: usize,
...@@ -446,17 +446,17 @@ pub const Builder = struct {...@@ -446,17 +446,17 @@ pub const Builder = struct {
446446
447 pub const Error = Analyze.Error;447 pub const Error = Analyze.Error;
448448
449 pub fn init(module: *Module, parsed_file: *ParsedFile) !Builder {449 pub fn init(comp: *Compilation, parsed_file: *ParsedFile) !Builder {
450 const code = try module.a().create(Code{450 const code = try comp.a().create(Code{
451 .basic_block_list = undefined,451 .basic_block_list = undefined,
452 .arena = std.heap.ArenaAllocator.init(module.a()),452 .arena = std.heap.ArenaAllocator.init(comp.a()),
453 .return_type = null,453 .return_type = null,
454 });454 });
455 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);455 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
456 errdefer code.destroy(module.a());456 errdefer code.destroy(comp.a());
457457
458 return Builder{458 return Builder{
459 .module = module,459 .comp = comp,
460 .parsed_file = parsed_file,460 .parsed_file = parsed_file,
461 .current_basic_block = undefined,461 .current_basic_block = undefined,
462 .code = code,462 .code = code,
...@@ -466,7 +466,7 @@ pub const Builder = struct {...@@ -466,7 +466,7 @@ pub const Builder = struct {
466 }466 }
467467
468 pub fn abort(self: *Builder) void {468 pub fn abort(self: *Builder) void {
469 self.code.destroy(self.module.a());469 self.code.destroy(self.comp.a());
470 }470 }
471471
472 /// Call code.destroy() when done472 /// Call code.destroy() when done
...@@ -581,7 +581,7 @@ pub const Builder = struct {...@@ -581,7 +581,7 @@ pub const Builder = struct {
581 }581 }
582582
583 pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Instruction {583 pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Instruction {
584 const block_scope = try Scope.Block.create(irb.module, parent_scope);584 const block_scope = try Scope.Block.create(irb.comp, parent_scope);
585585
586 const outer_block_scope = &block_scope.base;586 const outer_block_scope = &block_scope.base;
587 var child_scope = outer_block_scope;587 var child_scope = outer_block_scope;
...@@ -623,8 +623,8 @@ pub const Builder = struct {...@@ -623,8 +623,8 @@ pub const Builder = struct {
623 Token.Id.Keyword_errdefer => Scope.Defer.Kind.ErrorExit,623 Token.Id.Keyword_errdefer => Scope.Defer.Kind.ErrorExit,
624 else => unreachable,624 else => unreachable,
625 };625 };
626 const defer_expr_scope = try Scope.DeferExpr.create(irb.module, parent_scope, defer_node.expr);626 const defer_expr_scope = try Scope.DeferExpr.create(irb.comp, parent_scope, defer_node.expr);
627 const defer_child_scope = try Scope.Defer.create(irb.module, parent_scope, kind, defer_expr_scope);627 const defer_child_scope = try Scope.Defer.create(irb.comp, parent_scope, kind, defer_expr_scope);
628 child_scope = &defer_child_scope.base;628 child_scope = &defer_child_scope.base;
629 continue;629 continue;
630 }630 }
...@@ -770,8 +770,8 @@ pub const Builder = struct {...@@ -770,8 +770,8 @@ pub const Builder = struct {
770 .debug_id = self.next_debug_id,770 .debug_id = self.next_debug_id,
771 .val = switch (I.ir_val_init) {771 .val = switch (I.ir_val_init) {
772 IrVal.Init.Unknown => IrVal.Unknown,772 IrVal.Init.Unknown => IrVal.Unknown,
773 IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.module).base },773 IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
774 IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.module).base },774 IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
775 },775 },
776 .ref_count = 0,776 .ref_count = 0,
777 .span = span,777 .span = span,
...@@ -819,13 +819,13 @@ pub const Builder = struct {...@@ -819,13 +819,13 @@ pub const Builder = struct {
819819
820 fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Instruction {820 fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Instruction {
821 const inst = try self.build(Instruction.Const, scope, span, Instruction.Const.Params{});821 const inst = try self.build(Instruction.Const, scope, span, Instruction.Const.Params{});
822 inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.module, x).base };822 inst.val = IrVal{ .KnownValue = &Value.Bool.get(self.comp, x).base };
823 return inst;823 return inst;
824 }824 }
825825
826 fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Instruction {826 fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Instruction {
827 const inst = try self.buildExtra(Instruction.Const, scope, span, Instruction.Const.Params{}, is_generated);827 const inst = try self.buildExtra(Instruction.Const, scope, span, Instruction.Const.Params{}, is_generated);
828 inst.val = IrVal{ .KnownValue = &Value.Void.get(self.module).base };828 inst.val = IrVal{ .KnownValue = &Value.Void.get(self.comp).base };
829 return inst;829 return inst;
830 }830 }
831};831};
...@@ -850,8 +850,8 @@ const Analyze = struct {...@@ -850,8 +850,8 @@ const Analyze = struct {
850 OutOfMemory,850 OutOfMemory,
851 };851 };
852852
853 pub fn init(module: *Module, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {853 pub fn init(comp: *Compilation, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
854 var irb = try Builder.init(module, parsed_file);854 var irb = try Builder.init(comp, parsed_file);
855 errdefer irb.abort();855 errdefer irb.abort();
856856
857 return Analyze{857 return Analyze{
...@@ -929,12 +929,12 @@ const Analyze = struct {...@@ -929,12 +929,12 @@ const Analyze = struct {
929 }929 }
930930
931 fn addCompileError(self: *Analyze, span: Span, comptime fmt: []const u8, args: ...) !void {931 fn addCompileError(self: *Analyze, span: Span, comptime fmt: []const u8, args: ...) !void {
932 return self.irb.module.addCompileError(self.irb.parsed_file, span, fmt, args);932 return self.irb.comp.addCompileError(self.irb.parsed_file, span, fmt, args);
933 }933 }
934934
935 fn resolvePeerTypes(self: *Analyze, expected_type: ?*Type, peers: []const *Instruction) Analyze.Error!*Type {935 fn resolvePeerTypes(self: *Analyze, expected_type: ?*Type, peers: []const *Instruction) Analyze.Error!*Type {
936 // TODO actual implementation936 // TODO actual implementation
937 return &Type.Void.get(self.irb.module).base;937 return &Type.Void.get(self.irb.comp).base;
938 }938 }
939939
940 fn implicitCast(self: *Analyze, target: *Instruction, optional_dest_type: ?*Type) Analyze.Error!*Instruction {940 fn implicitCast(self: *Analyze, target: *Instruction, optional_dest_type: ?*Type) Analyze.Error!*Instruction {
...@@ -959,13 +959,13 @@ const Analyze = struct {...@@ -959,13 +959,13 @@ const Analyze = struct {
959};959};
960960
961pub async fn gen(961pub async fn gen(
962 module: *Module,962 comp: *Compilation,
963 body_node: *ast.Node,963 body_node: *ast.Node,
964 scope: *Scope,964 scope: *Scope,
965 end_span: Span,965 end_span: Span,
966 parsed_file: *ParsedFile,966 parsed_file: *ParsedFile,
967) !*Code {967) !*Code {
968 var irb = try Builder.init(module, parsed_file);968 var irb = try Builder.init(comp, parsed_file);
969 errdefer irb.abort();969 errdefer irb.abort();
970970
971 const entry_block = try irb.createBasicBlock(scope, "Entry");971 const entry_block = try irb.createBasicBlock(scope, "Entry");
...@@ -991,8 +991,8 @@ pub async fn gen(...@@ -991,8 +991,8 @@ pub async fn gen(
991 return irb.finish();991 return irb.finish();
992}992}
993993
994pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {994pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
995 var ira = try Analyze.init(module, parsed_file, expected_type);995 var ira = try Analyze.init(comp, parsed_file, expected_type);
996 errdefer ira.abort();996 errdefer ira.abort();
997997
998 const old_entry_bb = old_code.basic_block_list.at(0);998 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,...@@ -1025,7 +1025,7 @@ pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code,
1025 }1025 }
10261026
1027 if (ira.src_implicit_return_type_list.len == 0) {1027 if (ira.src_implicit_return_type_list.len == 0) {
1028 ira.irb.code.return_type = &Type.NoReturn.get(module).base;1028 ira.irb.code.return_type = &Type.NoReturn.get(comp).base;
1029 return ira.irb.finish();1029 return ira.irb.finish();
1030 }1030 }
10311031
src-self-hosted/main.zig+57-57
...@@ -14,8 +14,8 @@ const c = @import("c.zig");...@@ -14,8 +14,8 @@ const c = @import("c.zig");
14const introspect = @import("introspect.zig");14const introspect = @import("introspect.zig");
15const Args = arg.Args;15const Args = arg.Args;
16const Flag = arg.Flag;16const Flag = arg.Flag;
17const EventLoopLocal = @import("module.zig").EventLoopLocal;17const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
18const Module = @import("module.zig").Module;18const Compilation = @import("compilation.zig").Compilation;
19const Target = @import("target.zig").Target;19const Target = @import("target.zig").Target;
20const errmsg = @import("errmsg.zig");20const errmsg = @import("errmsg.zig");
2121
...@@ -258,7 +258,7 @@ const args_build_generic = []Flag{...@@ -258,7 +258,7 @@ const args_build_generic = []Flag{
258 Flag.Arg1("--ver-patch"),258 Flag.Arg1("--ver-patch"),
259};259};
260260
261fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Module.Kind) !void {261fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
262 var flags = try Args.parse(allocator, args_build_generic, args);262 var flags = try Args.parse(allocator, args_build_generic, args);
263 defer flags.deinit();263 defer flags.deinit();
264264
...@@ -300,14 +300,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo...@@ -300,14 +300,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
300 const emit_type = blk: {300 const emit_type = blk: {
301 if (flags.single("emit")) |emit_flag| {301 if (flags.single("emit")) |emit_flag| {
302 if (mem.eql(u8, emit_flag, "asm")) {302 if (mem.eql(u8, emit_flag, "asm")) {
303 break :blk Module.Emit.Assembly;303 break :blk Compilation.Emit.Assembly;
304 } else if (mem.eql(u8, emit_flag, "bin")) {304 } else if (mem.eql(u8, emit_flag, "bin")) {
305 break :blk Module.Emit.Binary;305 break :blk Compilation.Emit.Binary;
306 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {306 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {
307 break :blk Module.Emit.LlvmIr;307 break :blk Compilation.Emit.LlvmIr;
308 } else unreachable;308 } else unreachable;
309 } else {309 } else {
310 break :blk Module.Emit.Binary;310 break :blk Compilation.Emit.Binary;
311 }311 }
312 };312 };
313313
...@@ -370,7 +370,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo...@@ -370,7 +370,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
370 os.exit(1);370 os.exit(1);
371 }371 }
372372
373 if (out_type == Module.Kind.Obj and link_objects.len != 0) {373 if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
374 try stderr.write("When building an object file, --object arguments are invalid\n");374 try stderr.write("When building an object file, --object arguments are invalid\n");
375 os.exit(1);375 os.exit(1);
376 }376 }
...@@ -392,7 +392,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo...@@ -392,7 +392,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
392 var event_loop_local = EventLoopLocal.init(&loop);392 var event_loop_local = EventLoopLocal.init(&loop);
393 defer event_loop_local.deinit();393 defer event_loop_local.deinit();
394394
395 var module = try Module.create(395 var comp = try Compilation.create(
396 &event_loop_local,396 &event_loop_local,
397 root_name,397 root_name,
398 root_source_file,398 root_source_file,
...@@ -402,16 +402,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo...@@ -402,16 +402,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
402 zig_lib_dir,402 zig_lib_dir,
403 full_cache_dir,403 full_cache_dir,
404 );404 );
405 defer module.destroy();405 defer comp.destroy();
406406
407 module.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);407 comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
408 module.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);408 comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
409 module.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);409 comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
410410
411 module.is_test = false;411 comp.is_test = false;
412412
413 module.linker_script = flags.single("linker-script");413 comp.linker_script = flags.single("linker-script");
414 module.each_lib_rpath = flags.present("each-lib-rpath");414 comp.each_lib_rpath = flags.present("each-lib-rpath");
415415
416 var clang_argv_buf = ArrayList([]const u8).init(allocator);416 var clang_argv_buf = ArrayList([]const u8).init(allocator);
417 defer clang_argv_buf.deinit();417 defer clang_argv_buf.deinit();
...@@ -422,51 +422,51 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo...@@ -422,51 +422,51 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
422 try clang_argv_buf.append(mllvm);422 try clang_argv_buf.append(mllvm);
423 }423 }
424424
425 module.llvm_argv = mllvm_flags;425 comp.llvm_argv = mllvm_flags;
426 module.clang_argv = clang_argv_buf.toSliceConst();426 comp.clang_argv = clang_argv_buf.toSliceConst();
427427
428 module.strip = flags.present("strip");428 comp.strip = flags.present("strip");
429 module.is_static = flags.present("static");429 comp.is_static = flags.present("static");
430430
431 if (flags.single("libc-lib-dir")) |libc_lib_dir| {431 if (flags.single("libc-lib-dir")) |libc_lib_dir| {
432 module.libc_lib_dir = libc_lib_dir;432 comp.libc_lib_dir = libc_lib_dir;
433 }433 }
434 if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| {434 if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| {
435 module.libc_static_lib_dir = libc_static_lib_dir;435 comp.libc_static_lib_dir = libc_static_lib_dir;
436 }436 }
437 if (flags.single("libc-include-dir")) |libc_include_dir| {437 if (flags.single("libc-include-dir")) |libc_include_dir| {
438 module.libc_include_dir = libc_include_dir;438 comp.libc_include_dir = libc_include_dir;
439 }439 }
440 if (flags.single("msvc-lib-dir")) |msvc_lib_dir| {440 if (flags.single("msvc-lib-dir")) |msvc_lib_dir| {
441 module.msvc_lib_dir = msvc_lib_dir;441 comp.msvc_lib_dir = msvc_lib_dir;
442 }442 }
443 if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| {443 if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| {
444 module.kernel32_lib_dir = kernel32_lib_dir;444 comp.kernel32_lib_dir = kernel32_lib_dir;
445 }445 }
446 if (flags.single("dynamic-linker")) |dynamic_linker| {446 if (flags.single("dynamic-linker")) |dynamic_linker| {
447 module.dynamic_linker = dynamic_linker;447 comp.dynamic_linker = dynamic_linker;
448 }448 }
449449
450 module.verbose_tokenize = flags.present("verbose-tokenize");450 comp.verbose_tokenize = flags.present("verbose-tokenize");
451 module.verbose_ast_tree = flags.present("verbose-ast-tree");451 comp.verbose_ast_tree = flags.present("verbose-ast-tree");
452 module.verbose_ast_fmt = flags.present("verbose-ast-fmt");452 comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
453 module.verbose_link = flags.present("verbose-link");453 comp.verbose_link = flags.present("verbose-link");
454 module.verbose_ir = flags.present("verbose-ir");454 comp.verbose_ir = flags.present("verbose-ir");
455 module.verbose_llvm_ir = flags.present("verbose-llvm-ir");455 comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
456 module.verbose_cimport = flags.present("verbose-cimport");456 comp.verbose_cimport = flags.present("verbose-cimport");
457457
458 module.err_color = color;458 comp.err_color = color;
459 module.lib_dirs = flags.many("library-path");459 comp.lib_dirs = flags.many("library-path");
460 module.darwin_frameworks = flags.many("framework");460 comp.darwin_frameworks = flags.many("framework");
461 module.rpath_list = flags.many("rpath");461 comp.rpath_list = flags.many("rpath");
462462
463 if (flags.single("output-h")) |output_h| {463 if (flags.single("output-h")) |output_h| {
464 module.out_h_path = output_h;464 comp.out_h_path = output_h;
465 }465 }
466466
467 module.windows_subsystem_windows = flags.present("mwindows");467 comp.windows_subsystem_windows = flags.present("mwindows");
468 module.windows_subsystem_console = flags.present("mconsole");468 comp.windows_subsystem_console = flags.present("mconsole");
469 module.linker_rdynamic = flags.present("rdynamic");469 comp.linker_rdynamic = flags.present("rdynamic");
470470
471 if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {471 if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {
472 try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");472 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...@@ -474,37 +474,37 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
474 }474 }
475475
476 if (flags.single("mmacosx-version-min")) |ver| {476 if (flags.single("mmacosx-version-min")) |ver| {
477 module.darwin_version_min = Module.DarwinVersionMin{ .MacOS = ver };477 comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
478 }478 }
479 if (flags.single("mios-version-min")) |ver| {479 if (flags.single("mios-version-min")) |ver| {
480 module.darwin_version_min = Module.DarwinVersionMin{ .Ios = ver };480 comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
481 }481 }
482482
483 module.emit_file_type = emit_type;483 comp.emit_file_type = emit_type;
484 module.link_objects = link_objects;484 comp.link_objects = link_objects;
485 module.assembly_files = assembly_files;485 comp.assembly_files = assembly_files;
486 module.link_out_file = flags.single("out-file");486 comp.link_out_file = flags.single("out-file");
487487
488 try module.build();488 try comp.build();
489 const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color);489 const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
490 defer cancel process_build_events_handle;490 defer cancel process_build_events_handle;
491 loop.run();491 loop.run();
492}492}
493493
494async fn processBuildEvents(module: *Module, color: errmsg.Color) void {494async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
495 // TODO directly awaiting async should guarantee memory allocation elision495 // TODO directly awaiting async should guarantee memory allocation elision
496 const build_event = await (async module.events.get() catch unreachable);496 const build_event = await (async comp.events.get() catch unreachable);
497497
498 switch (build_event) {498 switch (build_event) {
499 Module.Event.Ok => {499 Compilation.Event.Ok => {
500 std.debug.warn("Build succeeded\n");500 std.debug.warn("Build succeeded\n");
501 return;501 return;
502 },502 },
503 Module.Event.Error => |err| {503 Compilation.Event.Error => |err| {
504 std.debug.warn("build failed: {}\n", @errorName(err));504 std.debug.warn("build failed: {}\n", @errorName(err));
505 os.exit(1);505 os.exit(1);
506 },506 },
507 Module.Event.Fail => |msgs| {507 Compilation.Event.Fail => |msgs| {
508 for (msgs) |msg| {508 for (msgs) |msg| {
509 errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);509 errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);
510 }510 }
...@@ -513,15 +513,15 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {...@@ -513,15 +513,15 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
513}513}
514514
515fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {515fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {
516 return buildOutputType(allocator, args, Module.Kind.Exe);516 return buildOutputType(allocator, args, Compilation.Kind.Exe);
517}517}
518518
519fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {519fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {
520 return buildOutputType(allocator, args, Module.Kind.Lib);520 return buildOutputType(allocator, args, Compilation.Kind.Lib);
521}521}
522522
523fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {523fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
524 return buildOutputType(allocator, args, Module.Kind.Obj);524 return buildOutputType(allocator, args, Compilation.Kind.Obj);
525}525}
526526
527const usage_fmt =527const usage_fmt =
src-self-hosted/module.zig deleted-747
...@@ -1,747 +0,0 @@
1const std = @import("std");
2const os = std.os;
3const io = std.io;
4const mem = std.mem;
5const Allocator = mem.Allocator;
6const Buffer = std.Buffer;
7const llvm = @import("llvm.zig");
8const c = @import("c.zig");
9const builtin = @import("builtin");
10const Target = @import("target.zig").Target;
11const warn = std.debug.warn;
12const Token = std.zig.Token;
13const ArrayList = std.ArrayList;
14const errmsg = @import("errmsg.zig");
15const ast = std.zig.ast;
16const event = std.event;
17const assert = std.debug.assert;
18const AtomicRmwOp = builtin.AtomicRmwOp;
19const AtomicOrder = builtin.AtomicOrder;
20const Scope = @import("scope.zig").Scope;
21const Decl = @import("decl.zig").Decl;
22const ir = @import("ir.zig");
23const Visib = @import("visib.zig").Visib;
24const ParsedFile = @import("parsed_file.zig").ParsedFile;
25const Value = @import("value.zig").Value;
26const Type = Value.Type;
27const Span = errmsg.Span;
28const codegen = @import("codegen.zig");
29
30/// Data that is local to the event loop.
31pub const EventLoopLocal = struct {
32 loop: *event.Loop,
33 llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
34
35 fn init(loop: *event.Loop) EventLoopLocal {
36 return EventLoopLocal{
37 .loop = loop,
38 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
39 };
40 }
41
42 fn deinit(self: *EventLoopLocal) void {
43 while (self.llvm_handle_pool.pop()) |node| {
44 c.LLVMContextDispose(node.data);
45 self.loop.allocator.destroy(node);
46 }
47 }
48
49 /// Gets an exclusive handle on any LlvmContext.
50 /// Caller must release the handle when done.
51 pub fn getAnyLlvmContext(self: *EventLoopLocal) !LlvmHandle {
52 if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
53
54 const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
55 errdefer c.LLVMContextDispose(context_ref);
56
57 const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node{
58 .next = undefined,
59 .data = context_ref,
60 });
61 errdefer self.loop.allocator.destroy(node);
62
63 return LlvmHandle{ .node = node };
64 }
65};
66
67pub const LlvmHandle = struct {
68 node: *std.atomic.Stack(llvm.ContextRef).Node,
69
70 pub fn release(self: LlvmHandle, event_loop_local: *EventLoopLocal) void {
71 event_loop_local.llvm_handle_pool.push(self.node);
72 }
73};
74
75pub const Module = struct {
76 event_loop_local: *EventLoopLocal,
77 loop: *event.Loop,
78 name: Buffer,
79 root_src_path: ?[]const u8,
80 target: Target,
81 build_mode: builtin.Mode,
82 zig_lib_dir: []const u8,
83
84 version_major: u32,
85 version_minor: u32,
86 version_patch: u32,
87
88 linker_script: ?[]const u8,
89 cache_dir: []const u8,
90 libc_lib_dir: ?[]const u8,
91 libc_static_lib_dir: ?[]const u8,
92 libc_include_dir: ?[]const u8,
93 msvc_lib_dir: ?[]const u8,
94 kernel32_lib_dir: ?[]const u8,
95 dynamic_linker: ?[]const u8,
96 out_h_path: ?[]const u8,
97
98 is_test: bool,
99 each_lib_rpath: bool,
100 strip: bool,
101 is_static: bool,
102 linker_rdynamic: bool,
103
104 clang_argv: []const []const u8,
105 llvm_argv: []const []const u8,
106 lib_dirs: []const []const u8,
107 rpath_list: []const []const u8,
108 assembly_files: []const []const u8,
109 link_objects: []const []const u8,
110
111 windows_subsystem_windows: bool,
112 windows_subsystem_console: bool,
113
114 link_libs_list: ArrayList(*LinkLib),
115 libc_link_lib: ?*LinkLib,
116
117 err_color: errmsg.Color,
118
119 verbose_tokenize: bool,
120 verbose_ast_tree: bool,
121 verbose_ast_fmt: bool,
122 verbose_cimport: bool,
123 verbose_ir: bool,
124 verbose_llvm_ir: bool,
125 verbose_link: bool,
126
127 darwin_frameworks: []const []const u8,
128 darwin_version_min: DarwinVersionMin,
129
130 test_filters: []const []const u8,
131 test_name_prefix: ?[]const u8,
132
133 emit_file_type: Emit,
134
135 kind: Kind,
136
137 link_out_file: ?[]const u8,
138 events: *event.Channel(Event),
139
140 exported_symbol_names: event.Locked(Decl.Table),
141
142 /// Before code generation starts, must wait on this group to make sure
143 /// the build is complete.
144 build_group: event.Group(BuildError!void),
145
146 compile_errors: event.Locked(CompileErrList),
147
148 meta_type: *Type.MetaType,
149 void_type: *Type.Void,
150 bool_type: *Type.Bool,
151 noreturn_type: *Type.NoReturn,
152
153 void_value: *Value.Void,
154 true_value: *Value.Bool,
155 false_value: *Value.Bool,
156 noreturn_value: *Value.NoReturn,
157
158 const CompileErrList = std.ArrayList(*errmsg.Msg);
159
160 // TODO handle some of these earlier and report them in a way other than error codes
161 pub const BuildError = error{
162 OutOfMemory,
163 EndOfStream,
164 BadFd,
165 Io,
166 IsDir,
167 Unexpected,
168 SystemResources,
169 SharingViolation,
170 PathAlreadyExists,
171 FileNotFound,
172 AccessDenied,
173 PipeBusy,
174 FileTooBig,
175 SymLinkLoop,
176 ProcessFdQuotaExceeded,
177 NameTooLong,
178 SystemFdQuotaExceeded,
179 NoDevice,
180 PathNotFound,
181 NoSpaceLeft,
182 NotDir,
183 FileSystem,
184 OperationAborted,
185 IoPending,
186 BrokenPipe,
187 WouldBlock,
188 FileClosed,
189 DestinationAddressRequired,
190 DiskQuota,
191 InputOutput,
192 NoStdHandles,
193 Overflow,
194 NotSupported,
195 BufferTooSmall,
196 Unimplemented, // TODO remove this one
197 SemanticAnalysisFailed, // TODO remove this one
198 };
199
200 pub const Event = union(enum) {
201 Ok,
202 Error: BuildError,
203 Fail: []*errmsg.Msg,
204 };
205
206 pub const DarwinVersionMin = union(enum) {
207 None,
208 MacOS: []const u8,
209 Ios: []const u8,
210 };
211
212 pub const Kind = enum {
213 Exe,
214 Lib,
215 Obj,
216 };
217
218 pub const LinkLib = struct {
219 name: []const u8,
220 path: ?[]const u8,
221
222 /// the list of symbols we depend on from this lib
223 symbols: ArrayList([]u8),
224 provided_explicitly: bool,
225 };
226
227 pub const Emit = enum {
228 Binary,
229 Assembly,
230 LlvmIr,
231 };
232
233 pub fn create(
234 event_loop_local: *EventLoopLocal,
235 name: []const u8,
236 root_src_path: ?[]const u8,
237 target: *const Target,
238 kind: Kind,
239 build_mode: builtin.Mode,
240 zig_lib_dir: []const u8,
241 cache_dir: []const u8,
242 ) !*Module {
243 const loop = event_loop_local.loop;
244
245 var name_buffer = try Buffer.init(loop.allocator, name);
246 errdefer name_buffer.deinit();
247
248 const events = try event.Channel(Event).create(loop, 0);
249 errdefer events.destroy();
250
251 const module = try loop.allocator.create(Module{
252 .loop = loop,
253 .event_loop_local = event_loop_local,
254 .events = events,
255 .name = name_buffer,
256 .root_src_path = root_src_path,
257 .target = target.*,
258 .kind = kind,
259 .build_mode = build_mode,
260 .zig_lib_dir = zig_lib_dir,
261 .cache_dir = cache_dir,
262
263 .version_major = 0,
264 .version_minor = 0,
265 .version_patch = 0,
266
267 .verbose_tokenize = false,
268 .verbose_ast_tree = false,
269 .verbose_ast_fmt = false,
270 .verbose_cimport = false,
271 .verbose_ir = false,
272 .verbose_llvm_ir = false,
273 .verbose_link = false,
274
275 .linker_script = null,
276 .libc_lib_dir = null,
277 .libc_static_lib_dir = null,
278 .libc_include_dir = null,
279 .msvc_lib_dir = null,
280 .kernel32_lib_dir = null,
281 .dynamic_linker = null,
282 .out_h_path = null,
283 .is_test = false,
284 .each_lib_rpath = false,
285 .strip = false,
286 .is_static = false,
287 .linker_rdynamic = false,
288 .clang_argv = [][]const u8{},
289 .llvm_argv = [][]const u8{},
290 .lib_dirs = [][]const u8{},
291 .rpath_list = [][]const u8{},
292 .assembly_files = [][]const u8{},
293 .link_objects = [][]const u8{},
294 .windows_subsystem_windows = false,
295 .windows_subsystem_console = false,
296 .link_libs_list = ArrayList(*LinkLib).init(loop.allocator),
297 .libc_link_lib = null,
298 .err_color = errmsg.Color.Auto,
299 .darwin_frameworks = [][]const u8{},
300 .darwin_version_min = DarwinVersionMin.None,
301 .test_filters = [][]const u8{},
302 .test_name_prefix = null,
303 .emit_file_type = Emit.Binary,
304 .link_out_file = null,
305 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
306 .build_group = event.Group(BuildError!void).init(loop),
307 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
308
309 .meta_type = undefined,
310 .void_type = undefined,
311 .void_value = undefined,
312 .bool_type = undefined,
313 .true_value = undefined,
314 .false_value = undefined,
315 .noreturn_type = undefined,
316 .noreturn_value = undefined,
317 });
318 try module.initTypes();
319 return module;
320 }
321
322 fn initTypes(module: *Module) !void {
323 module.meta_type = try module.a().create(Type.MetaType{
324 .base = Type{
325 .base = Value{
326 .id = Value.Id.Type,
327 .typeof = undefined,
328 .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
329 },
330 .id = builtin.TypeId.Type,
331 },
332 .value = undefined,
333 });
334 module.meta_type.value = &module.meta_type.base;
335 module.meta_type.base.base.typeof = &module.meta_type.base;
336 errdefer module.a().destroy(module.meta_type);
337
338 module.void_type = try module.a().create(Type.Void{
339 .base = Type{
340 .base = Value{
341 .id = Value.Id.Type,
342 .typeof = &Type.MetaType.get(module).base,
343 .ref_count = std.atomic.Int(usize).init(1),
344 },
345 .id = builtin.TypeId.Void,
346 },
347 });
348 errdefer module.a().destroy(module.void_type);
349
350 module.noreturn_type = try module.a().create(Type.NoReturn{
351 .base = Type{
352 .base = Value{
353 .id = Value.Id.Type,
354 .typeof = &Type.MetaType.get(module).base,
355 .ref_count = std.atomic.Int(usize).init(1),
356 },
357 .id = builtin.TypeId.NoReturn,
358 },
359 });
360 errdefer module.a().destroy(module.noreturn_type);
361
362 module.bool_type = try module.a().create(Type.Bool{
363 .base = Type{
364 .base = Value{
365 .id = Value.Id.Type,
366 .typeof = &Type.MetaType.get(module).base,
367 .ref_count = std.atomic.Int(usize).init(1),
368 },
369 .id = builtin.TypeId.Bool,
370 },
371 });
372 errdefer module.a().destroy(module.bool_type);
373
374 module.void_value = try module.a().create(Value.Void{
375 .base = Value{
376 .id = Value.Id.Void,
377 .typeof = &Type.Void.get(module).base,
378 .ref_count = std.atomic.Int(usize).init(1),
379 },
380 });
381 errdefer module.a().destroy(module.void_value);
382
383 module.true_value = try module.a().create(Value.Bool{
384 .base = Value{
385 .id = Value.Id.Bool,
386 .typeof = &Type.Bool.get(module).base,
387 .ref_count = std.atomic.Int(usize).init(1),
388 },
389 .x = true,
390 });
391 errdefer module.a().destroy(module.true_value);
392
393 module.false_value = try module.a().create(Value.Bool{
394 .base = Value{
395 .id = Value.Id.Bool,
396 .typeof = &Type.Bool.get(module).base,
397 .ref_count = std.atomic.Int(usize).init(1),
398 },
399 .x = false,
400 });
401 errdefer module.a().destroy(module.false_value);
402
403 module.noreturn_value = try module.a().create(Value.NoReturn{
404 .base = Value{
405 .id = Value.Id.NoReturn,
406 .typeof = &Type.NoReturn.get(module).base,
407 .ref_count = std.atomic.Int(usize).init(1),
408 },
409 });
410 errdefer module.a().destroy(module.noreturn_value);
411 }
412
413 pub fn destroy(self: *Module) void {
414 self.noreturn_value.base.deref(self);
415 self.void_value.base.deref(self);
416 self.false_value.base.deref(self);
417 self.true_value.base.deref(self);
418 self.noreturn_type.base.base.deref(self);
419 self.void_type.base.base.deref(self);
420 self.meta_type.base.base.deref(self);
421
422 self.events.destroy();
423 self.name.deinit();
424
425 self.a().destroy(self);
426 }
427
428 pub fn build(self: *Module) !void {
429 if (self.llvm_argv.len != 0) {
430 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.a(), [][]const []const u8{
431 [][]const u8{"zig (LLVM option parsing)"},
432 self.llvm_argv,
433 });
434 defer c_compatible_args.deinit();
435 // TODO this sets global state
436 c.ZigLLVMParseCommandLineOptions(self.llvm_argv.len + 1, c_compatible_args.ptr);
437 }
438
439 _ = try async<self.a()> self.buildAsync();
440 }
441
442 async fn buildAsync(self: *Module) void {
443 while (true) {
444 // TODO directly awaiting async should guarantee memory allocation elision
445 // TODO also async before suspending should guarantee memory allocation elision
446 const build_result = await (async self.addRootSrc() catch unreachable);
447
448 // this makes a handy error return trace and stack trace in debug mode
449 if (std.debug.runtime_safety) {
450 build_result catch unreachable;
451 }
452
453 const compile_errors = blk: {
454 const held = await (async self.compile_errors.acquire() catch unreachable);
455 defer held.release();
456 break :blk held.value.toOwnedSlice();
457 };
458
459 if (build_result) |_| {
460 if (compile_errors.len == 0) {
461 await (async self.events.put(Event.Ok) catch unreachable);
462 } else {
463 await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
464 }
465 } else |err| {
466 // if there's an error then the compile errors have dangling references
467 self.a().free(compile_errors);
468
469 await (async self.events.put(Event{ .Error = err }) catch unreachable);
470 }
471
472 // for now we stop after 1
473 return;
474 }
475 }
476
477 async fn addRootSrc(self: *Module) !void {
478 const root_src_path = self.root_src_path orelse @panic("TODO handle null root src path");
479 // TODO async/await os.path.real
480 const root_src_real_path = os.path.real(self.a(), root_src_path) catch |err| {
481 try printError("unable to get real path '{}': {}", root_src_path, err);
482 return err;
483 };
484 errdefer self.a().free(root_src_real_path);
485
486 // TODO async/await readFileAlloc()
487 const source_code = io.readFileAlloc(self.a(), root_src_real_path) catch |err| {
488 try printError("unable to open '{}': {}", root_src_real_path, err);
489 return err;
490 };
491 errdefer self.a().free(source_code);
492
493 const parsed_file = try self.a().create(ParsedFile{
494 .tree = undefined,
495 .realpath = root_src_real_path,
496 });
497 errdefer self.a().destroy(parsed_file);
498
499 parsed_file.tree = try std.zig.parse(self.a(), source_code);
500 errdefer parsed_file.tree.deinit();
501
502 const tree = &parsed_file.tree;
503
504 // create empty struct for it
505 const decls = try Scope.Decls.create(self, null);
506 defer decls.base.deref(self);
507
508 var decl_group = event.Group(BuildError!void).init(self.loop);
509 errdefer decl_group.cancelAll();
510
511 var it = tree.root_node.decls.iterator(0);
512 while (it.next()) |decl_ptr| {
513 const decl = decl_ptr.*;
514 switch (decl.id) {
515 ast.Node.Id.Comptime => @panic("TODO"),
516 ast.Node.Id.VarDecl => @panic("TODO"),
517 ast.Node.Id.FnProto => {
518 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
519
520 const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
521 try self.addCompileError(parsed_file, Span{
522 .first = fn_proto.fn_token,
523 .last = fn_proto.fn_token + 1,
524 }, "missing function name");
525 continue;
526 };
527
528 const fn_decl = try self.a().create(Decl.Fn{
529 .base = Decl{
530 .id = Decl.Id.Fn,
531 .name = name,
532 .visib = parseVisibToken(tree, fn_proto.visib_token),
533 .resolution = event.Future(BuildError!void).init(self.loop),
534 .resolution_in_progress = 0,
535 .parsed_file = parsed_file,
536 .parent_scope = &decls.base,
537 },
538 .value = Decl.Fn.Val{ .Unresolved = {} },
539 .fn_proto = fn_proto,
540 });
541 errdefer self.a().destroy(fn_decl);
542
543 try decl_group.call(addTopLevelDecl, self, &fn_decl.base);
544 },
545 ast.Node.Id.TestDecl => @panic("TODO"),
546 else => unreachable,
547 }
548 }
549 try await (async decl_group.wait() catch unreachable);
550 try await (async self.build_group.wait() catch unreachable);
551 }
552
553 async fn addTopLevelDecl(self: *Module, decl: *Decl) !void {
554 const is_export = decl.isExported(&decl.parsed_file.tree);
555
556 if (is_export) {
557 try self.build_group.call(verifyUniqueSymbol, self, decl);
558 try self.build_group.call(resolveDecl, self, decl);
559 }
560 }
561
562 fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
563 const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
564 errdefer self.loop.allocator.free(text);
565
566 try self.build_group.call(addCompileErrorAsync, self, parsed_file, span, text);
567 }
568
569 async fn addCompileErrorAsync(
570 self: *Module,
571 parsed_file: *ParsedFile,
572 span: Span,
573 text: []u8,
574 ) !void {
575 const msg = try self.loop.allocator.create(errmsg.Msg{
576 .path = parsed_file.realpath,
577 .text = text,
578 .span = span,
579 .tree = &parsed_file.tree,
580 });
581 errdefer self.loop.allocator.destroy(msg);
582
583 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
584 defer compile_errors.release();
585
586 try compile_errors.value.append(msg);
587 }
588
589 async fn verifyUniqueSymbol(self: *Module, decl: *Decl) !void {
590 const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
591 defer exported_symbol_names.release();
592
593 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
594 try self.addCompileError(
595 decl.parsed_file,
596 decl.getSpan(),
597 "exported symbol collision: '{}'",
598 decl.name,
599 );
600 // TODO add error note showing location of other symbol
601 }
602 }
603
604 pub fn link(self: *Module, out_file: ?[]const u8) !void {
605 warn("TODO link");
606 return error.Todo;
607 }
608
609 pub fn addLinkLib(self: *Module, name: []const u8, provided_explicitly: bool) !*LinkLib {
610 const is_libc = mem.eql(u8, name, "c");
611
612 if (is_libc) {
613 if (self.libc_link_lib) |libc_link_lib| {
614 return libc_link_lib;
615 }
616 }
617
618 for (self.link_libs_list.toSliceConst()) |existing_lib| {
619 if (mem.eql(u8, name, existing_lib.name)) {
620 return existing_lib;
621 }
622 }
623
624 const link_lib = try self.a().create(LinkLib{
625 .name = name,
626 .path = null,
627 .provided_explicitly = provided_explicitly,
628 .symbols = ArrayList([]u8).init(self.a()),
629 });
630 try self.link_libs_list.append(link_lib);
631 if (is_libc) {
632 self.libc_link_lib = link_lib;
633 }
634 return link_lib;
635 }
636
637 fn a(self: Module) *mem.Allocator {
638 return self.loop.allocator;
639 }
640};
641
642fn printError(comptime format: []const u8, args: ...) !void {
643 var stderr_file = try std.io.getStdErr();
644 var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file);
645 const out_stream = &stderr_file_out_stream.stream;
646 try out_stream.print(format, args);
647}
648
649fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib {
650 if (optional_token_index) |token_index| {
651 const token = tree.tokens.at(token_index);
652 assert(token.id == Token.Id.Keyword_pub);
653 return Visib.Pub;
654 } else {
655 return Visib.Private;
656 }
657}
658
659/// This declaration has been blessed as going into the final code generation.
660pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
661 if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
662 decl.resolution.data = await (async generateDecl(module, decl) catch unreachable);
663 decl.resolution.resolve();
664 return decl.resolution.data;
665 } else {
666 return (await (async decl.resolution.get() catch unreachable)).*;
667 }
668}
669
670/// The function that actually does the generation.
671async fn generateDecl(module: *Module, decl: *Decl) !void {
672 switch (decl.id) {
673 Decl.Id.Var => @panic("TODO"),
674 Decl.Id.Fn => {
675 const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
676 return await (async generateDeclFn(module, fn_decl) catch unreachable);
677 },
678 Decl.Id.CompTime => @panic("TODO"),
679 }
680}
681
682async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
683 const body_node = fn_decl.fn_proto.body_node orelse @panic("TODO extern fn proto decl");
684
685 const fndef_scope = try Scope.FnDef.create(module, fn_decl.base.parent_scope);
686 defer fndef_scope.base.deref(module);
687
688 // TODO actually look at the return type of the AST
689 const return_type = &Type.Void.get(module).base;
690 defer return_type.base.deref(module);
691
692 const is_var_args = false;
693 const params = ([*]Type.Fn.Param)(undefined)[0..0];
694 const fn_type = try Type.Fn.create(module, return_type, params, is_var_args);
695 defer fn_type.base.base.deref(module);
696
697 var symbol_name = try std.Buffer.init(module.a(), fn_decl.base.name);
698 errdefer symbol_name.deinit();
699
700 const fn_val = try Value.Fn.create(module, fn_type, fndef_scope, symbol_name);
701 defer fn_val.base.deref(module);
702
703 fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
704
705 const unanalyzed_code = (await (async ir.gen(
706 module,
707 body_node,
708 &fndef_scope.base,
709 Span.token(body_node.lastToken()),
710 fn_decl.base.parsed_file,
711 ) catch unreachable)) catch |err| switch (err) {
712 // This poison value should not cause the errdefers to run. It simply means
713 // that self.compile_errors is populated.
714 // TODO https://github.com/ziglang/zig/issues/769
715 error.SemanticAnalysisFailed => return {},
716 else => return err,
717 };
718 defer unanalyzed_code.destroy(module.a());
719
720 if (module.verbose_ir) {
721 std.debug.warn("unanalyzed:\n");
722 unanalyzed_code.dump();
723 }
724
725 const analyzed_code = (await (async ir.analyze(
726 module,
727 fn_decl.base.parsed_file,
728 unanalyzed_code,
729 null,
730 ) catch unreachable)) catch |err| switch (err) {
731 // This poison value should not cause the errdefers to run. It simply means
732 // that self.compile_errors is populated.
733 // TODO https://github.com/ziglang/zig/issues/769
734 error.SemanticAnalysisFailed => return {},
735 else => return err,
736 };
737 errdefer analyzed_code.destroy(module.a());
738
739 if (module.verbose_ir) {
740 std.debug.warn("analyzed:\n");
741 analyzed_code.dump();
742 }
743
744 // Kick off rendering to LLVM module, but it doesn't block the fn decl
745 // analysis from being complete.
746 try module.build_group.call(codegen.renderToLlvm, module, fn_val, analyzed_code);
747}
src-self-hosted/scope.zig+36-36
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const Allocator = mem.Allocator;2const Allocator = mem.Allocator;
3const Decl = @import("decl.zig").Decl;3const Decl = @import("decl.zig").Decl;
4const Module = @import("module.zig").Module;4const Compilation = @import("compilation.zig").Compilation;
5const mem = std.mem;5const mem = std.mem;
6const ast = std.zig.ast;6const ast = std.zig.ast;
7const Value = @import("value.zig").Value;7const Value = @import("value.zig").Value;
...@@ -16,17 +16,17 @@ pub const Scope = struct {...@@ -16,17 +16,17 @@ pub const Scope = struct {
16 base.ref_count += 1;16 base.ref_count += 1;
17 }17 }
1818
19 pub fn deref(base: *Scope, module: *Module) void {19 pub fn deref(base: *Scope, comp: *Compilation) void {
20 base.ref_count -= 1;20 base.ref_count -= 1;
21 if (base.ref_count == 0) {21 if (base.ref_count == 0) {
22 if (base.parent) |parent| parent.deref(module);22 if (base.parent) |parent| parent.deref(comp);
23 switch (base.id) {23 switch (base.id) {
24 Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(),24 Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(),
25 Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),25 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
26 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(module),26 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
27 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(module),27 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
28 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(module),28 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
29 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(module),29 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
30 }30 }
31 }31 }
32 }32 }
...@@ -61,8 +61,8 @@ pub const Scope = struct {...@@ -61,8 +61,8 @@ pub const Scope = struct {
61 table: Decl.Table,61 table: Decl.Table,
6262
63 /// Creates a Decls scope with 1 reference63 /// Creates a Decls scope with 1 reference
64 pub fn create(module: *Module, parent: ?*Scope) !*Decls {64 pub fn create(comp: *Compilation, parent: ?*Scope) !*Decls {
65 const self = try module.a().create(Decls{65 const self = try comp.a().create(Decls{
66 .base = Scope{66 .base = Scope{
67 .id = Id.Decls,67 .id = Id.Decls,
68 .parent = parent,68 .parent = parent,
...@@ -70,9 +70,9 @@ pub const Scope = struct {...@@ -70,9 +70,9 @@ pub const Scope = struct {
70 },70 },
71 .table = undefined,71 .table = undefined,
72 });72 });
73 errdefer module.a().destroy(self);73 errdefer comp.a().destroy(self);
7474
75 self.table = Decl.Table.init(module.a());75 self.table = Decl.Table.init(comp.a());
76 errdefer self.table.deinit();76 errdefer self.table.deinit();
7777
78 if (parent) |p| p.ref();78 if (parent) |p| p.ref();
...@@ -94,8 +94,8 @@ pub const Scope = struct {...@@ -94,8 +94,8 @@ pub const Scope = struct {
94 is_comptime: *ir.Instruction,94 is_comptime: *ir.Instruction,
9595
96 /// Creates a Block scope with 1 reference96 /// Creates a Block scope with 1 reference
97 pub fn create(module: *Module, parent: ?*Scope) !*Block {97 pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {
98 const self = try module.a().create(Block{98 const self = try comp.a().create(Block{
99 .base = Scope{99 .base = Scope{
100 .id = Id.Block,100 .id = Id.Block,
101 .parent = parent,101 .parent = parent,
...@@ -106,14 +106,14 @@ pub const Scope = struct {...@@ -106,14 +106,14 @@ pub const Scope = struct {
106 .end_block = undefined,106 .end_block = undefined,
107 .is_comptime = undefined,107 .is_comptime = undefined,
108 });108 });
109 errdefer module.a().destroy(self);109 errdefer comp.a().destroy(self);
110110
111 if (parent) |p| p.ref();111 if (parent) |p| p.ref();
112 return self;112 return self;
113 }113 }
114114
115 pub fn destroy(self: *Block, module: *Module) void {115 pub fn destroy(self: *Block, comp: *Compilation) void {
116 module.a().destroy(self);116 comp.a().destroy(self);
117 }117 }
118 };118 };
119119
...@@ -125,8 +125,8 @@ pub const Scope = struct {...@@ -125,8 +125,8 @@ pub const Scope = struct {
125125
126 /// Creates a FnDef scope with 1 reference126 /// Creates a FnDef scope with 1 reference
127 /// Must set the fn_val later127 /// Must set the fn_val later
128 pub fn create(module: *Module, parent: ?*Scope) !*FnDef {128 pub fn create(comp: *Compilation, parent: ?*Scope) !*FnDef {
129 const self = try module.a().create(FnDef{129 const self = try comp.a().create(FnDef{
130 .base = Scope{130 .base = Scope{
131 .id = Id.FnDef,131 .id = Id.FnDef,
132 .parent = parent,132 .parent = parent,
...@@ -140,8 +140,8 @@ pub const Scope = struct {...@@ -140,8 +140,8 @@ pub const Scope = struct {
140 return self;140 return self;
141 }141 }
142142
143 pub fn destroy(self: *FnDef, module: *Module) void {143 pub fn destroy(self: *FnDef, comp: *Compilation) void {
144 module.a().destroy(self);144 comp.a().destroy(self);
145 }145 }
146 };146 };
147147
...@@ -149,8 +149,8 @@ pub const Scope = struct {...@@ -149,8 +149,8 @@ pub const Scope = struct {
149 base: Scope,149 base: Scope,
150150
151 /// Creates a CompTime scope with 1 reference151 /// Creates a CompTime scope with 1 reference
152 pub fn create(module: *Module, parent: ?*Scope) !*CompTime {152 pub fn create(comp: *Compilation, parent: ?*Scope) !*CompTime {
153 const self = try module.a().create(CompTime{153 const self = try comp.a().create(CompTime{
154 .base = Scope{154 .base = Scope{
155 .id = Id.CompTime,155 .id = Id.CompTime,
156 .parent = parent,156 .parent = parent,
...@@ -162,8 +162,8 @@ pub const Scope = struct {...@@ -162,8 +162,8 @@ pub const Scope = struct {
162 return self;162 return self;
163 }163 }
164164
165 pub fn destroy(self: *CompTime, module: *Module) void {165 pub fn destroy(self: *CompTime, comp: *Compilation) void {
166 module.a().destroy(self);166 comp.a().destroy(self);
167 }167 }
168 };168 };
169169
...@@ -179,12 +179,12 @@ pub const Scope = struct {...@@ -179,12 +179,12 @@ pub const Scope = struct {
179179
180 /// Creates a Defer scope with 1 reference180 /// Creates a Defer scope with 1 reference
181 pub fn create(181 pub fn create(
182 module: *Module,182 comp: *Compilation,
183 parent: ?*Scope,183 parent: ?*Scope,
184 kind: Kind,184 kind: Kind,
185 defer_expr_scope: *DeferExpr,185 defer_expr_scope: *DeferExpr,
186 ) !*Defer {186 ) !*Defer {
187 const self = try module.a().create(Defer{187 const self = try comp.a().create(Defer{
188 .base = Scope{188 .base = Scope{
189 .id = Id.Defer,189 .id = Id.Defer,
190 .parent = parent,190 .parent = parent,
...@@ -193,7 +193,7 @@ pub const Scope = struct {...@@ -193,7 +193,7 @@ pub const Scope = struct {
193 .defer_expr_scope = defer_expr_scope,193 .defer_expr_scope = defer_expr_scope,
194 .kind = kind,194 .kind = kind,
195 });195 });
196 errdefer module.a().destroy(self);196 errdefer comp.a().destroy(self);
197197
198 defer_expr_scope.base.ref();198 defer_expr_scope.base.ref();
199199
...@@ -201,9 +201,9 @@ pub const Scope = struct {...@@ -201,9 +201,9 @@ pub const Scope = struct {
201 return self;201 return self;
202 }202 }
203203
204 pub fn destroy(self: *Defer, module: *Module) void {204 pub fn destroy(self: *Defer, comp: *Compilation) void {
205 self.defer_expr_scope.base.deref(module);205 self.defer_expr_scope.base.deref(comp);
206 module.a().destroy(self);206 comp.a().destroy(self);
207 }207 }
208 };208 };
209209
...@@ -212,8 +212,8 @@ pub const Scope = struct {...@@ -212,8 +212,8 @@ pub const Scope = struct {
212 expr_node: *ast.Node,212 expr_node: *ast.Node,
213213
214 /// Creates a DeferExpr scope with 1 reference214 /// Creates a DeferExpr scope with 1 reference
215 pub fn create(module: *Module, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {215 pub fn create(comp: *Compilation, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
216 const self = try module.a().create(DeferExpr{216 const self = try comp.a().create(DeferExpr{
217 .base = Scope{217 .base = Scope{
218 .id = Id.DeferExpr,218 .id = Id.DeferExpr,
219 .parent = parent,219 .parent = parent,
...@@ -221,14 +221,14 @@ pub const Scope = struct {...@@ -221,14 +221,14 @@ pub const Scope = struct {
221 },221 },
222 .expr_node = expr_node,222 .expr_node = expr_node,
223 });223 });
224 errdefer module.a().destroy(self);224 errdefer comp.a().destroy(self);
225225
226 if (parent) |p| p.ref();226 if (parent) |p| p.ref();
227 return self;227 return self;
228 }228 }
229229
230 pub fn destroy(self: *DeferExpr, module: *Module) void {230 pub fn destroy(self: *DeferExpr, comp: *Compilation) void {
231 module.a().destroy(self);231 comp.a().destroy(self);
232 }232 }
233 };233 };
234};234};
src-self-hosted/test.zig+13-13
...@@ -2,11 +2,11 @@ const std = @import("std");...@@ -2,11 +2,11 @@ const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const Target = @import("target.zig").Target;4const Target = @import("target.zig").Target;
5const Module = @import("module.zig").Module;5const Compilation = @import("compilation.zig").Compilation;
6const introspect = @import("introspect.zig");6const introspect = @import("introspect.zig");
7const assertOrPanic = std.debug.assertOrPanic;7const assertOrPanic = std.debug.assertOrPanic;
8const errmsg = @import("errmsg.zig");8const errmsg = @import("errmsg.zig");
9const EventLoopLocal = @import("module.zig").EventLoopLocal;9const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
1010
11test "compile errors" {11test "compile errors" {
12 var ctx: TestContext = undefined;12 var ctx: TestContext = undefined;
...@@ -100,42 +100,42 @@ pub const TestContext = struct {...@@ -100,42 +100,42 @@ pub const TestContext = struct {
100 // TODO async I/O100 // TODO async I/O
101 try std.io.writeFile(allocator, file1_path, source);101 try std.io.writeFile(allocator, file1_path, source);
102102
103 var module = try Module.create(103 var comp = try Compilation.create(
104 &self.event_loop_local,104 &self.event_loop_local,
105 "test",105 "test",
106 file1_path,106 file1_path,
107 Target.Native,107 Target.Native,
108 Module.Kind.Obj,108 Compilation.Kind.Obj,
109 builtin.Mode.Debug,109 builtin.Mode.Debug,
110 self.zig_lib_dir,110 self.zig_lib_dir,
111 self.zig_cache_dir,111 self.zig_cache_dir,
112 );112 );
113 errdefer module.destroy();113 errdefer comp.destroy();
114114
115 try module.build();115 try comp.build();
116116
117 try self.group.call(getModuleEvent, module, source, path, line, column, msg);117 try self.group.call(getModuleEvent, comp, source, path, line, column, msg);
118 }118 }
119119
120 async fn getModuleEvent(120 async fn getModuleEvent(
121 module: *Module,121 comp: *Compilation,
122 source: []const u8,122 source: []const u8,
123 path: []const u8,123 path: []const u8,
124 line: usize,124 line: usize,
125 column: usize,125 column: usize,
126 text: []const u8,126 text: []const u8,
127 ) !void {127 ) !void {
128 defer module.destroy();128 defer comp.destroy();
129 const build_event = await (async module.events.get() catch unreachable);129 const build_event = await (async comp.events.get() catch unreachable);
130130
131 switch (build_event) {131 switch (build_event) {
132 Module.Event.Ok => {132 Compilation.Event.Ok => {
133 @panic("build incorrectly succeeded");133 @panic("build incorrectly succeeded");
134 },134 },
135 Module.Event.Error => |err| {135 Compilation.Event.Error => |err| {
136 @panic("build incorrectly failed");136 @panic("build incorrectly failed");
137 },137 },
138 Module.Event.Fail => |msgs| {138 Compilation.Event.Fail => |msgs| {
139 assertOrPanic(msgs.len != 0);139 assertOrPanic(msgs.len != 0);
140 for (msgs) |msg| {140 for (msgs) |msg| {
141 if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) {141 if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) {
src-self-hosted/type.zig+134-134
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Scope = @import("scope.zig").Scope;3const Scope = @import("scope.zig").Scope;
4const Module = @import("module.zig").Module;4const Compilation = @import("compilation.zig").Compilation;
5const Value = @import("value.zig").Value;5const Value = @import("value.zig").Value;
6const llvm = @import("llvm.zig");6const llvm = @import("llvm.zig");
7const CompilationUnit = @import("codegen.zig").CompilationUnit;7const ObjectFile = @import("codegen.zig").ObjectFile;
88
9pub const Type = struct {9pub const Type = struct {
10 base: Value,10 base: Value,
...@@ -12,63 +12,63 @@ pub const Type = struct {...@@ -12,63 +12,63 @@ pub const Type = struct {
1212
13 pub const Id = builtin.TypeId;13 pub const Id = builtin.TypeId;
1414
15 pub fn destroy(base: *Type, module: *Module) void {15 pub fn destroy(base: *Type, comp: *Compilation) void {
16 switch (base.id) {16 switch (base.id) {
17 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(module),17 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
18 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),18 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
19 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(module),19 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
20 Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),20 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
21 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),21 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
22 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),22 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
23 Id.Int => @fieldParentPtr(Int, "base", base).destroy(module),23 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
24 Id.Float => @fieldParentPtr(Float, "base", base).destroy(module),24 Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),
25 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(module),25 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
26 Id.Array => @fieldParentPtr(Array, "base", base).destroy(module),26 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
27 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(module),27 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
28 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(module),28 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
29 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(module),29 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
30 Id.Null => @fieldParentPtr(Null, "base", base).destroy(module),30 Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),
31 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(module),31 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
32 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(module),32 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
33 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(module),33 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
34 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(module),34 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
35 Id.Union => @fieldParentPtr(Union, "base", base).destroy(module),35 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
36 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(module),36 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
37 Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),37 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
38 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(module),38 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
39 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(module),39 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
40 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(module),40 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
41 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(module),41 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
42 }42 }
43 }43 }
4444
45 pub fn getLlvmType(base: *Type, cunit: *CompilationUnit) (error{OutOfMemory}!llvm.TypeRef) {45 pub fn getLlvmType(base: *Type, ofile: *ObjectFile) (error{OutOfMemory}!llvm.TypeRef) {
46 switch (base.id) {46 switch (base.id) {
47 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(cunit),47 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(ofile),
48 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(cunit),48 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(ofile),
49 Id.Type => unreachable,49 Id.Type => unreachable,
50 Id.Void => unreachable,50 Id.Void => unreachable,
51 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(cunit),51 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(ofile),
52 Id.NoReturn => unreachable,52 Id.NoReturn => unreachable,
53 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(cunit),53 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(ofile),
54 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(cunit),54 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(ofile),
55 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(cunit),55 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(ofile),
56 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(cunit),56 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(ofile),
57 Id.ComptimeFloat => unreachable,57 Id.ComptimeFloat => unreachable,
58 Id.ComptimeInt => unreachable,58 Id.ComptimeInt => unreachable,
59 Id.Undefined => unreachable,59 Id.Undefined => unreachable,
60 Id.Null => unreachable,60 Id.Null => unreachable,
61 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(cunit),61 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(ofile),
62 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(cunit),62 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(ofile),
63 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(cunit),63 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(ofile),
64 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(cunit),64 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(ofile),
65 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(cunit),65 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(ofile),
66 Id.Namespace => unreachable,66 Id.Namespace => unreachable,
67 Id.Block => unreachable,67 Id.Block => unreachable,
68 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(cunit),68 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(ofile),
69 Id.ArgTuple => unreachable,69 Id.ArgTuple => unreachable,
70 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(cunit),70 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(ofile),
71 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(cunit),71 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(ofile),
72 }72 }
73 }73 }
7474
...@@ -76,7 +76,7 @@ pub const Type = struct {...@@ -76,7 +76,7 @@ pub const Type = struct {
76 std.debug.warn("{}", @tagName(base.id));76 std.debug.warn("{}", @tagName(base.id));
77 }77 }
7878
79 pub fn getAbiAlignment(base: *Type, module: *Module) u32 {79 pub fn getAbiAlignment(base: *Type, comp: *Compilation) u32 {
80 @panic("TODO getAbiAlignment");80 @panic("TODO getAbiAlignment");
81 }81 }
8282
...@@ -84,11 +84,11 @@ pub const Type = struct {...@@ -84,11 +84,11 @@ pub const Type = struct {
84 base: Type,84 base: Type,
85 decls: *Scope.Decls,85 decls: *Scope.Decls,
8686
87 pub fn destroy(self: *Struct, module: *Module) void {87 pub fn destroy(self: *Struct, comp: *Compilation) void {
88 module.a().destroy(self);88 comp.a().destroy(self);
89 }89 }
9090
91 pub fn getLlvmType(self: *Struct, cunit: *CompilationUnit) llvm.TypeRef {91 pub fn getLlvmType(self: *Struct, ofile: *ObjectFile) llvm.TypeRef {
92 @panic("TODO");92 @panic("TODO");
93 }93 }
94 };94 };
...@@ -104,12 +104,12 @@ pub const Type = struct {...@@ -104,12 +104,12 @@ pub const Type = struct {
104 typeof: *Type,104 typeof: *Type,
105 };105 };
106106
107 pub fn create(module: *Module, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {107 pub fn create(comp: *Compilation, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
108 const result = try module.a().create(Fn{108 const result = try comp.a().create(Fn{
109 .base = Type{109 .base = Type{
110 .base = Value{110 .base = Value{
111 .id = Value.Id.Type,111 .id = Value.Id.Type,
112 .typeof = &MetaType.get(module).base,112 .typeof = &MetaType.get(comp).base,
113 .ref_count = std.atomic.Int(usize).init(1),113 .ref_count = std.atomic.Int(usize).init(1),
114 },114 },
115 .id = builtin.TypeId.Fn,115 .id = builtin.TypeId.Fn,
...@@ -118,7 +118,7 @@ pub const Type = struct {...@@ -118,7 +118,7 @@ pub const Type = struct {
118 .params = params,118 .params = params,
119 .is_var_args = is_var_args,119 .is_var_args = is_var_args,
120 });120 });
121 errdefer module.a().destroy(result);121 errdefer comp.a().destroy(result);
122122
123 result.return_type.base.ref();123 result.return_type.base.ref();
124 for (result.params) |param| {124 for (result.params) |param| {
...@@ -127,23 +127,23 @@ pub const Type = struct {...@@ -127,23 +127,23 @@ pub const Type = struct {
127 return result;127 return result;
128 }128 }
129129
130 pub fn destroy(self: *Fn, module: *Module) void {130 pub fn destroy(self: *Fn, comp: *Compilation) void {
131 self.return_type.base.deref(module);131 self.return_type.base.deref(comp);
132 for (self.params) |param| {132 for (self.params) |param| {
133 param.typeof.base.deref(module);133 param.typeof.base.deref(comp);
134 }134 }
135 module.a().destroy(self);135 comp.a().destroy(self);
136 }136 }
137137
138 pub fn getLlvmType(self: *Fn, cunit: *CompilationUnit) !llvm.TypeRef {138 pub fn getLlvmType(self: *Fn, ofile: *ObjectFile) !llvm.TypeRef {
139 const llvm_return_type = switch (self.return_type.id) {139 const llvm_return_type = switch (self.return_type.id) {
140 Type.Id.Void => llvm.VoidTypeInContext(cunit.context) orelse return error.OutOfMemory,140 Type.Id.Void => llvm.VoidTypeInContext(ofile.context) orelse return error.OutOfMemory,
141 else => try self.return_type.getLlvmType(cunit),141 else => try self.return_type.getLlvmType(ofile),
142 };142 };
143 const llvm_param_types = try cunit.a().alloc(llvm.TypeRef, self.params.len);143 const llvm_param_types = try ofile.a().alloc(llvm.TypeRef, self.params.len);
144 defer cunit.a().free(llvm_param_types);144 defer ofile.a().free(llvm_param_types);
145 for (llvm_param_types) |*llvm_param_type, i| {145 for (llvm_param_types) |*llvm_param_type, i| {
146 llvm_param_type.* = try self.params[i].typeof.getLlvmType(cunit);146 llvm_param_type.* = try self.params[i].typeof.getLlvmType(ofile);
147 }147 }
148148
149 return llvm.FunctionType(149 return llvm.FunctionType(
...@@ -160,13 +160,13 @@ pub const Type = struct {...@@ -160,13 +160,13 @@ pub const Type = struct {
160 value: *Type,160 value: *Type,
161161
162 /// Adds 1 reference to the resulting type162 /// Adds 1 reference to the resulting type
163 pub fn get(module: *Module) *MetaType {163 pub fn get(comp: *Compilation) *MetaType {
164 module.meta_type.base.base.ref();164 comp.meta_type.base.base.ref();
165 return module.meta_type;165 return comp.meta_type;
166 }166 }
167167
168 pub fn destroy(self: *MetaType, module: *Module) void {168 pub fn destroy(self: *MetaType, comp: *Compilation) void {
169 module.a().destroy(self);169 comp.a().destroy(self);
170 }170 }
171 };171 };
172172
...@@ -174,13 +174,13 @@ pub const Type = struct {...@@ -174,13 +174,13 @@ pub const Type = struct {
174 base: Type,174 base: Type,
175175
176 /// Adds 1 reference to the resulting type176 /// Adds 1 reference to the resulting type
177 pub fn get(module: *Module) *Void {177 pub fn get(comp: *Compilation) *Void {
178 module.void_type.base.base.ref();178 comp.void_type.base.base.ref();
179 return module.void_type;179 return comp.void_type;
180 }180 }
181181
182 pub fn destroy(self: *Void, module: *Module) void {182 pub fn destroy(self: *Void, comp: *Compilation) void {
183 module.a().destroy(self);183 comp.a().destroy(self);
184 }184 }
185 };185 };
186186
...@@ -188,16 +188,16 @@ pub const Type = struct {...@@ -188,16 +188,16 @@ pub const Type = struct {
188 base: Type,188 base: Type,
189189
190 /// Adds 1 reference to the resulting type190 /// Adds 1 reference to the resulting type
191 pub fn get(module: *Module) *Bool {191 pub fn get(comp: *Compilation) *Bool {
192 module.bool_type.base.base.ref();192 comp.bool_type.base.base.ref();
193 return module.bool_type;193 return comp.bool_type;
194 }194 }
195195
196 pub fn destroy(self: *Bool, module: *Module) void {196 pub fn destroy(self: *Bool, comp: *Compilation) void {
197 module.a().destroy(self);197 comp.a().destroy(self);
198 }198 }
199199
200 pub fn getLlvmType(self: *Bool, cunit: *CompilationUnit) llvm.TypeRef {200 pub fn getLlvmType(self: *Bool, ofile: *ObjectFile) llvm.TypeRef {
201 @panic("TODO");201 @panic("TODO");
202 }202 }
203 };203 };
...@@ -206,24 +206,24 @@ pub const Type = struct {...@@ -206,24 +206,24 @@ pub const Type = struct {
206 base: Type,206 base: Type,
207207
208 /// Adds 1 reference to the resulting type208 /// Adds 1 reference to the resulting type
209 pub fn get(module: *Module) *NoReturn {209 pub fn get(comp: *Compilation) *NoReturn {
210 module.noreturn_type.base.base.ref();210 comp.noreturn_type.base.base.ref();
211 return module.noreturn_type;211 return comp.noreturn_type;
212 }212 }
213213
214 pub fn destroy(self: *NoReturn, module: *Module) void {214 pub fn destroy(self: *NoReturn, comp: *Compilation) void {
215 module.a().destroy(self);215 comp.a().destroy(self);
216 }216 }
217 };217 };
218218
219 pub const Int = struct {219 pub const Int = struct {
220 base: Type,220 base: Type,
221221
222 pub fn destroy(self: *Int, module: *Module) void {222 pub fn destroy(self: *Int, comp: *Compilation) void {
223 module.a().destroy(self);223 comp.a().destroy(self);
224 }224 }
225225
226 pub fn getLlvmType(self: *Int, cunit: *CompilationUnit) llvm.TypeRef {226 pub fn getLlvmType(self: *Int, ofile: *ObjectFile) llvm.TypeRef {
227 @panic("TODO");227 @panic("TODO");
228 }228 }
229 };229 };
...@@ -231,11 +231,11 @@ pub const Type = struct {...@@ -231,11 +231,11 @@ pub const Type = struct {
231 pub const Float = struct {231 pub const Float = struct {
232 base: Type,232 base: Type,
233233
234 pub fn destroy(self: *Float, module: *Module) void {234 pub fn destroy(self: *Float, comp: *Compilation) void {
235 module.a().destroy(self);235 comp.a().destroy(self);
236 }236 }
237237
238 pub fn getLlvmType(self: *Float, cunit: *CompilationUnit) llvm.TypeRef {238 pub fn getLlvmType(self: *Float, ofile: *ObjectFile) llvm.TypeRef {
239 @panic("TODO");239 @panic("TODO");
240 }240 }
241 };241 };
...@@ -256,12 +256,12 @@ pub const Type = struct {...@@ -256,12 +256,12 @@ pub const Type = struct {
256 };256 };
257 pub const Size = builtin.TypeInfo.Pointer.Size;257 pub const Size = builtin.TypeInfo.Pointer.Size;
258258
259 pub fn destroy(self: *Pointer, module: *Module) void {259 pub fn destroy(self: *Pointer, comp: *Compilation) void {
260 module.a().destroy(self);260 comp.a().destroy(self);
261 }261 }
262262
263 pub fn get(263 pub fn get(
264 module: *Module,264 comp: *Compilation,
265 elem_type: *Type,265 elem_type: *Type,
266 mut: Mut,266 mut: Mut,
267 vol: Vol,267 vol: Vol,
...@@ -271,7 +271,7 @@ pub const Type = struct {...@@ -271,7 +271,7 @@ pub const Type = struct {
271 @panic("TODO get pointer");271 @panic("TODO get pointer");
272 }272 }
273273
274 pub fn getLlvmType(self: *Pointer, cunit: *CompilationUnit) llvm.TypeRef {274 pub fn getLlvmType(self: *Pointer, ofile: *ObjectFile) llvm.TypeRef {
275 @panic("TODO");275 @panic("TODO");
276 }276 }
277 };277 };
...@@ -279,11 +279,11 @@ pub const Type = struct {...@@ -279,11 +279,11 @@ pub const Type = struct {
279 pub const Array = struct {279 pub const Array = struct {
280 base: Type,280 base: Type,
281281
282 pub fn destroy(self: *Array, module: *Module) void {282 pub fn destroy(self: *Array, comp: *Compilation) void {
283 module.a().destroy(self);283 comp.a().destroy(self);
284 }284 }
285285
286 pub fn getLlvmType(self: *Array, cunit: *CompilationUnit) llvm.TypeRef {286 pub fn getLlvmType(self: *Array, ofile: *ObjectFile) llvm.TypeRef {
287 @panic("TODO");287 @panic("TODO");
288 }288 }
289 };289 };
...@@ -291,43 +291,43 @@ pub const Type = struct {...@@ -291,43 +291,43 @@ pub const Type = struct {
291 pub const ComptimeFloat = struct {291 pub const ComptimeFloat = struct {
292 base: Type,292 base: Type,
293293
294 pub fn destroy(self: *ComptimeFloat, module: *Module) void {294 pub fn destroy(self: *ComptimeFloat, comp: *Compilation) void {
295 module.a().destroy(self);295 comp.a().destroy(self);
296 }296 }
297 };297 };
298298
299 pub const ComptimeInt = struct {299 pub const ComptimeInt = struct {
300 base: Type,300 base: Type,
301301
302 pub fn destroy(self: *ComptimeInt, module: *Module) void {302 pub fn destroy(self: *ComptimeInt, comp: *Compilation) void {
303 module.a().destroy(self);303 comp.a().destroy(self);
304 }304 }
305 };305 };
306306
307 pub const Undefined = struct {307 pub const Undefined = struct {
308 base: Type,308 base: Type,
309309
310 pub fn destroy(self: *Undefined, module: *Module) void {310 pub fn destroy(self: *Undefined, comp: *Compilation) void {
311 module.a().destroy(self);311 comp.a().destroy(self);
312 }312 }
313 };313 };
314314
315 pub const Null = struct {315 pub const Null = struct {
316 base: Type,316 base: Type,
317317
318 pub fn destroy(self: *Null, module: *Module) void {318 pub fn destroy(self: *Null, comp: *Compilation) void {
319 module.a().destroy(self);319 comp.a().destroy(self);
320 }320 }
321 };321 };
322322
323 pub const Optional = struct {323 pub const Optional = struct {
324 base: Type,324 base: Type,
325325
326 pub fn destroy(self: *Optional, module: *Module) void {326 pub fn destroy(self: *Optional, comp: *Compilation) void {
327 module.a().destroy(self);327 comp.a().destroy(self);
328 }328 }
329329
330 pub fn getLlvmType(self: *Optional, cunit: *CompilationUnit) llvm.TypeRef {330 pub fn getLlvmType(self: *Optional, ofile: *ObjectFile) llvm.TypeRef {
331 @panic("TODO");331 @panic("TODO");
332 }332 }
333 };333 };
...@@ -335,11 +335,11 @@ pub const Type = struct {...@@ -335,11 +335,11 @@ pub const Type = struct {
335 pub const ErrorUnion = struct {335 pub const ErrorUnion = struct {
336 base: Type,336 base: Type,
337337
338 pub fn destroy(self: *ErrorUnion, module: *Module) void {338 pub fn destroy(self: *ErrorUnion, comp: *Compilation) void {
339 module.a().destroy(self);339 comp.a().destroy(self);
340 }340 }
341341
342 pub fn getLlvmType(self: *ErrorUnion, cunit: *CompilationUnit) llvm.TypeRef {342 pub fn getLlvmType(self: *ErrorUnion, ofile: *ObjectFile) llvm.TypeRef {
343 @panic("TODO");343 @panic("TODO");
344 }344 }
345 };345 };
...@@ -347,11 +347,11 @@ pub const Type = struct {...@@ -347,11 +347,11 @@ pub const Type = struct {
347 pub const ErrorSet = struct {347 pub const ErrorSet = struct {
348 base: Type,348 base: Type,
349349
350 pub fn destroy(self: *ErrorSet, module: *Module) void {350 pub fn destroy(self: *ErrorSet, comp: *Compilation) void {
351 module.a().destroy(self);351 comp.a().destroy(self);
352 }352 }
353353
354 pub fn getLlvmType(self: *ErrorSet, cunit: *CompilationUnit) llvm.TypeRef {354 pub fn getLlvmType(self: *ErrorSet, ofile: *ObjectFile) llvm.TypeRef {
355 @panic("TODO");355 @panic("TODO");
356 }356 }
357 };357 };
...@@ -359,11 +359,11 @@ pub const Type = struct {...@@ -359,11 +359,11 @@ pub const Type = struct {
359 pub const Enum = struct {359 pub const Enum = struct {
360 base: Type,360 base: Type,
361361
362 pub fn destroy(self: *Enum, module: *Module) void {362 pub fn destroy(self: *Enum, comp: *Compilation) void {
363 module.a().destroy(self);363 comp.a().destroy(self);
364 }364 }
365365
366 pub fn getLlvmType(self: *Enum, cunit: *CompilationUnit) llvm.TypeRef {366 pub fn getLlvmType(self: *Enum, ofile: *ObjectFile) llvm.TypeRef {
367 @panic("TODO");367 @panic("TODO");
368 }368 }
369 };369 };
...@@ -371,11 +371,11 @@ pub const Type = struct {...@@ -371,11 +371,11 @@ pub const Type = struct {
371 pub const Union = struct {371 pub const Union = struct {
372 base: Type,372 base: Type,
373373
374 pub fn destroy(self: *Union, module: *Module) void {374 pub fn destroy(self: *Union, comp: *Compilation) void {
375 module.a().destroy(self);375 comp.a().destroy(self);
376 }376 }
377377
378 pub fn getLlvmType(self: *Union, cunit: *CompilationUnit) llvm.TypeRef {378 pub fn getLlvmType(self: *Union, ofile: *ObjectFile) llvm.TypeRef {
379 @panic("TODO");379 @panic("TODO");
380 }380 }
381 };381 };
...@@ -383,27 +383,27 @@ pub const Type = struct {...@@ -383,27 +383,27 @@ pub const Type = struct {
383 pub const Namespace = struct {383 pub const Namespace = struct {
384 base: Type,384 base: Type,
385385
386 pub fn destroy(self: *Namespace, module: *Module) void {386 pub fn destroy(self: *Namespace, comp: *Compilation) void {
387 module.a().destroy(self);387 comp.a().destroy(self);
388 }388 }
389 };389 };
390390
391 pub const Block = struct {391 pub const Block = struct {
392 base: Type,392 base: Type,
393393
394 pub fn destroy(self: *Block, module: *Module) void {394 pub fn destroy(self: *Block, comp: *Compilation) void {
395 module.a().destroy(self);395 comp.a().destroy(self);
396 }396 }
397 };397 };
398398
399 pub const BoundFn = struct {399 pub const BoundFn = struct {
400 base: Type,400 base: Type,
401401
402 pub fn destroy(self: *BoundFn, module: *Module) void {402 pub fn destroy(self: *BoundFn, comp: *Compilation) void {
403 module.a().destroy(self);403 comp.a().destroy(self);
404 }404 }
405405
406 pub fn getLlvmType(self: *BoundFn, cunit: *CompilationUnit) llvm.TypeRef {406 pub fn getLlvmType(self: *BoundFn, ofile: *ObjectFile) llvm.TypeRef {
407 @panic("TODO");407 @panic("TODO");
408 }408 }
409 };409 };
...@@ -411,19 +411,19 @@ pub const Type = struct {...@@ -411,19 +411,19 @@ pub const Type = struct {
411 pub const ArgTuple = struct {411 pub const ArgTuple = struct {
412 base: Type,412 base: Type,
413413
414 pub fn destroy(self: *ArgTuple, module: *Module) void {414 pub fn destroy(self: *ArgTuple, comp: *Compilation) void {
415 module.a().destroy(self);415 comp.a().destroy(self);
416 }416 }
417 };417 };
418418
419 pub const Opaque = struct {419 pub const Opaque = struct {
420 base: Type,420 base: Type,
421421
422 pub fn destroy(self: *Opaque, module: *Module) void {422 pub fn destroy(self: *Opaque, comp: *Compilation) void {
423 module.a().destroy(self);423 comp.a().destroy(self);
424 }424 }
425425
426 pub fn getLlvmType(self: *Opaque, cunit: *CompilationUnit) llvm.TypeRef {426 pub fn getLlvmType(self: *Opaque, ofile: *ObjectFile) llvm.TypeRef {
427 @panic("TODO");427 @panic("TODO");
428 }428 }
429 };429 };
...@@ -431,11 +431,11 @@ pub const Type = struct {...@@ -431,11 +431,11 @@ pub const Type = struct {
431 pub const Promise = struct {431 pub const Promise = struct {
432 base: Type,432 base: Type,
433433
434 pub fn destroy(self: *Promise, module: *Module) void {434 pub fn destroy(self: *Promise, comp: *Compilation) void {
435 module.a().destroy(self);435 comp.a().destroy(self);
436 }436 }
437437
438 pub fn getLlvmType(self: *Promise, cunit: *CompilationUnit) llvm.TypeRef {438 pub fn getLlvmType(self: *Promise, ofile: *ObjectFile) llvm.TypeRef {
439 @panic("TODO");439 @panic("TODO");
440 }440 }
441 };441 };
src-self-hosted/value.zig+33-33
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Scope = @import("scope.zig").Scope;3const Scope = @import("scope.zig").Scope;
4const Module = @import("module.zig").Module;4const Compilation = @import("compilation.zig").Compilation;
55
6/// Values are ref-counted, heap-allocated, and copy-on-write6/// Values are ref-counted, heap-allocated, and copy-on-write
7/// If there is only 1 ref then write need not copy7/// If there is only 1 ref then write need not copy
...@@ -16,16 +16,16 @@ pub const Value = struct {...@@ -16,16 +16,16 @@ pub const Value = struct {
16 }16 }
1717
18 /// Thread-safe18 /// Thread-safe
19 pub fn deref(base: *Value, module: *Module) void {19 pub fn deref(base: *Value, comp: *Compilation) void {
20 if (base.ref_count.decr() == 1) {20 if (base.ref_count.decr() == 1) {
21 base.typeof.base.deref(module);21 base.typeof.base.deref(comp);
22 switch (base.id) {22 switch (base.id) {
23 Id.Type => @fieldParentPtr(Type, "base", base).destroy(module),23 Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
25 Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),25 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
26 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),26 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
27 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),27 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
28 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(module),28 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
29 }29 }
30 }30 }
31 }31 }
...@@ -68,8 +68,8 @@ pub const Value = struct {...@@ -68,8 +68,8 @@ pub const Value = struct {
6868
69 /// Creates a Fn value with 1 ref69 /// Creates a Fn value with 1 ref
70 /// Takes ownership of symbol_name70 /// Takes ownership of symbol_name
71 pub fn create(module: *Module, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {71 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
72 const self = try module.a().create(Fn{72 const self = try comp.a().create(Fn{
73 .base = Value{73 .base = Value{
74 .id = Value.Id.Fn,74 .id = Value.Id.Fn,
75 .typeof = &fn_type.base,75 .typeof = &fn_type.base,
...@@ -86,23 +86,23 @@ pub const Value = struct {...@@ -86,23 +86,23 @@ pub const Value = struct {
86 return self;86 return self;
87 }87 }
8888
89 pub fn destroy(self: *Fn, module: *Module) void {89 pub fn destroy(self: *Fn, comp: *Compilation) void {
90 self.fndef_scope.base.deref(module);90 self.fndef_scope.base.deref(comp);
91 self.symbol_name.deinit();91 self.symbol_name.deinit();
92 module.a().destroy(self);92 comp.a().destroy(self);
93 }93 }
94 };94 };
9595
96 pub const Void = struct {96 pub const Void = struct {
97 base: Value,97 base: Value,
9898
99 pub fn get(module: *Module) *Void {99 pub fn get(comp: *Compilation) *Void {
100 module.void_value.base.ref();100 comp.void_value.base.ref();
101 return module.void_value;101 return comp.void_value;
102 }102 }
103103
104 pub fn destroy(self: *Void, module: *Module) void {104 pub fn destroy(self: *Void, comp: *Compilation) void {
105 module.a().destroy(self);105 comp.a().destroy(self);
106 }106 }
107 };107 };
108108
...@@ -110,31 +110,31 @@ pub const Value = struct {...@@ -110,31 +110,31 @@ pub const Value = struct {
110 base: Value,110 base: Value,
111 x: bool,111 x: bool,
112112
113 pub fn get(module: *Module, x: bool) *Bool {113 pub fn get(comp: *Compilation, x: bool) *Bool {
114 if (x) {114 if (x) {
115 module.true_value.base.ref();115 comp.true_value.base.ref();
116 return module.true_value;116 return comp.true_value;
117 } else {117 } else {
118 module.false_value.base.ref();118 comp.false_value.base.ref();
119 return module.false_value;119 return comp.false_value;
120 }120 }
121 }121 }
122122
123 pub fn destroy(self: *Bool, module: *Module) void {123 pub fn destroy(self: *Bool, comp: *Compilation) void {
124 module.a().destroy(self);124 comp.a().destroy(self);
125 }125 }
126 };126 };
127127
128 pub const NoReturn = struct {128 pub const NoReturn = struct {
129 base: Value,129 base: Value,
130130
131 pub fn get(module: *Module) *NoReturn {131 pub fn get(comp: *Compilation) *NoReturn {
132 module.noreturn_value.base.ref();132 comp.noreturn_value.base.ref();
133 return module.noreturn_value;133 return comp.noreturn_value;
134 }134 }
135135
136 pub fn destroy(self: *NoReturn, module: *Module) void {136 pub fn destroy(self: *NoReturn, comp: *Compilation) void {
137 module.a().destroy(self);137 comp.a().destroy(self);
138 }138 }
139 };139 };
140140
...@@ -147,8 +147,8 @@ pub const Value = struct {...@@ -147,8 +147,8 @@ pub const Value = struct {
147 RunTime,147 RunTime,
148 };148 };
149149
150 pub fn destroy(self: *Ptr, module: *Module) void {150 pub fn destroy(self: *Ptr, comp: *Compilation) void {
151 module.a().destroy(self);151 comp.a().destroy(self);
152 }152 }
153 };153 };
154};154};