Skip to content

Commit e78b1b8

Browse files
committedJul 14, 2018
self-hosted: basic IR pass2
·
0.15.10.3.0
1 parent c87102c commit e78b1b8

File tree

7 files changed

+708
-205
lines changed

7 files changed

+708
-205
lines changed
 

‎src-self-hosted/errmsg.zig‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ pub const Color = enum {
1414
pub const Span = struct {
1515
first: ast.TokenIndex,
1616
last: ast.TokenIndex,
17+
18+
pub fn token(i: TokenIndex) Span {
19+
return Span {
20+
.first = i,
21+
.last = i,
22+
};
23+
}
1724
};
1825

1926
pub const Msg = struct {

‎src-self-hosted/ir.zig‎

Lines changed: 569 additions & 181 deletions
Large diffs are not rendered by default.

‎src-self-hosted/main.zig‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
497497
},
498498
Module.Event.Error => |err| {
499499
std.debug.warn("build failed: {}\n", @errorName(err));
500-
@panic("TODO error return trace");
500+
os.exit(1);
501501
},
502502
Module.Event.Fail => |msgs| {
503503
for (msgs) |msg| {

‎src-self-hosted/module.zig‎

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const Visib = @import("visib.zig").Visib;
2424
const ParsedFile = @import("parsed_file.zig").ParsedFile;
2525
const Value = @import("value.zig").Value;
2626
const Type = Value.Type;
27+
const Span = errmsg.Span;
2728

2829
pub const Module = struct {
2930
loop: *event.Loop,
@@ -148,13 +149,14 @@ pub const Module = struct {
148149
Overflow,
149150
NotSupported,
150151
BufferTooSmall,
151-
Unimplemented,
152+
Unimplemented, // TODO remove this one
153+
SemanticAnalysisFailed, // TODO remove this one
152154
};
153155

154156
pub const Event = union(enum) {
155157
Ok,
156-
Fail: []*errmsg.Msg,
157158
Error: BuildError,
159+
Fail: []*errmsg.Msg,
158160
};
159161

160162
pub const DarwinVersionMin = union(enum) {
@@ -413,21 +415,32 @@ pub const Module = struct {
413415
while (true) {
414416
// TODO directly awaiting async should guarantee memory allocation elision
415417
// TODO also async before suspending should guarantee memory allocation elision
416-
(await (async self.addRootSrc() catch unreachable)) catch |err| {
417-
await (async self.events.put(Event{ .Error = err }) catch unreachable);
418-
return;
419-
};
418+
const build_result = await (async self.addRootSrc() catch unreachable);
419+
420+
// this makes a handy error return trace and stack trace in debug mode
421+
if (std.debug.runtime_safety) {
422+
build_result catch unreachable;
423+
}
424+
420425
const compile_errors = blk: {
421426
const held = await (async self.compile_errors.acquire() catch unreachable);
422427
defer held.release();
423428
break :blk held.value.toOwnedSlice();
424429
};
425430

426-
if (compile_errors.len == 0) {
427-
await (async self.events.put(Event.Ok) catch unreachable);
428-
} else {
429-
await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
431+
if (build_result) |_| {
432+
if (compile_errors.len == 0) {
433+
await (async self.events.put(Event.Ok) catch unreachable);
434+
} else {
435+
await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
436+
}
437+
} else |err| {
438+
// if there's an error then the compile errors have dangling references
439+
self.a().free(compile_errors);
440+
441+
await (async self.events.put(Event{ .Error = err }) catch unreachable);
430442
}
443+
431444
// for now we stop after 1
432445
return;
433446
}
@@ -477,7 +490,7 @@ pub const Module = struct {
477490
const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
478491

479492
const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
480-
try self.addCompileError(parsed_file, errmsg.Span{
493+
try self.addCompileError(parsed_file, Span{
481494
.first = fn_proto.fn_token,
482495
.last = fn_proto.fn_token + 1,
483496
}, "missing function name");
@@ -518,27 +531,23 @@ pub const Module = struct {
518531
}
519532
}
520533

521-
fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: errmsg.Span, comptime fmt: []const u8, args: ...) !void {
534+
fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: Span, comptime fmt: []const u8, args: ...) !void {
522535
const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
523536
errdefer self.loop.allocator.free(text);
524537

525-
try self.build_group.call(addCompileErrorAsync, self, parsed_file, span.first, span.last, text);
538+
try self.build_group.call(addCompileErrorAsync, self, parsed_file, span, text);
526539
}
527540

528541
async fn addCompileErrorAsync(
529542
self: *Module,
530543
parsed_file: *ParsedFile,
531-
first_token: ast.TokenIndex,
532-
last_token: ast.TokenIndex,
544+
span: Span,
533545
text: []u8,
534546
) !void {
535547
const msg = try self.loop.allocator.create(errmsg.Msg{
536548
.path = parsed_file.realpath,
537549
.text = text,
538-
.span = errmsg.Span{
539-
.first = first_token,
540-
.last = last_token,
541-
},
550+
.span = span,
542551
.tree = &parsed_file.tree,
543552
});
544553
errdefer self.loop.allocator.destroy(msg);
@@ -624,6 +633,7 @@ pub async fn resolveDecl(module: *Module, decl: *Decl) !void {
624633
if (@atomicRmw(u8, &decl.resolution_in_progress, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {
625634
decl.resolution.data = await (async generateDecl(module, decl) catch unreachable);
626635
decl.resolution.resolve();
636+
return decl.resolution.data;
627637
} else {
628638
return (await (async decl.resolution.get() catch unreachable)).*;
629639
}
@@ -655,12 +665,41 @@ async fn generateDeclFn(module: *Module, fn_decl: *Decl.Fn) !void {
655665

656666
fn_decl.value = Decl.Fn.Val{ .Ok = fn_val };
657667

658-
const code = try await (async ir.gen(
668+
const unanalyzed_code = (await (async ir.gen(
659669
module,
660670
body_node,
661671
&fndef_scope.base,
672+
Span.token(body_node.lastToken()),
673+
fn_decl.base.parsed_file,
674+
) catch unreachable)) catch |err| switch (err) {
675+
// This poison value should not cause the errdefers to run. It simply means
676+
// that self.compile_errors is populated.
677+
error.SemanticAnalysisFailed => return {},
678+
else => return err,
679+
};
680+
defer unanalyzed_code.destroy(module.a());
681+
682+
if (module.verbose_ir) {
683+
std.debug.warn("unanalyzed:\n");
684+
unanalyzed_code.dump();
685+
}
686+
687+
const analyzed_code = (await (async ir.analyze(
688+
module,
662689
fn_decl.base.parsed_file,
663-
) catch unreachable);
664-
//code.dump();
665-
//try await (async irAnalyze(module, func) catch unreachable);
690+
unanalyzed_code,
691+
null,
692+
) catch unreachable)) catch |err| switch (err) {
693+
// This poison value should not cause the errdefers to run. It simply means
694+
// that self.compile_errors is populated.
695+
error.SemanticAnalysisFailed => return {},
696+
else => return err,
697+
};
698+
defer analyzed_code.destroy(module.a());
699+
700+
if (module.verbose_ir) {
701+
std.debug.warn("analyzed:\n");
702+
analyzed_code.dump();
703+
}
704+
// TODO now render to LLVM module
666705
}

‎src-self-hosted/type.zig‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ pub const Type = struct {
3939
}
4040
}
4141

42+
pub fn dump(base: *const Type) void {
43+
std.debug.warn("{}", @tagName(base.id));
44+
}
45+
46+
pub fn getAbiAlignment(base: *Type, module: *Module) u32 {
47+
@panic("TODO getAbiAlignment");
48+
}
49+
4250
pub const Struct = struct {
4351
base: Type,
4452
decls: *Scope.Decls,
@@ -143,10 +151,35 @@ pub const Type = struct {
143151
};
144152
pub const Pointer = struct {
145153
base: Type,
154+
mut: Mut,
155+
vol: Vol,
156+
size: Size,
157+
alignment: u32,
158+
159+
pub const Mut = enum {
160+
Mut,
161+
Const,
162+
};
163+
pub const Vol = enum {
164+
Non,
165+
Volatile,
166+
};
167+
pub const Size = builtin.TypeInfo.Pointer.Size;
146168

147169
pub fn destroy(self: *Pointer, module: *Module) void {
148170
module.a().destroy(self);
149171
}
172+
173+
pub fn get(
174+
module: *Module,
175+
elem_type: *Type,
176+
mut: Mut,
177+
vol: Vol,
178+
size: Size,
179+
alignment: u32,
180+
) *Pointer {
181+
@panic("TODO get pointer");
182+
}
150183
};
151184
pub const Array = struct {
152185
base: Type,

‎src-self-hosted/value.zig‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@ pub const Value = struct {
2424
Id.Void => @fieldParentPtr(Void, "base", base).destroy(module),
2525
Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(module),
2626
Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(module),
27+
Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(module),
2728
}
2829
}
2930
}
3031

32+
pub fn getRef(base: *Value) *Value {
33+
base.ref();
34+
return base;
35+
}
36+
3137
pub fn dump(base: *const Value) void {
3238
std.debug.warn("{}", @tagName(base.id));
3339
}
@@ -38,6 +44,7 @@ pub const Value = struct {
3844
Void,
3945
Bool,
4046
NoReturn,
47+
Ptr,
4148
};
4249

4350
pub const Type = @import("type.zig").Type;
@@ -122,4 +129,18 @@ pub const Value = struct {
122129
module.a().destroy(self);
123130
}
124131
};
132+
133+
pub const Ptr = struct {
134+
base: Value,
135+
136+
pub const Mut = enum {
137+
CompTimeConst,
138+
CompTimeVar,
139+
RunTime,
140+
};
141+
142+
pub fn destroy(self: *Ptr, module: *Module) void {
143+
module.a().destroy(self);
144+
}
145+
};
125146
};

‎std/event/loop.zig‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,21 @@ pub const Loop = struct {
382382
return async<self.allocator> S.asyncFunc(self, &handle, args);
383383
}
384384

385+
/// Awaiting a yield lets the event loop run, starting any unstarted async operations.
386+
/// Note that async operations automatically start when a function yields for any other reason,
387+
/// for example, when async I/O is performed. This function is intended to be used only when
388+
/// CPU bound tasks would be waiting in the event loop but never get started because no async I/O
389+
/// is performed.
390+
pub async fn yield(self: *Loop) void {
391+
suspend |p| {
392+
var my_tick_node = Loop.NextTickNode{
393+
.next = undefined,
394+
.data = p,
395+
};
396+
loop.onNextTick(&my_tick_node);
397+
}
398+
}
399+
385400
fn workerRun(self: *Loop) void {
386401
start_over: while (true) {
387402
if (@atomicRmw(u8, &self.dispatch_lock, AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) == 0) {

0 commit comments

Comments
 (0)
Please sign in to comment.