cbe: misc fixes

This commit is contained in:
Jacob Young 2022-10-18 21:41:00 -04:00
parent 1dd4a6102f
commit b48417aed2
4 changed files with 75 additions and 52 deletions

View file

@ -88,23 +88,9 @@ pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsC
} }
const reserved_idents = std.ComptimeStringMap(void, .{ const reserved_idents = std.ComptimeStringMap(void, .{
.{ "_Alignas", { .{ "alignas", {
@setEvalBranchQuota(4000); @setEvalBranchQuota(4000);
} }, } },
.{ "_Alignof", {} },
.{ "_Atomic", {} },
.{ "_Bool", {} },
.{ "_Complex", {} },
.{ "_Decimal128", {} },
.{ "_Decimal32", {} },
.{ "_Decimal64", {} },
.{ "_Generic", {} },
.{ "_Imaginary", {} },
.{ "_Noreturn", {} },
.{ "_Pragma", {} },
.{ "_Static_assert", {} },
.{ "_Thread_local", {} },
.{ "alignas", {} },
.{ "alignof", {} }, .{ "alignof", {} },
.{ "asm", {} }, .{ "asm", {} },
.{ "atomic_bool", {} }, .{ "atomic_bool", {} },
@ -199,6 +185,15 @@ const reserved_idents = std.ComptimeStringMap(void, .{
.{ "while ", {} }, .{ "while ", {} },
}); });
fn isReservedIdent(ident: []const u8) bool {
if (ident.len >= 2 and ident[0] == '_') {
switch (ident[1]) {
'A'...'Z', '_' => return true,
else => return false,
}
} else return reserved_idents.has(ident);
}
fn formatIdent( fn formatIdent(
ident: []const u8, ident: []const u8,
comptime fmt: []const u8, comptime fmt: []const u8,
@ -207,7 +202,7 @@ fn formatIdent(
) !void { ) !void {
_ = options; _ = options;
const solo = fmt.len != 0 and fmt[0] == ' '; // space means solo; not part of a bigger ident. const solo = fmt.len != 0 and fmt[0] == ' '; // space means solo; not part of a bigger ident.
if (solo and reserved_idents.has(ident)) { if (solo and isReservedIdent(ident)) {
try writer.writeAll("zig_e_"); try writer.writeAll("zig_e_");
} }
for (ident) |c, i| { for (ident) |c, i| {
@ -601,12 +596,17 @@ pub const DeclGen = struct {
try dg.renderTypecast(writer, ty); try dg.renderTypecast(writer, ty);
try writer.writeAll("){"); try writer.writeAll("){");
if (ty.unionTagTypeSafety()) |tag_ty| {
try writer.writeAll(".tag = ");
try dg.renderValue(writer, tag_ty, val, location);
try writer.writeAll(", .payload = {");
}
for (ty.unionFields().values()) |field| { for (ty.unionFields().values()) |field| {
if (!field.ty.hasRuntimeBits()) continue; if (!field.ty.hasRuntimeBits()) continue;
try dg.renderValue(writer, field.ty, val, location); try dg.renderValue(writer, field.ty, val, location);
break; break;
} else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
return writer.writeByte('}'); return writer.writeByte('}');
}, },
.ErrorUnion => { .ErrorUnion => {
@ -3469,22 +3469,22 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i += (constraint.len + name.len + (2 + 3)) / 4; extra_i += (constraint.len + name.len + (2 + 3)) / 4;
const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType(); const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType();
if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) {
try writer.writeAll("register "); try writer.writeAll("register ");
try f.object.dg.renderTypeAndName(writer, output_ty, .{ try f.object.dg.renderTypeAndName(writer, output_ty, .{
.local = output_locals_begin + index, .local = output_locals_begin + index,
}, .Mut, 0); }, .Mut, 0);
if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) {
try writer.writeAll(" __asm(\""); try writer.writeAll(" __asm(\"");
try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
try writer.writeAll("\")"); try writer.writeAll("\")");
} else if (constraint.len < 2 or constraint[0] != '=') {
return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
}
if (f.wantSafety()) { if (f.wantSafety()) {
try writer.writeAll(" = "); try writer.writeAll(" = ");
try f.object.dg.renderValue(writer, output_ty, Value.undef, .Other); try f.object.dg.renderValue(writer, output_ty, Value.undef, .Other);
} }
try writer.writeAll(";\n"); try writer.writeAll(";\n");
} else if (constraint.len < 2 or constraint[0] != '=') {
return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
}
} }
const input_locals_begin = f.next_local_index; const input_locals_begin = f.next_local_index;
f.next_local_index += inputs.len; f.next_local_index += inputs.len;
@ -3497,20 +3497,29 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i += (constraint.len + name.len + (2 + 3)) / 4; extra_i += (constraint.len + name.len + (2 + 3)) / 4;
const input_ty = f.air.typeOf(input); const input_ty = f.air.typeOf(input);
if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) {
try writer.writeAll("register "); try writer.writeAll("register ");
try f.object.dg.renderTypeAndName(writer, input_ty, .{ try f.object.dg.renderTypeAndName(writer, input_ty, .{
.local = input_locals_begin + index, .local = input_locals_begin + index,
}, .Const, 0); }, .Const, 0);
if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) {
try writer.writeAll(" __asm(\""); try writer.writeAll(" __asm(\"");
try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
try writer.writeAll("\")"); try writer.writeAll("\") = ");
} else if (constraint.len < 1 or std.mem.indexOfScalar(u8, "=+&%", constraint[0]) != null) {
return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
}
try writer.writeAll(" = ");
try f.writeCValue(writer, try f.resolveInst(input)); try f.writeCValue(writer, try f.resolveInst(input));
try writer.writeAll(";\n"); try writer.writeAll(";\n");
} else if (constraint.len >= 1 and std.mem.indexOfScalar(u8, "=+&%", constraint[0]) == null) {
const input_val = try f.resolveInst(input);
if (input_val == .constant) {
try f.object.dg.renderTypeAndName(writer, input_ty, .{
.local = input_locals_begin + index,
}, .Const, 0);
try writer.writeAll(" = ");
try f.writeCValue(writer, input_val);
try writer.writeAll(";\n");
}
} else {
return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
}
} }
{ {
var clobber_i: u32 = 0; var clobber_i: u32 = 0;
@ -3529,7 +3538,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i = constraints_extra_begin; extra_i = constraints_extra_begin;
try writer.writeByte(':'); try writer.writeByte(':');
for (outputs) |_, index| { for (outputs) |output, index| {
const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
const constraint = std.mem.sliceTo(extra_bytes, 0); const constraint = std.mem.sliceTo(extra_bytes, 0);
const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
@ -3538,12 +3547,18 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i += (constraint.len + name.len + (2 + 3)) / 4; extra_i += (constraint.len + name.len + (2 + 3)) / 4;
if (index > 0) try writer.writeByte(','); if (index > 0) try writer.writeByte(',');
try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[1] == '{') "=r" else constraint)}); try writer.writeByte(' ');
if (constraint[1] == '{') {
try writer.print("{s}(", .{fmtStringLiteral("=r")});
try f.writeCValue(writer, .{ .local = output_locals_begin + index }); try f.writeCValue(writer, .{ .local = output_locals_begin + index });
} else {
try writer.print("{s}(", .{fmtStringLiteral(constraint)});
try f.writeCValueDeref(writer, try f.resolveInst(output));
}
try writer.writeByte(')'); try writer.writeByte(')');
} }
try writer.writeByte(':'); try writer.writeByte(':');
for (inputs) |_, index| { for (inputs) |input, index| {
const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
const constraint = std.mem.sliceTo(extra_bytes, 0); const constraint = std.mem.sliceTo(extra_bytes, 0);
const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
@ -3552,8 +3567,17 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
extra_i += (constraint.len + name.len + (2 + 3)) / 4; extra_i += (constraint.len + name.len + (2 + 3)) / 4;
if (index > 0) try writer.writeByte(','); if (index > 0) try writer.writeByte(',');
try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[0] == '{') "r" else constraint)}); try writer.writeByte(' ');
if (constraint[0] == '{') {
try writer.print("{s}(", .{fmtStringLiteral("r")});
try f.writeCValue(writer, .{ .local = input_locals_begin + index }); try f.writeCValue(writer, .{ .local = input_locals_begin + index });
} else {
const input_val = try f.resolveInst(input);
try writer.print("{s}(", .{fmtStringLiteral(constraint)});
try f.writeCValue(writer, if (input_val == .constant) .{
.local = input_locals_begin + index,
} else input_val);
}
try writer.writeByte(')'); try writer.writeByte(')');
} }
try writer.writeByte(':'); try writer.writeByte(':');
@ -3582,6 +3606,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
// for the string, we still use the next u32 for the null terminator. // for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4; extra_i += (constraint.len + name.len + (2 + 3)) / 4;
if (constraint[1] == '{') {
try f.writeCValueDeref(writer, if (output == .none) CValue{ try f.writeCValueDeref(writer, if (output == .none) CValue{
.local_ref = local.local, .local_ref = local.local,
} else try f.resolveInst(output)); } else try f.resolveInst(output));
@ -3589,6 +3614,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try f.writeCValue(writer, .{ .local = output_locals_begin + index }); try f.writeCValue(writer, .{ .local = output_locals_begin + index });
try writer.writeAll(";\n"); try writer.writeAll(";\n");
} }
}
f.object.indent_writer.popIndent(); f.object.indent_writer.popIndent();
try writer.writeAll("}\n"); try writer.writeAll("}\n");
@ -4415,12 +4441,12 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
const elem_ty = inst_ty.childType(); const elem_ty = inst_ty.childType();
var empty = true; var empty = true;
for (elements) |element| { for (elements) |element| {
if (empty) try writer.writeAll(", "); if (!empty) try writer.writeAll(", ");
try f.writeCValue(writer, try f.resolveInst(element)); try f.writeCValue(writer, try f.resolveInst(element));
empty = false; empty = false;
} }
if (inst_ty.sentinel()) |sentinel| { if (inst_ty.sentinel()) |sentinel| {
if (empty) try writer.writeAll(", "); if (!empty) try writer.writeAll(", ");
try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other); try f.object.dg.renderValue(writer, elem_ty, sentinel, .Other);
empty = false; empty = false;
} }

View file

@ -112,7 +112,6 @@ test "sized integer/float in asm input" {
} }
test "struct/array/union types as input values" { test "struct/array/union types as input values" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

View file

@ -5,7 +5,6 @@ pub fn f(_: [:null]const ?u8) void {}
test { test {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
const c: u8 = 42; const c: u8 = 42;
f(&[_:null]?u8{c}); f(&[_:null]?u8{c});

View file

@ -12,7 +12,6 @@ fn foo(val: U) !void {
} }
test "runtime union init, most-aligned field != largest" { test "runtime union init, most-aligned field != largest" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO