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
signature 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 @@
11const std = @import("std");
22const mem = std.mem;
33const log = std.log.scoped(.c);
4const Writer = std.ArrayList(u8).Writer;
54
65const link = @import("../link.zig");
76const Module = @import("../Module.zig");
......@@ -42,6 +41,7 @@ pub const Object = struct {
4241 value_map: CValueMap,
4342 next_arg_index: usize = 0,
4443 next_local_index: usize = 0,
44 indent_writer: std.io.AutoIndentingStream(std.ArrayList(u8).Writer),
4545
4646 fn resolveInst(o: *Object, inst: *Inst) !CValue {
4747 if (inst.value()) |_| {
......@@ -58,31 +58,28 @@ pub const Object = struct {
5858
5959 fn allocLocal(o: *Object, ty: Type, mutability: Mutability) !CValue {
6060 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);
6262 return local_value;
6363 }
6464
65 fn indent(o: *Object) !void {
66 const indent_size = 4;
67 const indent_level = 1;
68 const indent_amt = indent_size * indent_level;
69 try o.code.writer().writeByteNTimes(' ', indent_amt);
65 fn writer(o: *Object) std.io.AutoIndentingStream(std.ArrayList(u8).Writer).Writer {
66 return o.indent_writer.writer();
7067 }
7168
72 fn writeCValue(o: *Object, writer: Writer, c_value: CValue) !void {
69 fn writeCValue(o: *Object, w: anytype, c_value: CValue) !void {
7370 switch (c_value) {
7471 .none => unreachable,
75 .local => |i| return writer.print("t{d}", .{i}),
76 .local_ref => |i| return writer.print("&t{d}", .{i}),
77 .constant => |inst| return o.dg.renderValue(writer, inst.ty, inst.value().?),
78 .arg => |i| return writer.print("a{d}", .{i}),
79 .decl => |decl| return writer.writeAll(mem.span(decl.name)),
72 .local => |i| return w.print("t{d}", .{i}),
73 .local_ref => |i| return w.print("&t{d}", .{i}),
74 .constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),
75 .arg => |i| return w.print("a{d}", .{i}),
76 .decl => |decl| return w.writeAll(mem.span(decl.name)),
8077 }
8178 }
8279
8380 fn renderTypeAndName(
8481 o: *Object,
85 writer: Writer,
82 w: anytype,
8683 ty: Type,
8784 name: CValue,
8885 mutability: Mutability,
......@@ -98,15 +95,15 @@ pub const Object = struct {
9895 render_ty = render_ty.elemType();
9996 }
10097
101 try o.dg.renderType(writer, render_ty);
98 try o.dg.renderType(w, render_ty);
10299
103100 const const_prefix = switch (mutability) {
104101 .Const => "const ",
105102 .Mut => "",
106103 };
107 try writer.print(" {s}", .{const_prefix});
108 try o.writeCValue(writer, name);
109 try writer.writeAll(suffix.items);
104 try w.print(" {s}", .{const_prefix});
105 try o.writeCValue(w, name);
106 try w.writeAll(suffix.items);
110107 }
111108};
112109
......@@ -127,7 +124,7 @@ pub const DeclGen = struct {
127124
128125 fn renderValue(
129126 dg: *DeclGen,
130 writer: Writer,
127 writer: anytype,
131128 t: Type,
132129 val: Value,
133130 ) error{ OutOfMemory, AnalysisFail }!void {
......@@ -204,7 +201,7 @@ pub const DeclGen = struct {
204201 }
205202 }
206203
207 fn renderFunctionSignature(dg: *DeclGen, w: Writer, is_global: bool) !void {
204 fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void {
208205 if (!is_global) {
209206 try w.writeAll("static ");
210207 }
......@@ -228,7 +225,7 @@ pub const DeclGen = struct {
228225 try w.writeByte(')');
229226 }
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 {
232229 switch (t.zigTypeTag()) {
233230 .NoReturn => {
234231 try w.writeAll("zig_noreturn void");
......@@ -325,20 +322,19 @@ pub fn genDecl(o: *Object) !void {
325322 try fwd_decl_writer.writeAll(";\n");
326323
327324 const func: *Module.Fn = func_payload.data;
328 const writer = o.code.writer();
329 try writer.writeAll("\n");
330 try o.dg.renderFunctionSignature(writer, is_global);
325 try o.indent_writer.insertNewline();
326 try o.dg.renderFunctionSignature(o.writer(), is_global);
331327
332328 try genBody(o, func.body);
333329
334 try writer.writeAll("\n");
330 try o.indent_writer.insertNewline();
335331 } else if (tv.val.tag() == .extern_fn) {
336 const writer = o.code.writer();
332 const writer = o.writer();
337333 try writer.writeAll("ZIG_EXTERN_C ");
338334 try o.dg.renderFunctionSignature(writer, true);
339335 try writer.writeAll(";\n");
340336 } else {
341 const writer = o.code.writer();
337 const writer = o.writer();
342338 try writer.writeAll("static ");
343339
344340 // TODO ask the Decl if it is const
......@@ -374,15 +370,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
374370}
375371
376372pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void {
377 const writer = o.code.writer();
373 const writer = o.writer();
378374 if (body.instructions.len == 0) {
379375 try writer.writeAll(" {}");
380376 return;
381377 }
382378
383 try writer.writeAll(" {");
379 try writer.writeAll(" {\n");
380 o.indent_writer.pushIndent();
384381
385 try writer.writeAll("\n");
386382 for (body.instructions) |inst| {
387383 const result_value = switch (inst.tag) {
388384 .add => try genBinOp(o, inst.castTag(.add).?, " + "),
......@@ -416,14 +412,14 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
416412 }
417413 }
418414
415 o.indent_writer.popIndent();
419416 try writer.writeAll("}");
420417}
421418
422419fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {
423 const writer = o.code.writer();
420 const writer = o.writer();
424421
425422 // First line: the variable used as data storage.
426 try o.indent();
427423 const elem_type = alloc.base.ty.elemType();
428424 const mutability: Mutability = if (alloc.base.ty.isConstPtr()) .Const else .Mut;
429425 const local = try o.allocLocal(elem_type, mutability);
......@@ -439,15 +435,13 @@ fn genArg(o: *Object) CValue {
439435}
440436
441437fn genRetVoid(o: *Object) !CValue {
442 try o.indent();
443 try o.code.writer().print("return;\n", .{});
438 try o.writer().print("return;\n", .{});
444439 return CValue.none;
445440}
446441
447442fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
448443 const operand = try o.resolveInst(inst.operand);
449 const writer = o.code.writer();
450 try o.indent();
444 const writer = o.writer();
451445 const local = try o.allocLocal(inst.base.ty, .Const);
452446 switch (operand) {
453447 .local_ref => |i| {
......@@ -467,8 +461,7 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
467461
468462fn genRet(o: *Object, inst: *Inst.UnOp) !CValue {
469463 const operand = try o.resolveInst(inst.operand);
470 try o.indent();
471 const writer = o.code.writer();
464 const writer = o.writer();
472465 try writer.writeAll("return ");
473466 try o.writeCValue(writer, operand);
474467 try writer.writeAll(";\n");
......@@ -481,8 +474,7 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {
481474
482475 const from = try o.resolveInst(inst.operand);
483476
484 try o.indent();
485 const writer = o.code.writer();
477 const writer = o.writer();
486478 const local = try o.allocLocal(inst.base.ty, .Const);
487479 try writer.writeAll(" = (");
488480 try o.dg.renderType(writer, inst.base.ty);
......@@ -497,8 +489,7 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
497489 const dest_ptr = try o.resolveInst(inst.lhs);
498490 const src_val = try o.resolveInst(inst.rhs);
499491
500 try o.indent();
501 const writer = o.code.writer();
492 const writer = o.writer();
502493 switch (dest_ptr) {
503494 .local_ref => |i| {
504495 const dest: CValue = .{ .local = i };
......@@ -525,8 +516,7 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
525516 const lhs = try o.resolveInst(inst.lhs);
526517 const rhs = try o.resolveInst(inst.rhs);
527518
528 try o.indent();
529 const writer = o.code.writer();
519 const writer = o.writer();
530520 const local = try o.allocLocal(inst.base.ty, .Const);
531521
532522 try writer.writeAll(" = ");
......@@ -552,8 +542,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
552542 const unused_result = inst.base.isUnused();
553543 var result_local: CValue = .none;
554544
555 try o.indent();
556 const writer = o.code.writer();
545 const writer = o.writer();
557546 if (unused_result) {
558547 if (ret_ty.hasCodeGenBits()) {
559548 try writer.print("(void)", .{});
......@@ -596,8 +585,7 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
596585fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
597586 const operand = try o.resolveInst(inst.operand);
598587
599 const writer = o.code.writer();
600 try o.indent();
588 const writer = o.writer();
601589 if (inst.base.ty.zigTypeTag() == .Pointer and inst.operand.ty.zigTypeTag() == .Pointer) {
602590 const local = try o.allocLocal(inst.base.ty, .Const);
603591 try writer.writeAll(" = (");
......@@ -611,7 +599,6 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
611599
612600 const local = try o.allocLocal(inst.base.ty, .Mut);
613601 try writer.writeAll(";\n");
614 try o.indent();
615602
616603 try writer.writeAll("memcpy(&");
617604 try o.writeCValue(writer, local);
......@@ -625,22 +612,19 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
625612}
626613
627614fn genBreakpoint(o: *Object, inst: *Inst.NoOp) !CValue {
628 try o.indent();
629 try o.code.writer().writeAll("zig_breakpoint();\n");
615 try o.writer().writeAll("zig_breakpoint();\n");
630616 return CValue.none;
631617}
632618
633619fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue {
634 try o.indent();
635 try o.code.writer().writeAll("zig_unreachable();\n");
620 try o.writer().writeAll("zig_unreachable();\n");
636621 return CValue.none;
637622}
638623
639624fn genLoop(o: *Object, inst: *Inst.Loop) !CValue {
640 try o.indent();
641 try o.code.writer().writeAll("while (true)");
625 try o.writer().writeAll("while (true)");
642626 try genBody(o, inst.body);
643 try o.code.writer().writeAll("\n");
627 try o.indent_writer.insertNewline();
644628 return CValue.none;
645629}
646630
......@@ -648,13 +632,12 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
648632 if (as.base.isUnused() and !as.is_volatile)
649633 return CValue.none;
650634
651 const writer = o.code.writer();
635 const writer = o.writer();
652636 for (as.inputs) |i, index| {
653637 if (i[0] == '{' and i[i.len - 1] == '}') {
654638 const reg = i[1 .. i.len - 1];
655639 const arg = as.args[index];
656640 const arg_c_value = try o.resolveInst(arg);
657 try o.indent();
658641 try writer.writeAll("register ");
659642 try o.dg.renderType(writer, arg.ty);
660643
......@@ -665,7 +648,6 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
665648 return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
666649 }
667650 }
668 try o.indent();
669651 const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
670652 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
671653 if (as.output) |_| {
src/link/C.zig+2
......@@ -95,7 +95,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
9595 .gpa = module.gpa,
9696 .code = code.toManaged(module.gpa),
9797 .value_map = codegen.CValueMap.init(module.gpa),
98 .indent_writer = undefined, // set later so we can get a pointer to object.code
9899 };
100 object.indent_writer = std.io.autoIndentingStream(4, object.code.writer());
99101 defer object.value_map.deinit();
100102 defer object.code.deinit();
101103 defer object.dg.fwd_decl.deinit();