mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2 cbe: use AutoIndentingStream
This commit is contained in:
parent
81c512f35b
commit
6ca0ff90b6
@ -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) |_| {
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user