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 @@
11const std = @import("std");
2// TODO codegen pretends that Module is renamed to Build because I plan to
3// do that refactor at some point
4const Build = @import("module.zig").Module;
2const Compilation = @import("compilation.zig").Compilation;
53// we go through llvm instead of c for 2 reasons:
64// 1. to avoid accidentally calling the non-thread-safe functions
75// 2. patch up some of the types to remove nullability
......@@ -11,51 +9,51 @@ const Value = @import("value.zig").Value;
119const Type = @import("type.zig").Type;
1210const 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 {
1513 fn_val.base.ref();
16 defer fn_val.base.deref(build);
17 defer code.destroy(build.a());
14 defer fn_val.base.deref(comp);
15 defer code.destroy(comp.a());
1816
19 const llvm_handle = try build.event_loop_local.getAnyLlvmContext();
20 defer llvm_handle.release(build.event_loop_local);
17 const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
18 defer llvm_handle.release(comp.event_loop_local);
2119
2220 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;
2523 defer llvm.DisposeModule(module);
2624
2725 const builder = llvm.CreateBuilderInContext(context) orelse return error.OutOfMemory;
2826 defer llvm.DisposeBuilder(builder);
2927
30 var cunit = CompilationUnit{
31 .build = build,
28 var ofile = ObjectFile{
29 .comp = comp,
3230 .module = module,
3331 .builder = builder,
3432 .context = context,
35 .lock = event.Lock.init(build.loop),
33 .lock = event.Lock.init(comp.loop),
3634 };
3735
38 try renderToLlvmModule(&cunit, fn_val, code);
36 try renderToLlvmModule(&ofile, fn_val, code);
3937
40 if (build.verbose_llvm_ir) {
41 llvm.DumpModule(cunit.module);
38 if (comp.verbose_llvm_ir) {
39 llvm.DumpModule(ofile.module);
4240 }
4341}
4442
45pub const CompilationUnit = struct {
46 build: *Build,
43pub const ObjectFile = struct {
44 comp: *Compilation,
4745 module: llvm.ModuleRef,
4846 builder: llvm.BuilderRef,
4947 context: llvm.ContextRef,
5048 lock: event.Lock,
5149
52 fn a(self: *CompilationUnit) *std.mem.Allocator {
53 return self.build.a();
50 fn a(self: *ObjectFile) *std.mem.Allocator {
51 return self.comp.a();
5452 }
5553};
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 {
5856 // 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);
60 const llvm_fn = llvm.AddFunction(cunit.module, fn_val.symbol_name.ptr(), llvm_fn_type);
57 const llvm_fn_type = try fn_val.base.typeof.getLlvmType(ofile);
58 const llvm_fn = llvm.AddFunction(ofile.module, fn_val.symbol_name.ptr(), llvm_fn_type);
6159}
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;
99const Token = std.zig.Token;
1010const errmsg = @import("errmsg.zig");
1111const Scope = @import("scope.zig").Scope;
12const Module = @import("module.zig").Module;
12const Compilation = @import("compilation.zig").Compilation;
1313
1414pub const Decl = struct {
1515 id: Id,
1616 name: []const u8,
1717 visib: Visib,
18 resolution: event.Future(Module.BuildError!void),
18 resolution: event.Future(Compilation.BuildError!void),
1919 resolution_in_progress: u8,
2020 parsed_file: *ParsedFile,
2121 parent_scope: *Scope,
src-self-hosted/ir.zig+28-28
......@@ -1,6 +1,6 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const Module = @import("module.zig").Module;
3const Compilation = @import("compilation.zig").Compilation;
44const Scope = @import("scope.zig").Scope;
55const ast = std.zig.ast;
66const Allocator = std.mem.Allocator;
......@@ -243,7 +243,7 @@ pub const Instruction = struct {
243243 Value.Ptr.Mut.CompTimeConst,
244244 self.params.mut,
245245 self.params.volatility,
246 val.typeof.getAbiAlignment(ira.irb.module),
246 val.typeof.getAbiAlignment(ira.irb.comp),
247247 );
248248 }
249249
......@@ -254,12 +254,12 @@ pub const Instruction = struct {
254254 });
255255 const elem_type = target.getKnownType();
256256 const ptr_type = Type.Pointer.get(
257 ira.irb.module,
257 ira.irb.comp,
258258 elem_type,
259259 self.params.mut,
260260 self.params.volatility,
261261 Type.Pointer.Size.One,
262 elem_type.getAbiAlignment(ira.irb.module),
262 elem_type.getAbiAlignment(ira.irb.comp),
263263 );
264264 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this
265265 // could be a ref of a global, for example
......@@ -417,7 +417,7 @@ pub const Code = struct {
417417 arena: std.heap.ArenaAllocator,
418418 return_type: ?*Type,
419419
420 /// allocator is module.a()
420 /// allocator is comp.a()
421421 pub fn destroy(self: *Code, allocator: *Allocator) void {
422422 self.arena.deinit();
423423 allocator.destroy(self);
......@@ -437,7 +437,7 @@ pub const Code = struct {
437437};
438438
439439pub const Builder = struct {
440 module: *Module,
440 comp: *Compilation,
441441 code: *Code,
442442 current_basic_block: *BasicBlock,
443443 next_debug_id: usize,
......@@ -446,17 +446,17 @@ pub const Builder = struct {
446446
447447 pub const Error = Analyze.Error;
448448
449 pub fn init(module: *Module, parsed_file: *ParsedFile) !Builder {
450 const code = try module.a().create(Code{
449 pub fn init(comp: *Compilation, parsed_file: *ParsedFile) !Builder {
450 const code = try comp.a().create(Code{
451451 .basic_block_list = undefined,
452 .arena = std.heap.ArenaAllocator.init(module.a()),
452 .arena = std.heap.ArenaAllocator.init(comp.a()),
453453 .return_type = null,
454454 });
455455 code.basic_block_list = std.ArrayList(*BasicBlock).init(&code.arena.allocator);
456 errdefer code.destroy(module.a());
456 errdefer code.destroy(comp.a());
457457
458458 return Builder{
459 .module = module,
459 .comp = comp,
460460 .parsed_file = parsed_file,
461461 .current_basic_block = undefined,
462462 .code = code,
......@@ -466,7 +466,7 @@ pub const Builder = struct {
466466 }
467467
468468 pub fn abort(self: *Builder) void {
469 self.code.destroy(self.module.a());
469 self.code.destroy(self.comp.a());
470470 }
471471
472472 /// Call code.destroy() when done
......@@ -581,7 +581,7 @@ pub const Builder = struct {
581581 }
582582
583583 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
586586 const outer_block_scope = &block_scope.base;
587587 var child_scope = outer_block_scope;
......@@ -623,8 +623,8 @@ pub const Builder = struct {
623623 Token.Id.Keyword_errdefer => Scope.Defer.Kind.ErrorExit,
624624 else => unreachable,
625625 };
626 const defer_expr_scope = try Scope.DeferExpr.create(irb.module, parent_scope, defer_node.expr);
627 const defer_child_scope = try Scope.Defer.create(irb.module, parent_scope, kind, defer_expr_scope);
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.comp, parent_scope, kind, defer_expr_scope);
628628 child_scope = &defer_child_scope.base;
629629 continue;
630630 }
......@@ -770,8 +770,8 @@ pub const Builder = struct {
770770 .debug_id = self.next_debug_id,
771771 .val = switch (I.ir_val_init) {
772772 IrVal.Init.Unknown => IrVal.Unknown,
773 IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.module).base },
774 IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.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.comp).base },
775775 },
776776 .ref_count = 0,
777777 .span = span,
......@@ -819,13 +819,13 @@ pub const Builder = struct {
819819
820820 fn buildConstBool(self: *Builder, scope: *Scope, span: Span, x: bool) !*Instruction {
821821 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 };
823823 return inst;
824824 }
825825
826826 fn buildConstVoid(self: *Builder, scope: *Scope, span: Span, is_generated: bool) !*Instruction {
827827 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 };
829829 return inst;
830830 }
831831};
......@@ -850,8 +850,8 @@ const Analyze = struct {
850850 OutOfMemory,
851851 };
852852
853 pub fn init(module: *Module, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
854 var irb = try Builder.init(module, parsed_file);
853 pub fn init(comp: *Compilation, parsed_file: *ParsedFile, explicit_return_type: ?*Type) !Analyze {
854 var irb = try Builder.init(comp, parsed_file);
855855 errdefer irb.abort();
856856
857857 return Analyze{
......@@ -929,12 +929,12 @@ const Analyze = struct {
929929 }
930930
931931 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);
933933 }
934934
935935 fn resolvePeerTypes(self: *Analyze, expected_type: ?*Type, peers: []const *Instruction) Analyze.Error!*Type {
936936 // TODO actual implementation
937 return &Type.Void.get(self.irb.module).base;
937 return &Type.Void.get(self.irb.comp).base;
938938 }
939939
940940 fn implicitCast(self: *Analyze, target: *Instruction, optional_dest_type: ?*Type) Analyze.Error!*Instruction {
......@@ -959,13 +959,13 @@ const Analyze = struct {
959959};
960960
961961pub async fn gen(
962 module: *Module,
962 comp: *Compilation,
963963 body_node: *ast.Node,
964964 scope: *Scope,
965965 end_span: Span,
966966 parsed_file: *ParsedFile,
967967) !*Code {
968 var irb = try Builder.init(module, parsed_file);
968 var irb = try Builder.init(comp, parsed_file);
969969 errdefer irb.abort();
970970
971971 const entry_block = try irb.createBasicBlock(scope, "Entry");
......@@ -991,8 +991,8 @@ pub async fn gen(
991991 return irb.finish();
992992}
993993
994pub async fn analyze(module: *Module, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
995 var ira = try Analyze.init(module, parsed_file, expected_type);
994pub async fn analyze(comp: *Compilation, parsed_file: *ParsedFile, old_code: *Code, expected_type: ?*Type) !*Code {
995 var ira = try Analyze.init(comp, parsed_file, expected_type);
996996 errdefer ira.abort();
997997
998998 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,
10251025 }
10261026
10271027 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;
10291029 return ira.irb.finish();
10301030 }
10311031
src-self-hosted/main.zig+57-57
......@@ -14,8 +14,8 @@ const c = @import("c.zig");
1414const introspect = @import("introspect.zig");
1515const Args = arg.Args;
1616const Flag = arg.Flag;
17const EventLoopLocal = @import("module.zig").EventLoopLocal;
18const Module = @import("module.zig").Module;
17const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
18const Compilation = @import("compilation.zig").Compilation;
1919const Target = @import("target.zig").Target;
2020const errmsg = @import("errmsg.zig");
2121
......@@ -258,7 +258,7 @@ const args_build_generic = []Flag{
258258 Flag.Arg1("--ver-patch"),
259259};
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 {
262262 var flags = try Args.parse(allocator, args_build_generic, args);
263263 defer flags.deinit();
264264
......@@ -300,14 +300,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
300300 const emit_type = blk: {
301301 if (flags.single("emit")) |emit_flag| {
302302 if (mem.eql(u8, emit_flag, "asm")) {
303 break :blk Module.Emit.Assembly;
303 break :blk Compilation.Emit.Assembly;
304304 } else if (mem.eql(u8, emit_flag, "bin")) {
305 break :blk Module.Emit.Binary;
305 break :blk Compilation.Emit.Binary;
306306 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {
307 break :blk Module.Emit.LlvmIr;
307 break :blk Compilation.Emit.LlvmIr;
308308 } else unreachable;
309309 } else {
310 break :blk Module.Emit.Binary;
310 break :blk Compilation.Emit.Binary;
311311 }
312312 };
313313
......@@ -370,7 +370,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
370370 os.exit(1);
371371 }
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) {
374374 try stderr.write("When building an object file, --object arguments are invalid\n");
375375 os.exit(1);
376376 }
......@@ -392,7 +392,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
392392 var event_loop_local = EventLoopLocal.init(&loop);
393393 defer event_loop_local.deinit();
394394
395 var module = try Module.create(
395 var comp = try Compilation.create(
396396 &event_loop_local,
397397 root_name,
398398 root_source_file,
......@@ -402,16 +402,16 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
402402 zig_lib_dir,
403403 full_cache_dir,
404404 );
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);
408 module.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);
407 comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
408 comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") 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");
414 module.each_lib_rpath = flags.present("each-lib-rpath");
413 comp.linker_script = flags.single("linker-script");
414 comp.each_lib_rpath = flags.present("each-lib-rpath");
415415
416416 var clang_argv_buf = ArrayList([]const u8).init(allocator);
417417 defer clang_argv_buf.deinit();
......@@ -422,51 +422,51 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
422422 try clang_argv_buf.append(mllvm);
423423 }
424424
425 module.llvm_argv = mllvm_flags;
426 module.clang_argv = clang_argv_buf.toSliceConst();
425 comp.llvm_argv = mllvm_flags;
426 comp.clang_argv = clang_argv_buf.toSliceConst();
427427
428 module.strip = flags.present("strip");
429 module.is_static = flags.present("static");
428 comp.strip = flags.present("strip");
429 comp.is_static = flags.present("static");
430430
431431 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;
433433 }
434434 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;
436436 }
437437 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;
439439 }
440440 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;
442442 }
443443 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;
445445 }
446446 if (flags.single("dynamic-linker")) |dynamic_linker| {
447 module.dynamic_linker = dynamic_linker;
447 comp.dynamic_linker = dynamic_linker;
448448 }
449449
450 module.verbose_tokenize = flags.present("verbose-tokenize");
451 module.verbose_ast_tree = flags.present("verbose-ast-tree");
452 module.verbose_ast_fmt = flags.present("verbose-ast-fmt");
453 module.verbose_link = flags.present("verbose-link");
454 module.verbose_ir = flags.present("verbose-ir");
455 module.verbose_llvm_ir = flags.present("verbose-llvm-ir");
456 module.verbose_cimport = flags.present("verbose-cimport");
450 comp.verbose_tokenize = flags.present("verbose-tokenize");
451 comp.verbose_ast_tree = flags.present("verbose-ast-tree");
452 comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
453 comp.verbose_link = flags.present("verbose-link");
454 comp.verbose_ir = flags.present("verbose-ir");
455 comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
456 comp.verbose_cimport = flags.present("verbose-cimport");
457457
458 module.err_color = color;
459 module.lib_dirs = flags.many("library-path");
460 module.darwin_frameworks = flags.many("framework");
461 module.rpath_list = flags.many("rpath");
458 comp.err_color = color;
459 comp.lib_dirs = flags.many("library-path");
460 comp.darwin_frameworks = flags.many("framework");
461 comp.rpath_list = flags.many("rpath");
462462
463463 if (flags.single("output-h")) |output_h| {
464 module.out_h_path = output_h;
464 comp.out_h_path = output_h;
465465 }
466466
467 module.windows_subsystem_windows = flags.present("mwindows");
468 module.windows_subsystem_console = flags.present("mconsole");
469 module.linker_rdynamic = flags.present("rdynamic");
467 comp.windows_subsystem_windows = flags.present("mwindows");
468 comp.windows_subsystem_console = flags.present("mconsole");
469 comp.linker_rdynamic = flags.present("rdynamic");
470470
471471 if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {
472472 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
474474 }
475475
476476 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 };
478478 }
479479 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 };
481481 }
482482
483 module.emit_file_type = emit_type;
484 module.link_objects = link_objects;
485 module.assembly_files = assembly_files;
486 module.link_out_file = flags.single("out-file");
483 comp.emit_file_type = emit_type;
484 comp.link_objects = link_objects;
485 comp.assembly_files = assembly_files;
486 comp.link_out_file = flags.single("out-file");
487487
488 try module.build();
489 const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color);
488 try comp.build();
489 const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
490490 defer cancel process_build_events_handle;
491491 loop.run();
492492}
493493
494async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
494async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
495495 // 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
498498 switch (build_event) {
499 Module.Event.Ok => {
499 Compilation.Event.Ok => {
500500 std.debug.warn("Build succeeded\n");
501501 return;
502502 },
503 Module.Event.Error => |err| {
503 Compilation.Event.Error => |err| {
504504 std.debug.warn("build failed: {}\n", @errorName(err));
505505 os.exit(1);
506506 },
507 Module.Event.Fail => |msgs| {
507 Compilation.Event.Fail => |msgs| {
508508 for (msgs) |msg| {
509509 errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);
510510 }
......@@ -513,15 +513,15 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
513513}
514514
515515fn cmdBuildExe(allocator: *Allocator, args: []const []const u8) !void {
516 return buildOutputType(allocator, args, Module.Kind.Exe);
516 return buildOutputType(allocator, args, Compilation.Kind.Exe);
517517}
518518
519519fn cmdBuildLib(allocator: *Allocator, args: []const []const u8) !void {
520 return buildOutputType(allocator, args, Module.Kind.Lib);
520 return buildOutputType(allocator, args, Compilation.Kind.Lib);
521521}
522522
523523fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
524 return buildOutputType(allocator, args, Module.Kind.Obj);
524 return buildOutputType(allocator, args, Compilation.Kind.Obj);
525525}
526526
527527const 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 @@
11const std = @import("std");
22const Allocator = mem.Allocator;
33const Decl = @import("decl.zig").Decl;
4const Module = @import("module.zig").Module;
4const Compilation = @import("compilation.zig").Compilation;
55const mem = std.mem;
66const ast = std.zig.ast;
77const Value = @import("value.zig").Value;
......@@ -16,17 +16,17 @@ pub const Scope = struct {
1616 base.ref_count += 1;
1717 }
1818
19 pub fn deref(base: *Scope, module: *Module) void {
19 pub fn deref(base: *Scope, comp: *Compilation) void {
2020 base.ref_count -= 1;
2121 if (base.ref_count == 0) {
22 if (base.parent) |parent| parent.deref(module);
22 if (base.parent) |parent| parent.deref(comp);
2323 switch (base.id) {
2424 Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(),
25 Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
26 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(module),
27 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(module),
28 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(module),
29 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(module),
25 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
26 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
27 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
28 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
29 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
3030 }
3131 }
3232 }
......@@ -61,8 +61,8 @@ pub const Scope = struct {
6161 table: Decl.Table,
6262
6363 /// Creates a Decls scope with 1 reference
64 pub fn create(module: *Module, parent: ?*Scope) !*Decls {
65 const self = try module.a().create(Decls{
64 pub fn create(comp: *Compilation, parent: ?*Scope) !*Decls {
65 const self = try comp.a().create(Decls{
6666 .base = Scope{
6767 .id = Id.Decls,
6868 .parent = parent,
......@@ -70,9 +70,9 @@ pub const Scope = struct {
7070 },
7171 .table = undefined,
7272 });
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());
7676 errdefer self.table.deinit();
7777
7878 if (parent) |p| p.ref();
......@@ -94,8 +94,8 @@ pub const Scope = struct {
9494 is_comptime: *ir.Instruction,
9595
9696 /// Creates a Block scope with 1 reference
97 pub fn create(module: *Module, parent: ?*Scope) !*Block {
98 const self = try module.a().create(Block{
97 pub fn create(comp: *Compilation, parent: ?*Scope) !*Block {
98 const self = try comp.a().create(Block{
9999 .base = Scope{
100100 .id = Id.Block,
101101 .parent = parent,
......@@ -106,14 +106,14 @@ pub const Scope = struct {
106106 .end_block = undefined,
107107 .is_comptime = undefined,
108108 });
109 errdefer module.a().destroy(self);
109 errdefer comp.a().destroy(self);
110110
111111 if (parent) |p| p.ref();
112112 return self;
113113 }
114114
115 pub fn destroy(self: *Block, module: *Module) void {
116 module.a().destroy(self);
115 pub fn destroy(self: *Block, comp: *Compilation) void {
116 comp.a().destroy(self);
117117 }
118118 };
119119
......@@ -125,8 +125,8 @@ pub const Scope = struct {
125125
126126 /// Creates a FnDef scope with 1 reference
127127 /// Must set the fn_val later
128 pub fn create(module: *Module, parent: ?*Scope) !*FnDef {
129 const self = try module.a().create(FnDef{
128 pub fn create(comp: *Compilation, parent: ?*Scope) !*FnDef {
129 const self = try comp.a().create(FnDef{
130130 .base = Scope{
131131 .id = Id.FnDef,
132132 .parent = parent,
......@@ -140,8 +140,8 @@ pub const Scope = struct {
140140 return self;
141141 }
142142
143 pub fn destroy(self: *FnDef, module: *Module) void {
144 module.a().destroy(self);
143 pub fn destroy(self: *FnDef, comp: *Compilation) void {
144 comp.a().destroy(self);
145145 }
146146 };
147147
......@@ -149,8 +149,8 @@ pub const Scope = struct {
149149 base: Scope,
150150
151151 /// Creates a CompTime scope with 1 reference
152 pub fn create(module: *Module, parent: ?*Scope) !*CompTime {
153 const self = try module.a().create(CompTime{
152 pub fn create(comp: *Compilation, parent: ?*Scope) !*CompTime {
153 const self = try comp.a().create(CompTime{
154154 .base = Scope{
155155 .id = Id.CompTime,
156156 .parent = parent,
......@@ -162,8 +162,8 @@ pub const Scope = struct {
162162 return self;
163163 }
164164
165 pub fn destroy(self: *CompTime, module: *Module) void {
166 module.a().destroy(self);
165 pub fn destroy(self: *CompTime, comp: *Compilation) void {
166 comp.a().destroy(self);
167167 }
168168 };
169169
......@@ -179,12 +179,12 @@ pub const Scope = struct {
179179
180180 /// Creates a Defer scope with 1 reference
181181 pub fn create(
182 module: *Module,
182 comp: *Compilation,
183183 parent: ?*Scope,
184184 kind: Kind,
185185 defer_expr_scope: *DeferExpr,
186186 ) !*Defer {
187 const self = try module.a().create(Defer{
187 const self = try comp.a().create(Defer{
188188 .base = Scope{
189189 .id = Id.Defer,
190190 .parent = parent,
......@@ -193,7 +193,7 @@ pub const Scope = struct {
193193 .defer_expr_scope = defer_expr_scope,
194194 .kind = kind,
195195 });
196 errdefer module.a().destroy(self);
196 errdefer comp.a().destroy(self);
197197
198198 defer_expr_scope.base.ref();
199199
......@@ -201,9 +201,9 @@ pub const Scope = struct {
201201 return self;
202202 }
203203
204 pub fn destroy(self: *Defer, module: *Module) void {
205 self.defer_expr_scope.base.deref(module);
206 module.a().destroy(self);
204 pub fn destroy(self: *Defer, comp: *Compilation) void {
205 self.defer_expr_scope.base.deref(comp);
206 comp.a().destroy(self);
207207 }
208208 };
209209
......@@ -212,8 +212,8 @@ pub const Scope = struct {
212212 expr_node: *ast.Node,
213213
214214 /// Creates a DeferExpr scope with 1 reference
215 pub fn create(module: *Module, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
216 const self = try module.a().create(DeferExpr{
215 pub fn create(comp: *Compilation, parent: ?*Scope, expr_node: *ast.Node) !*DeferExpr {
216 const self = try comp.a().create(DeferExpr{
217217 .base = Scope{
218218 .id = Id.DeferExpr,
219219 .parent = parent,
......@@ -221,14 +221,14 @@ pub const Scope = struct {
221221 },
222222 .expr_node = expr_node,
223223 });
224 errdefer module.a().destroy(self);
224 errdefer comp.a().destroy(self);
225225
226226 if (parent) |p| p.ref();
227227 return self;
228228 }
229229
230 pub fn destroy(self: *DeferExpr, module: *Module) void {
231 module.a().destroy(self);
230 pub fn destroy(self: *DeferExpr, comp: *Compilation) void {
231 comp.a().destroy(self);
232232 }
233233 };
234234};
src-self-hosted/test.zig+13-13
......@@ -2,11 +2,11 @@ const std = @import("std");
22const mem = std.mem;
33const builtin = @import("builtin");
44const Target = @import("target.zig").Target;
5const Module = @import("module.zig").Module;
5const Compilation = @import("compilation.zig").Compilation;
66const introspect = @import("introspect.zig");
77const assertOrPanic = std.debug.assertOrPanic;
88const errmsg = @import("errmsg.zig");
9const EventLoopLocal = @import("module.zig").EventLoopLocal;
9const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
1010
1111test "compile errors" {
1212 var ctx: TestContext = undefined;
......@@ -100,42 +100,42 @@ pub const TestContext = struct {
100100 // TODO async I/O
101101 try std.io.writeFile(allocator, file1_path, source);
102102
103 var module = try Module.create(
103 var comp = try Compilation.create(
104104 &self.event_loop_local,
105105 "test",
106106 file1_path,
107107 Target.Native,
108 Module.Kind.Obj,
108 Compilation.Kind.Obj,
109109 builtin.Mode.Debug,
110110 self.zig_lib_dir,
111111 self.zig_cache_dir,
112112 );
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);
118118 }
119119
120120 async fn getModuleEvent(
121 module: *Module,
121 comp: *Compilation,
122122 source: []const u8,
123123 path: []const u8,
124124 line: usize,
125125 column: usize,
126126 text: []const u8,
127127 ) !void {
128 defer module.destroy();
129 const build_event = await (async module.events.get() catch unreachable);
128 defer comp.destroy();
129 const build_event = await (async comp.events.get() catch unreachable);
130130
131131 switch (build_event) {
132 Module.Event.Ok => {
132 Compilation.Event.Ok => {
133133 @panic("build incorrectly succeeded");
134134 },
135 Module.Event.Error => |err| {
135 Compilation.Event.Error => |err| {
136136 @panic("build incorrectly failed");
137137 },
138 Module.Event.Fail => |msgs| {
138 Compilation.Event.Fail => |msgs| {
139139 assertOrPanic(msgs.len != 0);
140140 for (msgs) |msg| {
141141 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 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const Scope = @import("scope.zig").Scope;
4const Module = @import("module.zig").Module;
4const Compilation = @import("compilation.zig").Compilation;
55const Value = @import("value.zig").Value;
66const llvm = @import("llvm.zig");
7const CompilationUnit = @import("codegen.zig").CompilationUnit;
7const ObjectFile = @import("codegen.zig").ObjectFile;
88
99pub const Type = struct {
1010 base: Value,
......@@ -12,63 +12,63 @@ pub const Type = struct {
1212
1313 pub const Id = builtin.TypeId;
1414
15 pub fn destroy(base: *Type, module: *Module) void {
15 pub fn destroy(base: *Type, comp: *Compilation) void {
1616 switch (base.id) {
17 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(module),
18 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
19 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(module),
20 Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
21 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
22 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
23 Id.Int => @fieldParentPtr(Int, "base", base).destroy(module),
24 Id.Float => @fieldParentPtr(Float, "base", base).destroy(module),
25 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(module),
26 Id.Array => @fieldParentPtr(Array, "base", base).destroy(module),
27 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(module),
28 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(module),
29 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(module),
30 Id.Null => @fieldParentPtr(Null, "base", base).destroy(module),
31 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(module),
32 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(module),
33 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(module),
34 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(module),
35 Id.Union => @fieldParentPtr(Union, "base", base).destroy(module),
36 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(module),
37 Id.Block => @fieldParentPtr(Block, "base", base).destroy(module),
38 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(module),
39 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(module),
40 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(module),
41 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(module),
17 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
18 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
19 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
20 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
21 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
22 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
23 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
24 Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),
25 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
26 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
27 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
28 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
29 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
30 Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),
31 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
32 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
33 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
34 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
35 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
36 Id.Namespace => @fieldParentPtr(Namespace, "base", base).destroy(comp),
37 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
38 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
39 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
40 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
41 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
4242 }
4343 }
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) {
4646 switch (base.id) {
47 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(cunit),
48 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(cunit),
47 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(ofile),
48 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(ofile),
4949 Id.Type => unreachable,
5050 Id.Void => unreachable,
51 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(cunit),
51 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(ofile),
5252 Id.NoReturn => unreachable,
53 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(cunit),
54 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(cunit),
55 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(cunit),
56 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(cunit),
53 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(ofile),
54 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(ofile),
55 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(ofile),
56 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(ofile),
5757 Id.ComptimeFloat => unreachable,
5858 Id.ComptimeInt => unreachable,
5959 Id.Undefined => unreachable,
6060 Id.Null => unreachable,
61 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(cunit),
62 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(cunit),
63 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(cunit),
64 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(cunit),
65 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(cunit),
61 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(ofile),
62 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(ofile),
63 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(ofile),
64 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(ofile),
65 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(ofile),
6666 Id.Namespace => unreachable,
6767 Id.Block => unreachable,
68 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(cunit),
68 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(ofile),
6969 Id.ArgTuple => unreachable,
70 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(cunit),
71 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(cunit),
70 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(ofile),
71 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(ofile),
7272 }
7373 }
7474
......@@ -76,7 +76,7 @@ pub const Type = struct {
7676 std.debug.warn("{}", @tagName(base.id));
7777 }
7878
79 pub fn getAbiAlignment(base: *Type, module: *Module) u32 {
79 pub fn getAbiAlignment(base: *Type, comp: *Compilation) u32 {
8080 @panic("TODO getAbiAlignment");
8181 }
8282
......@@ -84,11 +84,11 @@ pub const Type = struct {
8484 base: Type,
8585 decls: *Scope.Decls,
8686
87 pub fn destroy(self: *Struct, module: *Module) void {
88 module.a().destroy(self);
87 pub fn destroy(self: *Struct, comp: *Compilation) void {
88 comp.a().destroy(self);
8989 }
9090
91 pub fn getLlvmType(self: *Struct, cunit: *CompilationUnit) llvm.TypeRef {
91 pub fn getLlvmType(self: *Struct, ofile: *ObjectFile) llvm.TypeRef {
9292 @panic("TODO");
9393 }
9494 };
......@@ -104,12 +104,12 @@ pub const Type = struct {
104104 typeof: *Type,
105105 };
106106
107 pub fn create(module: *Module, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
108 const result = try module.a().create(Fn{
107 pub fn create(comp: *Compilation, return_type: *Type, params: []Param, is_var_args: bool) !*Fn {
108 const result = try comp.a().create(Fn{
109109 .base = Type{
110110 .base = Value{
111111 .id = Value.Id.Type,
112 .typeof = &MetaType.get(module).base,
112 .typeof = &MetaType.get(comp).base,
113113 .ref_count = std.atomic.Int(usize).init(1),
114114 },
115115 .id = builtin.TypeId.Fn,
......@@ -118,7 +118,7 @@ pub const Type = struct {
118118 .params = params,
119119 .is_var_args = is_var_args,
120120 });
121 errdefer module.a().destroy(result);
121 errdefer comp.a().destroy(result);
122122
123123 result.return_type.base.ref();
124124 for (result.params) |param| {
......@@ -127,23 +127,23 @@ pub const Type = struct {
127127 return result;
128128 }
129129
130 pub fn destroy(self: *Fn, module: *Module) void {
131 self.return_type.base.deref(module);
130 pub fn destroy(self: *Fn, comp: *Compilation) void {
131 self.return_type.base.deref(comp);
132132 for (self.params) |param| {
133 param.typeof.base.deref(module);
133 param.typeof.base.deref(comp);
134134 }
135 module.a().destroy(self);
135 comp.a().destroy(self);
136136 }
137137
138 pub fn getLlvmType(self: *Fn, cunit: *CompilationUnit) !llvm.TypeRef {
138 pub fn getLlvmType(self: *Fn, ofile: *ObjectFile) !llvm.TypeRef {
139139 const llvm_return_type = switch (self.return_type.id) {
140 Type.Id.Void => llvm.VoidTypeInContext(cunit.context) orelse return error.OutOfMemory,
141 else => try self.return_type.getLlvmType(cunit),
140 Type.Id.Void => llvm.VoidTypeInContext(ofile.context) orelse return error.OutOfMemory,
141 else => try self.return_type.getLlvmType(ofile),
142142 };
143 const llvm_param_types = try cunit.a().alloc(llvm.TypeRef, self.params.len);
144 defer cunit.a().free(llvm_param_types);
143 const llvm_param_types = try ofile.a().alloc(llvm.TypeRef, self.params.len);
144 defer ofile.a().free(llvm_param_types);
145145 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);
147147 }
148148
149149 return llvm.FunctionType(
......@@ -160,13 +160,13 @@ pub const Type = struct {
160160 value: *Type,
161161
162162 /// Adds 1 reference to the resulting type
163 pub fn get(module: *Module) *MetaType {
164 module.meta_type.base.base.ref();
165 return module.meta_type;
163 pub fn get(comp: *Compilation) *MetaType {
164 comp.meta_type.base.base.ref();
165 return comp.meta_type;
166166 }
167167
168 pub fn destroy(self: *MetaType, module: *Module) void {
169 module.a().destroy(self);
168 pub fn destroy(self: *MetaType, comp: *Compilation) void {
169 comp.a().destroy(self);
170170 }
171171 };
172172
......@@ -174,13 +174,13 @@ pub const Type = struct {
174174 base: Type,
175175
176176 /// Adds 1 reference to the resulting type
177 pub fn get(module: *Module) *Void {
178 module.void_type.base.base.ref();
179 return module.void_type;
177 pub fn get(comp: *Compilation) *Void {
178 comp.void_type.base.base.ref();
179 return comp.void_type;
180180 }
181181
182 pub fn destroy(self: *Void, module: *Module) void {
183 module.a().destroy(self);
182 pub fn destroy(self: *Void, comp: *Compilation) void {
183 comp.a().destroy(self);
184184 }
185185 };
186186
......@@ -188,16 +188,16 @@ pub const Type = struct {
188188 base: Type,
189189
190190 /// Adds 1 reference to the resulting type
191 pub fn get(module: *Module) *Bool {
192 module.bool_type.base.base.ref();
193 return module.bool_type;
191 pub fn get(comp: *Compilation) *Bool {
192 comp.bool_type.base.base.ref();
193 return comp.bool_type;
194194 }
195195
196 pub fn destroy(self: *Bool, module: *Module) void {
197 module.a().destroy(self);
196 pub fn destroy(self: *Bool, comp: *Compilation) void {
197 comp.a().destroy(self);
198198 }
199199
200 pub fn getLlvmType(self: *Bool, cunit: *CompilationUnit) llvm.TypeRef {
200 pub fn getLlvmType(self: *Bool, ofile: *ObjectFile) llvm.TypeRef {
201201 @panic("TODO");
202202 }
203203 };
......@@ -206,24 +206,24 @@ pub const Type = struct {
206206 base: Type,
207207
208208 /// Adds 1 reference to the resulting type
209 pub fn get(module: *Module) *NoReturn {
210 module.noreturn_type.base.base.ref();
211 return module.noreturn_type;
209 pub fn get(comp: *Compilation) *NoReturn {
210 comp.noreturn_type.base.base.ref();
211 return comp.noreturn_type;
212212 }
213213
214 pub fn destroy(self: *NoReturn, module: *Module) void {
215 module.a().destroy(self);
214 pub fn destroy(self: *NoReturn, comp: *Compilation) void {
215 comp.a().destroy(self);
216216 }
217217 };
218218
219219 pub const Int = struct {
220220 base: Type,
221221
222 pub fn destroy(self: *Int, module: *Module) void {
223 module.a().destroy(self);
222 pub fn destroy(self: *Int, comp: *Compilation) void {
223 comp.a().destroy(self);
224224 }
225225
226 pub fn getLlvmType(self: *Int, cunit: *CompilationUnit) llvm.TypeRef {
226 pub fn getLlvmType(self: *Int, ofile: *ObjectFile) llvm.TypeRef {
227227 @panic("TODO");
228228 }
229229 };
......@@ -231,11 +231,11 @@ pub const Type = struct {
231231 pub const Float = struct {
232232 base: Type,
233233
234 pub fn destroy(self: *Float, module: *Module) void {
235 module.a().destroy(self);
234 pub fn destroy(self: *Float, comp: *Compilation) void {
235 comp.a().destroy(self);
236236 }
237237
238 pub fn getLlvmType(self: *Float, cunit: *CompilationUnit) llvm.TypeRef {
238 pub fn getLlvmType(self: *Float, ofile: *ObjectFile) llvm.TypeRef {
239239 @panic("TODO");
240240 }
241241 };
......@@ -256,12 +256,12 @@ pub const Type = struct {
256256 };
257257 pub const Size = builtin.TypeInfo.Pointer.Size;
258258
259 pub fn destroy(self: *Pointer, module: *Module) void {
260 module.a().destroy(self);
259 pub fn destroy(self: *Pointer, comp: *Compilation) void {
260 comp.a().destroy(self);
261261 }
262262
263263 pub fn get(
264 module: *Module,
264 comp: *Compilation,
265265 elem_type: *Type,
266266 mut: Mut,
267267 vol: Vol,
......@@ -271,7 +271,7 @@ pub const Type = struct {
271271 @panic("TODO get pointer");
272272 }
273273
274 pub fn getLlvmType(self: *Pointer, cunit: *CompilationUnit) llvm.TypeRef {
274 pub fn getLlvmType(self: *Pointer, ofile: *ObjectFile) llvm.TypeRef {
275275 @panic("TODO");
276276 }
277277 };
......@@ -279,11 +279,11 @@ pub const Type = struct {
279279 pub const Array = struct {
280280 base: Type,
281281
282 pub fn destroy(self: *Array, module: *Module) void {
283 module.a().destroy(self);
282 pub fn destroy(self: *Array, comp: *Compilation) void {
283 comp.a().destroy(self);
284284 }
285285
286 pub fn getLlvmType(self: *Array, cunit: *CompilationUnit) llvm.TypeRef {
286 pub fn getLlvmType(self: *Array, ofile: *ObjectFile) llvm.TypeRef {
287287 @panic("TODO");
288288 }
289289 };
......@@ -291,43 +291,43 @@ pub const Type = struct {
291291 pub const ComptimeFloat = struct {
292292 base: Type,
293293
294 pub fn destroy(self: *ComptimeFloat, module: *Module) void {
295 module.a().destroy(self);
294 pub fn destroy(self: *ComptimeFloat, comp: *Compilation) void {
295 comp.a().destroy(self);
296296 }
297297 };
298298
299299 pub const ComptimeInt = struct {
300300 base: Type,
301301
302 pub fn destroy(self: *ComptimeInt, module: *Module) void {
303 module.a().destroy(self);
302 pub fn destroy(self: *ComptimeInt, comp: *Compilation) void {
303 comp.a().destroy(self);
304304 }
305305 };
306306
307307 pub const Undefined = struct {
308308 base: Type,
309309
310 pub fn destroy(self: *Undefined, module: *Module) void {
311 module.a().destroy(self);
310 pub fn destroy(self: *Undefined, comp: *Compilation) void {
311 comp.a().destroy(self);
312312 }
313313 };
314314
315315 pub const Null = struct {
316316 base: Type,
317317
318 pub fn destroy(self: *Null, module: *Module) void {
319 module.a().destroy(self);
318 pub fn destroy(self: *Null, comp: *Compilation) void {
319 comp.a().destroy(self);
320320 }
321321 };
322322
323323 pub const Optional = struct {
324324 base: Type,
325325
326 pub fn destroy(self: *Optional, module: *Module) void {
327 module.a().destroy(self);
326 pub fn destroy(self: *Optional, comp: *Compilation) void {
327 comp.a().destroy(self);
328328 }
329329
330 pub fn getLlvmType(self: *Optional, cunit: *CompilationUnit) llvm.TypeRef {
330 pub fn getLlvmType(self: *Optional, ofile: *ObjectFile) llvm.TypeRef {
331331 @panic("TODO");
332332 }
333333 };
......@@ -335,11 +335,11 @@ pub const Type = struct {
335335 pub const ErrorUnion = struct {
336336 base: Type,
337337
338 pub fn destroy(self: *ErrorUnion, module: *Module) void {
339 module.a().destroy(self);
338 pub fn destroy(self: *ErrorUnion, comp: *Compilation) void {
339 comp.a().destroy(self);
340340 }
341341
342 pub fn getLlvmType(self: *ErrorUnion, cunit: *CompilationUnit) llvm.TypeRef {
342 pub fn getLlvmType(self: *ErrorUnion, ofile: *ObjectFile) llvm.TypeRef {
343343 @panic("TODO");
344344 }
345345 };
......@@ -347,11 +347,11 @@ pub const Type = struct {
347347 pub const ErrorSet = struct {
348348 base: Type,
349349
350 pub fn destroy(self: *ErrorSet, module: *Module) void {
351 module.a().destroy(self);
350 pub fn destroy(self: *ErrorSet, comp: *Compilation) void {
351 comp.a().destroy(self);
352352 }
353353
354 pub fn getLlvmType(self: *ErrorSet, cunit: *CompilationUnit) llvm.TypeRef {
354 pub fn getLlvmType(self: *ErrorSet, ofile: *ObjectFile) llvm.TypeRef {
355355 @panic("TODO");
356356 }
357357 };
......@@ -359,11 +359,11 @@ pub const Type = struct {
359359 pub const Enum = struct {
360360 base: Type,
361361
362 pub fn destroy(self: *Enum, module: *Module) void {
363 module.a().destroy(self);
362 pub fn destroy(self: *Enum, comp: *Compilation) void {
363 comp.a().destroy(self);
364364 }
365365
366 pub fn getLlvmType(self: *Enum, cunit: *CompilationUnit) llvm.TypeRef {
366 pub fn getLlvmType(self: *Enum, ofile: *ObjectFile) llvm.TypeRef {
367367 @panic("TODO");
368368 }
369369 };
......@@ -371,11 +371,11 @@ pub const Type = struct {
371371 pub const Union = struct {
372372 base: Type,
373373
374 pub fn destroy(self: *Union, module: *Module) void {
375 module.a().destroy(self);
374 pub fn destroy(self: *Union, comp: *Compilation) void {
375 comp.a().destroy(self);
376376 }
377377
378 pub fn getLlvmType(self: *Union, cunit: *CompilationUnit) llvm.TypeRef {
378 pub fn getLlvmType(self: *Union, ofile: *ObjectFile) llvm.TypeRef {
379379 @panic("TODO");
380380 }
381381 };
......@@ -383,27 +383,27 @@ pub const Type = struct {
383383 pub const Namespace = struct {
384384 base: Type,
385385
386 pub fn destroy(self: *Namespace, module: *Module) void {
387 module.a().destroy(self);
386 pub fn destroy(self: *Namespace, comp: *Compilation) void {
387 comp.a().destroy(self);
388388 }
389389 };
390390
391391 pub const Block = struct {
392392 base: Type,
393393
394 pub fn destroy(self: *Block, module: *Module) void {
395 module.a().destroy(self);
394 pub fn destroy(self: *Block, comp: *Compilation) void {
395 comp.a().destroy(self);
396396 }
397397 };
398398
399399 pub const BoundFn = struct {
400400 base: Type,
401401
402 pub fn destroy(self: *BoundFn, module: *Module) void {
403 module.a().destroy(self);
402 pub fn destroy(self: *BoundFn, comp: *Compilation) void {
403 comp.a().destroy(self);
404404 }
405405
406 pub fn getLlvmType(self: *BoundFn, cunit: *CompilationUnit) llvm.TypeRef {
406 pub fn getLlvmType(self: *BoundFn, ofile: *ObjectFile) llvm.TypeRef {
407407 @panic("TODO");
408408 }
409409 };
......@@ -411,19 +411,19 @@ pub const Type = struct {
411411 pub const ArgTuple = struct {
412412 base: Type,
413413
414 pub fn destroy(self: *ArgTuple, module: *Module) void {
415 module.a().destroy(self);
414 pub fn destroy(self: *ArgTuple, comp: *Compilation) void {
415 comp.a().destroy(self);
416416 }
417417 };
418418
419419 pub const Opaque = struct {
420420 base: Type,
421421
422 pub fn destroy(self: *Opaque, module: *Module) void {
423 module.a().destroy(self);
422 pub fn destroy(self: *Opaque, comp: *Compilation) void {
423 comp.a().destroy(self);
424424 }
425425
426 pub fn getLlvmType(self: *Opaque, cunit: *CompilationUnit) llvm.TypeRef {
426 pub fn getLlvmType(self: *Opaque, ofile: *ObjectFile) llvm.TypeRef {
427427 @panic("TODO");
428428 }
429429 };
......@@ -431,11 +431,11 @@ pub const Type = struct {
431431 pub const Promise = struct {
432432 base: Type,
433433
434 pub fn destroy(self: *Promise, module: *Module) void {
435 module.a().destroy(self);
434 pub fn destroy(self: *Promise, comp: *Compilation) void {
435 comp.a().destroy(self);
436436 }
437437
438 pub fn getLlvmType(self: *Promise, cunit: *CompilationUnit) llvm.TypeRef {
438 pub fn getLlvmType(self: *Promise, ofile: *ObjectFile) llvm.TypeRef {
439439 @panic("TODO");
440440 }
441441 };
src-self-hosted/value.zig+33-33
......@@ -1,7 +1,7 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const Scope = @import("scope.zig").Scope;
4const Module = @import("module.zig").Module;
4const Compilation = @import("compilation.zig").Compilation;
55
66/// Values are ref-counted, heap-allocated, and copy-on-write
77/// If there is only 1 ref then write need not copy
......@@ -16,16 +16,16 @@ pub const Value = struct {
1616 }
1717
1818 /// Thread-safe
19 pub fn deref(base: *Value, module: *Module) void {
19 pub fn deref(base: *Value, comp: *Compilation) void {
2020 if (base.ref_count.decr() == 1) {
21 base.typeof.base.deref(module);
21 base.typeof.base.deref(comp);
2222 switch (base.id) {
23 Id.Type => @fieldParentPtr(Type, "base", base).destroy(module),
24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(module),
25 Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
26 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
27 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
28 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(module),
23 Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
25 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
26 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
27 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
28 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
2929 }
3030 }
3131 }
......@@ -68,8 +68,8 @@ pub const Value = struct {
6868
6969 /// Creates a Fn value with 1 ref
7070 /// Takes ownership of symbol_name
71 pub fn create(module: *Module, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
72 const self = try module.a().create(Fn{
71 pub fn create(comp: *Compilation, fn_type: *Type.Fn, fndef_scope: *Scope.FnDef, symbol_name: std.Buffer) !*Fn {
72 const self = try comp.a().create(Fn{
7373 .base = Value{
7474 .id = Value.Id.Fn,
7575 .typeof = &fn_type.base,
......@@ -86,23 +86,23 @@ pub const Value = struct {
8686 return self;
8787 }
8888
89 pub fn destroy(self: *Fn, module: *Module) void {
90 self.fndef_scope.base.deref(module);
89 pub fn destroy(self: *Fn, comp: *Compilation) void {
90 self.fndef_scope.base.deref(comp);
9191 self.symbol_name.deinit();
92 module.a().destroy(self);
92 comp.a().destroy(self);
9393 }
9494 };
9595
9696 pub const Void = struct {
9797 base: Value,
9898
99 pub fn get(module: *Module) *Void {
100 module.void_value.base.ref();
101 return module.void_value;
99 pub fn get(comp: *Compilation) *Void {
100 comp.void_value.base.ref();
101 return comp.void_value;
102102 }
103103
104 pub fn destroy(self: *Void, module: *Module) void {
105 module.a().destroy(self);
104 pub fn destroy(self: *Void, comp: *Compilation) void {
105 comp.a().destroy(self);
106106 }
107107 };
108108
......@@ -110,31 +110,31 @@ pub const Value = struct {
110110 base: Value,
111111 x: bool,
112112
113 pub fn get(module: *Module, x: bool) *Bool {
113 pub fn get(comp: *Compilation, x: bool) *Bool {
114114 if (x) {
115 module.true_value.base.ref();
116 return module.true_value;
115 comp.true_value.base.ref();
116 return comp.true_value;
117117 } else {
118 module.false_value.base.ref();
119 return module.false_value;
118 comp.false_value.base.ref();
119 return comp.false_value;
120120 }
121121 }
122122
123 pub fn destroy(self: *Bool, module: *Module) void {
124 module.a().destroy(self);
123 pub fn destroy(self: *Bool, comp: *Compilation) void {
124 comp.a().destroy(self);
125125 }
126126 };
127127
128128 pub const NoReturn = struct {
129129 base: Value,
130130
131 pub fn get(module: *Module) *NoReturn {
132 module.noreturn_value.base.ref();
133 return module.noreturn_value;
131 pub fn get(comp: *Compilation) *NoReturn {
132 comp.noreturn_value.base.ref();
133 return comp.noreturn_value;
134134 }
135135
136 pub fn destroy(self: *NoReturn, module: *Module) void {
137 module.a().destroy(self);
136 pub fn destroy(self: *NoReturn, comp: *Compilation) void {
137 comp.a().destroy(self);
138138 }
139139 };
140140
......@@ -147,8 +147,8 @@ pub const Value = struct {
147147 RunTime,
148148 };
149149
150 pub fn destroy(self: *Ptr, module: *Module) void {
151 module.a().destroy(self);
150 pub fn destroy(self: *Ptr, comp: *Compilation) void {
151 comp.a().destroy(self);
152152 }
153153 };
154154};