cbe: support arrays in more places

This commit is contained in:
Jacob Young 2022-11-01 04:47:09 -04:00
parent 071404ff65
commit 09763435a8
3 changed files with 130 additions and 55 deletions

View File

@ -2597,19 +2597,36 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
} }
fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.air.typeOfIndex(inst);
const bin_op = f.air.instructions.items(.data)[inst].bin_op; const bin_op = f.air.instructions.items(.data)[inst].bin_op;
const ptr_ty = f.air.typeOf(bin_op.lhs); const ptr_ty = f.air.typeOf(bin_op.lhs);
if (!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none; if ((!ptr_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
!inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
const ptr = try f.resolveInst(bin_op.lhs); const ptr = try f.resolveInst(bin_op.lhs);
const index = try f.resolveInst(bin_op.rhs); const index = try f.resolveInst(bin_op.rhs);
const target = f.object.dg.module.getTarget();
const is_array = lowersToArray(inst_ty, target);
const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer(); const writer = f.object.writer();
const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); if (is_array) {
try writer.writeAll(" = "); try writer.writeAll(";\n");
try writer.writeAll("memcpy(");
try f.writeCValue(writer, local, .FunctionArgument);
try writer.writeAll(", ");
} else try writer.writeAll(" = ");
try f.writeCValue(writer, ptr, .Other); try f.writeCValue(writer, ptr, .Other);
try writer.writeByte('['); try writer.writeByte('[');
try f.writeCValue(writer, index, .Other); try f.writeCValue(writer, index, .Other);
try writer.writeAll("];\n"); try writer.writeByte(']');
if (is_array) {
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, inst_ty);
try writer.writeAll("))");
}
try writer.writeAll(";\n");
return local; return local;
} }
@ -2639,19 +2656,36 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
} }
fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
const inst_ty = f.air.typeOfIndex(inst);
const bin_op = f.air.instructions.items(.data)[inst].bin_op; const bin_op = f.air.instructions.items(.data)[inst].bin_op;
const slice_ty = f.air.typeOf(bin_op.lhs); const slice_ty = f.air.typeOf(bin_op.lhs);
if (!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) return CValue.none; if ((!slice_ty.isVolatilePtr() and f.liveness.isUnused(inst)) or
!inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
const slice = try f.resolveInst(bin_op.lhs); const slice = try f.resolveInst(bin_op.lhs);
const index = try f.resolveInst(bin_op.rhs); const index = try f.resolveInst(bin_op.rhs);
const target = f.object.dg.module.getTarget();
const is_array = lowersToArray(inst_ty, target);
const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer(); const writer = f.object.writer();
const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); if (is_array) {
try writer.writeAll(" = "); try writer.writeAll(";\n");
try writer.writeAll("memcpy(");
try f.writeCValue(writer, local, .FunctionArgument);
try writer.writeAll(", ");
} else try writer.writeAll(" = ");
try f.writeCValue(writer, slice, .Other); try f.writeCValue(writer, slice, .Other);
try writer.writeAll(".ptr["); try writer.writeAll(".ptr[");
try f.writeCValue(writer, index, .Other); try f.writeCValue(writer, index, .Other);
try writer.writeAll("];\n"); try writer.writeByte(']');
if (is_array) {
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, inst_ty);
try writer.writeAll("))");
}
try writer.writeAll(";\n");
return local; return local;
} }
@ -2674,18 +2708,34 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
} }
fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none; const inst_ty = f.air.typeOfIndex(inst);
if (f.liveness.isUnused(inst) or !inst_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
const bin_op = f.air.instructions.items(.data)[inst].bin_op; const bin_op = f.air.instructions.items(.data)[inst].bin_op;
const array = try f.resolveInst(bin_op.lhs); const array = try f.resolveInst(bin_op.lhs);
const index = try f.resolveInst(bin_op.rhs); const index = try f.resolveInst(bin_op.rhs);
const target = f.object.dg.module.getTarget();
const is_array = lowersToArray(inst_ty, target);
const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer(); const writer = f.object.writer();
const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const); if (is_array) {
try writer.writeAll(" = "); try writer.writeAll(";\n");
try writer.writeAll("memcpy(");
try f.writeCValue(writer, local, .FunctionArgument);
try writer.writeAll(", ");
} else try writer.writeAll(" = ");
try f.writeCValue(writer, array, .Other); try f.writeCValue(writer, array, .Other);
try writer.writeByte('['); try writer.writeByte('[');
try f.writeCValue(writer, index, .Other); try f.writeCValue(writer, index, .Other);
try writer.writeAll("];\n"); try writer.writeByte(']');
if (is_array) {
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, inst_ty);
try writer.writeAll("))");
}
try writer.writeAll(";\n");
return local; return local;
} }
@ -3592,13 +3642,26 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
// If result is .none then the value of the block is unused. // If result is .none then the value of the block is unused.
if (result != .none) { if (result != .none) {
const operand = try f.resolveInst(branch.operand); const operand = try f.resolveInst(branch.operand);
const operand_ty = f.air.typeOf(branch.operand);
const target = f.object.dg.module.getTarget();
if (lowersToArray(operand_ty, target)) {
try writer.writeAll("memcpy(");
try f.writeCValue(writer, result, .FunctionArgument);
try writer.writeAll(", ");
try f.writeCValue(writer, operand, .FunctionArgument);
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, operand_ty);
try writer.writeAll("))");
} else {
try f.writeCValue(writer, result, .Other); try f.writeCValue(writer, result, .Other);
try writer.writeAll(" = "); try writer.writeAll(" = ");
try f.writeCValue(writer, operand, .Other); try f.writeCValue(writer, operand, .Other);
}
try writer.writeAll(";\n"); try writer.writeAll(";\n");
} }
try f.object.writer().print("goto zig_block_{d};\n", .{block.block_id}); try writer.print("goto zig_block_{d};\n", .{block.block_id});
return CValue.none; return CValue.none;
} }
@ -4009,26 +4072,34 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none; if (f.liveness.isUnused(inst)) return CValue.none;
const ty_op = f.air.instructions.items(.data)[inst].ty_op; const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const writer = f.object.writer();
const operand = try f.resolveInst(ty_op.operand); const operand = try f.resolveInst(ty_op.operand);
const opt_ty = f.air.typeOf(ty_op.operand); const opt_ty = f.air.typeOf(ty_op.operand);
var buf: Type.Payload.ElemType = undefined; var buf: Type.Payload.ElemType = undefined;
const payload_ty = opt_ty.optionalChild(&buf); const payload_ty = opt_ty.optionalChild(&buf);
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return CValue.none;
return CValue.none; if (opt_ty.optionalReprIsPayload()) return operand;
}
if (opt_ty.optionalReprIsPayload()) {
return operand;
}
const inst_ty = f.air.typeOfIndex(inst); const inst_ty = f.air.typeOfIndex(inst);
const local = try f.allocLocal(inst_ty, .Const); const target = f.object.dg.module.getTarget();
try writer.writeAll(" = ("); const is_array = lowersToArray(inst_ty, target);
try f.writeCValue(writer, operand, .Other);
try writer.writeAll(").payload;\n"); const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer();
if (is_array) {
try writer.writeAll(";\n");
try writer.writeAll("memcpy(");
try f.writeCValue(writer, local, .FunctionArgument);
try writer.writeAll(", ");
} else try writer.writeAll(" = ");
try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
if (is_array) {
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, inst_ty);
try writer.writeAll("))");
}
try writer.writeAll(";\n");
return local; return local;
} }
@ -4387,25 +4458,33 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
} }
fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue { fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) if (f.liveness.isUnused(inst)) return CValue.none;
return CValue.none;
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const writer = f.object.writer();
const operand = try f.resolveInst(ty_op.operand);
const inst_ty = f.air.typeOfIndex(inst); const inst_ty = f.air.typeOfIndex(inst);
if (inst_ty.optionalReprIsPayload()) { const ty_op = f.air.instructions.items(.data)[inst].ty_op;
return operand; const payload = try f.resolveInst(ty_op.operand);
} if (inst_ty.optionalReprIsPayload()) return payload;
// .wrap_optional is used to convert non-optionals into optionals so it can never be null. const payload_ty = f.air.typeOf(ty_op.operand);
const local = try f.allocLocal(inst_ty, .Const); const target = f.object.dg.module.getTarget();
const is_array = lowersToArray(payload_ty, target);
const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer();
try writer.writeAll(" = { .payload = "); try writer.writeAll(" = { .payload = ");
try f.writeCValue(writer, operand, .Initializer); try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
try writer.writeAll(", .is_null = "); try writer.writeAll(", .is_null = ");
try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer); try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
try writer.writeAll(" };\n"); try writer.writeAll(" };\n");
if (is_array) {
try writer.writeAll("memcpy(");
try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
try writer.writeAll(", ");
try f.writeCValue(writer, payload, .FunctionArgument);
try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, payload_ty);
try writer.writeAll("));\n");
}
return local; return local;
} }
@ -4477,35 +4556,33 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
} }
fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) if (f.liveness.isUnused(inst)) return CValue.none;
return CValue.none;
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const writer = f.object.writer();
const operand = try f.resolveInst(ty_op.operand);
const inst_ty = f.air.typeOfIndex(inst); const inst_ty = f.air.typeOfIndex(inst);
const payload_ty = inst_ty.errorUnionPayload();
const error_ty = inst_ty.errorUnionSet(); const error_ty = inst_ty.errorUnionSet();
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const payload_ty = inst_ty.errorUnionPayload();
const payload = try f.resolveInst(ty_op.operand);
const target = f.object.dg.module.getTarget(); const target = f.object.dg.module.getTarget();
const is_array = lowersToArray(payload_ty, target); const is_array = lowersToArray(payload_ty, target);
const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const); const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
const writer = f.object.writer();
try writer.writeAll(" = { .payload = "); try writer.writeAll(" = { .payload = ");
try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer); try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else payload, .Initializer);
try writer.writeAll(", .error = "); try writer.writeAll(", .error = ");
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer); try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
try writer.writeAll(" };\n"); try writer.writeAll(" };\n");
if (is_array) { if (is_array) {
try writer.writeAll("memcpy("); try writer.writeAll("memcpy(");
try f.writeCValue(writer, local, .Other); try f.writeCValueMember(writer, local, .{ .identifier = "payload" });
try writer.writeAll(".payload, "); try writer.writeAll(", ");
try f.writeCValue(writer, operand, .FunctionArgument); try f.writeCValue(writer, payload, .FunctionArgument);
try writer.writeAll(", sizeof("); try writer.writeAll(", sizeof(");
try f.renderTypecast(writer, payload_ty); try f.renderTypecast(writer, payload_ty);
try writer.writeAll("));\n"); try writer.writeAll("));\n");
} }
return local; return local;
} }

View File

@ -3,7 +3,6 @@ const builtin = @import("builtin");
const expect = std.testing.expect; const expect = std.testing.expect;
test "store array of array of structs at comptime" { test "store array of array of structs at comptime" {
if (builtin.zig_backend == .stage2_c) 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_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

View File

@ -355,7 +355,6 @@ test "function call with anon list literal" {
} }
test "function call with anon list literal - 2D" { test "function call with anon list literal - 2D" {
if (builtin.zig_backend == .stage2_c) 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
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO