From 331f6a07a98206c3b5c096e73860ef1b7a3dfe85 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 4 Aug 2020 02:02:23 -0700 Subject: [PATCH] stage2: fix ZIR support and C back end --- src-self-hosted/codegen.zig | 27 ++++++++++++++++++--------- src-self-hosted/codegen/c.zig | 16 +++++++++++----- src-self-hosted/link.zig | 29 +++++++++++++++++++---------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 4bd126402b..7c2d8ca896 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -396,12 +396,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { const branch = try branch_stack.addOne(); branch.* = .{}; - const scope_file = module_fn.owner_decl.scope.cast(Module.Scope.File).?; - const tree = scope_file.contents.tree; - const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; - const block = fn_proto.body().?.castTag(.Block).?; - const lbrace_src = tree.token_locs[block.lbrace].start; - const rbrace_src = tree.token_locs[block.rbrace].start; + const src_data: struct {lbrace_src: usize, rbrace_src: usize, source: []const u8} = blk: { + if (module_fn.owner_decl.scope.cast(Module.Scope.File)) |scope_file| { + const tree = scope_file.contents.tree; + const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?; + const block = fn_proto.body().?.castTag(.Block).?; + const lbrace_src = tree.token_locs[block.lbrace].start; + const rbrace_src = tree.token_locs[block.rbrace].start; + break :blk .{ .lbrace_src = lbrace_src, .rbrace_src = rbrace_src, .source = tree.source }; + } else if (module_fn.owner_decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { + const byte_off = zir_module.contents.module.decls[module_fn.owner_decl.src_index].inst.src; + break :blk .{ .lbrace_src = byte_off, .rbrace_src = byte_off, .source = zir_module.source.bytes }; + } else { + unreachable; + } + }; var function = Self{ .gpa = bin_file.allocator, @@ -419,9 +428,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .src = src, .stack_align = undefined, .prev_di_pc = 0, - .prev_di_src = lbrace_src, - .rbrace_src = rbrace_src, - .source = tree.source, + .prev_di_src = src_data.lbrace_src, + .rbrace_src = src_data.rbrace_src, + .source = src_data.source, }; defer function.exitlude_jump_relocs.deinit(bin_file.allocator); diff --git a/src-self-hosted/codegen/c.zig b/src-self-hosted/codegen/c.zig index 509491677a..e8fe435af1 100644 --- a/src-self-hosted/codegen/c.zig +++ b/src-self-hosted/codegen/c.zig @@ -89,17 +89,17 @@ fn genFn(file: *C, decl: *Decl) !void { const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; const instructions = func.analysis.success.instructions; if (instructions.len > 0) { + try writer.writeAll("\n"); for (instructions) |inst| { - try writer.writeAll("\n "); switch (inst.tag) { .assembly => try genAsm(file, inst.castTag(.assembly).?, decl), .call => try genCall(file, inst.castTag(.call).?, decl), .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()), - .retvoid => try file.main.writer().print("return;", .{}), + .retvoid => try file.main.writer().print(" return;\n", .{}), + .dbg_stmt => try genDbgStmt(file, inst.castTag(.dbg_stmt).?, decl), else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}), } } - try writer.writeAll("\n"); } try writer.writeAll("}\n\n"); @@ -112,6 +112,7 @@ fn genRet(file: *C, inst: *Inst.UnOp, decl: *Decl, expected_return_type: Type) ! fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { const writer = file.main.writer(); const header = file.header.writer(); + try writer.writeAll(" "); if (inst.func.castTag(.constant)) |func_inst| { if (func_inst.val.cast(Value.Payload.Function)) |func_val| { const target = func_val.func.owner_decl; @@ -126,7 +127,7 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { try renderFunctionSignature(file, header, target); try header.writeAll(";\n"); } - try writer.print("{}();", .{tname}); + try writer.print("{}();\n", .{tname}); } else { return file.fail(decl.src(), "TODO non-function call target?", .{}); } @@ -138,8 +139,13 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { } } +fn genDbgStmt(file: *C, inst: *Inst.NoOp, decl: *Decl) !void { + // TODO emit #line directive here with line number and filename +} + fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void { const writer = file.main.writer(); + try writer.writeAll(" "); for (as.inputs) |i, index| { if (i[0] == '{' and i[i.len - 1] == '}') { const reg = i[1 .. i.len - 1]; @@ -187,5 +193,5 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void { } } } - try writer.writeAll(");"); + try writer.writeAll(");\n"); } diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index ee8322350d..7bf83d7576 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -1825,15 +1825,24 @@ pub const File = struct { // For functions we need to add a prologue to the debug line program. try dbg_line_buffer.ensureCapacity(26); - const scope_file = decl.scope.cast(Module.Scope.File).?; - const tree = scope_file.contents.tree; - const file_ast_decls = tree.root_node.decls(); - // TODO Look into improving the performance here by adding a token-index-to-line - // lookup table. Currently this involves scanning over the source code for newlines. - const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; - const block = fn_proto.body().?.castTag(.Block).?; - const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); - const casted_line_off = @intCast(u28, line_delta); + const line_off: u28 = blk: { + if (decl.scope.cast(Module.Scope.File)) |scope_file| { + const tree = scope_file.contents.tree; + const file_ast_decls = tree.root_node.decls(); + // TODO Look into improving the performance here by adding a token-index-to-line + // lookup table. Currently this involves scanning over the source code for newlines. + const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?; + const block = fn_proto.body().?.castTag(.Block).?; + const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start); + break :blk @intCast(u28, line_delta); + } else if (decl.scope.cast(Module.Scope.ZIRModule)) |zir_module| { + const byte_off = zir_module.contents.module.decls[decl.src_index].inst.src; + const line_delta = std.zig.lineDelta(zir_module.source.bytes, 0, byte_off); + break :blk @intCast(u28, line_delta); + } else { + unreachable; + } + }; const ptr_width_bytes = self.ptrWidthBytes(); dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{ @@ -1850,7 +1859,7 @@ pub const File = struct { // to this function's begin curly. assert(self.getRelocDbgLineOff() == dbg_line_buffer.items.len); // Here we use a ULEB128-fixed-4 to make sure this field can be overwritten later. - leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), casted_line_off); + leb128.writeUnsignedFixed(4, dbg_line_buffer.addManyAsArrayAssumeCapacity(4), line_off); dbg_line_buffer.appendAssumeCapacity(DW.LNS_set_file); assert(self.getRelocDbgFileIndex() == dbg_line_buffer.items.len);