authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-04 02:02:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-04 12:15:47-07:00
log331f6a07a98206c3b5c096e73860ef1b7a3dfe85
treeac5a8794de5467d828e375297e92b52c0ee40614
parentb7a883b7d1247e9342805a8d06e70fd4d02f11b3

stage2: fix ZIR support and C back end


3 files changed, 48 insertions(+), 24 deletions(-)

src-self-hosted/codegen.zig+18-9
...@@ -396,12 +396,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -396,12 +396,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
396 const branch = try branch_stack.addOne();396 const branch = try branch_stack.addOne();
397 branch.* = .{};397 branch.* = .{};
398398
399 const scope_file = module_fn.owner_decl.scope.cast(Module.Scope.File).?;399 const src_data: struct {lbrace_src: usize, rbrace_src: usize, source: []const u8} = blk: {
400 const tree = scope_file.contents.tree;400 if (module_fn.owner_decl.scope.cast(Module.Scope.File)) |scope_file| {
401 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;401 const tree = scope_file.contents.tree;
402 const block = fn_proto.body().?.castTag(.Block).?;402 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;
403 const lbrace_src = tree.token_locs[block.lbrace].start;403 const block = fn_proto.body().?.castTag(.Block).?;
404 const rbrace_src = tree.token_locs[block.rbrace].start;404 const lbrace_src = tree.token_locs[block.lbrace].start;
405 const rbrace_src = tree.token_locs[block.rbrace].start;
406 break :blk .{ .lbrace_src = lbrace_src, .rbrace_src = rbrace_src, .source = tree.source };
407 } else if (module_fn.owner_decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| {
408 const byte_off = zir_module.contents.module.decls[module_fn.owner_decl.src_index].inst.src;
409 break :blk .{ .lbrace_src = byte_off, .rbrace_src = byte_off, .source = zir_module.source.bytes };
410 } else {
411 unreachable;
412 }
413 };
405414
406 var function = Self{415 var function = Self{
407 .gpa = bin_file.allocator,416 .gpa = bin_file.allocator,
...@@ -419,9 +428,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -419,9 +428,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
419 .src = src,428 .src = src,
420 .stack_align = undefined,429 .stack_align = undefined,
421 .prev_di_pc = 0,430 .prev_di_pc = 0,
422 .prev_di_src = lbrace_src,431 .prev_di_src = src_data.lbrace_src,
423 .rbrace_src = rbrace_src,432 .rbrace_src = src_data.rbrace_src,
424 .source = tree.source,433 .source = src_data.source,
425 };434 };
426 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);435 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
427436
src-self-hosted/codegen/c.zig+11-5
...@@ -89,17 +89,17 @@ fn genFn(file: *C, decl: *Decl) !void {...@@ -89,17 +89,17 @@ fn genFn(file: *C, decl: *Decl) !void {
89 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;89 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
90 const instructions = func.analysis.success.instructions;90 const instructions = func.analysis.success.instructions;
91 if (instructions.len > 0) {91 if (instructions.len > 0) {
92 try writer.writeAll("\n");
92 for (instructions) |inst| {93 for (instructions) |inst| {
93 try writer.writeAll("\n ");
94 switch (inst.tag) {94 switch (inst.tag) {
95 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl),95 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl),
96 .call => try genCall(file, inst.castTag(.call).?, decl),96 .call => try genCall(file, inst.castTag(.call).?, decl),
97 .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()),97 .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()),
98 .retvoid => try file.main.writer().print("return;", .{}),98 .retvoid => try file.main.writer().print(" return;\n", .{}),
99 .dbg_stmt => try genDbgStmt(file, inst.castTag(.dbg_stmt).?, decl),
99 else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),100 else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),
100 }101 }
101 }102 }
102 try writer.writeAll("\n");
103 }103 }
104104
105 try writer.writeAll("}\n\n");105 try writer.writeAll("}\n\n");
...@@ -112,6 +112,7 @@ fn genRet(file: *C, inst: *Inst.UnOp, decl: *Decl, expected_return_type: Type) !...@@ -112,6 +112,7 @@ fn genRet(file: *C, inst: *Inst.UnOp, decl: *Decl, expected_return_type: Type) !
112fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {112fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {
113 const writer = file.main.writer();113 const writer = file.main.writer();
114 const header = file.header.writer();114 const header = file.header.writer();
115 try writer.writeAll(" ");
115 if (inst.func.castTag(.constant)) |func_inst| {116 if (inst.func.castTag(.constant)) |func_inst| {
116 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {117 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
117 const target = func_val.func.owner_decl;118 const target = func_val.func.owner_decl;
...@@ -126,7 +127,7 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {...@@ -126,7 +127,7 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {
126 try renderFunctionSignature(file, header, target);127 try renderFunctionSignature(file, header, target);
127 try header.writeAll(";\n");128 try header.writeAll(";\n");
128 }129 }
129 try writer.print("{}();", .{tname});130 try writer.print("{}();\n", .{tname});
130 } else {131 } else {
131 return file.fail(decl.src(), "TODO non-function call target?", .{});132 return file.fail(decl.src(), "TODO non-function call target?", .{});
132 }133 }
...@@ -138,8 +139,13 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {...@@ -138,8 +139,13 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {
138 }139 }
139}140}
140141
142fn genDbgStmt(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {
143 // TODO emit #line directive here with line number and filename
144}
145
141fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {146fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {
142 const writer = file.main.writer();147 const writer = file.main.writer();
148 try writer.writeAll(" ");
143 for (as.inputs) |i, index| {149 for (as.inputs) |i, index| {
144 if (i[0] == '{' and i[i.len - 1] == '}') {150 if (i[0] == '{' and i[i.len - 1] == '}') {
145 const reg = i[1 .. i.len - 1];151 const reg = i[1 .. i.len - 1];
...@@ -187,5 +193,5 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {...@@ -187,5 +193,5 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {
187 }193 }
188 }194 }
189 }195 }
190 try writer.writeAll(");");196 try writer.writeAll(");\n");
191}197}
src-self-hosted/link.zig+19-10
...@@ -1825,15 +1825,24 @@ pub const File = struct {...@@ -1825,15 +1825,24 @@ pub const File = struct {
1825 // For functions we need to add a prologue to the debug line program.1825 // For functions we need to add a prologue to the debug line program.
1826 try dbg_line_buffer.ensureCapacity(26);1826 try dbg_line_buffer.ensureCapacity(26);
18271827
1828 const scope_file = decl.scope.cast(Module.Scope.File).?;1828 const line_off: u28 = blk: {
1829 const tree = scope_file.contents.tree;1829 if (decl.scope.cast(Module.Scope.File)) |scope_file| {
1830 const file_ast_decls = tree.root_node.decls();1830 const tree = scope_file.contents.tree;
1831 // TODO Look into improving the performance here by adding a token-index-to-line1831 const file_ast_decls = tree.root_node.decls();
1832 // lookup table. Currently this involves scanning over the source code for newlines.1832 // TODO Look into improving the performance here by adding a token-index-to-line
1833 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;1833 // lookup table. Currently this involves scanning over the source code for newlines.
1834 const block = fn_proto.body().?.castTag(.Block).?;1834 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
1835 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);1835 const block = fn_proto.body().?.castTag(.Block).?;
1836 const casted_line_off = @intCast(u28, line_delta);1836 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
1837 break :blk @intCast(u28, line_delta);
1838 } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| {
1839 const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src;
1840 const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off);
1841 break :blk @intCast(u28, line_delta);
1842 } else {
1843 unreachable;
1844 }
1845 };
18371846
1838 const ptr_width_bytes = self.ptrWidthBytes();1847 const ptr_width_bytes = self.ptrWidthBytes();
1839 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{1848 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
...@@ -1850,7 +1859,7 @@ pub const File = struct {...@@ -1850,7 +1859,7 @@ pub const File = struct {
1850 // to this function's begin curly.1859 // to this function's begin curly.
1851 assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len);1860 assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len);
1852 // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later.1861 // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later.
1853 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), casted_line_off);1862 leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off);
18541863
1855 dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file);1864 dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file);
1856 assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len);1865 assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len);