diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-07-30 03:18:10 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-07-31 01:58:10 -0400 |
| commit | 817fa3af8631d894004fbdb668da0882836dbe9b (patch) | |
| tree | 3e63751b5ebb46fe8c45eca41a5248075d97bda8 /src/codegen/c.zig | |
| parent | 43b830415368ac4fb08bf5e154a222a38baf4a24 (diff) | |
| download | zig-817fa3af8631d894004fbdb668da0882836dbe9b.tar.gz zig-817fa3af8631d894004fbdb668da0882836dbe9b.zip | |
std: cleanup asm usage
After fixing some issues with inline assembly in the C backend, the std
cleanups have the side effect of making these functions compatible with
the backend, allowing it to be used on linux without linking libc.
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 2cfbbef2e1..1ae9527f04 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -30,7 +30,7 @@ pub const CValue = union(enum) { /// Address of a local. local_ref: LocalIndex, /// A constant instruction, to be rendered inline. - constant: Air.Inst.Ref, + constant: InternPool.Index, /// Index into the parameters arg: usize, /// The array field of a parameter @@ -302,7 +302,7 @@ pub const Function = struct { try f.object.dg.renderValue(writer, ty, val, .StaticInitializer); try writer.writeAll(";\n "); break :result decl_c_value; - } else .{ .constant = ref }; + } else .{ .constant = val.toIntern() }; gop.value_ptr.* = result; return result; @@ -352,57 +352,63 @@ pub const Function = struct { fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { switch (c_value) { - .constant => |inst| { - const mod = f.object.dg.module; - const ty = f.typeOf(inst); - const val = (try f.air.value(inst, mod)).?; - return f.object.dg.renderValue(w, ty, val, location); - }, - .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location), - else => return f.object.dg.writeCValue(w, c_value), + .constant => |val| try f.object.dg.renderValue( + w, + f.object.dg.module.intern_pool.typeOf(val).toType(), + val.toValue(), + location, + ), + .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location), + else => try f.object.dg.writeCValue(w, c_value), } } fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void { switch (c_value) { - .constant => |inst| { - const mod = f.object.dg.module; - const ty = f.typeOf(inst); - const val = (try f.air.value(inst, mod)).?; + .constant => |val| { try w.writeAll("(*"); - try f.object.dg.renderValue(w, ty, val, .Other); - return w.writeByte(')'); + try f.object.dg.renderValue( + w, + f.object.dg.module.intern_pool.typeOf(val).toType(), + val.toValue(), + .Other, + ); + try w.writeByte(')'); }, - else => return f.object.dg.writeCValueDeref(w, c_value), + else => try f.object.dg.writeCValueDeref(w, c_value), } } fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { switch (c_value) { - .constant => |inst| { - const mod = f.object.dg.module; - const ty = f.typeOf(inst); - const val = (try f.air.value(inst, mod)).?; - try f.object.dg.renderValue(w, ty, val, .Other); + .constant => |val| { + try f.object.dg.renderValue( + w, + f.object.dg.module.intern_pool.typeOf(val).toType(), + val.toValue(), + .Other, + ); try w.writeByte('.'); - return f.writeCValue(w, member, .Other); + try f.writeCValue(w, member, .Other); }, - else => return f.object.dg.writeCValueMember(w, c_value, member), + else => try f.object.dg.writeCValueMember(w, c_value, member), } } fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void { switch (c_value) { - .constant => |inst| { - const mod = f.object.dg.module; - const ty = f.typeOf(inst); - const val = (try f.air.value(inst, mod)).?; + .constant => |val| { try w.writeByte('('); - try f.object.dg.renderValue(w, ty, val, .Other); + try f.object.dg.renderValue( + w, + f.object.dg.module.intern_pool.typeOf(val).toType(), + val.toValue(), + .Other, + ); try w.writeAll(")->"); - return f.writeCValue(w, member, .Other); + try f.writeCValue(w, member, .Other); }, - else => return f.object.dg.writeCValueDerefMember(w, c_value, member), + else => try f.object.dg.writeCValueDerefMember(w, c_value, member), } } @@ -4763,11 +4769,20 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { return .none; } -fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool { +fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { return switch (constraint[0]) { '{' => true, 'i', 'r' => false, - else => value == .constant, + else => switch (value) { + .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) { + .ptr => |ptr| switch (ptr.addr) { + .decl => false, + else => true, + }, + else => true, + }, + else => false, + }, }; } @@ -4848,7 +4863,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const is_reg = constraint[0] == '{'; const input_val = try f.resolveInst(input); - if (asmInputNeedsLocal(constraint, input_val)) { + if (asmInputNeedsLocal(f, constraint, input_val)) { const input_ty = f.typeOf(input); if (is_reg) try writer.writeAll("register "); const alignment = 0; @@ -4969,7 +4984,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const is_reg = constraint[0] == '{'; const input_val = try f.resolveInst(input); try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); - try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: { + try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: { const input_local = .{ .local = locals_index }; locals_index += 1; break :local input_local; |
