authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-20 02:04:40-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log3d90ee50ff184dd7a94005f2769d055e460ad290
treee8bf4cbe145ed49f283296febaac91ab3d2ec009
parent4fdac5f1c9cad90450cbad5a8dd276a597aba870

cbe: allow immediate and register asm constraints in naked functions


1 files changed, 63 insertions(+), 53 deletions(-)

src/codegen/c.zig+63-53
...@@ -3526,6 +3526,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3526,6 +3526,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
3526 return CValue.none;3526 return CValue.none;
3527}3527}
35283528
3529fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {
3530 return switch (constraint[0]) {
3531 '{' => true,
3532 'i', 'r' => false,
3533 else => value == .constant,
3534 };
3535}
3536
3529fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {3537fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3530 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3538 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3531 const extra = f.air.extraData(Air.Asm, ty_pl.payload);3539 const extra = f.air.extraData(Air.Asm, ty_pl.payload);
...@@ -3551,10 +3559,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3551,10 +3559,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3551 break :local local;3559 break :local local;
3552 } else .none;3560 } else .none;
35533561
3554 const output_locals_begin = f.next_local_index;3562 const locals_begin = f.next_local_index;
3555 f.next_local_index += outputs.len;
3556 const constraints_extra_begin = extra_i;3563 const constraints_extra_begin = extra_i;
3557 for (outputs) |output, index| {3564 for (outputs) |output| {
3558 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);3565 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3559 const constraint = std.mem.sliceTo(extra_bytes, 0);3566 const constraint = std.mem.sliceTo(extra_bytes, 0);
3560 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);3567 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
...@@ -3562,12 +3569,17 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3562,12 +3569,17 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3562 // for the string, we still use the next u32 for the null terminator.3569 // for the string, we still use the next u32 for the null terminator.
3563 extra_i += (constraint.len + name.len + (2 + 3)) / 4;3570 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
35643571
3565 const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType();3572 if (constraint.len < 2 or constraint[0] != '=' or
3566 if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) {3573 (constraint[1] == '{' and constraint[constraint.len - 1] != '}'))
3574 {
3575 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
3576 }
3577
3578 const is_reg = constraint[1] == '{';
3579 if (is_reg) {
3580 const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType();
3567 try writer.writeAll("register ");3581 try writer.writeAll("register ");
3568 try f.object.dg.renderTypeAndName(writer, output_ty, .{3582 _ = try f.allocLocal(output_ty, .Mut);
3569 .local = output_locals_begin + index,
3570 }, .Mut, 0);
3571 try writer.writeAll(" __asm(\"");3583 try writer.writeAll(" __asm(\"");
3572 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);3584 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
3573 try writer.writeAll("\")");3585 try writer.writeAll("\")");
...@@ -3576,13 +3588,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3576,13 +3588,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3576 try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer);3588 try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer);
3577 }3589 }
3578 try writer.writeAll(";\n");3590 try writer.writeAll(";\n");
3579 } else if (constraint.len < 2 or constraint[0] != '=') {
3580 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
3581 }3591 }
3582 }3592 }
3583 const input_locals_begin = f.next_local_index;3593 for (inputs) |input| {
3584 f.next_local_index += inputs.len;
3585 for (inputs) |input, index| {
3586 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);3594 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3587 const constraint = std.mem.sliceTo(extra_bytes, 0);3595 const constraint = std.mem.sliceTo(extra_bytes, 0);
3588 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);3596 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
...@@ -3590,30 +3598,27 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3590,30 +3598,27 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3590 // for the string, we still use the next u32 for the null terminator.3598 // for the string, we still use the next u32 for the null terminator.
3591 extra_i += (constraint.len + name.len + (2 + 3)) / 4;3599 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
35923600
3593 const input_ty = f.air.typeOf(input);3601 if (constraint.len < 1 or std.mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
3594 if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) {3602 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
3595 try writer.writeAll("register ");3603 {
3596 try f.object.dg.renderTypeAndName(writer, input_ty, .{
3597 .local = input_locals_begin + index,
3598 }, .Const, 0);
3599 try writer.writeAll(" __asm(\"");
3600 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
3601 try writer.writeAll("\") = ");
3602 try f.writeCValue(writer, try f.resolveInst(input), .Initializer);
3603 try writer.writeAll(";\n");
3604 } else if (constraint.len >= 1 and std.mem.indexOfScalar(u8, "=+&%", constraint[0]) == null) {
3605 const input_val = try f.resolveInst(input);
3606 if (input_val == .constant) {
3607 try f.object.dg.renderTypeAndName(writer, input_ty, .{
3608 .local = input_locals_begin + index,
3609 }, .Const, 0);
3610 try writer.writeAll(" = ");
3611 try f.writeCValue(writer, input_val, .Initializer);
3612 try writer.writeAll(";\n");
3613 }
3614 } else {
3615 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});3604 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
3616 }3605 }
3606
3607 const is_reg = constraint[0] == '{';
3608 const input_val = try f.resolveInst(input);
3609 if (asmInputNeedsLocal(constraint, input_val)) {
3610 const input_ty = f.air.typeOf(input);
3611 if (is_reg) try writer.writeAll("register ");
3612 _ = try f.allocLocal(input_ty, .Const);
3613 if (is_reg) {
3614 try writer.writeAll(" __asm(\"");
3615 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
3616 try writer.writeAll("\")");
3617 }
3618 try writer.writeAll(" = ");
3619 try f.writeCValue(writer, input_val, .Initializer);
3620 try writer.writeAll(";\n");
3621 }
3617 }3622 }
3618 {3623 {
3619 var clobber_i: u32 = 0;3624 var clobber_i: u32 = 0;
...@@ -3631,6 +3636,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3631,6 +3636,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3631 try writer.print("({s}", .{fmtStringLiteral(asm_source)});3636 try writer.print("({s}", .{fmtStringLiteral(asm_source)});
36323637
3633 extra_i = constraints_extra_begin;3638 extra_i = constraints_extra_begin;
3639 var locals_index = locals_begin;
3634 try writer.writeByte(':');3640 try writer.writeByte(':');
3635 for (outputs) |output, index| {3641 for (outputs) |output, index| {
3636 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);3642 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
...@@ -3642,11 +3648,13 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3642,11 +3648,13 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36423648
3643 if (index > 0) try writer.writeByte(',');3649 if (index > 0) try writer.writeByte(',');
3644 try writer.writeByte(' ');3650 try writer.writeByte(' ');
3645 if (constraint[1] == '{') {3651 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
3646 try writer.print("{s}(", .{fmtStringLiteral("=r")});3652 const is_reg = constraint[1] == '{';
3647 try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other);3653 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint)});
3654 if (is_reg) {
3655 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
3656 locals_index += 1;
3648 } else {3657 } else {
3649 try writer.print("{s}(", .{fmtStringLiteral(constraint)});
3650 try f.writeCValueDeref(writer, try f.resolveInst(output));3658 try f.writeCValueDeref(writer, try f.resolveInst(output));
3651 }3659 }
3652 try writer.writeByte(')');3660 try writer.writeByte(')');
...@@ -3662,17 +3670,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3662,17 +3670,16 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
36623670
3663 if (index > 0) try writer.writeByte(',');3671 if (index > 0) try writer.writeByte(',');
3664 try writer.writeByte(' ');3672 try writer.writeByte(' ');
3665 if (constraint[0] == '{') {3673 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
3666 try writer.print("{s}(", .{fmtStringLiteral("r")});3674
3667 try f.writeCValue(writer, .{ .local = input_locals_begin + index }, .Other);3675 const is_reg = constraint[0] == '{';
3668 } else {3676 const input_val = try f.resolveInst(input);
3669 const input_val = try f.resolveInst(input);3677 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint)});
3670 try writer.print("{s}(", .{fmtStringLiteral(constraint)});3678 try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: {
3671 try f.writeCValue(writer, if (input_val == .constant)3679 const input_local = CValue{ .local = locals_index };
3672 CValue{ .local = input_locals_begin + index }3680 locals_index += 1;
3673 else3681 break :local input_local;
3674 input_val, .Other);3682 } else input_val, .Other);
3675 }
3676 try writer.writeByte(')');3683 try writer.writeByte(')');
3677 }3684 }
3678 try writer.writeByte(':');3685 try writer.writeByte(':');
...@@ -3693,7 +3700,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3693,7 +3700,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3693 try writer.writeAll(");\n");3700 try writer.writeAll(");\n");
36943701
3695 extra_i = constraints_extra_begin;3702 extra_i = constraints_extra_begin;
3696 for (outputs) |output, index| {3703 locals_index = locals_begin;
3704 for (outputs) |output| {
3697 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);3705 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3698 const constraint = std.mem.sliceTo(extra_bytes, 0);3706 const constraint = std.mem.sliceTo(extra_bytes, 0);
3699 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);3707 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
...@@ -3701,13 +3709,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3701,13 +3709,15 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
3701 // for the string, we still use the next u32 for the null terminator.3709 // for the string, we still use the next u32 for the null terminator.
3702 extra_i += (constraint.len + name.len + (2 + 3)) / 4;3710 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
37033711
3704 if (constraint[1] == '{') {3712 const is_reg = constraint[1] == '{';
3713 if (is_reg) {
3705 try f.writeCValueDeref(writer, if (output == .none)3714 try f.writeCValueDeref(writer, if (output == .none)
3706 CValue{ .local_ref = local.local }3715 CValue{ .local_ref = local.local }
3707 else3716 else
3708 try f.resolveInst(output));3717 try f.resolveInst(output));
3709 try writer.writeAll(" = ");3718 try writer.writeAll(" = ");
3710 try f.writeCValue(writer, .{ .local = output_locals_begin + index }, .Other);3719 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
3720 locals_index += 1;
3711 try writer.writeAll(";\n");3721 try writer.writeAll(";\n");
3712 }3722 }
3713 }3723 }