aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig100
-rw-r--r--src/link/C.zig2
2 files changed, 43 insertions, 59 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index ccde36a10d..9bccde5ffd 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -1,7 +1,6 @@
const std = @import("std");
const mem = std.mem;
const log = std.log.scoped(.c);
-const Writer = std.ArrayList(u8).Writer;
const link = @import("../link.zig");
const Module = @import("../Module.zig");
@@ -42,6 +41,7 @@ pub const Object = struct {
value_map: CValueMap,
next_arg_index: usize = 0,
next_local_index: usize = 0,
+ indent_writer: std.io.AutoIndentingStream(std.ArrayList(u8).Writer),
fn resolveInst(o: *Object, inst: *Inst) !CValue {
if (inst.value()) |_| {
@@ -58,31 +58,28 @@ pub const Object = struct {
fn allocLocal(o: *Object, ty: Type, mutability: Mutability) !CValue {
const local_value = o.allocLocalValue();
- try o.renderTypeAndName(o.code.writer(), ty, local_value, mutability);
+ try o.renderTypeAndName(o.writer(), ty, local_value, mutability);
return local_value;
}
- fn indent(o: *Object) !void {
- const indent_size = 4;
- const indent_level = 1;
- const indent_amt = indent_size * indent_level;
- try o.code.writer().writeByteNTimes(' ', indent_amt);
+ fn writer(o: *Object) std.io.AutoIndentingStream(std.ArrayList(u8).Writer).Writer {
+ return o.indent_writer.writer();
}
- fn writeCValue(o: *Object, writer: Writer, c_value: CValue) !void {
+ fn writeCValue(o: *Object, w: anytype, c_value: CValue) !void {
switch (c_value) {
.none => unreachable,
- .local => |i| return writer.print("t{d}", .{i}),
- .local_ref => |i| return writer.print("&t{d}", .{i}),
- .constant => |inst| return o.dg.renderValue(writer, inst.ty, inst.value().?),
- .arg => |i| return writer.print("a{d}", .{i}),
- .decl => |decl| return writer.writeAll(mem.span(decl.name)),
+ .local => |i| return w.print("t{d}", .{i}),
+ .local_ref => |i| return w.print("&t{d}", .{i}),
+ .constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),
+ .arg => |i| return w.print("a{d}", .{i}),
+ .decl => |decl| return w.writeAll(mem.span(decl.name)),
}
}
fn renderTypeAndName(
o: *Object,
- writer: Writer,
+ w: anytype,
ty: Type,
name: CValue,
mutability: Mutability,
@@ -98,15 +95,15 @@ pub const Object = struct {
render_ty = render_ty.elemType();
}
- try o.dg.renderType(writer, render_ty);
+ try o.dg.renderType(w, render_ty);
const const_prefix = switch (mutability) {
.Const => "const ",
.Mut => "",
};
- try writer.print(" {s}", .{const_prefix});
- try o.writeCValue(writer, name);
- try writer.writeAll(suffix.items);
+ try w.print(" {s}", .{const_prefix});
+ try o.writeCValue(w, name);
+ try w.writeAll(suffix.items);
}
};
@@ -127,7 +124,7 @@ pub const DeclGen = struct {
fn renderValue(
dg: *DeclGen,
- writer: Writer,
+ writer: anytype,
t: Type,
val: Value,
) error{ OutOfMemory, AnalysisFail }!void {
@@ -204,7 +201,7 @@ pub const DeclGen = struct {
}
}
- fn renderFunctionSignature(dg: *DeclGen, w: Writer, is_global: bool) !void {
+ fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void {
if (!is_global) {
try w.writeAll("static ");
}
@@ -228,7 +225,7 @@ pub const DeclGen = struct {
try w.writeByte(')');
}
- fn renderType(dg: *DeclGen, w: Writer, t: Type) error{ OutOfMemory, AnalysisFail }!void {
+ fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {
switch (t.zigTypeTag()) {
.NoReturn => {
try w.writeAll("zig_noreturn void");
@@ -325,20 +322,19 @@ pub fn genDecl(o: *Object) !void {
try fwd_decl_writer.writeAll(";\n");
const func: *Module.Fn = func_payload.data;
- const writer = o.code.writer();
- try writer.writeAll("\n");
- try o.dg.renderFunctionSignature(writer, is_global);
+ try o.indent_writer.insertNewline();
+ try o.dg.renderFunctionSignature(o.writer(), is_global);
try genBody(o, func.body);
- try writer.writeAll("\n");
+ try o.indent_writer.insertNewline();
} else if (tv.val.tag() == .extern_fn) {
- const writer = o.code.writer();
+ const writer = o.writer();
try writer.writeAll("ZIG_EXTERN_C ");
try o.dg.renderFunctionSignature(writer, true);
try writer.writeAll(";\n");
} else {
- const writer = o.code.writer();
+ const writer = o.writer();
try writer.writeAll("static ");
// TODO ask the Decl if it is const
@@ -374,15 +370,15 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
}
pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!void {
- const writer = o.code.writer();
+ const writer = o.writer();
if (body.instructions.len == 0) {
try writer.writeAll(" {}");
return;
}
- try writer.writeAll(" {");
+ try writer.writeAll(" {\n");
+ o.indent_writer.pushIndent();
- try writer.writeAll("\n");
for (body.instructions) |inst| {
const result_value = switch (inst.tag) {
.add => try genBinOp(o, inst.castTag(.add).?, " + "),
@@ -416,14 +412,14 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
}
}
+ o.indent_writer.popIndent();
try writer.writeAll("}");
}
fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {
- const writer = o.code.writer();
+ const writer = o.writer();
// First line: the variable used as data storage.
- try o.indent();
const elem_type = alloc.base.ty.elemType();
const mutability: Mutability = if (alloc.base.ty.isConstPtr()) .Const else .Mut;
const local = try o.allocLocal(elem_type, mutability);
@@ -439,15 +435,13 @@ fn genArg(o: *Object) CValue {
}
fn genRetVoid(o: *Object) !CValue {
- try o.indent();
- try o.code.writer().print("return;\n", .{});
+ try o.writer().print("return;\n", .{});
return CValue.none;
}
fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
const operand = try o.resolveInst(inst.operand);
- const writer = o.code.writer();
- try o.indent();
+ const writer = o.writer();
const local = try o.allocLocal(inst.base.ty, .Const);
switch (operand) {
.local_ref => |i| {
@@ -467,8 +461,7 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
fn genRet(o: *Object, inst: *Inst.UnOp) !CValue {
const operand = try o.resolveInst(inst.operand);
- try o.indent();
- const writer = o.code.writer();
+ const writer = o.writer();
try writer.writeAll("return ");
try o.writeCValue(writer, operand);
try writer.writeAll(";\n");
@@ -481,8 +474,7 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {
const from = try o.resolveInst(inst.operand);
- try o.indent();
- const writer = o.code.writer();
+ const writer = o.writer();
const local = try o.allocLocal(inst.base.ty, .Const);
try writer.writeAll(" = (");
try o.dg.renderType(writer, inst.base.ty);
@@ -497,8 +489,7 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
const dest_ptr = try o.resolveInst(inst.lhs);
const src_val = try o.resolveInst(inst.rhs);
- try o.indent();
- const writer = o.code.writer();
+ const writer = o.writer();
switch (dest_ptr) {
.local_ref => |i| {
const dest: CValue = .{ .local = i };
@@ -525,8 +516,7 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
const lhs = try o.resolveInst(inst.lhs);
const rhs = try o.resolveInst(inst.rhs);
- try o.indent();
- const writer = o.code.writer();
+ const writer = o.writer();
const local = try o.allocLocal(inst.base.ty, .Const);
try writer.writeAll(" = ");
@@ -552,8 +542,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
const unused_result = inst.base.isUnused();
var result_local: CValue = .none;
- try o.indent();
- const writer = o.code.writer();
+ const writer = o.writer();
if (unused_result) {
if (ret_ty.hasCodeGenBits()) {
try writer.print("(void)", .{});
@@ -596,8 +585,7 @@ fn genBlock(o: *Object, inst: *Inst.Block) !CValue {
fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
const operand = try o.resolveInst(inst.operand);
- const writer = o.code.writer();
- try o.indent();
+ const writer = o.writer();
if (inst.base.ty.zigTypeTag() == .Pointer and inst.operand.ty.zigTypeTag() == .Pointer) {
const local = try o.allocLocal(inst.base.ty, .Const);
try writer.writeAll(" = (");
@@ -611,7 +599,6 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
const local = try o.allocLocal(inst.base.ty, .Mut);
try writer.writeAll(";\n");
- try o.indent();
try writer.writeAll("memcpy(&");
try o.writeCValue(writer, local);
@@ -625,22 +612,19 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
}
fn genBreakpoint(o: *Object, inst: *Inst.NoOp) !CValue {
- try o.indent();
- try o.code.writer().writeAll("zig_breakpoint();\n");
+ try o.writer().writeAll("zig_breakpoint();\n");
return CValue.none;
}
fn genUnreach(o: *Object, inst: *Inst.NoOp) !CValue {
- try o.indent();
- try o.code.writer().writeAll("zig_unreachable();\n");
+ try o.writer().writeAll("zig_unreachable();\n");
return CValue.none;
}
fn genLoop(o: *Object, inst: *Inst.Loop) !CValue {
- try o.indent();
- try o.code.writer().writeAll("while (true)");
+ try o.writer().writeAll("while (true)");
try genBody(o, inst.body);
- try o.code.writer().writeAll("\n");
+ try o.indent_writer.insertNewline();
return CValue.none;
}
@@ -648,13 +632,12 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
if (as.base.isUnused() and !as.is_volatile)
return CValue.none;
- const writer = o.code.writer();
+ const writer = o.writer();
for (as.inputs) |i, index| {
if (i[0] == '{' and i[i.len - 1] == '}') {
const reg = i[1 .. i.len - 1];
const arg = as.args[index];
const arg_c_value = try o.resolveInst(arg);
- try o.indent();
try writer.writeAll("register ");
try o.dg.renderType(writer, arg.ty);
@@ -665,7 +648,6 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
}
}
- try o.indent();
const volatile_string: []const u8 = if (as.is_volatile) "volatile " else "";
try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, as.asm_source });
if (as.output) |_| {
diff --git a/src/link/C.zig b/src/link/C.zig
index a60d0efd8e..765249cd7d 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -95,7 +95,9 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
.gpa = module.gpa,
.code = code.toManaged(module.gpa),
.value_map = codegen.CValueMap.init(module.gpa),
+ .indent_writer = undefined, // set later so we can get a pointer to object.code
};
+ object.indent_writer = std.io.autoIndentingStream(4, object.code.writer());
defer object.value_map.deinit();
defer object.code.deinit();
defer object.dg.fwd_decl.deinit();