aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-01-05 13:59:33 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-01-05 17:41:14 -0700
commitcd95444e4729761033f35d689a3b6ad6f4630552 (patch)
treeda260237a3505ef174406590380364c36fbb3160 /src
parent58cfaa5982fc6c216627fb6f2cfd0d0e4e89d92b (diff)
downloadzig-cd95444e4729761033f35d689a3b6ad6f4630552.tar.gz
zig-cd95444e4729761033f35d689a3b6ad6f4630552.zip
stage2: C backend: remove format() hackery
All C backend tests passing now, except for emit-h tests. Next task in the branch is to restore emit-h.
Diffstat (limited to 'src')
-rw-r--r--src/codegen/c.zig131
-rw-r--r--src/link/C.zig10
-rw-r--r--src/link/C/zig.h27
3 files changed, 91 insertions, 77 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index ab66869d31..5e274e0351 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -27,42 +27,6 @@ pub const CValue = union(enum) {
arg: usize,
/// By-value
decl: *Decl,
-
- pub fn printed(value: CValue, object: *Object) Printed {
- return .{
- .value = value,
- .object = object,
- };
- }
-
- pub const Printed = struct {
- value: CValue,
- object: *Object,
-
- /// TODO this got unwieldly, I want to remove the ability to print this way
- pub fn format(
- self: Printed,
- comptime fmt: []const u8,
- options: std.fmt.FormatOptions,
- writer: anytype,
- ) error{OutOfMemory}!void {
- if (fmt.len != 0) @compileError("Unknown format string: '" ++ fmt ++ "'");
- switch (self.value) {
- .none => unreachable,
- .local => |i| return std.fmt.format(writer, "t{d}", .{i}),
- .local_ref => |i| return std.fmt.format(writer, "&t{d}", .{i}),
- .constant => |inst| {
- const o = self.object;
- o.dg.renderValue(writer, inst.ty, inst.value().?) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => return,
- };
- },
- .arg => |i| return std.fmt.format(writer, "a{d}", .{i}),
- .decl => |decl| return writer.writeAll(mem.span(decl.name)),
- }
- }
- };
};
pub const CValueMap = std.AutoHashMap(*Inst, CValue);
@@ -103,6 +67,17 @@ pub const Object = struct {
try o.code.writer().writeByteNTimes(' ', indent_amt);
}
+ fn writeCValue(o: *Object, writer: Writer, 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)),
+ }
+ }
+
fn renderTypeAndName(
o: *Object,
writer: Writer,
@@ -127,7 +102,9 @@ pub const Object = struct {
.Const => "const ",
.Mut => "",
};
- try writer.print(" {s}{}{s}", .{ const_prefix, name.printed(o), suffix.items });
+ try writer.print(" {s}", .{const_prefix});
+ try o.writeCValue(writer, name);
+ try writer.writeAll(suffix.items);
}
};
@@ -353,7 +330,7 @@ pub fn genDecl(o: *Object) !void {
try writer.writeAll("\n");
for (instructions) |inst| {
const result_value = switch (inst.tag) {
- .add => try genBinOp(o, inst.castTag(.add).?, "+"),
+ .add => try genBinOp(o, inst.castTag(.add).?, " + "),
.alloc => try genAlloc(o, inst.castTag(.alloc).?),
.arg => genArg(o),
.assembly => try genAsm(o, inst.castTag(.assembly).?),
@@ -361,19 +338,19 @@ pub fn genDecl(o: *Object) !void {
.bitcast => try genBitcast(o, inst.castTag(.bitcast).?),
.breakpoint => try genBreakpoint(o, inst.castTag(.breakpoint).?),
.call => try genCall(o, inst.castTag(.call).?),
- .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, "=="),
- .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, ">"),
- .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, ">="),
- .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, "<"),
- .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, "<="),
- .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, "!="),
+ .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, " == "),
+ .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, " > "),
+ .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, " >= "),
+ .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, " < "),
+ .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, " <= "),
+ .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, " != "),
.dbg_stmt => try genDbgStmt(o, inst.castTag(.dbg_stmt).?),
.intcast => try genIntCast(o, inst.castTag(.intcast).?),
.load => try genLoad(o, inst.castTag(.load).?),
.ret => try genRet(o, inst.castTag(.ret).?),
.retvoid => try genRetVoid(o),
.store => try genStore(o, inst.castTag(.store).?),
- .sub => try genBinOp(o, inst.castTag(.sub).?, "-"),
+ .sub => try genBinOp(o, inst.castTag(.sub).?, " - "),
.unreach => try genUnreach(o, inst.castTag(.unreach).?),
else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
};
@@ -457,10 +434,14 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
switch (operand) {
.local_ref => |i| {
const wrapped: CValue = .{ .local = i };
- try writer.print(" = {};\n", .{wrapped.printed(o)});
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, wrapped);
+ try writer.writeAll(";\n");
},
else => {
- try writer.print(" = *{};\n", .{operand.printed(o)});
+ try writer.writeAll(" = *");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(";\n");
},
}
return local;
@@ -469,7 +450,10 @@ 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();
- try o.code.writer().print("return {};\n", .{operand.printed(o)});
+ const writer = o.code.writer();
+ try writer.writeAll("return ");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(";\n");
return CValue.none;
}
@@ -484,7 +468,9 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {
const local = try o.allocLocal(inst.base.ty, .Const);
try writer.writeAll(" = (");
try o.dg.renderType(writer, inst.base.ty);
- try writer.print("){};\n", .{from.printed(o)});
+ try writer.writeAll(")");
+ try o.writeCValue(writer, from);
+ try writer.writeAll(";\n");
return local;
}
@@ -498,10 +484,17 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
switch (dest_ptr) {
.local_ref => |i| {
const dest: CValue = .{ .local = i };
- try writer.print("{} = {};\n", .{ dest.printed(o), src_val.printed(o) });
+ try o.writeCValue(writer, dest);
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, src_val);
+ try writer.writeAll(";\n");
},
else => {
- try writer.print("*{} = {};\n", .{ dest_ptr.printed(o), src_val.printed(o) });
+ try writer.writeAll("*");
+ try o.writeCValue(writer, dest_ptr);
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, src_val);
+ try writer.writeAll(";\n");
},
}
return CValue.none;
@@ -517,7 +510,13 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
try o.indent();
const writer = o.code.writer();
const local = try o.allocLocal(inst.base.ty, .Const);
- try writer.print(" = {} {s} {};\n", .{ lhs.printed(o), operator, rhs.printed(o) });
+
+ try writer.writeAll(" = ");
+ try o.writeCValue(writer, lhs);
+ try writer.writeAll(operator);
+ try o.writeCValue(writer, rhs);
+ try writer.writeAll(";\n");
+
return local;
}
@@ -556,7 +555,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
try o.dg.renderValue(writer, arg.ty, val);
} else {
const val = try o.resolveInst(arg);
- try writer.print("{}", .{val.printed(o)});
+ try o.writeCValue(writer, val);
}
}
}
@@ -585,16 +584,25 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
const local = try o.allocLocal(inst.base.ty, .Const);
try writer.writeAll(" = (");
try o.dg.renderType(writer, inst.base.ty);
- try writer.print("){};\n", .{operand.printed(o)});
+
+ try writer.writeAll(")");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(";\n");
return local;
}
const local = try o.allocLocal(inst.base.ty, .Mut);
try writer.writeAll(";\n");
try o.indent();
- try writer.print("memcpy(&{}, &{}, sizeof {});\n", .{
- local.printed(o), operand.printed(o), local.printed(o),
- });
+
+ try writer.writeAll("memcpy(&");
+ try o.writeCValue(writer, local);
+ try writer.writeAll(", &");
+ try o.writeCValue(writer, operand);
+ try writer.writeAll(", sizeof ");
+ try o.writeCValue(writer, local);
+ try writer.writeAll(");\n");
+
return local;
}
@@ -623,9 +631,10 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
try o.indent();
try writer.writeAll("register ");
try o.dg.renderType(writer, arg.ty);
- try writer.print(" {s}_constant __asm__(\"{s}\") = {};\n", .{
- reg, reg, arg_c_value.printed(o),
- });
+
+ try writer.print(" {s}_constant __asm__(\"{s}\") = ", .{ reg, reg });
+ try o.writeCValue(writer, arg_c_value);
+ try writer.writeAll(";\n");
} else {
return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
}
@@ -648,7 +657,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
if (index > 0) {
try writer.writeAll(", ");
}
- try writer.print("\"\"({s}_constant)", .{reg});
+ try writer.print("\"r\"({s}_constant)", .{reg});
} else {
// This is blocked by the earlier test
unreachable;
diff --git a/src/link/C.zig b/src/link/C.zig
index 68eb56c5b9..0bca77f25f 100644
--- a/src/link/C.zig
+++ b/src/link/C.zig
@@ -101,14 +101,12 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
defer object.dg.fwd_decl.deinit();
codegen.genDecl(&object) catch |err| switch (err) {
- error.AnalysisFail => {},
+ error.AnalysisFail => {
+ try module.failed_decls.put(module.gpa, decl, object.dg.error_msg.?);
+ return;
+ },
else => |e| return e,
};
- // The code may populate this error without returning error.AnalysisFail.
- if (object.dg.error_msg) |msg| {
- try module.failed_decls.put(module.gpa, decl, msg);
- return;
- }
fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
code.* = object.code.moveToUnmanaged();
diff --git a/src/link/C/zig.h b/src/link/C/zig.h
index 49f97210eb..fed799d348 100644
--- a/src/link/C/zig.h
+++ b/src/link/C/zig.h
@@ -22,24 +22,31 @@
#define zig_unreachable()
#endif
-#if defined(_MSC_VER)
-#define zig_breakpoint __debugbreak()
+#if __STDC_VERSION__ >= 199901L
+#define zig_restrict restrict
+#elif defined(__GNUC__)
+#define zig_restrict __restrict
#else
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#define zig_breakpoint __debugbreak()
+#define zig_restrict
+#endif
+
+#if defined(_MSC_VER)
+#define zig_breakpoint() __debugbreak()
+#elif defined(__MINGW32__) || defined(__MINGW64__)
+#define zig_breakpoint() __debugbreak()
#elif defined(__clang__)
-#define zig_breakpoint __builtin_debugtrap()
+#define zig_breakpoint() __builtin_debugtrap()
#elif defined(__GNUC__)
-#define zig_breakpoint __builtin_trap()
+#define zig_breakpoint() __builtin_trap()
#elif defined(__i386__) || defined(__x86_64__)
-#define zig_breakpoint __asm__ volatile("int $0x03");
+#define zig_breakpoint() __asm__ volatile("int $0x03");
#else
-#define zig_breakpoint raise(SIGTRAP)
-#endif
+#define zig_breakpoint() raise(SIGTRAP)
#endif
#include <stdint.h>
+#include <stddef.h>
#define int128_t __int128
#define uint128_t unsigned __int128
-#include <string.h>
+void *memcpy (void *zig_restrict, const void *zig_restrict, size_t);