| author | |
| committer | |
| log | adc3371e964920ff856589de0621665f99f87580 |
| tree | b7ed26e4570086a94fb865e70f76176583a46e54 |
| parent | c1d54bf8b06f71d81e8614572483a69720da4ea6 |
| signature | Commit is signed but in an unrecognized format. |
9 files changed, 175 insertions(+), 29 deletions(-)
CHANGELOG.md+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | ## 0.1.1-alpha | 1 | ## 0.1.1-alpha |
| 2 | 2 | ||
| 3 | - introduce `Report` and show errors during Transform. | 3 | - introduce `Report` and show errors during Tokenize, Parse, and Transform. |
| 4 | - add flag --dump-ir for enabling ir dumps | 4 | - add flag --dump-ir for enabling ir dumps |
| 5 | 5 | ||
| 6 | ## 0.1.0-alpha | 6 | ## 0.1.0-alpha |
build.zig+12| ... | @@ -6,12 +6,23 @@ pub fn build(b: *std.Build) void { | ... | @@ -6,12 +6,23 @@ pub fn build(b: *std.Build) void { |
| 6 | const target = b.standardTargetOptions(.{}); | 6 | const target = b.standardTargetOptions(.{}); |
| 7 | const optimize = b.standardOptimizeOption(.{}); | 7 | const optimize = b.standardOptimizeOption(.{}); |
| 8 | 8 | ||
| 9 | const tracing = b.option(enum { | ||
| 10 | none, | ||
| 11 | spall, | ||
| 12 | chrome, | ||
| 13 | log, | ||
| 14 | }, "trace", "Enable tracing") orelse .none; | ||
| 15 | |||
| 9 | const dep_opts = .{ .target = target, .optimize = optimize }; | 16 | const dep_opts = .{ .target = target, .optimize = optimize }; |
| 10 | 17 | ||
| 11 | const zg = b.dependency("zg", dep_opts); | 18 | const zg = b.dependency("zg", dep_opts); |
| 12 | const tracer = b.dependency("tracer", dep_opts); | 19 | const tracer = b.dependency("tracer", dep_opts); |
| 13 | // const ada = b.dependency("ada", dep_opts); | 20 | // const ada = b.dependency("ada", dep_opts); |
| 14 | 21 | ||
| 22 | const opts = b.addOptions(); | ||
| 23 | opts.addOption([]const u8, "tracing", @tagName(tracing)); | ||
| 24 | const opts_mod = opts.createModule(); | ||
| 25 | |||
| 15 | const exe = b.addExecutable(.{ | 26 | const exe = b.addExecutable(.{ |
| 16 | .name = "compiler", | 27 | .name = "compiler", |
| 17 | .root_source_file = b.path("src/compiler/main.zig"), | 28 | .root_source_file = b.path("src/compiler/main.zig"), |
| ... | @@ -20,6 +31,7 @@ pub fn build(b: *std.Build) void { | ... | @@ -20,6 +31,7 @@ pub fn build(b: *std.Build) void { |
| 20 | }); | 31 | }); |
| 21 | b.installArtifact(exe); | 32 | b.installArtifact(exe); |
| 22 | 33 | ||
| 34 | exe.root_module.addImport("build_options", opts_mod); | ||
| 23 | exe.root_module.addImport("zg:PropsData", zg.module("PropsData")); | 35 | exe.root_module.addImport("zg:PropsData", zg.module("PropsData")); |
| 24 | exe.root_module.addImport("tracer", tracer.module("tracer")); | 36 | exe.root_module.addImport("tracer", tracer.module("tracer")); |
| 25 | // if (!target.result.isWasm()) { | 37 | // if (!target.result.isWasm()) { |
demo.txt+25-1| ... | @@ -1 +1,25 @@ | ... | @@ -1 +1,25 @@ |
| 1 | no "waay | 1 | let print = @js("console").log; |
| 2 | |||
| 3 | fn doThing(x: float, y: float) -> float { | ||
| 4 | let math = if x < y { | ||
| 5 | x - y | ||
| 6 | } else b: { | ||
| 7 | let sum = x + y; | ||
| 8 | if sum > 100 { | ||
| 9 | break :b sum; | ||
| 10 | } | ||
| 11 | if x == y { | ||
| 12 | return 5; | ||
| 13 | } | ||
| 14 | sum * -sum | ||
| 15 | }; | ||
| 16 | if x == y { | ||
| 17 | return 5; | ||
| 18 | } | ||
| 19 | let divisor = if x > 10 { 2 } else { 3 }; | ||
| 20 | math / divisor | ||
| 21 | } | ||
| 22 | |||
| 23 | print(doThing(1, 6)); | ||
| 24 | print(doThing(6, 4)); | ||
| 25 | print(doThing(100, 52)); |
src/compiler/JsLink.zig+37| ... | @@ -19,6 +19,8 @@ pub fn linkJsCode( | ... | @@ -19,6 +19,8 @@ pub fn linkJsCode( |
| 19 | decls: []const Decl.Index, | 19 | decls: []const Decl.Index, |
| 20 | writer: anytype, | 20 | writer: anytype, |
| 21 | ) !void { | 21 | ) !void { |
| 22 | var t = tracer.trace(@src()); | ||
| 23 | defer t.end(); | ||
| 22 | 24 | ||
| 23 | // Arena allocator is used for the main flow | 25 | // Arena allocator is used for the main flow |
| 24 | var link: JsLink = .{ .comp = comp }; | 26 | var link: JsLink = .{ .comp = comp }; |
| ... | @@ -79,6 +81,9 @@ pub fn linkJsCode( | ... | @@ -79,6 +81,9 @@ pub fn linkJsCode( |
| 79 | } | 81 | } |
| 80 | 82 | ||
| 81 | fn deinit(link: *JsLink) void { | 83 | fn deinit(link: *JsLink) void { |
| 84 | var t = tracer.trace(@src()); | ||
| 85 | defer t.end(); | ||
| 86 | |||
| 82 | defer link.* = undefined; | 87 | defer link.* = undefined; |
| 83 | link.decls.deinit(link.comp.gpa); | 88 | link.decls.deinit(link.comp.gpa); |
| 84 | link.link_strings.deinit(link.comp.gpa); | 89 | link.link_strings.deinit(link.comp.gpa); |
| ... | @@ -86,6 +91,9 @@ fn deinit(link: *JsLink) void { | ... | @@ -86,6 +91,9 @@ fn deinit(link: *JsLink) void { |
| 86 | } | 91 | } |
| 87 | 92 | ||
| 88 | fn reserveExternSymbol(link: *JsLink, extern_symbol: String.WithLen) !void { | 93 | fn reserveExternSymbol(link: *JsLink, extern_symbol: String.WithLen) !void { |
| 94 | var t = tracer.trace(@src()); | ||
| 95 | defer t.end(); | ||
| 96 | |||
| 89 | const name = extern_symbol.toSlice(&link.comp.intern_pool); | 97 | const name = extern_symbol.toSlice(&link.comp.intern_pool); |
| 90 | const gop = try link.link_strings.getOrPutContextAdapted( | 98 | const gop = try link.link_strings.getOrPutContextAdapted( |
| 91 | link.comp.gpa, | 99 | link.comp.gpa, |
| ... | @@ -104,12 +112,18 @@ fn reserveExternSymbol(link: *JsLink, extern_symbol: String.WithLen) !void { | ... | @@ -104,12 +112,18 @@ fn reserveExternSymbol(link: *JsLink, extern_symbol: String.WithLen) !void { |
| 104 | } | 112 | } |
| 105 | 113 | ||
| 106 | fn appendLinkString(link: *JsLink, string: []const u8) !LinkString { | 114 | fn appendLinkString(link: *JsLink, string: []const u8) !LinkString { |
| 115 | var t = tracer.trace(@src()); | ||
| 116 | defer t.end(); | ||
| 117 | |||
| 107 | const start = link.string_bytes.items.len; | 118 | const start = link.string_bytes.items.len; |
| 108 | try link.string_bytes.appendSlice(link.comp.gpa, string); | 119 | try link.string_bytes.appendSlice(link.comp.gpa, string); |
| 109 | return .{ .start = @intCast(start), .len = @intCast(string.len) }; | 120 | return .{ .start = @intCast(start), .len = @intCast(string.len) }; |
| 110 | } | 121 | } |
| 111 | 122 | ||
| 112 | fn declIdentifier(link: *const JsLink, decl: Decl.Index) []const u8 { | 123 | fn declIdentifier(link: *const JsLink, decl: Decl.Index) []const u8 { |
| 124 | var t = tracer.trace(@src()); | ||
| 125 | defer t.end(); | ||
| 126 | |||
| 113 | return (link.decls.get(decl) orelse if (std.debug.runtime_safety) { | 127 | return (link.decls.get(decl) orelse if (std.debug.runtime_safety) { |
| 114 | std.debug.panic("Decl {d} ({}) is not present in link decl map", .{ | 128 | std.debug.panic("Decl {d} ({}) is not present in link decl map", .{ |
| 115 | @intFromEnum(decl), | 129 | @intFromEnum(decl), |
| ... | @@ -119,6 +133,9 @@ fn declIdentifier(link: *const JsLink, decl: Decl.Index) []const u8 { | ... | @@ -119,6 +133,9 @@ fn declIdentifier(link: *const JsLink, decl: Decl.Index) []const u8 { |
| 119 | } | 133 | } |
| 120 | 134 | ||
| 121 | fn printDecl(link: *JsLink, decl_index: Decl.Index, writer: anytype) !void { | 135 | fn printDecl(link: *JsLink, decl_index: Decl.Index, writer: anytype) !void { |
| 136 | var t = tracer.trace(@src()); | ||
| 137 | defer t.end(); | ||
| 138 | |||
| 122 | try writer.writeAll("let "); | 139 | try writer.writeAll("let "); |
| 123 | try writer.writeAll(link.declIdentifier(decl_index)); | 140 | try writer.writeAll(link.declIdentifier(decl_index)); |
| 124 | try writer.writeAll(" = "); | 141 | try writer.writeAll(" = "); |
| ... | @@ -137,6 +154,9 @@ fn printDecl(link: *JsLink, decl_index: Decl.Index, writer: anytype) !void { | ... | @@ -137,6 +154,9 @@ fn printDecl(link: *JsLink, decl_index: Decl.Index, writer: anytype) !void { |
| 137 | } | 154 | } |
| 138 | 155 | ||
| 139 | fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void { | 156 | fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void { |
| 157 | var t = tracer.trace(@src()); | ||
| 158 | defer t.end(); | ||
| 159 | |||
| 140 | for (tree.mainStatements()) |stmt| { | 160 | for (tree.mainStatements()) |stmt| { |
| 141 | try link.printExpr(tree, stmt, writer); | 161 | try link.printExpr(tree, stmt, writer); |
| 142 | try writer.writeAll(";\n"); | 162 | try writer.writeAll(";\n"); |
| ... | @@ -144,6 +164,9 @@ fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void | ... | @@ -144,6 +164,9 @@ fn printDeclContents(link: *JsLink, tree: *const JsTree, writer: anytype) !void |
| 144 | } | 164 | } |
| 145 | 165 | ||
| 146 | fn printBlockContents(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer: anytype) !void { | 166 | fn printBlockContents(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer: anytype) !void { |
| 167 | var t = tracer.trace(@src()); | ||
| 168 | defer t.end(); | ||
| 169 | |||
| 147 | assert(list.slice(tree).len > 0); | 170 | assert(list.slice(tree).len > 0); |
| 148 | for (list.slice(tree)) |stmt| { | 171 | for (list.slice(tree)) |stmt| { |
| 149 | try link.printExpr(tree, stmt, writer); | 172 | try link.printExpr(tree, stmt, writer); |
| ... | @@ -158,6 +181,9 @@ fn printBlockContents(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList | ... | @@ -158,6 +181,9 @@ fn printBlockContents(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList |
| 158 | } | 181 | } |
| 159 | 182 | ||
| 160 | fn printBlock(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer: anytype) !void { | 183 | fn printBlock(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer: anytype) !void { |
| 184 | var t = tracer.trace(@src()); | ||
| 185 | defer t.end(); | ||
| 186 | |||
| 161 | if (list.len != 1) { | 187 | if (list.len != 1) { |
| 162 | try writer.writeAll("{"); | 188 | try writer.writeAll("{"); |
| 163 | try link.printBlockContents(tree, list, writer); | 189 | try link.printBlockContents(tree, list, writer); |
| ... | @@ -168,6 +194,9 @@ fn printBlock(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer | ... | @@ -168,6 +194,9 @@ fn printBlock(link: *JsLink, tree: *const JsTree, list: JsTree.IndexList, writer |
| 168 | } | 194 | } |
| 169 | 195 | ||
| 170 | fn printExpr(link: *JsLink, tree: *const JsTree, node: Node.Index, writer: anytype) @TypeOf(writer).Error!void { | 196 | fn printExpr(link: *JsLink, tree: *const JsTree, node: Node.Index, writer: anytype) @TypeOf(writer).Error!void { |
| 197 | var t = tracer.trace(@src()); | ||
| 198 | defer t.end(); | ||
| 199 | |||
| 171 | switch (tree.nodeTag(node)) { | 200 | switch (tree.nodeTag(node)) { |
| 172 | else => |tag| std.debug.panic("TODO: printExpr .{s}", .{@tagName(tag)}), | 201 | else => |tag| std.debug.panic("TODO: printExpr .{s}", .{@tagName(tag)}), |
| 173 | .root => unreachable, | 202 | .root => unreachable, |
| ... | @@ -328,11 +357,17 @@ fn printExpr(link: *JsLink, tree: *const JsTree, node: Node.Index, writer: anyty | ... | @@ -328,11 +357,17 @@ fn printExpr(link: *JsLink, tree: *const JsTree, node: Node.Index, writer: anyty |
| 328 | } | 357 | } |
| 329 | 358 | ||
| 330 | fn printLocal(link: *JsLink, local: JsTree.LocalIndex, writer: anytype) !void { | 359 | fn printLocal(link: *JsLink, local: JsTree.LocalIndex, writer: anytype) !void { |
| 360 | var t = tracer.trace(@src()); | ||
| 361 | defer t.end(); | ||
| 362 | |||
| 331 | _ = link; // todo: be smarter about this | 363 | _ = link; // todo: be smarter about this |
| 332 | try writer.print("v{d}", .{local}); | 364 | try writer.print("v{d}", .{local}); |
| 333 | } | 365 | } |
| 334 | 366 | ||
| 335 | fn printLabelIdentifier(link: *JsLink, local: JsTree.LocalIndex, writer: anytype) !void { | 367 | fn printLabelIdentifier(link: *JsLink, local: JsTree.LocalIndex, writer: anytype) !void { |
| 368 | var t = tracer.trace(@src()); | ||
| 369 | defer t.end(); | ||
| 370 | |||
| 336 | _ = link; // todo: be smarter about this | 371 | _ = link; // todo: be smarter about this |
| 337 | try writer.print("label{d}", .{local}); | 372 | try writer.print("label{d}", .{local}); |
| 338 | } | 373 | } |
| ... | @@ -452,3 +487,5 @@ const Node = JsTree.Node; | ... | @@ -452,3 +487,5 @@ const Node = JsTree.Node; |
| 452 | 487 | ||
| 453 | const InternPool = @import("InternPool.zig"); | 488 | const InternPool = @import("InternPool.zig"); |
| 454 | const String = InternPool.String; | 489 | const String = InternPool.String; |
| 490 | |||
| 491 | const tracer = @import("tracer"); |
src/compiler/JsNodeGen.zig+46| ... | @@ -29,6 +29,9 @@ const MapEntry = union { | ... | @@ -29,6 +29,9 @@ const MapEntry = union { |
| 29 | }; | 29 | }; |
| 30 | 30 | ||
| 31 | pub fn init(gpa: Allocator, arena: Allocator, ip: *const InternPool, air: *const Air) !JsNodeGen { | 31 | pub fn init(gpa: Allocator, arena: Allocator, ip: *const InternPool, air: *const Air) !JsNodeGen { |
| 32 | const t = tracer.trace(@src()); | ||
| 33 | defer t.end(); | ||
| 34 | |||
| 32 | const air_node_map = try arena.alloc(MapEntry, air.insts.len); | 35 | const air_node_map = try arena.alloc(MapEntry, air.insts.len); |
| 33 | if (std.debug.runtime_safety) { | 36 | if (std.debug.runtime_safety) { |
| 34 | @memset(air_node_map, .{ .none = {} }); | 37 | @memset(air_node_map, .{ .none = {} }); |
| ... | @@ -52,6 +55,9 @@ pub fn init(gpa: Allocator, arena: Allocator, ip: *const InternPool, air: *const | ... | @@ -52,6 +55,9 @@ pub fn init(gpa: Allocator, arena: Allocator, ip: *const InternPool, air: *const |
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | pub fn deinit(c: *JsNodeGen) void { | 57 | pub fn deinit(c: *JsNodeGen) void { |
| 58 | const t = tracer.trace(@src()); | ||
| 59 | defer t.end(); | ||
| 60 | |||
| 55 | defer c.* = undefined; | 61 | defer c.* = undefined; |
| 56 | c.nodes.deinit(c.gpa); | 62 | c.nodes.deinit(c.gpa); |
| 57 | c.extra.deinit(c.gpa); | 63 | c.extra.deinit(c.gpa); |
| ... | @@ -62,6 +68,9 @@ pub fn deinit(c: *JsNodeGen) void { | ... | @@ -62,6 +68,9 @@ pub fn deinit(c: *JsNodeGen) void { |
| 62 | } | 68 | } |
| 63 | 69 | ||
| 64 | pub fn finalize(c: *JsNodeGen) !JsTree { | 70 | pub fn finalize(c: *JsNodeGen) !JsTree { |
| 71 | const t = tracer.trace(@src()); | ||
| 72 | defer t.end(); | ||
| 73 | |||
| 65 | // todo: errdefer will probably leave memory in a fully invalid state | 74 | // todo: errdefer will probably leave memory in a fully invalid state |
| 66 | try c.nodes.setCapacity(c.gpa, c.nodes.len); | 75 | try c.nodes.setCapacity(c.gpa, c.nodes.len); |
| 67 | 76 | ||
| ... | @@ -87,6 +96,9 @@ pub fn finalize(c: *JsNodeGen) !JsTree { | ... | @@ -87,6 +96,9 @@ pub fn finalize(c: *JsNodeGen) !JsTree { |
| 87 | } | 96 | } |
| 88 | 97 | ||
| 89 | pub fn build(c: *JsNodeGen) !void { | 98 | pub fn build(c: *JsNodeGen) !void { |
| 99 | const t = tracer.trace(@src()); | ||
| 100 | defer t.end(); | ||
| 101 | |||
| 90 | assert(c.air.instTag(.main_block) == .block); | 102 | assert(c.air.instTag(.main_block) == .block); |
| 91 | const statements = c.air.instData(.block, .main_block).slice(c.air); | 103 | const statements = c.air.instData(.block, .main_block).slice(c.air); |
| 92 | 104 | ||
| ... | @@ -117,6 +129,9 @@ pub fn build(c: *JsNodeGen) !void { | ... | @@ -117,6 +129,9 @@ pub fn build(c: *JsNodeGen) !void { |
| 117 | } | 129 | } |
| 118 | 130 | ||
| 119 | fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { | 131 | fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { |
| 132 | const t = tracer.traceFmt(@src(), "#{d} {s}", .{ @intFromEnum(inst), @tagName(c.air.instTag(inst)) }); | ||
| 133 | defer t.end(); | ||
| 134 | |||
| 120 | switch (c.air.instTag(inst)) { | 135 | switch (c.air.instTag(inst)) { |
| 121 | .arg => unreachable, // codegen must skip over these instructions. | 136 | .arg => unreachable, // codegen must skip over these instructions. |
| 122 | 137 | ||
| ... | @@ -290,6 +305,9 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { | ... | @@ -290,6 +305,9 @@ fn codeGenInst(c: *JsNodeGen, inst: Air.Inst.Index) Error!void { |
| 290 | } | 305 | } |
| 291 | 306 | ||
| 292 | fn markExpression(c: *JsNodeGen, inst: Air.Inst.Index, node: Node.Index) !void { | 307 | fn markExpression(c: *JsNodeGen, inst: Air.Inst.Index, node: Node.Index) !void { |
| 308 | const t = tracer.trace(@src()); | ||
| 309 | defer t.end(); | ||
| 310 | |||
| 293 | const flags: Air.Flags = c.air.instFlags(inst); | 311 | const flags: Air.Flags = c.air.instFlags(inst); |
| 294 | const i = @intFromEnum(inst); | 312 | const i = @intFromEnum(inst); |
| 295 | switch (flags.uses) { | 313 | switch (flags.uses) { |
| ... | @@ -314,6 +332,9 @@ fn markExpression(c: *JsNodeGen, inst: Air.Inst.Index, node: Node.Index) !void { | ... | @@ -314,6 +332,9 @@ fn markExpression(c: *JsNodeGen, inst: Air.Inst.Index, node: Node.Index) !void { |
| 314 | } | 332 | } |
| 315 | 333 | ||
| 316 | fn fetchExpression(c: *JsNodeGen, inst: Air.Inst.Ref) !Node.Index { | 334 | fn fetchExpression(c: *JsNodeGen, inst: Air.Inst.Ref) !Node.Index { |
| 335 | const t = tracer.trace(@src()); | ||
| 336 | defer t.end(); | ||
| 337 | |||
| 317 | return switch (inst.unwrap()) { | 338 | return switch (inst.unwrap()) { |
| 318 | .value => |v| c.valueToExpression(v), | 339 | .value => |v| c.valueToExpression(v), |
| 319 | .inst => |index| { | 340 | .inst => |index| { |
| ... | @@ -332,6 +353,9 @@ fn fetchExpression(c: *JsNodeGen, inst: Air.Inst.Ref) !Node.Index { | ... | @@ -332,6 +353,9 @@ fn fetchExpression(c: *JsNodeGen, inst: Air.Inst.Ref) !Node.Index { |
| 332 | } | 353 | } |
| 333 | 354 | ||
| 334 | fn valueToExpression(c: *JsNodeGen, v: Value) !Node.Index { | 355 | fn valueToExpression(c: *JsNodeGen, v: Value) !Node.Index { |
| 356 | const t = tracer.trace(@src()); | ||
| 357 | defer t.end(); | ||
| 358 | |||
| 335 | const intern_tag = c.ip.items.items(.tag)[@intFromEnum(v.toIntern())]; | 359 | const intern_tag = c.ip.items.items(.tag)[@intFromEnum(v.toIntern())]; |
| 336 | switch (intern_tag) { | 360 | switch (intern_tag) { |
| 337 | .removed => unreachable, // UAF | 361 | .removed => unreachable, // UAF |
| ... | @@ -352,6 +376,9 @@ fn valueToExpression(c: *JsNodeGen, v: Value) !Node.Index { | ... | @@ -352,6 +376,9 @@ fn valueToExpression(c: *JsNodeGen, v: Value) !Node.Index { |
| 352 | } | 376 | } |
| 353 | 377 | ||
| 354 | fn addTemporary(c: *JsNodeGen) !Node.Index { | 378 | fn addTemporary(c: *JsNodeGen) !Node.Index { |
| 379 | const t = tracer.trace(@src()); | ||
| 380 | defer t.end(); | ||
| 381 | |||
| 355 | try c.addStmt(try c.add(.stmt_declare_local, .{ | 382 | try c.addStmt(try c.add(.stmt_declare_local, .{ |
| 356 | .identifier_index = c.next_id, | 383 | .identifier_index = c.next_id, |
| 357 | .init = .none, | 384 | .init = .none, |
| ... | @@ -367,6 +394,9 @@ const Branch = struct { | ... | @@ -367,6 +394,9 @@ const Branch = struct { |
| 367 | }; | 394 | }; |
| 368 | 395 | ||
| 369 | fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Branch { | 396 | fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Branch { |
| 397 | const t = tracer.trace(@src()); | ||
| 398 | defer t.end(); | ||
| 399 | |||
| 370 | const scratch_top = c.scratch.items.len; | 400 | const scratch_top = c.scratch.items.len; |
| 371 | defer c.scratch.shrinkRetainingCapacity(scratch_top); | 401 | defer c.scratch.shrinkRetainingCapacity(scratch_top); |
| 372 | 402 | ||
| ... | @@ -430,6 +460,9 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br | ... | @@ -430,6 +460,9 @@ fn codeGenBranch(c: *JsNodeGen, inst: Air.Inst.Ref, temporary: ?Node.Index) !?Br |
| 430 | } | 460 | } |
| 431 | 461 | ||
| 432 | fn codeGenBlock(c: *JsNodeGen, inst: Air.Inst.Index) !void { | 462 | fn codeGenBlock(c: *JsNodeGen, inst: Air.Inst.Index) !void { |
| 463 | const t = tracer.trace(@src()); | ||
| 464 | defer t.end(); | ||
| 465 | |||
| 433 | const scratch_top = c.scratch.items.len; | 466 | const scratch_top = c.scratch.items.len; |
| 434 | errdefer c.scratch.shrinkRetainingCapacity(scratch_top); | 467 | errdefer c.scratch.shrinkRetainingCapacity(scratch_top); |
| 435 | 468 | ||
| ... | @@ -467,6 +500,9 @@ fn codeGenBlock(c: *JsNodeGen, inst: Air.Inst.Index) !void { | ... | @@ -467,6 +500,9 @@ fn codeGenBlock(c: *JsNodeGen, inst: Air.Inst.Index) !void { |
| 467 | } | 500 | } |
| 468 | 501 | ||
| 469 | fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { | 502 | fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { |
| 503 | const t = tracer.trace(@src()); | ||
| 504 | defer t.end(); | ||
| 505 | |||
| 470 | return switch (inst.unwrap()) { | 506 | return switch (inst.unwrap()) { |
| 471 | .value => true, | 507 | .value => true, |
| 472 | .inst => |index| switch (c.air.instTag(index)) { | 508 | .inst => |index| switch (c.air.instTag(index)) { |
| ... | @@ -493,6 +529,9 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { | ... | @@ -493,6 +529,9 @@ fn canLowerToExpression(c: *const JsNodeGen, inst: Air.Inst.Ref) bool { |
| 493 | } | 529 | } |
| 494 | 530 | ||
| 495 | fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { | 531 | fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { |
| 532 | const t = tracer.trace(@src()); | ||
| 533 | defer t.end(); | ||
| 534 | |||
| 496 | assert(c.canLowerToExpression(ref)); | 535 | assert(c.canLowerToExpression(ref)); |
| 497 | return switch (ref.unwrap()) { | 536 | return switch (ref.unwrap()) { |
| 498 | .value => |v| try c.valueToExpression(v), | 537 | .value => |v| try c.valueToExpression(v), |
| ... | @@ -504,6 +543,9 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { | ... | @@ -504,6 +543,9 @@ fn lowerToExpression(c: *JsNodeGen, ref: Air.Inst.Ref) !Node.Index { |
| 504 | } | 543 | } |
| 505 | 544 | ||
| 506 | fn add(c: *JsNodeGen, comptime tag: JsTree.Tag, data: tag.Data()) !Node.Index { | 545 | fn add(c: *JsNodeGen, comptime tag: JsTree.Tag, data: tag.Data()) !Node.Index { |
| 546 | const t = tracer.trace(@src()); | ||
| 547 | defer t.end(); | ||
| 548 | |||
| 507 | try c.nodes.append(c.gpa, .{ | 549 | try c.nodes.append(c.gpa, .{ |
| 508 | .tag = tag, | 550 | .tag = tag, |
| 509 | .data = EncodedData.encode(tag, data), | 551 | .data = EncodedData.encode(tag, data), |
| ... | @@ -512,6 +554,9 @@ fn add(c: *JsNodeGen, comptime tag: JsTree.Tag, data: tag.Data()) !Node.Index { | ... | @@ -512,6 +554,9 @@ fn add(c: *JsNodeGen, comptime tag: JsTree.Tag, data: tag.Data()) !Node.Index { |
| 512 | } | 554 | } |
| 513 | 555 | ||
| 514 | fn addStmt(c: *JsNodeGen, stmt: Node.Index) !void { | 556 | fn addStmt(c: *JsNodeGen, stmt: Node.Index) !void { |
| 557 | const t = tracer.trace(@src()); | ||
| 558 | defer t.end(); | ||
| 559 | |||
| 515 | try c.scratch.append(c.arena, @intFromEnum(stmt)); | 560 | try c.scratch.append(c.arena, @intFromEnum(stmt)); |
| 516 | } | 561 | } |
| 517 | 562 | ||
| ... | @@ -537,3 +582,4 @@ const Air = @import("Air.zig"); | ... | @@ -537,3 +582,4 @@ const Air = @import("Air.zig"); |
| 537 | const Value = @import("Value.zig"); | 582 | const Value = @import("Value.zig"); |
| 538 | 583 | ||
| 539 | const dod = @import("dod.zig"); | 584 | const dod = @import("dod.zig"); |
| 585 | const tracer = @import("tracer"); |
src/compiler/Report.zig+16-9| ... | @@ -183,8 +183,7 @@ pub fn deinit(report: Report, gpa: Allocator) void { | ... | @@ -183,8 +183,7 @@ pub fn deinit(report: Report, gpa: Allocator) void { |
| 183 | gpa.free(report.string_bytes); | 183 | gpa.free(report.string_bytes); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | pub fn dumpToWriter(report: Report, comp: *Comp, writer: anytype) !void { | 186 | pub fn dumpToWriter(report: Report, comp: *Comp, writer: anytype, tty: std.io.tty.Config) !void { |
| 187 | const tty = util.detectTTYFromWriter(writer); | ||
| 188 | try writer.print("{d} errors, {d} warnings\n", .{ report.errors.len, report.warnings.len }); | 187 | try writer.print("{d} errors, {d} warnings\n", .{ report.errors.len, report.warnings.len }); |
| 189 | for (report.errors) |item| { | 188 | for (report.errors) |item| { |
| 190 | try report.formatItem(item, .@"error", comp, writer, tty); | 189 | try report.formatItem(item, .@"error", comp, writer, tty); |
| ... | @@ -348,13 +347,21 @@ pub fn formatItem( | ... | @@ -348,13 +347,21 @@ pub fn formatItem( |
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | pub fn dumpToStdErr(report: Report, comp: *Comp) !void { | 349 | pub fn dumpToStdErr(report: Report, comp: *Comp) !void { |
| 351 | const stderr = std.io.getStdErr().writer(); | 350 | const builtin = @import("builtin"); |
| 352 | 351 | ||
| 353 | // Disabled because of coloring issues. | 352 | const stderr = std.io.getStdErr(); |
| 354 | // var buf = std.io.bufferedWriter(stderr); | 353 | const tty = std.io.tty.detectConfig(stderr); |
| 355 | // const writer = buf.writer(); | 354 | |
| 356 | try dumpToWriter(report, comp, stderr); | 355 | if (builtin.os.tag == .windows and tty == .windows_api) { |
| 357 | // try buf.flush(); | 356 | // Windows API uses it's own API calls, so a buffered writer |
| 357 | // cannot be used :/ | ||
| 358 | try dumpToWriter(report, comp, stderr.writer(), tty); | ||
| 359 | } else { | ||
| 360 | var buf = std.io.bufferedWriter(stderr.writer()); | ||
| 361 | const writer = buf.writer(); | ||
| 362 | try dumpToWriter(report, comp, writer, tty); | ||
| 363 | try buf.flush(); | ||
| 364 | } | ||
| 358 | } | 365 | } |
| 359 | 366 | ||
| 360 | pub const Builder = struct { | 367 | pub const Builder = struct { |
src/compiler/Sema.zig+5-3| ... | @@ -92,9 +92,11 @@ pub fn deinit(s: *Sema) void { | ... | @@ -92,9 +92,11 @@ pub fn deinit(s: *Sema) void { |
| 92 | pub fn finalize(s: *Sema) !void { | 92 | pub fn finalize(s: *Sema) !void { |
| 93 | const air: Air = s.tempAir(); | 93 | const air: Air = s.tempAir(); |
| 94 | 94 | ||
| 95 | std.debug.print("=" ** 20, .{}); | 95 | if (s.comp.options.dump_ir) { |
| 96 | std.debug.print("\nAir for @ {d}\n", .{@intFromEnum(s.decl.teg_decl_index)}); | 96 | std.debug.print("=" ** 20, .{}); |
| 97 | air.dumpToWriter(s.ip, std.io.getStdErr().writer()) catch {}; | 97 | std.debug.print("\nAir for @ {d}\n", .{@intFromEnum(s.decl.teg_decl_index)}); |
| 98 | air.dumpToWriter(s.ip, std.io.getStdErr().writer()) catch {}; | ||
| 99 | } | ||
| 98 | 100 | ||
| 99 | try s.comp.codeGenDecl(s.decl, &air); | 101 | try s.comp.codeGenDecl(s.decl, &air); |
| 100 | } | 102 | } |
src/compiler/Transform.zig+4-2| ... | @@ -603,6 +603,8 @@ fn transformExpression(t: *Transform, decl: BlockContext, node: NodeIndex) Alloc | ... | @@ -603,6 +603,8 @@ fn transformExpression(t: *Transform, decl: BlockContext, node: NodeIndex) Alloc |
| 603 | return .void_value; | 603 | return .void_value; |
| 604 | }; | 604 | }; |
| 605 | 605 | ||
| 606 | lookup.mutated = true; | ||
| 607 | |||
| 606 | return switch (lookup.data) { | 608 | return switch (lookup.data) { |
| 607 | .declaration => try t.addInstRef(.{ | 609 | .declaration => try t.addInstRef(.{ |
| 608 | .tag = .load_decl, | 610 | .tag = .load_decl, |
| ... | @@ -1235,11 +1237,11 @@ fn scratchToIndexList(t: *Transform, scratch_top: usize) !IndexList { | ... | @@ -1235,11 +1237,11 @@ fn scratchToIndexList(t: *Transform, scratch_top: usize) !IndexList { |
| 1235 | }; | 1237 | }; |
| 1236 | } | 1238 | } |
| 1237 | 1239 | ||
| 1238 | fn lookupId(t: *Transform, id: []const u8) ?Scope.Symbol { | 1240 | fn lookupId(t: *Transform, id: []const u8) ?*Scope.Symbol { |
| 1239 | var i = t.scopes.items.len; | 1241 | var i = t.scopes.items.len; |
| 1240 | while (i > 0) { | 1242 | while (i > 0) { |
| 1241 | i -= 1; | 1243 | i -= 1; |
| 1242 | if (t.scopes.items[i].symbols.get(id)) |sym| { | 1244 | if (t.scopes.items[i].symbols.getPtr(id)) |sym| { |
| 1243 | return sym; | 1245 | return sym; |
| 1244 | } | 1246 | } |
| 1245 | } | 1247 | } |
src/compiler/main.zig+29-13| ... | @@ -1,30 +1,40 @@ | ... | @@ -1,30 +1,40 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 2 | const Tokenizer = @import("Tokenizer.zig"); | 4 | const Tokenizer = @import("Tokenizer.zig"); |
| 3 | const Parse = @import("Parse.zig"); | 5 | const Parse = @import("Parse.zig"); |
| 4 | const Transform = @import("Transform.zig"); | 6 | const Transform = @import("Transform.zig"); |
| 5 | const Comp = @import("Comp.zig"); | 7 | const Comp = @import("Comp.zig"); |
| 6 | const unicode_props = @import("unicode_props.zig"); | 8 | const unicode_props = @import("unicode_props.zig"); |
| 7 | const T = @import("tracer"); | 9 | |
| 8 | pub const tracer_impl = @field(T, "none"); | 10 | const tracer = @import("tracer"); |
| 11 | |||
| 12 | pub const tracer_impl = @field(tracer, @import("build_options").tracing); | ||
| 9 | 13 | ||
| 10 | pub const Report = @import("Report.zig"); | 14 | pub const Report = @import("Report.zig"); |
| 11 | 15 | ||
| 12 | pub fn main() !void { | 16 | pub fn main() !void { |
| 17 | try tracer.init(); | ||
| 18 | defer tracer.deinit(); | ||
| 19 | try tracer.init_thread(null); | ||
| 20 | defer tracer.deinit_thread(); | ||
| 21 | |||
| 13 | try unicode_props.init(); | 22 | try unicode_props.init(); |
| 14 | 23 | ||
| 15 | std.debug.print("\r\x1b[K", .{}); | 24 | std.debug.print("\r\x1b[K", .{}); |
| 16 | 25 | ||
| 17 | try T.init(); | 26 | const use_gpa = builtin.mode == .Debug; |
| 18 | defer T.deinit(); | ||
| 19 | |||
| 20 | try T.init_thread(null); | ||
| 21 | defer T.deinit_thread(); | ||
| 22 | 27 | ||
| 23 | var gpa: std.heap.GeneralPurposeAllocator(.{ | 28 | var gpa: if (use_gpa) std.heap.GeneralPurposeAllocator(.{ |
| 24 | .stack_trace_frames = 100, | 29 | .stack_trace_frames = 100, |
| 25 | }) = .{}; | 30 | }) else struct {} = .{}; |
| 26 | defer _ = gpa.deinit(); | 31 | defer if (use_gpa) { |
| 27 | const alloc = gpa.allocator(); | 32 | _ = gpa.deinit(); |
| 33 | }; | ||
| 34 | const alloc = if (use_gpa) | ||
| 35 | gpa.allocator() | ||
| 36 | else | ||
| 37 | std.heap.c_allocator; | ||
| 28 | 38 | ||
| 29 | var maybe_file_path: ?[]const u8 = null; | 39 | var maybe_file_path: ?[]const u8 = null; |
| 30 | defer if (maybe_file_path) |path| alloc.free(path); | 40 | defer if (maybe_file_path) |path| alloc.free(path); |
| ... | @@ -60,7 +70,7 @@ pub fn main() !void { | ... | @@ -60,7 +70,7 @@ pub fn main() !void { |
| 60 | std.process.exit(1); | 70 | std.process.exit(1); |
| 61 | }; | 71 | }; |
| 62 | 72 | ||
| 63 | var comp: Comp = .{ .gpa = T.tracingAllocator(&alloc) }; | 73 | var comp: Comp = .{ .gpa = tracer.tracingAllocator(&alloc) }; |
| 64 | try comp.init(); | 74 | try comp.init(); |
| 65 | defer comp.deinit(); | 75 | defer comp.deinit(); |
| 66 | const main_file = try comp.getFile(file_path); | 76 | const main_file = try comp.getFile(file_path); |
| ... | @@ -72,10 +82,14 @@ pub fn main() !void { | ... | @@ -72,10 +82,14 @@ pub fn main() !void { |
| 72 | try fail_report.dumpToStdErr(&comp); | 82 | try fail_report.dumpToStdErr(&comp); |
| 73 | std.process.exit(1); | 83 | std.process.exit(1); |
| 74 | }, | 84 | }, |
| 85 | error.ParseFail => { | ||
| 86 | // Already printed. | ||
| 87 | std.process.exit(1); | ||
| 88 | }, | ||
| 75 | else => return err, | 89 | else => return err, |
| 76 | }; | 90 | }; |
| 77 | 91 | ||
| 78 | { | 92 | if (comp.options.dump_ir) { |
| 79 | const stderr = std.io.getStdErr().writer(); | 93 | const stderr = std.io.getStdErr().writer(); |
| 80 | try teg.dumpToWriter(stderr); | 94 | try teg.dumpToWriter(stderr); |
| 81 | } | 95 | } |
| ... | @@ -88,6 +102,8 @@ pub fn main() !void { | ... | @@ -88,6 +102,8 @@ pub fn main() !void { |
| 88 | try comp.link(writer); | 102 | try comp.link(writer); |
| 89 | try bufw.flush(); | 103 | try bufw.flush(); |
| 90 | 104 | ||
| 105 | std.process.cleanExit(); | ||
| 106 | |||
| 91 | // var error_pos: u32 = 0; | 107 | // var error_pos: u32 = 0; |
| 92 | // var tokens = Tokenizer.tokenize(source, alloc.allocator(), &error_pos) catch |err| { | 108 | // var tokens = Tokenizer.tokenize(source, alloc.allocator(), &error_pos) catch |err| { |
| 93 | // var line: usize = 1; | 109 | // var line: usize = 1; |