authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-11-01 04:47:09-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-11-01 20:39:06-04:00
log09763435a85a6108cc4624b51ac1b016746078b6
tree0e922817d4ceba843f68d031b272b87ec5640375
parent071404ff6500d26c3f8c5b08645bd90ebb3a901b

cbe: support arrays in more places


3 files changed, 129 insertions(+), 54 deletions(-)

src/codegen/c.zig+129-52
...@@ -2597,19 +2597,36 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -2597,19 +2597,36 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
2597}2597}
25982598
2599fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2599fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2600 const inst_ty = f.air.typeOfIndex(inst);
2600 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2601 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2601 const ptr_ty = f.air.typeOf(bin_op.lhs);2602 const ptr_ty = f.air.typeOf(bin_op.lhs);
2602 if (!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none;2603 if ((!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
2604 !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26032605
2604 const ptr = try f.resolveInst(bin_op.lhs);2606 const ptr = try f.resolveInst(bin_op.lhs);
2605 const index = try f.resolveInst(bin_op.rhs);2607 const index = try f.resolveInst(bin_op.rhs);
2608
2609 const target = f.object.dg.module.getTarget();
2610 const is_array = lowersToArray(inst_ty, target);
2611
2612 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2606 const writer = f.object.writer();2613 const writer = f.object.writer();
2607 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2614 if (is_array) {
2608 try writer.writeAll(" = ");2615 try writer.writeAll(";\n");
2616 try writer.writeAll("memcpy(");
2617 try f.writeCValue(writer, local, .FunctionArgument);
2618 try writer.writeAll(", ");
2619 } else try writer.writeAll(" = ");
2609 try f.writeCValue(writer, ptr, .Other);2620 try f.writeCValue(writer, ptr, .Other);
2610 try writer.writeByte('[');2621 try writer.writeByte('[');
2611 try f.writeCValue(writer, index, .Other);2622 try f.writeCValue(writer, index, .Other);
2612 try writer.writeAll("];\n");2623 try writer.writeByte(']');
2624 if (is_array) {
2625 try writer.writeAll(", sizeof(");
2626 try f.renderTypecast(writer, inst_ty);
2627 try writer.writeAll("))");
2628 }
2629 try writer.writeAll(";\n");
2613 return local;2630 return local;
2614}2631}
26152632
...@@ -2639,19 +2656,36 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2639,19 +2656,36 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
2639}2656}
26402657
2641fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2658fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2659 const inst_ty = f.air.typeOfIndex(inst);
2642 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2660 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2643 const slice_ty = f.air.typeOf(bin_op.lhs);2661 const slice_ty = f.air.typeOf(bin_op.lhs);
2644 if (!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none;2662 if ((!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
2663 !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26452664
2646 const slice = try f.resolveInst(bin_op.lhs);2665 const slice = try f.resolveInst(bin_op.lhs);
2647 const index = try f.resolveInst(bin_op.rhs);2666 const index = try f.resolveInst(bin_op.rhs);
2667
2668 const target = f.object.dg.module.getTarget();
2669 const is_array = lowersToArray(inst_ty, target);
2670
2671 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2648 const writer = f.object.writer();2672 const writer = f.object.writer();
2649 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2673 if (is_array) {
2650 try writer.writeAll(" = ");2674 try writer.writeAll(";\n");
2675 try writer.writeAll("memcpy(");
2676 try f.writeCValue(writer, local, .FunctionArgument);
2677 try writer.writeAll(", ");
2678 } else try writer.writeAll(" = ");
2651 try f.writeCValue(writer, slice, .Other);2679 try f.writeCValue(writer, slice, .Other);
2652 try writer.writeAll(".ptr[");2680 try writer.writeAll(".ptr[");
2653 try f.writeCValue(writer, index, .Other);2681 try f.writeCValue(writer, index, .Other);
2654 try writer.writeAll("];\n");2682 try writer.writeByte(']');
2683 if (is_array) {
2684 try writer.writeAll(", sizeof(");
2685 try f.renderTypecast(writer, inst_ty);
2686 try writer.writeAll("))");
2687 }
2688 try writer.writeAll(";\n");
2655 return local;2689 return local;
2656}2690}
26572691
...@@ -2674,18 +2708,34 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2674,18 +2708,34 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
2674}2708}
26752709
2676fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {2710fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
2677 if (f.liveness.isUnused(inst)) return CValue.none;2711 const inst_ty = f.air.typeOfIndex(inst);
2712 if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
26782713
2679 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2714 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2680 const array = try f.resolveInst(bin_op.lhs);2715 const array = try f.resolveInst(bin_op.lhs);
2681 const index = try f.resolveInst(bin_op.rhs);2716 const index = try f.resolveInst(bin_op.rhs);
2717
2718 const target = f.object.dg.module.getTarget();
2719 const is_array = lowersToArray(inst_ty, target);
2720
2721 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
2682 const writer = f.object.writer();2722 const writer = f.object.writer();
2683 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);2723 if (is_array) {
2684 try writer.writeAll(" = ");2724 try writer.writeAll(";\n");
2725 try writer.writeAll("memcpy(");
2726 try f.writeCValue(writer, local, .FunctionArgument);
2727 try writer.writeAll(", ");
2728 } else try writer.writeAll(" = ");
2685 try f.writeCValue(writer, array, .Other);2729 try f.writeCValue(writer, array, .Other);
2686 try writer.writeByte('[');2730 try writer.writeByte('[');
2687 try f.writeCValue(writer, index, .Other);2731 try f.writeCValue(writer, index, .Other);
2688 try writer.writeAll("];\n");2732 try writer.writeByte(']');
2733 if (is_array) {
2734 try writer.writeAll(", sizeof(");
2735 try f.renderTypecast(writer, inst_ty);
2736 try writer.writeAll("))");
2737 }
2738 try writer.writeAll(";\n");
2689 return local;2739 return local;
2690}2740}
26912741
...@@ -3592,13 +3642,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3592,13 +3642,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
3592 // If result is .none then the value of the block is unused.3642 // If result is .none then the value of the block is unused.
3593 if (result != .none) {3643 if (result != .none) {
3594 const operand = try f.resolveInst(branch.operand);3644 const operand = try f.resolveInst(branch.operand);
3595 try f.writeCValue(writer, result, .Other);3645
3596 try writer.writeAll(" = ");3646 const operand_ty = f.air.typeOf(branch.operand);
3597 try f.writeCValue(writer, operand, .Other);3647 const target = f.object.dg.module.getTarget();
3648 if (lowersToArray(operand_ty, target)) {
3649 try writer.writeAll("memcpy(");
3650 try f.writeCValue(writer, result, .FunctionArgument);
3651 try writer.writeAll(", ");
3652 try f.writeCValue(writer, operand, .FunctionArgument);
3653 try writer.writeAll(", sizeof(");
3654 try f.renderTypecast(writer, operand_ty);
3655 try writer.writeAll("))");
3656 } else {
3657 try f.writeCValue(writer, result, .Other);
3658 try writer.writeAll(" = ");
3659 try f.writeCValue(writer, operand, .Other);
3660 }
3598 try writer.writeAll(";\n");3661 try writer.writeAll(";\n");
3599 }3662 }
36003663
3601 try f.object.writer().print("goto zig_block_{d};\n", .{block.block_id});3664 try writer.print("goto zig_block_{d};\n", .{block.block_id});
3602 return CValue.none;3665 return CValue.none;
3603}3666}
36043667
...@@ -4009,26 +4072,34 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4009,26 +4072,34 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
4009 if (f.liveness.isUnused(inst)) return CValue.none;4072 if (f.liveness.isUnused(inst)) return CValue.none;
40104073
4011 const ty_op = f.air.instructions.items(.data)[inst].ty_op;4074 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4012 const writer = f.object.writer();
4013 const operand = try f.resolveInst(ty_op.operand);4075 const operand = try f.resolveInst(ty_op.operand);
4014 const opt_ty = f.air.typeOf(ty_op.operand);4076 const opt_ty = f.air.typeOf(ty_op.operand);
40154077
4016 var buf: Type.Payload.ElemType = undefined;4078 var buf: Type.Payload.ElemType = undefined;
4017 const payload_ty = opt_ty.optionalChild(&buf);4079 const payload_ty = opt_ty.optionalChild(&buf);
40184080
4019 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {4081 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
4020 return CValue.none;4082 if (opt_ty.optionalReprIsPayload()) return operand;
4021 }
4022
4023 if (opt_ty.optionalReprIsPayload()) {
4024 return operand;
4025 }
40264083
4027 const inst_ty = f.air.typeOfIndex(inst);4084 const inst_ty = f.air.typeOfIndex(inst);
4028 const local = try f.allocLocal(inst_ty, .Const);4085 const target = f.object.dg.module.getTarget();
4029 try writer.writeAll(" = (");4086 const is_array = lowersToArray(inst_ty, target);
4030 try f.writeCValue(writer, operand, .Other);4087
4031 try writer.writeAll(").payload;\n");4088 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4089 const writer = f.object.writer();
4090 if (is_array) {
4091 try writer.writeAll(";\n");
4092 try writer.writeAll("memcpy(");
4093 try f.writeCValue(writer, local, .FunctionArgument);
4094 try writer.writeAll(", ");
4095 } else try writer.writeAll(" = ");
4096 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
4097 if (is_array) {
4098 try writer.writeAll(", sizeof(");
4099 try f.renderTypecast(writer, inst_ty);
4100 try writer.writeAll("))");
4101 }
4102 try writer.writeAll(";\n");
4032 return local;4103 return local;
4033}4104}
40344105
...@@ -4387,25 +4458,33 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -4387,25 +4458,33 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
4387}4458}
43884459
4389fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {4460fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
4390 if (f.liveness.isUnused(inst))4461 if (f.liveness.isUnused(inst)) return CValue.none;
4391 return CValue.none;
43924462
4463 const inst_ty = f.air.typeOfIndex(inst);
4393 const ty_op = f.air.instructions.items(.data)[inst].ty_op;4464 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4394 const writer = f.object.writer();4465 const payload = try f.resolveInst(ty_op.operand);
4395 const operand = try f.resolveInst(ty_op.operand);4466 if (inst_ty.optionalReprIsPayload()) return payload;
43964467
4397 const inst_ty = f.air.typeOfIndex(inst);4468 const payload_ty = f.air.typeOf(ty_op.operand);
4398 if (inst_ty.optionalReprIsPayload()) {4469 const target = f.object.dg.module.getTarget();
4399 return operand;4470 const is_array = lowersToArray(payload_ty, target);
4400 }
44014471
4402 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.4472 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4403 const local = try f.allocLocal(inst_ty, .Const);4473 const writer = f.object.writer();
4404 try writer.writeAll(" = { .payload = ");4474 try writer.writeAll(" = { .payload = ");
4405 try f.writeCValue(writer, operand, .Initializer);4475 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
4406 try writer.writeAll(", .is_null = ");4476 try writer.writeAll(", .is_null = ");
4407 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);4477 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4408 try writer.writeAll(" };\n");4478 try writer.writeAll(" };\n");
4479 if (is_array) {
4480 try writer.writeAll("memcpy(");
4481 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
4482 try writer.writeAll(", ");
4483 try f.writeCValue(writer, payload, .FunctionArgument);
4484 try writer.writeAll(", sizeof(");
4485 try f.renderTypecast(writer, payload_ty);
4486 try writer.writeAll("));\n");
4487 }
4409 return local;4488 return local;
4410}4489}
44114490
...@@ -4477,35 +4556,33 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4477,35 +4556,33 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
4477}4556}
44784557
4479fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {4558fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
4480 if (f.liveness.isUnused(inst))4559 if (f.liveness.isUnused(inst)) return CValue.none;
4481 return CValue.none;
4482
4483 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4484 const writer = f.object.writer();
4485 const operand = try f.resolveInst(ty_op.operand);
44864560
4487 const inst_ty = f.air.typeOfIndex(inst);4561 const inst_ty = f.air.typeOfIndex(inst);
4488 const payload_ty = inst_ty.errorUnionPayload();
4489 const error_ty = inst_ty.errorUnionSet();4562 const error_ty = inst_ty.errorUnionSet();
4563 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4564 const payload_ty = inst_ty.errorUnionPayload();
4565 const payload = try f.resolveInst(ty_op.operand);
4566
4490 const target = f.object.dg.module.getTarget();4567 const target = f.object.dg.module.getTarget();
4491 const is_array = lowersToArray(payload_ty, target);4568 const is_array = lowersToArray(payload_ty, target);
4569
4492 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);4570 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4571 const writer = f.object.writer();
4493 try writer.writeAll(" = { .payload = ");4572 try writer.writeAll(" = { .payload = ");
4494 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer);4573 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
4495 try writer.writeAll(", .error = ");4574 try writer.writeAll(", .error = ");
4496 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);4575 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
4497 try writer.writeAll(" };\n");4576 try writer.writeAll(" };\n");
4498
4499 if (is_array) {4577 if (is_array) {
4500 try writer.writeAll("memcpy(");4578 try writer.writeAll("memcpy(");
4501 try f.writeCValue(writer, local, .Other);4579 try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
4502 try writer.writeAll(".payload, ");4580 try writer.writeAll(", ");
4503 try f.writeCValue(writer, operand, .FunctionArgument);4581 try f.writeCValue(writer, payload, .FunctionArgument);
4504 try writer.writeAll(", sizeof(");4582 try writer.writeAll(", sizeof(");
4505 try f.renderTypecast(writer, payload_ty);4583 try f.renderTypecast(writer, payload_ty);
4506 try writer.writeAll("));\n");4584 try writer.writeAll("));\n");
4507 }4585 }
4508
4509 return local;4586 return local;
4510}4587}
45114588
test/behavior/bugs/11139.zig-1
...@@ -3,7 +3,6 @@ const builtin = @import("builtin");...@@ -3,7 +3,6 @@ const builtin = @import("builtin");
3const expect = std.testing.expect;3const expect = std.testing.expect;
44
5test "store array of array of structs at comptime" {5test "store array of array of structs at comptime" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
98
test/behavior/fn.zig-1
...@@ -355,7 +355,6 @@ test "function call with anon list literal" {...@@ -355,7 +355,6 @@ test "function call with anon list literal" {
355}355}
356356
357test "function call with anon list literal - 2D" {357test "function call with anon list literal - 2D" {
358 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
359 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO358 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
360 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO