| author | |
| committer | |
| log | 50993a8f08595b690e0b566cea3266c5ce2c5131 |
| tree | 115dcf108d4016c417d035f4ba9d5fca0f30cff7 |
| parent | 485e20884cfe7b6597e6d7c615195bb263d38abb |
3 files changed, 111 insertions(+), 66 deletions(-)
src/arch/x86_64/CodeGen.zig+56-20| ... | ... | @@ -2478,8 +2478,11 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet { |
| 2478 | 2478 | else => abi.RegisterClass.sse, |
| 2479 | 2479 | }, |
| 2480 | 2480 | .Vector => switch (ty.childType(mod).toIntern()) { |
| 2481 | .bool_type => abi.RegisterClass.gp, | |
| 2482 | else => abi.RegisterClass.sse, | |
| 2481 | .bool_type, .u1_type => abi.RegisterClass.gp, | |
| 2482 | else => if (ty.isAbiInt(mod) and ty.intInfo(mod).bits == 1) | |
| 2483 | abi.RegisterClass.gp | |
| 2484 | else | |
| 2485 | abi.RegisterClass.sse, | |
| 2483 | 2486 | }, |
| 2484 | 2487 | else => abi.RegisterClass.gp, |
| 2485 | 2488 | }; |
| ... | ... | @@ -5152,7 +5155,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5152 | 5155 | defer if (index_lock) |lock| self.register_manager.unlockReg(lock); |
| 5153 | 5156 | |
| 5154 | 5157 | try self.spillEflagsIfOccupied(); |
| 5155 | if (array_ty.isVector(mod) and elem_ty.toIntern() == .bool_type) { | |
| 5158 | if (array_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) { | |
| 5156 | 5159 | const index_reg = switch (index_mcv) { |
| 5157 | 5160 | .register => |reg| reg, |
| 5158 | 5161 | else => try self.copyToTmpRegister(index_ty, index_mcv), |
| ... | ... | @@ -15475,26 +15478,59 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 15475 | 15478 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| 15476 | 15479 | }, |
| 15477 | 15480 | .Array, .Vector => { |
| 15478 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod)); | |
| 15479 | 15481 | const elem_ty = result_ty.childType(mod); |
| 15480 | const elem_size: u32 = @intCast(elem_ty.abiSize(mod)); | |
| 15482 | if (result_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) { | |
| 15483 | const result_size: u32 = @intCast(result_ty.abiSize(mod)); | |
| 15484 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); | |
| 15485 | try self.asmRegisterRegister( | |
| 15486 | .{ ._, .xor }, | |
| 15487 | registerAlias(dst_reg, @min(result_size, 4)), | |
| 15488 | registerAlias(dst_reg, @min(result_size, 4)), | |
| 15489 | ); | |
| 15481 | 15490 | |
| 15482 | for (elements, 0..) |elem, elem_i| { | |
| 15483 | const elem_mcv = try self.resolveInst(elem); | |
| 15484 | const mat_elem_mcv = switch (elem_mcv) { | |
| 15485 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, | |
| 15486 | else => elem_mcv, | |
| 15487 | }; | |
| 15488 | const elem_off: i32 = @intCast(elem_size * elem_i); | |
| 15489 | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv); | |
| 15491 | for (elements, 0..) |elem, elem_i| { | |
| 15492 | const elem_reg = try self.copyToTmpRegister(elem_ty, .{ .air_ref = elem }); | |
| 15493 | const elem_lock = self.register_manager.lockRegAssumeUnused(elem_reg); | |
| 15494 | defer self.register_manager.unlockReg(elem_lock); | |
| 15495 | ||
| 15496 | try self.asmRegisterImmediate( | |
| 15497 | .{ ._, .@"and" }, | |
| 15498 | registerAlias(elem_reg, @min(result_size, 4)), | |
| 15499 | Immediate.u(1), | |
| 15500 | ); | |
| 15501 | if (elem_i > 0) try self.asmRegisterImmediate( | |
| 15502 | .{ ._l, .sh }, | |
| 15503 | registerAlias(elem_reg, result_size), | |
| 15504 | Immediate.u(@intCast(elem_i)), | |
| 15505 | ); | |
| 15506 | try self.asmRegisterRegister( | |
| 15507 | .{ ._, .@"or" }, | |
| 15508 | registerAlias(dst_reg, result_size), | |
| 15509 | registerAlias(elem_reg, result_size), | |
| 15510 | ); | |
| 15511 | } | |
| 15512 | break :result .{ .register = dst_reg }; | |
| 15513 | } else { | |
| 15514 | const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod)); | |
| 15515 | const elem_size: u32 = @intCast(elem_ty.abiSize(mod)); | |
| 15516 | ||
| 15517 | for (elements, 0..) |elem, elem_i| { | |
| 15518 | const elem_mcv = try self.resolveInst(elem); | |
| 15519 | const mat_elem_mcv = switch (elem_mcv) { | |
| 15520 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, | |
| 15521 | else => elem_mcv, | |
| 15522 | }; | |
| 15523 | const elem_off: i32 = @intCast(elem_size * elem_i); | |
| 15524 | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv); | |
| 15525 | } | |
| 15526 | if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem( | |
| 15527 | .{ .frame = frame_index }, | |
| 15528 | @intCast(elem_size * elements.len), | |
| 15529 | elem_ty, | |
| 15530 | try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), | |
| 15531 | ); | |
| 15532 | break :result .{ .load_frame = .{ .index = frame_index } }; | |
| 15490 | 15533 | } |
| 15491 | if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem( | |
| 15492 | .{ .frame = frame_index }, | |
| 15493 | @intCast(elem_size * elements.len), | |
| 15494 | elem_ty, | |
| 15495 | try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), | |
| 15496 | ); | |
| 15497 | break :result .{ .load_frame = .{ .index = frame_index } }; | |
| 15498 | 15534 | }, |
| 15499 | 15535 | else => unreachable, |
| 15500 | 15536 | } |
src/codegen.zig+55-45| ... | ... | @@ -391,53 +391,63 @@ pub fn generateSymbol( |
| 391 | 391 | .vector_type => |vector_type| { |
| 392 | 392 | const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse |
| 393 | 393 | return error.Overflow; |
| 394 | switch (vector_type.child) { | |
| 395 | .bool_type => { | |
| 396 | const bytes = try code.addManyAsSlice(abi_size); | |
| 397 | @memset(bytes, 0xaa); | |
| 398 | var index: usize = 0; | |
| 399 | const len = math.cast(usize, vector_type.len) orelse return error.Overflow; | |
| 400 | while (index < len) : (index += 1) { | |
| 401 | const bit_index = switch (endian) { | |
| 402 | .big => len - 1 - index, | |
| 403 | .little => index, | |
| 404 | }; | |
| 405 | const byte = &bytes[bit_index / 8]; | |
| 406 | const mask = @as(u8, 1) << @truncate(bit_index); | |
| 407 | if (switch (switch (aggregate.storage) { | |
| 408 | .bytes => unreachable, | |
| 409 | .elems => |elems| elems[index], | |
| 410 | .repeated_elem => |elem| elem, | |
| 411 | }) { | |
| 412 | .bool_true => true, | |
| 413 | .bool_false => false, | |
| 414 | else => |elem| { | |
| 415 | assert(mod.intern_pool.indexToKey(elem).undef == .bool_type); | |
| 416 | continue; | |
| 394 | if (Type.fromInterned(vector_type.child).bitSize(mod) == 1) { | |
| 395 | const bytes = try code.addManyAsSlice(abi_size); | |
| 396 | @memset(bytes, 0xaa); | |
| 397 | var index: usize = 0; | |
| 398 | const len = math.cast(usize, vector_type.len) orelse return error.Overflow; | |
| 399 | while (index < len) : (index += 1) { | |
| 400 | const bit_index = switch (endian) { | |
| 401 | .big => len - 1 - index, | |
| 402 | .little => index, | |
| 403 | }; | |
| 404 | const byte = &bytes[bit_index / 8]; | |
| 405 | const mask = @as(u8, 1) << @truncate(bit_index); | |
| 406 | if (switch (switch (aggregate.storage) { | |
| 407 | .bytes => unreachable, | |
| 408 | .elems => |elems| elems[index], | |
| 409 | .repeated_elem => |elem| elem, | |
| 410 | }) { | |
| 411 | .bool_true => true, | |
| 412 | .bool_false => false, | |
| 413 | else => |elem| switch (mod.intern_pool.indexToKey(elem)) { | |
| 414 | .undef => continue, | |
| 415 | .int => |int| switch (int.storage) { | |
| 416 | .u64 => |x| switch (x) { | |
| 417 | 0 => false, | |
| 418 | 1 => true, | |
| 419 | else => unreachable, | |
| 420 | }, | |
| 421 | .i64 => |x| switch (x) { | |
| 422 | -1 => true, | |
| 423 | 0 => false, | |
| 424 | else => unreachable, | |
| 425 | }, | |
| 426 | else => unreachable, | |
| 417 | 427 | }, |
| 418 | }) byte.* |= mask else byte.* &= ~mask; | |
| 419 | } | |
| 420 | }, | |
| 421 | else => switch (aggregate.storage) { | |
| 422 | .bytes => |bytes| try code.appendSlice(bytes), | |
| 423 | .elems, .repeated_elem => { | |
| 424 | var index: u64 = 0; | |
| 425 | while (index < vector_type.len) : (index += 1) { | |
| 426 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 427 | .ty = Type.fromInterned(vector_type.child), | |
| 428 | .val = Value.fromInterned(switch (aggregate.storage) { | |
| 429 | .bytes => unreachable, | |
| 430 | .elems => |elems| elems[ | |
| 431 | math.cast(usize, index) orelse return error.Overflow | |
| 432 | ], | |
| 433 | .repeated_elem => |elem| elem, | |
| 434 | }), | |
| 435 | }, code, debug_output, reloc_info)) { | |
| 436 | .ok => {}, | |
| 437 | .fail => |em| return .{ .fail = em }, | |
| 438 | } | |
| 428 | else => unreachable, | |
| 429 | }, | |
| 430 | }) byte.* |= mask else byte.* &= ~mask; | |
| 431 | } | |
| 432 | } else switch (aggregate.storage) { | |
| 433 | .bytes => |bytes| try code.appendSlice(bytes), | |
| 434 | .elems, .repeated_elem => { | |
| 435 | var index: u64 = 0; | |
| 436 | while (index < vector_type.len) : (index += 1) { | |
| 437 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 438 | .ty = Type.fromInterned(vector_type.child), | |
| 439 | .val = Value.fromInterned(switch (aggregate.storage) { | |
| 440 | .bytes => unreachable, | |
| 441 | .elems => |elems| elems[ | |
| 442 | math.cast(usize, index) orelse return error.Overflow | |
| 443 | ], | |
| 444 | .repeated_elem => |elem| elem, | |
| 445 | }), | |
| 446 | }, code, debug_output, reloc_info)) { | |
| 447 | .ok => {}, | |
| 448 | .fail => |em| return .{ .fail = em }, | |
| 439 | 449 | } |
| 440 | }, | |
| 450 | } | |
| 441 | 451 | }, |
| 442 | 452 | } |
| 443 | 453 |
test/behavior/cast.zig-1| ... | ... | @@ -2420,7 +2420,6 @@ test "@intFromFloat on vector" { |
| 2420 | 2420 | |
| 2421 | 2421 | test "@intFromBool on vector" { |
| 2422 | 2422 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 2423 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 2424 | 2423 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 2425 | 2424 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2426 | 2425 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |