authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-01-26 20:25:30+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-01 08:47:25+02:00
log6ca0ff90b63cea79d8d63519a3c133cfde111884
tree874af7fa49e91088d0862058a794bb277fdd28c1
parent81c512f35b1926cf3fb6f29b97e68256aa164f68
signaturelock-open Commit is signed but in an unrecognized format.

stage2 cbe: use AutoIndentingStream


2 files changed, 43 insertions(+), 59 deletions(-)

src/codegen/c.zig+41-59
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const log = std.log.scoped(.c);3const log = std.log.scoped(.c);
4const Writer = std.ArrayList(u8).Writer;
54
6const link = @import("../link.zig");5const link = @import("../link.zig");
7const Module = @import("../Module.zig");6const Module = @import("../Module.zig");
...@@ -42,6 +41,7 @@ pub const Object = struct {...@@ -42,6 +41,7 @@ pub const Object = struct {
42 value_map: CValueMap,41 value_map: CValueMap,
43 next_arg_index: usize = 0,42 next_arg_index: usize = 0,
44 next_local_index: usize = 0,43 next_local_index: usize = 0,
44 indent_writer: std.io.AutoIndentingStream(std.ArrayList(u8).Writer),
4545
46 fn resolveInst(o: *Object, inst: *Inst) !CValue {46 fn resolveInst(o: *Object, inst: *Inst) !CValue {
47 if (inst.value()) |_| {47 if (inst.value()) |_| {
...@@ -58,31 +58,28 @@ pub const Object = struct {...@@ -58,31 +58,28 @@ pub const Object = struct {
5858
59 fn allocLocal(o: *Object, ty: Type, mutability: Mutability) !CValue {59 fn allocLocal(o: *Object, ty: Type, mutability: Mutability) !CValue {
60 const local_value = o.allocLocalValue();60 const local_value = o.allocLocalValue();
61 try o.renderTypeAndName(o.code.writer(), ty, local_value, mutability);61 try o.renderTypeAndName(o.writer(), ty, local_value, mutability);
62 return local_value;62 return local_value;
63 }63 }
6464
65 fn indent(o: *Object) !void {65 fn writer(o: *Object) std.io.AutoIndentingStream(std.ArrayList(u8).Writer).Writer {
66 const indent_size = 4;66 return o.indent_writer.writer();
67 const indent_level = 1;
68 const indent_amt = indent_size * indent_level;
69 try o.code.writer().writeByteNTimes(' ', indent_amt);
70 }67 }
7168
72 fn writeCValue(o: *Object, writer: Writer, c_value: CValue) !void {69 fn writeCValue(o: *Object, w: anytype, c_value: CValue) !void {
73 switch (c_value) {70 switch (c_value) {
74 .none => unreachable,71 .none => unreachable,
75 .local => |i| return writer.print("t{d}", .{i}),72 .local => |i| return w.print("t{d}", .{i}),
76 .local_ref => |i| return writer.print("&t{d}", .{i}),73 .local_ref => |i| return w.print("&t{d}", .{i}),
77 .constant => |inst| return o.dg.renderValue(writer, inst.ty, inst.value().?),74 .constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),
78 .arg => |i| return writer.print("a{d}", .{i}),75 .arg => |i| return w.print("a{d}", .{i}),
79 .decl => |decl| return writer.writeAll(mem.span(decl.name)),76 .decl => |decl| return w.writeAll(mem.span(decl.name)),
80 }77 }
81 }78 }
8279
83 fn renderTypeAndName(80 fn renderTypeAndName(
84 o: *Object,81 o: *Object,
85 writer: Writer,82 w: anytype,
86 ty: Type,83 ty: Type,
87 name: CValue,84 name: CValue,
88 mutability: Mutability,85 mutability: Mutability,
...@@ -98,15 +95,15 @@ pub const Object = struct {...@@ -98,15 +95,15 @@ pub const Object = struct {
98 render_ty = render_ty.elemType();95 render_ty = render_ty.elemType();
99 }96 }
10097
101 try o.dg.renderType(writer, render_ty);98 try o.dg.renderType(w, render_ty);
10299
103 const const_prefix = switch (mutability) {100 const const_prefix = switch (mutability) {
104 .Const => "const ",101 .Const => "const ",
105 .Mut => "",102 .Mut => "",
106 };103 };
107 try writer.print(" {s}", .{const_prefix});104 try w.print(" {s}", .{const_prefix});
108 try o.writeCValue(writer, name);105 try o.writeCValue(w, name);
109 try writer.writeAll(suffix.items);106 try w.writeAll(suffix.items);
110 }107 }
111};108};
112109
...@@ -127,7 +124,7 @@ pub const DeclGen = struct {...@@ -127,7 +124,7 @@ pub const DeclGen = struct {
127124
128 fn renderValue(125 fn renderValue(
129 dg: *DeclGen,126 dg: *DeclGen,
130 writer: Writer,127 writer: anytype,
131 t: Type,128 t: Type,
132 val: Value,129 val: Value,
133 ) error{ OutOfMemory, AnalysisFail }!void {130 ) error{ OutOfMemory, AnalysisFail }!void {
...@@ -204,7 +201,7 @@ pub const DeclGen = struct {...@@ -204,7 +201,7 @@ pub const DeclGen = struct {
204 }201 }
205 }202 }
206203
207 fn renderFunctionSignature(dg: *DeclGen, w: Writer, is_global: bool) !void {204 fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void {
208 if (!is_global) {205 if (!is_global) {
209 try w.writeAll("static ");206 try w.writeAll("static ");
210 }207 }
...@@ -228,7 +225,7 @@ pub const DeclGen = struct {...@@ -228,7 +225,7 @@ pub const DeclGen = struct {
228 try w.writeByte(')');225 try w.writeByte(')');
229 }226 }
230227
231 fn renderType(dg: *DeclGen, w: Writer, t: Type) error{ OutOfMemory, AnalysisFail }!void {228 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {
232 switch (t.zigTypeTag()) {229 switch (t.zigTypeTag()) {
233 .NoReturn => {230 .NoReturn => {
234 try w.writeAll("zig_noreturn void");231 try w.writeAll("zig_noreturn void");
...@@ -325,20 +322,19 @@ pub fn genDecl(o: *Object) !void {...@@ -325,20 +322,19 @@ pub fn genDecl(o: *Object) !void {
325 try fwd_decl_writer.writeAll(";\n");322 try fwd_decl_writer.writeAll(";\n");
326323
327 const func: *Module.Fn = func_payload.data;324 const func: *Module.Fn = func_payload.data;
328 const writer = o.code.writer();325 try o.indent_writer.insertNewline();
329 try writer.writeAll("\n");326 try o.dg.renderFunctionSignature(o.writer(), is_global);
330 try o.dg.renderFunctionSignature(writer, is_global);
331 327
332 try genBody(o, func.body);328 try genBody(o, func.body);
333329
334 try writer.writeAll("\n");330 try o.indent_writer.insertNewline();
335 } else if (tv.val.tag() == .extern_fn) {331 } else if (tv.val.tag() == .extern_fn) {
336 const writer = o.code.writer();332 const writer = o.writer();
337 try writer.writeAll("ZIG_EXTERN_C ");333 try writer.writeAll("ZIG_EXTERN_C ");
338 try o.dg.renderFunctionSignature(writer, true);334 try o.dg.renderFunctionSignature(writer, true);
339 try writer.writeAll(";\n");335 try writer.writeAll(";\n");
340 } else {336 } else {
341 const writer = o.code.writer();337 const writer = o.writer();
342 try writer.writeAll("static ");338 try writer.writeAll("static ");
343339
344 // TODO ask the Decl if it is const340 // TODO ask the Decl if it is const
...@@ -374,15 +370,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -374,15 +370,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
374}370}
375371
376pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void {372pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void {
377 const writer = o.code.writer();373 const writer = o.writer();
378 if (body.instructions.len == 0) {374 if (body.instructions.len == 0) {
379 try writer.writeAll(" {}");375 try writer.writeAll(" {}");
380 return;376 return;
381 }377 }
382378
383 try writer.writeAll(" {");379 try writer.writeAll(" {\n");
380 o.indent_writer.pushIndent();
384381
385 try writer.writeAll("\n");
386 for (body.instructions) |inst| {382 for (body.instructions) |inst| {
387 const result_value = switch (inst.tag) {383 const result_value = switch (inst.tag) {
388 .add => try genBinOp(o, inst.castTag(.add).?, " + "),384 .add => try genBinOp(o, inst.castTag(.add).?, " + "),
...@@ -416,14 +412,14 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi...@@ -416,14 +412,14 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
416 }412 }
417 }413 }
418414
415 o.indent_writer.popIndent();
419 try writer.writeAll("}");416 try writer.writeAll("}");
420}417}
421418
422fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {419fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {
423 const writer = o.code.writer();420 const writer = o.writer();
424421
425 // First line: the variable used as data storage.422 // First line: the variable used as data storage.
426 try o.indent();
427 const elem_type = alloc.base.ty.elemType();423 const elem_type = alloc.base.ty.elemType();
428 const mutability: Mutability = if (alloc.base.ty.isConstPtr()) .Const else .Mut;424 const mutability: Mutability = if (alloc.base.ty.isConstPtr()) .Const else .Mut;
429 const local = try o.allocLocal(elem_type, mutability);425 const local = try o.allocLocal(elem_type, mutability);
...@@ -439,15 +435,13 @@ fn genArg(o: *Object) CValue {...@@ -439,15 +435,13 @@ fn genArg(o: *Object) CValue {
439}435}
440436
441fn genRetVoid(o: *Object) !CValue {437fn genRetVoid(o: *Object) !CValue {
442 try o.indent();438 try o.writer().print("return;\n", .{});
443 try o.code.writer().print("return;\n", .{});
444 return CValue.none;439 return CValue.none;
445}440}
446441
447fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {442fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
448 const operand = try o.resolveInst(inst.operand);443 const operand = try o.resolveInst(inst.operand);
449 const writer = o.code.writer();444 const writer = o.writer();
450 try o.indent();
451 const local = try o.allocLocal(inst.base.ty, .Const);445 const local = try o.allocLocal(inst.base.ty, .Const);
452 switch (operand) {446 switch (operand) {
453 .local_ref => |i| {447 .local_ref => |i| {
...@@ -467,8 +461,7 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -467,8 +461,7 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
467461
468fn genRet(o: *Object, inst: *Inst.UnOp) !CValue {462fn genRet(o: *Object, inst: *Inst.UnOp) !CValue {
469 const operand = try o.resolveInst(inst.operand);463 const operand = try o.resolveInst(inst.operand);
470 try o.indent();464 const writer = o.writer();
471 const writer = o.code.writer();
472 try writer.writeAll("return ");465 try writer.writeAll("return ");
473 try o.writeCValue(writer, operand);466 try o.writeCValue(writer, operand);
474 try writer.writeAll(";\n");467 try writer.writeAll(";\n");
...@@ -481,8 +474,7 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -481,8 +474,7 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {
481474
482 const from = try o.resolveInst(inst.operand);475 const from = try o.resolveInst(inst.operand);
483476
484 try o.indent();477 const writer = o.writer();
485 const writer = o.code.writer();
486 const local = try o.allocLocal(inst.base.ty, .Const);478 const local = try o.allocLocal(inst.base.ty, .Const);
487 try writer.writeAll(" = (");479 try writer.writeAll(" = (");
488 try o.dg.renderType(writer, inst.base.ty);480 try o.dg.renderType(writer, inst.base.ty);
...@@ -497,8 +489,7 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {...@@ -497,8 +489,7 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
497 const dest_ptr = try o.resolveInst(inst.lhs);489 const dest_ptr = try o.resolveInst(inst.lhs);
498 const src_val = try o.resolveInst(inst.rhs);490 const src_val = try o.resolveInst(inst.rhs);
499491
500 try o.indent();492 const writer = o.writer();
501 const writer = o.code.writer();
502 switch (dest_ptr) {493 switch (dest_ptr) {
503 .local_ref => |i| {494 .local_ref => |i| {
504 const dest: CValue = .{ .local = i };495 const dest: CValue = .{ .local = i };
...@@ -525,8 +516,7 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {...@@ -525,8 +516,7 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
525 const lhs = try o.resolveInst(inst.lhs);516 const lhs = try o.resolveInst(inst.lhs);
526 const rhs = try o.resolveInst(inst.rhs);517 const rhs = try o.resolveInst(inst.rhs);
527518
528 try o.indent();519 const writer = o.writer();
529 const writer = o.code.writer();
530 const local = try o.allocLocal(inst.base.ty, .Const);520 const local = try o.allocLocal(inst.base.ty, .Const);
531521
532 try writer.writeAll(" = ");522 try writer.writeAll(" = ");
...@@ -552,8 +542,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {...@@ -552,8 +542,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
552 const unused_result = inst.base.isUnused();542 const unused_result = inst.base.isUnused();
553 var result_local: CValue = .none;543 var result_local: CValue = .none;
554544
555 try o.indent();545 const writer = o.writer();
556 const writer = o.code.writer();
557 if (unused_result) {546 if (unused_result) {
558 if (ret_ty.hasCodeGenBits()) {547 if (ret_ty.hasCodeGenBits()) {
559 try writer.print("(void)", .{});548 try writer.print("(void)", .{});
...@@ -596,8 +585,7 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {...@@ -596,8 +585,7 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
596fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {585fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
597 const operand = try o.resolveInst(inst.operand);586 const operand = try o.resolveInst(inst.operand);
598587
599 const writer = o.code.writer();588 const writer = o.writer();
600 try o.indent();
601 if (inst.base.ty.zigTypeTag() == .Pointer and inst.operand.ty.zigTypeTag() == .Pointer) {589 if (inst.base.ty.zigTypeTag() == .Pointer and inst.operand.ty.zigTypeTag() == .Pointer) {
602 const local = try o.allocLocal(inst.base.ty, .Const);590 const local = try o.allocLocal(inst.base.ty, .Const);
603 try writer.writeAll(" = (");591 try writer.writeAll(" = (");
...@@ -611,7 +599,6 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -611,7 +599,6 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
611599
612 const local = try o.allocLocal(inst.base.ty, .Mut);600 const local = try o.allocLocal(inst.base.ty, .Mut);
613 try writer.writeAll(";\n");601 try writer.writeAll(";\n");
614 try o.indent();
615602
616 try writer.writeAll("memcpy(&");603 try writer.writeAll("memcpy(&");
617 try o.writeCValue(writer, local);604 try o.writeCValue(writer, local);
...@@ -625,22 +612,19 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {...@@ -625,22 +612,19 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
625}612}
626613
627fn genBreakpoint(o: *Object, inst: *Inst.NoOp) !CValue {614fn genBreakpoint(o: *Object, inst: *Inst.NoOp) !CValue {
628 try o.indent();615 try o.writer().writeAll("zig_breakpoint();\n");
629 try o.code.writer().writeAll("zig_breakpoint();\n");
630 return CValue.none;616 return CValue.none;
631}617}
632618
633fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue {619fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue {
634 try o.indent();620 try o.writer().writeAll("zig_unreachable();\n");
635 try o.code.writer().writeAll("zig_unreachable();\n");
636 return CValue.none;621 return CValue.none;
637}622}
638623
639fn genLoop(o: *Object, inst: *Inst.Loop) !CValue {624fn genLoop(o: *Object, inst: *Inst.Loop) !CValue {
640 try o.indent();625 try o.writer().writeAll("while (true)");
641 try o.code.writer().writeAll("while (true)");
642 try genBody(o, inst.body);626 try genBody(o, inst.body);
643 try o.code.writer().writeAll("\n");627 try o.indent_writer.insertNewline();
644 return CValue.none;628 return CValue.none;
645}629}
646630
...@@ -648,13 +632,12 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {...@@ -648,13 +632,12 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
648 if (as.base.isUnused() and !as.is_volatile)632 if (as.base.isUnused() and !as.is_volatile)
649 return CValue.none;633 return CValue.none;
650634
651 const writer = o.code.writer();635 const writer = o.writer();
652 for (as.inputs) |i, index| {636 for (as.inputs) |i, index| {
653 if (i[0] == '{' and i[i.len - 1] == '}') {637 if (i[0] == '{' and i[i.len - 1] == '}') {
654 const reg = i[1 .. i.len - 1];638 const reg = i[1 .. i.len - 1];
655 const arg = as.args[index];639 const arg = as.args[index];
656 const arg_c_value = try o.resolveInst(arg);640 const arg_c_value = try o.resolveInst(arg);
657 try o.indent();
658 try writer.writeAll("register ");641 try writer.writeAll("register ");
659 try o.dg.renderType(writer, arg.ty);642 try o.dg.renderType(writer, arg.ty);
660643
...@@ -665,7 +648,6 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {...@@ -665,7 +648,6 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
665 return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});648 return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
666 }649 }
667 }650 }
668 try o.indent();
669 const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";651 const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
670 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });652 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
671 if (as.output) |_| {653 if (as.output) |_| {
src/link/C.zig+2
...@@ -95,7 +95,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {...@@ -95,7 +95,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
95 .gpa = module.gpa,95 .gpa = module.gpa,
96 .code = code.toManaged(module.gpa),96 .code = code.toManaged(module.gpa),
97 .value_map = codegen.CValueMap.init(module.gpa),97 .value_map = codegen.CValueMap.init(module.gpa),
98 .indent_writer = undefined, // set later so we can get a pointer to object.code
98 };99 };
100 object.indent_writer = std.io.autoIndentingStream(4, object.code.writer());
99 defer object.value_map.deinit();101 defer object.value_map.deinit();
100 defer object.code.deinit();102 defer object.code.deinit();
101 defer object.dg.fwd_decl.deinit();103 defer object.dg.fwd_decl.deinit();