| ... | @@ -193,6 +193,11 @@ pub const MCValue = union(enum) { | ... | @@ -193,6 +193,11 @@ pub const MCValue = union(enum) { |
| 193 | /// The value is in memory at a hard-coded address. | 193 | /// The value is in memory at a hard-coded address. |
| 194 | /// If the type is a pointer, it means the pointer address is stored at this memory location. | 194 | /// If the type is a pointer, it means the pointer address is stored at this memory location. |
| 195 | memory: u64, | 195 | memory: u64, |
| | 196 | /// The value is in memory at an address not-yet-allocated by the linker. |
| | 197 | /// This traditionally corresponds to a relocation emitted in a relocatable object file. |
| | 198 | load_symbol: u32, |
| | 199 | /// The address of the memory location not-yet-allocated by the linker. |
| | 200 | lea_symbol: u32, |
| 196 | /// The value is in memory at a constant offset from the address in a register. | 201 | /// The value is in memory at a constant offset from the address in a register. |
| 197 | indirect: RegisterOffset, | 202 | indirect: RegisterOffset, |
| 198 | /// The value is in memory. | 203 | /// The value is in memory. |
| ... | @@ -207,12 +212,6 @@ pub const MCValue = union(enum) { | ... | @@ -207,12 +212,6 @@ pub const MCValue = union(enum) { |
| 207 | /// The value is a pointer to a value referenced indirectly via GOT. | 212 | /// The value is a pointer to a value referenced indirectly via GOT. |
| 208 | /// Payload is a symbol index. | 213 | /// Payload is a symbol index. |
| 209 | lea_got: u32, | 214 | lea_got: u32, |
| 210 | /// The value is an extern variable referenced via GOT. | | |
| 211 | /// Payload is a symbol index. | | |
| 212 | load_extern_got: u32, | | |
| 213 | /// The value is a pointer to an extern variable referenced via GOT. | | |
| 214 | /// Payload is a symbol index. | | |
| 215 | lea_extern_got: u32, | | |
| 216 | /// The value is a threadlocal variable. | 215 | /// The value is a threadlocal variable. |
| 217 | /// Payload is a symbol index. | 216 | /// Payload is a symbol index. |
| 218 | load_tlv: u32, | 217 | load_tlv: u32, |
| ... | @@ -299,9 +298,9 @@ pub const MCValue = union(enum) { | ... | @@ -299,9 +298,9 @@ pub const MCValue = union(enum) { |
| 299 | .register_pair, | 298 | .register_pair, |
| 300 | .register_offset, | 299 | .register_offset, |
| 301 | .register_overflow, | 300 | .register_overflow, |
| | 301 | .lea_symbol, |
| 302 | .lea_direct, | 302 | .lea_direct, |
| 303 | .lea_got, | 303 | .lea_got, |
| 304 | .lea_extern_got, | | |
| 305 | .lea_tlv, | 304 | .lea_tlv, |
| 306 | .lea_frame, | 305 | .lea_frame, |
| 307 | .reserved_frame, | 306 | .reserved_frame, |
| ... | @@ -315,8 +314,8 @@ pub const MCValue = union(enum) { | ... | @@ -315,8 +314,8 @@ pub const MCValue = union(enum) { |
| 315 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, | 314 | .load_direct => |sym_index| .{ .lea_direct = sym_index }, |
| 316 | .load_got => |sym_index| .{ .lea_got = sym_index }, | 315 | .load_got => |sym_index| .{ .lea_got = sym_index }, |
| 317 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, | 316 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 318 | .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index }, | | |
| 319 | .load_frame => |frame_addr| .{ .lea_frame = frame_addr }, | 317 | .load_frame => |frame_addr| .{ .lea_frame = frame_addr }, |
| | 318 | .load_symbol => |sym_index| .{ .lea_symbol = sym_index }, |
| 320 | }; | 319 | }; |
| 321 | } | 320 | } |
| 322 | | 321 | |
| ... | @@ -333,9 +332,9 @@ pub const MCValue = union(enum) { | ... | @@ -333,9 +332,9 @@ pub const MCValue = union(enum) { |
| 333 | .indirect, | 332 | .indirect, |
| 334 | .load_direct, | 333 | .load_direct, |
| 335 | .load_got, | 334 | .load_got, |
| 336 | .load_extern_got, | | |
| 337 | .load_tlv, | 335 | .load_tlv, |
| 338 | .load_frame, | 336 | .load_frame, |
| | 337 | .load_symbol, |
| 339 | .reserved_frame, | 338 | .reserved_frame, |
| 340 | .air_ref, | 339 | .air_ref, |
| 341 | => unreachable, // not dereferenceable | 340 | => unreachable, // not dereferenceable |
| ... | @@ -344,9 +343,9 @@ pub const MCValue = union(enum) { | ... | @@ -344,9 +343,9 @@ pub const MCValue = union(enum) { |
| 344 | .register_offset => |reg_off| .{ .indirect = reg_off }, | 343 | .register_offset => |reg_off| .{ .indirect = reg_off }, |
| 345 | .lea_direct => |sym_index| .{ .load_direct = sym_index }, | 344 | .lea_direct => |sym_index| .{ .load_direct = sym_index }, |
| 346 | .lea_got => |sym_index| .{ .load_got = sym_index }, | 345 | .lea_got => |sym_index| .{ .load_got = sym_index }, |
| 347 | .lea_extern_got => |sym_index| .{ .load_extern_got = sym_index }, | | |
| 348 | .lea_tlv => |sym_index| .{ .load_tlv = sym_index }, | 346 | .lea_tlv => |sym_index| .{ .load_tlv = sym_index }, |
| 349 | .lea_frame => |frame_addr| .{ .load_frame = frame_addr }, | 347 | .lea_frame => |frame_addr| .{ .load_frame = frame_addr }, |
| | 348 | .lea_symbol => |sym_index| .{ .load_symbol = sym_index }, |
| 350 | }; | 349 | }; |
| 351 | } | 350 | } |
| 352 | | 351 | |
| ... | @@ -368,11 +367,11 @@ pub const MCValue = union(enum) { | ... | @@ -368,11 +367,11 @@ pub const MCValue = union(enum) { |
| 368 | .lea_direct, | 367 | .lea_direct, |
| 369 | .load_got, | 368 | .load_got, |
| 370 | .lea_got, | 369 | .lea_got, |
| 371 | .load_extern_got, | | |
| 372 | .lea_extern_got, | | |
| 373 | .load_tlv, | 370 | .load_tlv, |
| 374 | .lea_tlv, | 371 | .lea_tlv, |
| 375 | .load_frame, | 372 | .load_frame, |
| | 373 | .load_symbol, |
| | 374 | .lea_symbol, |
| 376 | => switch (off) { | 375 | => switch (off) { |
| 377 | 0 => mcv, | 376 | 0 => mcv, |
| 378 | else => unreachable, // not offsettable | 377 | else => unreachable, // not offsettable |
| ... | @@ -404,13 +403,13 @@ pub const MCValue = union(enum) { | ... | @@ -404,13 +403,13 @@ pub const MCValue = union(enum) { |
| 404 | .lea_direct, | 403 | .lea_direct, |
| 405 | .load_got, | 404 | .load_got, |
| 406 | .lea_got, | 405 | .lea_got, |
| 407 | .load_extern_got, | | |
| 408 | .lea_extern_got, | | |
| 409 | .load_tlv, | 406 | .load_tlv, |
| 410 | .lea_tlv, | 407 | .lea_tlv, |
| 411 | .lea_frame, | 408 | .lea_frame, |
| 412 | .reserved_frame, | 409 | .reserved_frame, |
| 413 | .air_ref, | 410 | .air_ref, |
| | 411 | .load_symbol, |
| | 412 | .lea_symbol, |
| 414 | => unreachable, | 413 | => unreachable, |
| 415 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| | 414 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 416 | Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr }) | 415 | Memory.sib(ptr_size, .{ .base = .{ .reg = .ds }, .disp = small_addr }) |
| ... | @@ -448,14 +447,14 @@ pub const MCValue = union(enum) { | ... | @@ -448,14 +447,14 @@ pub const MCValue = union(enum) { |
| 448 | .lea_direct => |pl| try writer.print("direct:{d}", .{pl}), | 447 | .lea_direct => |pl| try writer.print("direct:{d}", .{pl}), |
| 449 | .load_got => |pl| try writer.print("[got:{d}]", .{pl}), | 448 | .load_got => |pl| try writer.print("[got:{d}]", .{pl}), |
| 450 | .lea_got => |pl| try writer.print("got:{d}", .{pl}), | 449 | .lea_got => |pl| try writer.print("got:{d}", .{pl}), |
| 451 | .load_extern_got => |pl| try writer.print("[extern_got:{d}]", .{pl}), | | |
| 452 | .lea_extern_got => |pl| try writer.print("extern_got:{d}", .{pl}), | | |
| 453 | .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}), | 450 | .load_tlv => |pl| try writer.print("[tlv:{d}]", .{pl}), |
| 454 | .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}), | 451 | .lea_tlv => |pl| try writer.print("tlv:{d}", .{pl}), |
| 455 | .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }), | 452 | .load_frame => |pl| try writer.print("[{} + 0x{x}]", .{ pl.index, pl.off }), |
| 456 | .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }), | 453 | .lea_frame => |pl| try writer.print("{} + 0x{x}", .{ pl.index, pl.off }), |
| 457 | .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}), | 454 | .reserved_frame => |pl| try writer.print("(dead:{})", .{pl}), |
| 458 | .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}), | 455 | .air_ref => |pl| try writer.print("(air:0x{x})", .{@intFromEnum(pl)}), |
| | 456 | .load_symbol => |pl| try writer.print("[symbol:{d}]", .{pl}), |
| | 457 | .lea_symbol => |pl| try writer.print("symbol:{d}", .{pl}), |
| 459 | } | 458 | } |
| 460 | } | 459 | } |
| 461 | }; | 460 | }; |
| ... | @@ -477,12 +476,12 @@ const InstTracking = struct { | ... | @@ -477,12 +476,12 @@ const InstTracking = struct { |
| 477 | .lea_direct, | 476 | .lea_direct, |
| 478 | .load_got, | 477 | .load_got, |
| 479 | .lea_got, | 478 | .lea_got, |
| 480 | .load_extern_got, | | |
| 481 | .lea_extern_got, | | |
| 482 | .load_tlv, | 479 | .load_tlv, |
| 483 | .lea_tlv, | 480 | .lea_tlv, |
| 484 | .load_frame, | 481 | .load_frame, |
| 485 | .lea_frame, | 482 | .lea_frame, |
| | 483 | .load_symbol, |
| | 484 | .lea_symbol, |
| 486 | => result, | 485 | => result, |
| 487 | .dead, | 486 | .dead, |
| 488 | .reserved_frame, | 487 | .reserved_frame, |
| ... | @@ -538,12 +537,12 @@ const InstTracking = struct { | ... | @@ -538,12 +537,12 @@ const InstTracking = struct { |
| 538 | .lea_direct, | 537 | .lea_direct, |
| 539 | .load_got, | 538 | .load_got, |
| 540 | .lea_got, | 539 | .lea_got, |
| 541 | .load_extern_got, | | |
| 542 | .lea_extern_got, | | |
| 543 | .load_tlv, | 540 | .load_tlv, |
| 544 | .lea_tlv, | 541 | .lea_tlv, |
| 545 | .load_frame, | 542 | .load_frame, |
| 546 | .lea_frame, | 543 | .lea_frame, |
| | 544 | .load_symbol, |
| | 545 | .lea_symbol, |
| 547 | => self.long, | 546 | => self.long, |
| 548 | .dead, | 547 | .dead, |
| 549 | .eflags, | 548 | .eflags, |
| ... | @@ -575,11 +574,11 @@ const InstTracking = struct { | ... | @@ -575,11 +574,11 @@ const InstTracking = struct { |
| 575 | .lea_direct, | 574 | .lea_direct, |
| 576 | .load_got, | 575 | .load_got, |
| 577 | .lea_got, | 576 | .lea_got, |
| 578 | .load_extern_got, | | |
| 579 | .lea_extern_got, | | |
| 580 | .load_tlv, | 577 | .load_tlv, |
| 581 | .lea_tlv, | 578 | .lea_tlv, |
| 582 | .lea_frame, | 579 | .lea_frame, |
| | 580 | .load_symbol, |
| | 581 | .lea_symbol, |
| 583 | => assert(std.meta.eql(self.long, target.long)), | 582 | => assert(std.meta.eql(self.long, target.long)), |
| 584 | .load_frame, | 583 | .load_frame, |
| 585 | .reserved_frame, | 584 | .reserved_frame, |
| ... | @@ -883,6 +882,7 @@ pub fn generate( | ... | @@ -883,6 +882,7 @@ pub fn generate( |
| 883 | | 882 | |
| 884 | var emit = Emit{ | 883 | var emit = Emit{ |
| 885 | .lower = .{ | 884 | .lower = .{ |
| | 885 | .bin_file = bin_file, |
| 886 | .allocator = bin_file.allocator, | 886 | .allocator = bin_file.allocator, |
| 887 | .mir = mir, | 887 | .mir = mir, |
| 888 | .cc = cc, | 888 | .cc = cc, |
| ... | @@ -970,6 +970,7 @@ pub fn generateLazy( | ... | @@ -970,6 +970,7 @@ pub fn generateLazy( |
| 970 | | 970 | |
| 971 | var emit = Emit{ | 971 | var emit = Emit{ |
| 972 | .lower = .{ | 972 | .lower = .{ |
| | 973 | .bin_file = bin_file, |
| 973 | .allocator = bin_file.allocator, | 974 | .allocator = bin_file.allocator, |
| 974 | .mir = mir, | 975 | .mir = mir, |
| 975 | .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), | 976 | .cc = abi.resolveCallingConvention(.Unspecified, function.target.*), |
| ... | @@ -1060,6 +1061,7 @@ fn formatWipMir( | ... | @@ -1060,6 +1061,7 @@ fn formatWipMir( |
| 1060 | writer: anytype, | 1061 | writer: anytype, |
| 1061 | ) @TypeOf(writer).Error!void { | 1062 | ) @TypeOf(writer).Error!void { |
| 1062 | var lower = Lower{ | 1063 | var lower = Lower{ |
| | 1064 | .bin_file = data.self.bin_file, |
| 1063 | .allocator = data.self.gpa, | 1065 | .allocator = data.self.gpa, |
| 1064 | .mir = .{ | 1066 | .mir = .{ |
| 1065 | .instructions = data.self.mir_instructions.slice(), | 1067 | .instructions = data.self.mir_instructions.slice(), |
| ... | @@ -3261,25 +3263,51 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3261,25 +3263,51 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 3261 | defer self.register_manager.unlockReg(tmp_lock); | 3263 | defer self.register_manager.unlockReg(tmp_lock); |
| 3262 | | 3264 | |
| 3263 | const lhs_mcv = try self.resolveInst(bin_op.lhs); | 3265 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 3264 | if (lhs_mcv.isMemory()) try self.asmRegisterMemory( | 3266 | const mat_lhs_mcv = switch (lhs_mcv) { |
| | 3267 | .load_symbol => mat_lhs_mcv: { |
| | 3268 | // TODO clean this up! |
| | 3269 | const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address()); |
| | 3270 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 3271 | }, |
| | 3272 | else => lhs_mcv, |
| | 3273 | }; |
| | 3274 | const mat_lhs_lock = switch (mat_lhs_mcv) { |
| | 3275 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 3276 | else => null, |
| | 3277 | }; |
| | 3278 | defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3279 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 3265 | .{ ._, .mov }, | 3280 | .{ ._, .mov }, |
| 3266 | tmp_reg, | 3281 | tmp_reg, |
| 3267 | lhs_mcv.address().offset(8).deref().mem(.qword), | 3282 | mat_lhs_mcv.address().offset(8).deref().mem(.qword), |
| 3268 | ) else try self.asmRegisterRegister( | 3283 | ) else try self.asmRegisterRegister( |
| 3269 | .{ ._, .mov }, | 3284 | .{ ._, .mov }, |
| 3270 | tmp_reg, | 3285 | tmp_reg, |
| 3271 | lhs_mcv.register_pair[1], | 3286 | mat_lhs_mcv.register_pair[1], |
| 3272 | ); | 3287 | ); |
| 3273 | | 3288 | |
| 3274 | const rhs_mcv = try self.resolveInst(bin_op.rhs); | 3289 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| 3275 | if (rhs_mcv.isMemory()) try self.asmRegisterMemory( | 3290 | const mat_rhs_mcv = switch (rhs_mcv) { |
| | 3291 | .load_symbol => mat_rhs_mcv: { |
| | 3292 | // TODO clean this up! |
| | 3293 | const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address()); |
| | 3294 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 3295 | }, |
| | 3296 | else => rhs_mcv, |
| | 3297 | }; |
| | 3298 | const mat_rhs_lock = switch (mat_rhs_mcv) { |
| | 3299 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 3300 | else => null, |
| | 3301 | }; |
| | 3302 | defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3303 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 3276 | .{ ._, .xor }, | 3304 | .{ ._, .xor }, |
| 3277 | tmp_reg, | 3305 | tmp_reg, |
| 3278 | rhs_mcv.address().offset(8).deref().mem(.qword), | 3306 | mat_rhs_mcv.address().offset(8).deref().mem(.qword), |
| 3279 | ) else try self.asmRegisterRegister( | 3307 | ) else try self.asmRegisterRegister( |
| 3280 | .{ ._, .xor }, | 3308 | .{ ._, .xor }, |
| 3281 | tmp_reg, | 3309 | tmp_reg, |
| 3282 | rhs_mcv.register_pair[1], | 3310 | mat_rhs_mcv.register_pair[1], |
| 3283 | ); | 3311 | ); |
| 3284 | const reloc = try self.asmJccReloc(.ns, undefined); | 3312 | const reloc = try self.asmJccReloc(.ns, undefined); |
| 3285 | | 3313 | |
| ... | @@ -3353,20 +3381,37 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3353,20 +3381,37 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void { |
| 3353 | defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock); | 3381 | defer for (tmp_locks) |lock| self.register_manager.unlockReg(lock); |
| 3354 | | 3382 | |
| 3355 | const rhs_mcv = try self.resolveInst(bin_op.rhs); | 3383 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| | 3384 | const mat_rhs_mcv = switch (rhs_mcv) { |
| | 3385 | .load_symbol => mat_rhs_mcv: { |
| | 3386 | // TODO clean this up! |
| | 3387 | const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address()); |
| | 3388 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 3389 | }, |
| | 3390 | else => rhs_mcv, |
| | 3391 | }; |
| | 3392 | const mat_rhs_lock = switch (mat_rhs_mcv) { |
| | 3393 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 3394 | else => null, |
| | 3395 | }; |
| | 3396 | defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3356 | | 3397 | |
| 3357 | for (tmp_regs, dst_regs) |tmp_reg, dst_reg| | 3398 | for (tmp_regs, dst_regs) |tmp_reg, dst_reg| |
| 3358 | try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg); | 3399 | try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, dst_reg); |
| 3359 | if (rhs_mcv.isMemory()) { | 3400 | if (mat_rhs_mcv.isMemory()) { |
| 3360 | try self.asmRegisterMemory(.{ ._, .add }, tmp_regs[0], rhs_mcv.mem(.qword)); | 3401 | try self.asmRegisterMemory( |
| | 3402 | .{ ._, .add }, |
| | 3403 | tmp_regs[0], |
| | 3404 | mat_rhs_mcv.mem(.qword), |
| | 3405 | ); |
| 3361 | try self.asmRegisterMemory( | 3406 | try self.asmRegisterMemory( |
| 3362 | .{ ._, .adc }, | 3407 | .{ ._, .adc }, |
| 3363 | tmp_regs[1], | 3408 | tmp_regs[1], |
| 3364 | rhs_mcv.address().offset(8).deref().mem(.qword), | 3409 | mat_rhs_mcv.address().offset(8).deref().mem(.qword), |
| 3365 | ); | 3410 | ); |
| 3366 | } else for ( | 3411 | } else for ( |
| 3367 | [_]Mir.Inst.Tag{ .add, .adc }, | 3412 | [_]Mir.Inst.Tag{ .add, .adc }, |
| 3368 | tmp_regs, | 3413 | tmp_regs, |
| 3369 | rhs_mcv.register_pair, | 3414 | mat_rhs_mcv.register_pair, |
| 3370 | ) |op, tmp_reg, rhs_reg| | 3415 | ) |op, tmp_reg, rhs_reg| |
| 3371 | try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg); | 3416 | try self.asmRegisterRegister(.{ ._, op }, tmp_reg, rhs_reg); |
| 3372 | try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]); | 3417 | try self.asmRegisterRegister(.{ ._, .@"test" }, dst_regs[1], dst_regs[1]); |
| ... | @@ -3871,39 +3916,65 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3871,39 +3916,65 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3871 | | 3916 | |
| 3872 | const lhs_mcv = try self.resolveInst(bin_op.lhs); | 3917 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 3873 | const rhs_mcv = try self.resolveInst(bin_op.rhs); | 3918 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| | 3919 | const mat_lhs_mcv = switch (lhs_mcv) { |
| | 3920 | .load_symbol => mat_lhs_mcv: { |
| | 3921 | // TODO clean this up! |
| | 3922 | const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address()); |
| | 3923 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 3924 | }, |
| | 3925 | else => lhs_mcv, |
| | 3926 | }; |
| | 3927 | const mat_lhs_lock = switch (mat_lhs_mcv) { |
| | 3928 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 3929 | else => null, |
| | 3930 | }; |
| | 3931 | defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 3932 | const mat_rhs_mcv = switch (rhs_mcv) { |
| | 3933 | .load_symbol => mat_rhs_mcv: { |
| | 3934 | // TODO clean this up! |
| | 3935 | const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address()); |
| | 3936 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 3937 | }, |
| | 3938 | else => rhs_mcv, |
| | 3939 | }; |
| | 3940 | const mat_rhs_lock = switch (mat_rhs_mcv) { |
| | 3941 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 3942 | else => null, |
| | 3943 | }; |
| | 3944 | defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3874 | | 3945 | |
| 3875 | if (lhs_mcv.isMemory()) | 3946 | if (mat_lhs_mcv.isMemory()) |
| 3876 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword)) | 3947 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword)) |
| 3877 | else | 3948 | else |
| 3878 | try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]); | 3949 | try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]); |
| 3879 | if (rhs_mcv.isMemory()) try self.asmRegisterMemory( | 3950 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 3880 | .{ ._, .mov }, | 3951 | .{ ._, .mov }, |
| 3881 | tmp_regs[0], | 3952 | tmp_regs[0], |
| 3882 | rhs_mcv.address().offset(8).deref().mem(.qword), | 3953 | mat_rhs_mcv.address().offset(8).deref().mem(.qword), |
| 3883 | ) else try self.asmRegisterRegister( | 3954 | ) else try self.asmRegisterRegister( |
| 3884 | .{ ._, .mov }, | 3955 | .{ ._, .mov }, |
| 3885 | tmp_regs[0], | 3956 | tmp_regs[0], |
| 3886 | rhs_mcv.register_pair[1], | 3957 | mat_rhs_mcv.register_pair[1], |
| 3887 | ); | 3958 | ); |
| 3888 | try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]); | 3959 | try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]); |
| 3889 | try self.asmSetccRegister(.nz, tmp_regs[1].to8()); | 3960 | try self.asmSetccRegister(.nz, tmp_regs[1].to8()); |
| 3890 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax); | 3961 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_regs[0], .rax); |
| 3891 | try self.asmSetccRegister(.o, tmp_regs[2].to8()); | 3962 | try self.asmSetccRegister(.o, tmp_regs[2].to8()); |
| 3892 | if (rhs_mcv.isMemory()) | 3963 | if (mat_rhs_mcv.isMemory()) |
| 3893 | try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword)) | 3964 | try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword)) |
| 3894 | else | 3965 | else |
| 3895 | try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]); | 3966 | try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]); |
| 3896 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]); | 3967 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_regs[0]); |
| 3897 | try self.asmSetccRegister(.c, tmp_regs[3].to8()); | 3968 | try self.asmSetccRegister(.c, tmp_regs[3].to8()); |
| 3898 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[2].to8(), tmp_regs[3].to8()); | 3969 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[2].to8(), tmp_regs[3].to8()); |
| 3899 | if (lhs_mcv.isMemory()) try self.asmRegisterMemory( | 3970 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 3900 | .{ ._, .mov }, | 3971 | .{ ._, .mov }, |
| 3901 | tmp_regs[0], | 3972 | tmp_regs[0], |
| 3902 | lhs_mcv.address().offset(8).deref().mem(.qword), | 3973 | mat_lhs_mcv.address().offset(8).deref().mem(.qword), |
| 3903 | ) else try self.asmRegisterRegister( | 3974 | ) else try self.asmRegisterRegister( |
| 3904 | .{ ._, .mov }, | 3975 | .{ ._, .mov }, |
| 3905 | tmp_regs[0], | 3976 | tmp_regs[0], |
| 3906 | lhs_mcv.register_pair[1], | 3977 | mat_lhs_mcv.register_pair[1], |
| 3907 | ); | 3978 | ); |
| 3908 | try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]); | 3979 | try self.asmRegisterRegister(.{ ._, .@"test" }, tmp_regs[0], tmp_regs[0]); |
| 3909 | try self.asmSetccRegister(.nz, tmp_regs[3].to8()); | 3980 | try self.asmSetccRegister(.nz, tmp_regs[3].to8()); |
| ... | @@ -3913,13 +3984,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3913,13 +3984,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3913 | tmp_regs[3].to8(), | 3984 | tmp_regs[3].to8(), |
| 3914 | ); | 3985 | ); |
| 3915 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8()); | 3986 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8()); |
| 3916 | if (rhs_mcv.isMemory()) | 3987 | if (mat_rhs_mcv.isMemory()) |
| 3917 | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], rhs_mcv.mem(.qword)) | 3988 | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_regs[0], mat_rhs_mcv.mem(.qword)) |
| 3918 | else | 3989 | else |
| 3919 | try self.asmRegisterRegister( | 3990 | try self.asmRegisterRegister( |
| 3920 | .{ .i_, .mul }, | 3991 | .{ .i_, .mul }, |
| 3921 | tmp_regs[0], | 3992 | tmp_regs[0], |
| 3922 | rhs_mcv.register_pair[0], | 3993 | mat_rhs_mcv.register_pair[0], |
| 3923 | ); | 3994 | ); |
| 3924 | try self.asmSetccRegister(.o, tmp_regs[2].to8()); | 3995 | try self.asmSetccRegister(.o, tmp_regs[2].to8()); |
| 3925 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8()); | 3996 | try self.asmRegisterRegister(.{ ._, .@"or" }, tmp_regs[1].to8(), tmp_regs[2].to8()); |
| ... | @@ -4729,12 +4800,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4729,12 +4800,12 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4729 | Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }), | 4800 | Memory.sib(.qword, .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off }), |
| 4730 | ), | 4801 | ), |
| 4731 | .memory, | 4802 | .memory, |
| | 4803 | .load_symbol, |
| 4732 | .load_direct, | 4804 | .load_direct, |
| 4733 | .load_got, | 4805 | .load_got, |
| 4734 | .load_extern_got, | | |
| 4735 | .load_tlv, | 4806 | .load_tlv, |
| 4736 | => try self.genSetReg(addr_reg, Type.usize, array.address()), | 4807 | => try self.genSetReg(addr_reg, Type.usize, array.address()), |
| 4737 | .lea_direct, .lea_tlv => unreachable, | 4808 | .lea_symbol, .lea_direct, .lea_tlv => unreachable, |
| 4738 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), | 4809 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| 4739 | } | 4810 | } |
| 4740 | | 4811 | |
| ... | @@ -6327,17 +6398,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro | ... | @@ -6327,17 +6398,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro |
| 6327 | .immediate, | 6398 | .immediate, |
| 6328 | .register, | 6399 | .register, |
| 6329 | .register_offset, | 6400 | .register_offset, |
| | 6401 | .lea_symbol, |
| 6330 | .lea_direct, | 6402 | .lea_direct, |
| 6331 | .lea_got, | 6403 | .lea_got, |
| 6332 | .lea_extern_got, | | |
| 6333 | .lea_tlv, | 6404 | .lea_tlv, |
| 6334 | .lea_frame, | 6405 | .lea_frame, |
| 6335 | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), | 6406 | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), |
| 6336 | .memory, | 6407 | .memory, |
| 6337 | .indirect, | 6408 | .indirect, |
| | 6409 | .load_symbol, |
| 6338 | .load_direct, | 6410 | .load_direct, |
| 6339 | .load_got, | 6411 | .load_got, |
| 6340 | .load_extern_got, | | |
| 6341 | .load_tlv, | 6412 | .load_tlv, |
| 6342 | .load_frame, | 6413 | .load_frame, |
| 6343 | => { | 6414 | => { |
| ... | @@ -6476,17 +6547,17 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr | ... | @@ -6476,17 +6547,17 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr |
| 6476 | .immediate, | 6547 | .immediate, |
| 6477 | .register, | 6548 | .register, |
| 6478 | .register_offset, | 6549 | .register_offset, |
| | 6550 | .lea_symbol, |
| 6479 | .lea_direct, | 6551 | .lea_direct, |
| 6480 | .lea_got, | 6552 | .lea_got, |
| 6481 | .lea_extern_got, | | |
| 6482 | .lea_tlv, | 6553 | .lea_tlv, |
| 6483 | .lea_frame, | 6554 | .lea_frame, |
| 6484 | => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv), | 6555 | => try self.genCopy(src_ty, ptr_mcv.deref(), src_mcv), |
| 6485 | .memory, | 6556 | .memory, |
| 6486 | .indirect, | 6557 | .indirect, |
| | 6558 | .load_symbol, |
| 6487 | .load_direct, | 6559 | .load_direct, |
| 6488 | .load_got, | 6560 | .load_got, |
| 6489 | .load_extern_got, | | |
| 6490 | .load_tlv, | 6561 | .load_tlv, |
| 6491 | .load_frame, | 6562 | .load_frame, |
| 6492 | => { | 6563 | => { |
| ... | @@ -6587,12 +6658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6587,12 +6658,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6587 | const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg); | 6658 | const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 6588 | defer self.register_manager.unlockReg(src_reg_lock); | 6659 | defer self.register_manager.unlockReg(src_reg_lock); |
| 6589 | | 6660 | |
| 6590 | const dst_reg = if (field_rc.supersetOf(container_rc) and | 6661 | const src_in_field_rc = |
| 6591 | self.reuseOperand(inst, operand, 0, src_mcv)) | 6662 | field_rc.isSet(RegisterManager.indexOfRegIntoTracked(src_reg).?); |
| | 6663 | const dst_reg = if (src_in_field_rc and self.reuseOperand(inst, operand, 0, src_mcv)) |
| 6592 | src_reg | 6664 | src_reg |
| | 6665 | else if (field_off == 0) |
| | 6666 | (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register |
| 6593 | else | 6667 | else |
| 6594 | try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); | 6668 | try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| 6595 | const dst_mcv = MCValue{ .register = dst_reg }; | 6669 | const dst_mcv: MCValue = .{ .register = dst_reg }; |
| 6596 | const dst_lock = self.register_manager.lockReg(dst_reg); | 6670 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 6597 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 6671 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 6598 | | 6672 | |
| ... | @@ -6602,9 +6676,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6602,9 +6676,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6602 | dst_mcv, | 6676 | dst_mcv, |
| 6603 | .{ .immediate = field_off }, | 6677 | .{ .immediate = field_off }, |
| 6604 | ); | 6678 | ); |
| 6605 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); | 6679 | if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and |
| | 6680 | container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod)) |
| | 6681 | try self.truncateRegister(field_ty, dst_reg); |
| 6606 | | 6682 | |
| 6607 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) | 6683 | break :result if (field_off == 0 or field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6608 | dst_mcv | 6684 | dst_mcv |
| 6609 | else | 6685 | else |
| 6610 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); | 6686 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| ... | @@ -6908,15 +6984,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC | ... | @@ -6908,15 +6984,15 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC |
| 6908 | .register_overflow, | 6984 | .register_overflow, |
| 6909 | .lea_direct, | 6985 | .lea_direct, |
| 6910 | .lea_got, | 6986 | .lea_got, |
| 6911 | .lea_extern_got, | | |
| 6912 | .lea_tlv, | 6987 | .lea_tlv, |
| 6913 | .lea_frame, | 6988 | .lea_frame, |
| 6914 | .reserved_frame, | 6989 | .reserved_frame, |
| 6915 | .air_ref, | 6990 | .air_ref, |
| | 6991 | .lea_symbol, |
| 6916 | => unreachable, // unmodifiable destination | 6992 | => unreachable, // unmodifiable destination |
| 6917 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), | 6993 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 6918 | .register_pair => unreachable, // unimplemented | 6994 | .register_pair => unreachable, // unimplemented |
| 6919 | .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => { | 6995 | .memory, .load_symbol, .load_got, .load_direct, .load_tlv => { |
| 6920 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); | 6996 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6921 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 6997 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6922 | defer self.register_manager.unlockReg(addr_reg_lock); | 6998 | defer self.register_manager.unlockReg(addr_reg_lock); |
| ... | @@ -7352,34 +7428,61 @@ fn genMulDivBinOp( | ... | @@ -7352,34 +7428,61 @@ fn genMulDivBinOp( |
| 7352 | const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx }); | 7428 | const reg_locks = self.register_manager.lockRegsAssumeUnused(2, .{ .rax, .rdx }); |
| 7353 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); | 7429 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| 7354 | | 7430 | |
| | 7431 | const mat_lhs_mcv = switch (lhs_mcv) { |
| | 7432 | .load_symbol => mat_lhs_mcv: { |
| | 7433 | // TODO clean this up! |
| | 7434 | const addr_reg = try self.copyToTmpRegister(Type.usize, lhs_mcv.address()); |
| | 7435 | break :mat_lhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 7436 | }, |
| | 7437 | else => lhs_mcv, |
| | 7438 | }; |
| | 7439 | const mat_lhs_lock = switch (mat_lhs_mcv) { |
| | 7440 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 7441 | else => null, |
| | 7442 | }; |
| | 7443 | defer if (mat_lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7444 | const mat_rhs_mcv = switch (rhs_mcv) { |
| | 7445 | .load_symbol => mat_rhs_mcv: { |
| | 7446 | // TODO clean this up! |
| | 7447 | const addr_reg = try self.copyToTmpRegister(Type.usize, rhs_mcv.address()); |
| | 7448 | break :mat_rhs_mcv MCValue{ .indirect = .{ .reg = addr_reg } }; |
| | 7449 | }, |
| | 7450 | else => rhs_mcv, |
| | 7451 | }; |
| | 7452 | const mat_rhs_lock = switch (mat_rhs_mcv) { |
| | 7453 | .indirect => |reg_off| self.register_manager.lockReg(reg_off.reg), |
| | 7454 | else => null, |
| | 7455 | }; |
| | 7456 | defer if (mat_rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| | 7457 | |
| 7355 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); | 7458 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 7356 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7459 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7357 | defer self.register_manager.unlockReg(tmp_lock); | 7460 | defer self.register_manager.unlockReg(tmp_lock); |
| 7358 | | 7461 | |
| 7359 | if (lhs_mcv.isMemory()) | 7462 | if (mat_lhs_mcv.isMemory()) |
| 7360 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, lhs_mcv.mem(.qword)) | 7463 | try self.asmRegisterMemory(.{ ._, .mov }, .rax, mat_lhs_mcv.mem(.qword)) |
| 7361 | else | 7464 | else |
| 7362 | try self.asmRegisterRegister(.{ ._, .mov }, .rax, lhs_mcv.register_pair[0]); | 7465 | try self.asmRegisterRegister(.{ ._, .mov }, .rax, mat_lhs_mcv.register_pair[0]); |
| 7363 | if (rhs_mcv.isMemory()) try self.asmRegisterMemory( | 7466 | if (mat_rhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 7364 | .{ ._, .mov }, | 7467 | .{ ._, .mov }, |
| 7365 | tmp_reg, | 7468 | tmp_reg, |
| 7366 | rhs_mcv.address().offset(8).deref().mem(.qword), | 7469 | mat_rhs_mcv.address().offset(8).deref().mem(.qword), |
| 7367 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, rhs_mcv.register_pair[1]); | 7470 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_rhs_mcv.register_pair[1]); |
| 7368 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax); | 7471 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, .rax); |
| 7369 | if (rhs_mcv.isMemory()) | 7472 | if (mat_rhs_mcv.isMemory()) |
| 7370 | try self.asmMemory(.{ ._, .mul }, rhs_mcv.mem(.qword)) | 7473 | try self.asmMemory(.{ ._, .mul }, mat_rhs_mcv.mem(.qword)) |
| 7371 | else | 7474 | else |
| 7372 | try self.asmRegister(.{ ._, .mul }, rhs_mcv.register_pair[0]); | 7475 | try self.asmRegister(.{ ._, .mul }, mat_rhs_mcv.register_pair[0]); |
| 7373 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); | 7476 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); |
| 7374 | if (lhs_mcv.isMemory()) try self.asmRegisterMemory( | 7477 | if (mat_lhs_mcv.isMemory()) try self.asmRegisterMemory( |
| 7375 | .{ ._, .mov }, | 7478 | .{ ._, .mov }, |
| 7376 | tmp_reg, | 7479 | tmp_reg, |
| 7377 | lhs_mcv.address().offset(8).deref().mem(.qword), | 7480 | mat_lhs_mcv.address().offset(8).deref().mem(.qword), |
| 7378 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, lhs_mcv.register_pair[1]); | 7481 | ) else try self.asmRegisterRegister(.{ ._, .mov }, tmp_reg, mat_lhs_mcv.register_pair[1]); |
| 7379 | if (rhs_mcv.isMemory()) | 7482 | if (mat_rhs_mcv.isMemory()) |
| 7380 | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, rhs_mcv.mem(.qword)) | 7483 | try self.asmRegisterMemory(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.mem(.qword)) |
| 7381 | else | 7484 | else |
| 7382 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, rhs_mcv.register_pair[0]); | 7485 | try self.asmRegisterRegister(.{ .i_, .mul }, tmp_reg, mat_rhs_mcv.register_pair[0]); |
| 7383 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); | 7486 | try self.asmRegisterRegister(.{ ._, .add }, .rdx, tmp_reg); |
| 7384 | return .{ .register_pair = .{ .rax, .rdx } }; | 7487 | return .{ .register_pair = .{ .rax, .rdx } }; |
| 7385 | } | 7488 | } |
| ... | @@ -7968,12 +8071,12 @@ fn genBinOp( | ... | @@ -7968,12 +8071,12 @@ fn genBinOp( |
| 7968 | .immediate, | 8071 | .immediate, |
| 7969 | .eflags, | 8072 | .eflags, |
| 7970 | .register_offset, | 8073 | .register_offset, |
| | 8074 | .load_symbol, |
| | 8075 | .lea_symbol, |
| 7971 | .load_direct, | 8076 | .load_direct, |
| 7972 | .lea_direct, | 8077 | .lea_direct, |
| 7973 | .load_got, | 8078 | .load_got, |
| 7974 | .lea_got, | 8079 | .lea_got, |
| 7975 | .load_extern_got, | | |
| 7976 | .lea_extern_got, | | |
| 7977 | .load_tlv, | 8080 | .load_tlv, |
| 7978 | .lea_tlv, | 8081 | .lea_tlv, |
| 7979 | .lea_frame, | 8082 | .lea_frame, |
| ... | @@ -8026,12 +8129,12 @@ fn genBinOp( | ... | @@ -8026,12 +8129,12 @@ fn genBinOp( |
| 8026 | .register_pair, | 8129 | .register_pair, |
| 8027 | .register_offset, | 8130 | .register_offset, |
| 8028 | .register_overflow, | 8131 | .register_overflow, |
| | 8132 | .load_symbol, |
| | 8133 | .lea_symbol, |
| 8029 | .load_direct, | 8134 | .load_direct, |
| 8030 | .lea_direct, | 8135 | .lea_direct, |
| 8031 | .load_got, | 8136 | .load_got, |
| 8032 | .lea_got, | 8137 | .lea_got, |
| 8033 | .load_extern_got, | | |
| 8034 | .lea_extern_got, | | |
| 8035 | .load_tlv, | 8138 | .load_tlv, |
| 8036 | .lea_tlv, | 8139 | .lea_tlv, |
| 8037 | .lea_frame, | 8140 | .lea_frame, |
| ... | @@ -9159,9 +9262,9 @@ fn genBinOpMir( | ... | @@ -9159,9 +9262,9 @@ fn genBinOpMir( |
| 9159 | .register_overflow, | 9262 | .register_overflow, |
| 9160 | .lea_direct, | 9263 | .lea_direct, |
| 9161 | .lea_got, | 9264 | .lea_got, |
| 9162 | .lea_extern_got, | | |
| 9163 | .lea_tlv, | 9265 | .lea_tlv, |
| 9164 | .lea_frame, | 9266 | .lea_frame, |
| | 9267 | .lea_symbol, |
| 9165 | .reserved_frame, | 9268 | .reserved_frame, |
| 9166 | .air_ref, | 9269 | .air_ref, |
| 9167 | => unreachable, // unmodifiable destination | 9270 | => unreachable, // unmodifiable destination |
| ... | @@ -9244,12 +9347,12 @@ fn genBinOpMir( | ... | @@ -9244,12 +9347,12 @@ fn genBinOpMir( |
| 9244 | .register_offset, | 9347 | .register_offset, |
| 9245 | .memory, | 9348 | .memory, |
| 9246 | .indirect, | 9349 | .indirect, |
| | 9350 | .load_symbol, |
| | 9351 | .lea_symbol, |
| 9247 | .load_direct, | 9352 | .load_direct, |
| 9248 | .lea_direct, | 9353 | .lea_direct, |
| 9249 | .load_got, | 9354 | .load_got, |
| 9250 | .lea_got, | 9355 | .lea_got, |
| 9251 | .load_extern_got, | | |
| 9252 | .lea_extern_got, | | |
| 9253 | .load_tlv, | 9356 | .load_tlv, |
| 9254 | .lea_tlv, | 9357 | .lea_tlv, |
| 9255 | .load_frame, | 9358 | .load_frame, |
| ... | @@ -9280,9 +9383,9 @@ fn genBinOpMir( | ... | @@ -9280,9 +9383,9 @@ fn genBinOpMir( |
| 9280 | switch (src_mcv) { | 9383 | switch (src_mcv) { |
| 9281 | .eflags, | 9384 | .eflags, |
| 9282 | .register_offset, | 9385 | .register_offset, |
| | 9386 | .lea_symbol, |
| 9283 | .lea_direct, | 9387 | .lea_direct, |
| 9284 | .lea_got, | 9388 | .lea_got, |
| 9285 | .lea_extern_got, | | |
| 9286 | .lea_tlv, | 9389 | .lea_tlv, |
| 9287 | .lea_frame, | 9390 | .lea_frame, |
| 9288 | => { | 9391 | => { |
| ... | @@ -9296,9 +9399,9 @@ fn genBinOpMir( | ... | @@ -9296,9 +9399,9 @@ fn genBinOpMir( |
| 9296 | ); | 9399 | ); |
| 9297 | }, | 9400 | }, |
| 9298 | .memory, | 9401 | .memory, |
| | 9402 | .load_symbol, |
| 9299 | .load_direct, | 9403 | .load_direct, |
| 9300 | .load_got, | 9404 | .load_got, |
| 9301 | .load_extern_got, | | |
| 9302 | .load_tlv, | 9405 | .load_tlv, |
| 9303 | => { | 9406 | => { |
| 9304 | const ptr_ty = try mod.singleConstPtrType(ty); | 9407 | const ptr_ty = try mod.singleConstPtrType(ty); |
| ... | @@ -9319,13 +9422,13 @@ fn genBinOpMir( | ... | @@ -9319,13 +9422,13 @@ fn genBinOpMir( |
| 9319 | } | 9422 | } |
| 9320 | } | 9423 | } |
| 9321 | }, | 9424 | }, |
| 9322 | .memory, .indirect, .load_got, .load_extern_got, .load_direct, .load_tlv, .load_frame => { | 9425 | .memory, .indirect, .load_symbol, .load_got, .load_direct, .load_tlv, .load_frame => { |
| 9323 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; | 9426 | const OpInfo = ?struct { addr_reg: Register, addr_lock: RegisterLock }; |
| 9324 | const limb_abi_size: u32 = @min(abi_size, 8); | 9427 | const limb_abi_size: u32 = @min(abi_size, 8); |
| 9325 | | 9428 | |
| 9326 | const dst_info: OpInfo = switch (dst_mcv) { | 9429 | const dst_info: OpInfo = switch (dst_mcv) { |
| 9327 | else => unreachable, | 9430 | else => unreachable, |
| 9328 | .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => dst: { | 9431 | .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: { |
| 9329 | const dst_addr_reg = | 9432 | const dst_addr_reg = |
| 9330 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); | 9433 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 9331 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); | 9434 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| ... | @@ -9359,17 +9462,17 @@ fn genBinOpMir( | ... | @@ -9359,17 +9462,17 @@ fn genBinOpMir( |
| 9359 | .indirect, | 9462 | .indirect, |
| 9360 | .lea_direct, | 9463 | .lea_direct, |
| 9361 | .lea_got, | 9464 | .lea_got, |
| 9362 | .lea_extern_got, | | |
| 9363 | .lea_tlv, | 9465 | .lea_tlv, |
| 9364 | .load_frame, | 9466 | .load_frame, |
| 9365 | .lea_frame, | 9467 | .lea_frame, |
| | 9468 | .lea_symbol, |
| 9366 | => null, | 9469 | => null, |
| 9367 | .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => src: { | 9470 | .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: { |
| 9368 | switch (resolved_src_mcv) { | 9471 | switch (resolved_src_mcv) { |
| 9369 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and | 9472 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr))) != null and |
| 9370 | math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null) | 9473 | math.cast(i32, @as(i64, @bitCast(addr)) + abi_size - limb_abi_size) != null) |
| 9371 | break :src null, | 9474 | break :src null, |
| 9372 | .load_got, .load_extern_got, .load_direct, .load_tlv => {}, | 9475 | .load_symbol, .load_got, .load_direct, .load_tlv => {}, |
| 9373 | else => unreachable, | 9476 | else => unreachable, |
| 9374 | } | 9477 | } |
| 9375 | | 9478 | |
| ... | @@ -9411,8 +9514,8 @@ fn genBinOpMir( | ... | @@ -9411,8 +9514,8 @@ fn genBinOpMir( |
| 9411 | Memory.PtrSize.fromSize(limb_abi_size), | 9514 | Memory.PtrSize.fromSize(limb_abi_size), |
| 9412 | switch (dst_mcv) { | 9515 | switch (dst_mcv) { |
| 9413 | .memory, | 9516 | .memory, |
| | 9517 | .load_symbol, |
| 9414 | .load_got, | 9518 | .load_got, |
| 9415 | .load_extern_got, | | |
| 9416 | .load_direct, | 9519 | .load_direct, |
| 9417 | .load_tlv, | 9520 | .load_tlv, |
| 9418 | => .{ .base = .{ .reg = dst_info.?.addr_reg }, .disp = off }, | 9521 | => .{ .base = .{ .reg = dst_info.?.addr_reg }, .disp = off }, |
| ... | @@ -9493,12 +9596,12 @@ fn genBinOpMir( | ... | @@ -9493,12 +9596,12 @@ fn genBinOpMir( |
| 9493 | .eflags, | 9596 | .eflags, |
| 9494 | .memory, | 9597 | .memory, |
| 9495 | .indirect, | 9598 | .indirect, |
| | 9599 | .load_symbol, |
| | 9600 | .lea_symbol, |
| 9496 | .load_direct, | 9601 | .load_direct, |
| 9497 | .lea_direct, | 9602 | .lea_direct, |
| 9498 | .load_got, | 9603 | .load_got, |
| 9499 | .lea_got, | 9604 | .lea_got, |
| 9500 | .load_extern_got, | | |
| 9501 | .lea_extern_got, | | |
| 9502 | .load_tlv, | 9605 | .load_tlv, |
| 9503 | .lea_tlv, | 9606 | .lea_tlv, |
| 9504 | .load_frame, | 9607 | .load_frame, |
| ... | @@ -9512,9 +9615,9 @@ fn genBinOpMir( | ... | @@ -9512,9 +9615,9 @@ fn genBinOpMir( |
| 9512 | }, | 9615 | }, |
| 9513 | .eflags, | 9616 | .eflags, |
| 9514 | .register_offset, | 9617 | .register_offset, |
| | 9618 | .lea_symbol, |
| 9515 | .lea_direct, | 9619 | .lea_direct, |
| 9516 | .lea_got, | 9620 | .lea_got, |
| 9517 | .lea_extern_got, | | |
| 9518 | .lea_tlv, | 9621 | .lea_tlv, |
| 9519 | .lea_frame, | 9622 | .lea_frame, |
| 9520 | => switch (limb_i) { | 9623 | => switch (limb_i) { |
| ... | @@ -9563,9 +9666,9 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -9563,9 +9666,9 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 9563 | .eflags, | 9666 | .eflags, |
| 9564 | .register_offset, | 9667 | .register_offset, |
| 9565 | .register_overflow, | 9668 | .register_overflow, |
| | 9669 | .lea_symbol, |
| 9566 | .lea_direct, | 9670 | .lea_direct, |
| 9567 | .lea_got, | 9671 | .lea_got, |
| 9568 | .lea_extern_got, | | |
| 9569 | .lea_tlv, | 9672 | .lea_tlv, |
| 9570 | .lea_frame, | 9673 | .lea_frame, |
| 9571 | .reserved_frame, | 9674 | .reserved_frame, |
| ... | @@ -9610,12 +9713,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -9610,12 +9713,12 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 9610 | }, | 9713 | }, |
| 9611 | .register_offset, | 9714 | .register_offset, |
| 9612 | .eflags, | 9715 | .eflags, |
| | 9716 | .load_symbol, |
| | 9717 | .lea_symbol, |
| 9613 | .load_direct, | 9718 | .load_direct, |
| 9614 | .lea_direct, | 9719 | .lea_direct, |
| 9615 | .load_got, | 9720 | .load_got, |
| 9616 | .lea_got, | 9721 | .lea_got, |
| 9617 | .load_extern_got, | | |
| 9618 | .lea_extern_got, | | |
| 9619 | .load_tlv, | 9722 | .load_tlv, |
| 9620 | .lea_tlv, | 9723 | .lea_tlv, |
| 9621 | .lea_frame, | 9724 | .lea_frame, |
| ... | @@ -9654,7 +9757,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M | ... | @@ -9654,7 +9757,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M |
| 9654 | } | 9757 | } |
| 9655 | }, | 9758 | }, |
| 9656 | .register_pair => unreachable, // unimplemented | 9759 | .register_pair => unreachable, // unimplemented |
| 9657 | .memory, .indirect, .load_direct, .load_got, .load_extern_got, .load_tlv, .load_frame => { | 9760 | .memory, .indirect, .load_symbol, .load_direct, .load_got, .load_tlv, .load_frame => { |
| 9658 | const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); | 9761 | const tmp_reg = try self.copyToTmpRegister(dst_ty, dst_mcv); |
| 9659 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 9762 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 9660 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 9763 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | @@ -9674,17 +9777,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -9674,17 +9777,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 9674 | self.arg_index = arg_index + 1; | 9777 | self.arg_index = arg_index + 1; |
| 9675 | | 9778 | |
| 9676 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { | 9779 | const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: { |
| 9677 | const dst_mcv = self.args[arg_index]; | 9780 | const arg_ty = self.typeOfIndex(inst); |
| 9678 | switch (dst_mcv) { | 9781 | const src_mcv = self.args[arg_index]; |
| 9679 | .register, .register_pair, .load_frame => for (dst_mcv.getRegs()) |reg| | 9782 | const dst_mcv = switch (src_mcv) { |
| 9680 | self.register_manager.getRegAssumeFree(reg, inst), | 9783 | .register, .register_pair, .load_frame => dst: { |
| 9681 | else => return self.fail("TODO implement arg for {}", .{dst_mcv}), | 9784 | for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst); |
| 9682 | } | 9785 | break :dst src_mcv; |
| | 9786 | }, |
| | 9787 | .indirect => |reg_off| dst: { |
| | 9788 | self.register_manager.getRegAssumeFree(reg_off.reg, inst); |
| | 9789 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| | 9790 | try self.genCopy(arg_ty, dst_mcv, src_mcv); |
| | 9791 | break :dst dst_mcv; |
| | 9792 | }, |
| | 9793 | else => return self.fail("TODO implement arg for {}", .{src_mcv}), |
| | 9794 | }; |
| 9683 | | 9795 | |
| 9684 | const ty = self.typeOfIndex(inst); | | |
| 9685 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 9796 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; |
| 9686 | const name = mod.getParamName(self.owner.func_index, src_index); | 9797 | const name = mod.getParamName(self.owner.func_index, src_index); |
| 9687 | try self.genArgDbgInfo(ty, name, dst_mcv); | 9798 | try self.genArgDbgInfo(arg_ty, name, src_mcv); |
| 9688 | | 9799 | |
| 9689 | break :result dst_mcv; | 9800 | break :result dst_mcv; |
| 9690 | }; | 9801 | }; |
| ... | @@ -9746,8 +9857,8 @@ fn genVarDbgInfo( | ... | @@ -9746,8 +9857,8 @@ fn genVarDbgInfo( |
| 9746 | // .offset = -off, | 9857 | // .offset = -off, |
| 9747 | //} }, | 9858 | //} }, |
| 9748 | .memory => |address| .{ .memory = address }, | 9859 | .memory => |address| .{ .memory = address }, |
| | 9860 | .load_symbol => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, // TODO |
| 9749 | .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } }, | 9861 | .load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } }, |
| 9750 | .load_extern_got => |sym_index| .{ .linker_load = .{ .type = .extern_got, .sym_index = sym_index } }, | | |
| 9751 | .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, | 9862 | .load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } }, |
| 9752 | .immediate => |x| .{ .immediate = x }, | 9863 | .immediate => |x| .{ .immediate = x }, |
| 9753 | .undef => .undef, | 9864 | .undef => .undef, |
| ... | @@ -9863,7 +9974,8 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -9863,7 +9974,8 @@ fn genCall(self: *Self, info: union(enum) { |
| 9863 | | 9974 | |
| 9864 | const ExpectedContents = extern struct { | 9975 | const ExpectedContents = extern struct { |
| 9865 | var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)), | 9976 | var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)), |
| 9866 | arg_regs: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)), | 9977 | frame_indices: [16]FrameIndex, |
| | 9978 | reg_locks: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)), |
| 9867 | }; | 9979 | }; |
| 9868 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = | 9980 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = |
| 9869 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); | 9981 | std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| ... | @@ -9873,10 +9985,13 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -9873,10 +9985,13 @@ fn genCall(self: *Self, info: union(enum) { |
| 9873 | defer allocator.free(var_args); | 9985 | defer allocator.free(var_args); |
| 9874 | for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty; | 9986 | for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty; |
| 9875 | | 9987 | |
| 9876 | var arg_locks = std.ArrayList(?RegisterLock).init(allocator); | 9988 | const frame_indices = try allocator.alloc(FrameIndex, args.len); |
| 9877 | defer arg_locks.deinit(); | 9989 | defer allocator.free(frame_indices); |
| 9878 | try arg_locks.ensureTotalCapacity(16); | 9990 | |
| 9879 | defer for (arg_locks.items) |arg_lock| if (arg_lock) |lock| self.register_manager.unlockReg(lock); | 9991 | var reg_locks = std.ArrayList(?RegisterLock).init(allocator); |
| | 9992 | defer reg_locks.deinit(); |
| | 9993 | try reg_locks.ensureTotalCapacity(16); |
| | 9994 | defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock); |
| 9880 | | 9995 | |
| 9881 | var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame); | 9996 | var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame); |
| 9882 | defer call_info.deinit(self); | 9997 | defer call_info.deinit(self); |
| ... | @@ -9908,44 +10023,69 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -9908,44 +10023,69 @@ fn genCall(self: *Self, info: union(enum) { |
| 9908 | .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}), | 10023 | .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}), |
| 9909 | else => unreachable, | 10024 | else => unreachable, |
| 9910 | } | 10025 | } |
| 9911 | for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) { | 10026 | for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index| |
| 9912 | .none => {}, | 10027 | switch (dst_arg) { |
| 9913 | .register => |reg| { | 10028 | .none => {}, |
| 9914 | try self.spillRegisters(&.{reg}); | 10029 | .register => |reg| { |
| 9915 | try arg_locks.append(self.register_manager.lockReg(reg)); | 10030 | try self.spillRegisters(&.{reg}); |
| 9916 | }, | 10031 | try reg_locks.append(self.register_manager.lockReg(reg)); |
| 9917 | .register_pair => |regs| { | 10032 | }, |
| 9918 | try self.spillRegisters(&regs); | 10033 | .register_pair => |regs| { |
| 9919 | try arg_locks.appendSlice(&self.register_manager.lockRegs(2, regs)); | 10034 | try self.spillRegisters(&regs); |
| 9920 | }, | 10035 | try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs)); |
| 9921 | .load_frame => { | 10036 | }, |
| 9922 | try self.genCopy(arg_ty, dst_arg, src_arg); | 10037 | .indirect => |reg_off| { |
| 9923 | try self.freeValue(src_arg); | 10038 | frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod)); |
| 9924 | }, | 10039 | try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg); |
| 9925 | else => unreachable, | 10040 | try self.spillRegisters(&.{reg_off.reg}); |
| 9926 | }; | 10041 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| | 10042 | }, |
| | 10043 | .load_frame => { |
| | 10044 | try self.genCopy(arg_ty, dst_arg, src_arg); |
| | 10045 | try self.freeValue(src_arg); |
| | 10046 | }, |
| | 10047 | else => unreachable, |
| | 10048 | }; |
| 9927 | | 10049 | |
| 9928 | // now we are free to set register arguments | 10050 | // now we are free to set register arguments |
| 9929 | const ret_lock = switch (call_info.return_value.long) { | 10051 | switch (call_info.return_value.long) { |
| 9930 | .none, .unreach => null, | 10052 | .none, .unreach => {}, |
| 9931 | .indirect => |reg_off| lock: { | 10053 | .indirect => |reg_off| { |
| 9932 | const ret_ty = fn_info.return_type.toType(); | 10054 | const ret_ty = fn_info.return_type.toType(); |
| 9933 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod)); | 10055 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod)); |
| 9934 | try self.genSetReg(reg_off.reg, Type.usize, .{ | 10056 | try self.genSetReg(reg_off.reg, Type.usize, .{ |
| 9935 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, | 10057 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| 9936 | }); | 10058 | }); |
| 9937 | call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; | 10059 | call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } }; |
| 9938 | break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg); | 10060 | try reg_locks.append(self.register_manager.lockReg(reg_off.reg)); |
| 9939 | }, | 10061 | }, |
| 9940 | else => unreachable, | 10062 | else => unreachable, |
| 9941 | }; | 10063 | } |
| 9942 | defer if (ret_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 9943 | | 10064 | |
| 9944 | for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) { | 10065 | for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| |
| 9945 | .none, .load_frame => {}, | 10066 | switch (dst_arg) { |
| 9946 | .register, .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg), | 10067 | .none, .load_frame => {}, |
| 9947 | else => unreachable, | 10068 | .register => |dst_reg| switch (fn_info.cc) { |
| 9948 | }; | 10069 | else => try self.genSetReg( |
| | 10070 | registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))), |
| | 10071 | arg_ty, |
| | 10072 | src_arg, |
| | 10073 | ), |
| | 10074 | .C, .SysV, .Win64 => { |
| | 10075 | const promoted_ty = self.promoteInt(arg_ty); |
| | 10076 | const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod)); |
| | 10077 | const dst_alias = registerAlias(dst_reg, promoted_abi_size); |
| | 10078 | try self.genSetReg(dst_alias, promoted_ty, src_arg); |
| | 10079 | if (promoted_ty.toIntern() != arg_ty.toIntern()) |
| | 10080 | try self.truncateRegister(arg_ty, dst_alias); |
| | 10081 | }, |
| | 10082 | }, |
| | 10083 | .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg), |
| | 10084 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{ |
| | 10085 | .lea_frame = .{ .index = frame_index, .off = -reg_off.off }, |
| | 10086 | }), |
| | 10087 | else => unreachable, |
| | 10088 | }; |
| 9949 | | 10089 | |
| 9950 | if (fn_info.is_var_args) | 10090 | if (fn_info.is_var_args) |
| 9951 | try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count)); | 10091 | try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count)); |
| ... | @@ -9969,12 +10109,12 @@ fn genCall(self: *Self, info: union(enum) { | ... | @@ -9969,12 +10109,12 @@ fn genCall(self: *Self, info: union(enum) { |
| 9969 | const sym = elf_file.symbol(sym_index); | 10109 | const sym = elf_file.symbol(sym_index); |
| 9970 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | 10110 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 9971 | if (self.bin_file.options.pic) { | 10111 | if (self.bin_file.options.pic) { |
| 9972 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym.esym_index }); | 10112 | try self.genSetReg(.rax, Type.usize, .{ .load_symbol = sym.esym_index }); |
| 9973 | try self.asmRegister(.{ ._, .call }, .rax); | 10113 | try self.asmRegister(.{ ._, .call }, .rax); |
| 9974 | } else { | 10114 | } else { |
| 9975 | _ = try self.addInst(.{ | 10115 | _ = try self.addInst(.{ |
| 9976 | .tag = .call, | 10116 | .tag = .call, |
| 9977 | .ops = .direct_got_reloc, | 10117 | .ops = .linker_reloc, |
| 9978 | .data = .{ .reloc = .{ | 10118 | .data = .{ .reloc = .{ |
| 9979 | .atom_index = try self.owner.getSymbolIndex(self), | 10119 | .atom_index = try self.owner.getSymbolIndex(self), |
| 9980 | .sym_index = sym.esym_index, | 10120 | .sym_index = sym.esym_index, |
| ... | @@ -10054,7 +10194,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10054,7 +10194,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 10054 | const ptr_ty = self.typeOf(un_op); | 10194 | const ptr_ty = self.typeOf(un_op); |
| 10055 | switch (self.ret_mcv.short) { | 10195 | switch (self.ret_mcv.short) { |
| 10056 | .none => {}, | 10196 | .none => {}, |
| 10057 | .register => try self.load(self.ret_mcv.short, ptr_ty, ptr), | 10197 | .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr), |
| 10058 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), | 10198 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), |
| 10059 | else => unreachable, | 10199 | else => unreachable, |
| 10060 | } | 10200 | } |
| ... | @@ -10115,20 +10255,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10115,20 +10255,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10115 | try self.spillEflagsIfOccupied(); | 10255 | try self.spillEflagsIfOccupied(); |
| 10116 | | 10256 | |
| 10117 | const lhs_mcv = try self.resolveInst(bin_op.lhs); | 10257 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 10118 | const lhs_lock = switch (lhs_mcv) { | 10258 | const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) { |
| 10119 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), | 10259 | .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null }, |
| 10120 | .register_offset => |ro| self.register_manager.lockRegAssumeUnused(ro.reg), | 10260 | .register_pair => |lhs_regs| locks: { |
| 10121 | else => null, | 10261 | const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs); |
| | 10262 | break :locks .{ locks[0], locks[1] }; |
| | 10263 | }, |
| | 10264 | .register_offset => |lhs_ro| .{ |
| | 10265 | self.register_manager.lockRegAssumeUnused(lhs_ro.reg), |
| | 10266 | null, |
| | 10267 | }, |
| | 10268 | else => .{null} ** 2, |
| 10122 | }; | 10269 | }; |
| 10123 | defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); | 10270 | defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 10124 | | 10271 | |
| 10125 | const rhs_mcv = try self.resolveInst(bin_op.rhs); | 10272 | const rhs_mcv = try self.resolveInst(bin_op.rhs); |
| 10126 | const rhs_lock = switch (rhs_mcv) { | 10273 | const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) { |
| 10127 | .register => |reg| self.register_manager.lockReg(reg), | 10274 | .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null }, |
| 10128 | .register_offset => |ro| self.register_manager.lockReg(ro.reg), | 10275 | .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs), |
| 10129 | else => null, | 10276 | .register_offset => |rhs_ro| .{ self.register_manager.lockReg(rhs_ro.reg), null }, |
| | 10277 | else => .{null} ** 2, |
| 10130 | }; | 10278 | }; |
| 10131 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 10279 | defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 10132 | | 10280 | |
| 10133 | switch (ty.zigTypeTag(mod)) { | 10281 | switch (ty.zigTypeTag(mod)) { |
| 10134 | else => { | 10282 | else => { |
| ... | @@ -10159,7 +10307,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10159,7 +10307,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10159 | if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 10307 | if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 10160 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 10308 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 10161 | | 10309 | |
| 10162 | const src_mcv = if (flipped) lhs_mcv else rhs_mcv; | 10310 | const src_mcv = try self.resolveInst(if (flipped) bin_op.lhs else bin_op.rhs); |
| 10163 | const src_lock = | 10311 | const src_lock = |
| 10164 | if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 10312 | if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 10165 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 10313 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | @@ -10191,14 +10339,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10191,14 +10339,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10191 | .indirect, | 10339 | .indirect, |
| 10192 | .lea_direct, | 10340 | .lea_direct, |
| 10193 | .lea_got, | 10341 | .lea_got, |
| 10194 | .lea_extern_got, | | |
| 10195 | .lea_tlv, | 10342 | .lea_tlv, |
| 10196 | .lea_frame, | 10343 | .lea_frame, |
| | 10344 | .lea_symbol, |
| 10197 | .reserved_frame, | 10345 | .reserved_frame, |
| 10198 | .air_ref, | 10346 | .air_ref, |
| 10199 | => unreachable, | 10347 | => unreachable, |
| 10200 | .register_pair, .load_frame => null, | 10348 | .register_pair, .load_frame => null, |
| 10201 | .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => dst: { | 10349 | .memory, .load_symbol, .load_got, .load_direct, .load_tlv => dst: { |
| 10202 | switch (resolved_dst_mcv) { | 10350 | switch (resolved_dst_mcv) { |
| 10203 | .memory => |addr| if (math.cast( | 10351 | .memory => |addr| if (math.cast( |
| 10204 | i32, | 10352 | i32, |
| ... | @@ -10207,7 +10355,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10207,7 +10355,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10207 | i32, | 10355 | i32, |
| 10208 | @as(i64, @bitCast(addr)) + abi_size - 8, | 10356 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 10209 | ) != null) break :dst null, | 10357 | ) != null) break :dst null, |
| 10210 | .load_got, .load_extern_got, .load_direct, .load_tlv => {}, | 10358 | .load_symbol, .load_got, .load_direct, .load_tlv => {}, |
| 10211 | else => unreachable, | 10359 | else => unreachable, |
| 10212 | } | 10360 | } |
| 10213 | | 10361 | |
| ... | @@ -10248,16 +10396,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10248,16 +10396,16 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10248 | .register_offset, | 10396 | .register_offset, |
| 10249 | .register_overflow, | 10397 | .register_overflow, |
| 10250 | .indirect, | 10398 | .indirect, |
| | 10399 | .lea_symbol, |
| 10251 | .lea_direct, | 10400 | .lea_direct, |
| 10252 | .lea_got, | 10401 | .lea_got, |
| 10253 | .lea_extern_got, | | |
| 10254 | .lea_tlv, | 10402 | .lea_tlv, |
| 10255 | .lea_frame, | 10403 | .lea_frame, |
| 10256 | .reserved_frame, | 10404 | .reserved_frame, |
| 10257 | .air_ref, | 10405 | .air_ref, |
| 10258 | => unreachable, | 10406 | => unreachable, |
| 10259 | .register_pair, .load_frame => null, | 10407 | .register_pair, .load_frame => null, |
| 10260 | .memory, .load_got, .load_extern_got, .load_direct, .load_tlv => src: { | 10408 | .memory, .load_symbol, .load_got, .load_direct, .load_tlv => src: { |
| 10261 | switch (resolved_src_mcv) { | 10409 | switch (resolved_src_mcv) { |
| 10262 | .memory => |addr| if (math.cast( | 10410 | .memory => |addr| if (math.cast( |
| 10263 | i32, | 10411 | i32, |
| ... | @@ -10266,7 +10414,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10266,7 +10414,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10266 | i32, | 10414 | i32, |
| 10267 | @as(i64, @bitCast(addr)) + abi_size - 8, | 10415 | @as(i64, @bitCast(addr)) + abi_size - 8, |
| 10268 | ) != null) break :src null, | 10416 | ) != null) break :src null, |
| 10269 | .load_got, .load_extern_got, .load_direct, .load_tlv => {}, | 10417 | .load_symbol, .load_got, .load_direct, .load_tlv => {}, |
| 10270 | else => unreachable, | 10418 | else => unreachable, |
| 10271 | } | 10419 | } |
| 10272 | | 10420 | |
| ... | @@ -10350,13 +10498,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | ... | @@ -10350,13 +10498,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 10350 | }, | 10498 | }, |
| 10351 | ); | 10499 | ); |
| 10352 | | 10500 | |
| 10353 | if (limb_i > 0) try self.asmRegisterRegister( | 10501 | if (limb_i > 0) |
| 10354 | .{ ._, .@"or" }, | 10502 | try self.asmRegisterRegister(.{ ._, .@"or" }, acc_reg, tmp_reg); |
| 10355 | acc_reg, | | |
| 10356 | tmp_reg, | | |
| 10357 | ); | | |
| 10358 | } | 10503 | } |
| 10359 | try self.asmRegisterRegister(.{ ._, .@"test" }, acc_reg, acc_reg); | 10504 | assert(limbs_len >= 2); // use flags from or |
| 10360 | break :result_op flipped_op; | 10505 | break :result_op flipped_op; |
| 10361 | }, | 10506 | }, |
| 10362 | }; | 10507 | }; |
| ... | @@ -10692,9 +10837,9 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -10692,9 +10837,9 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 10692 | .register_overflow, | 10837 | .register_overflow, |
| 10693 | .lea_direct, | 10838 | .lea_direct, |
| 10694 | .lea_got, | 10839 | .lea_got, |
| 10695 | .lea_extern_got, | | |
| 10696 | .lea_tlv, | 10840 | .lea_tlv, |
| 10697 | .lea_frame, | 10841 | .lea_frame, |
| | 10842 | .lea_symbol, |
| 10698 | .reserved_frame, | 10843 | .reserved_frame, |
| 10699 | .air_ref, | 10844 | .air_ref, |
| 10700 | => unreachable, | 10845 | => unreachable, |
| ... | @@ -10718,8 +10863,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC | ... | @@ -10718,8 +10863,8 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 10718 | }, | 10863 | }, |
| 10719 | | 10864 | |
| 10720 | .memory, | 10865 | .memory, |
| | 10866 | .load_symbol, |
| 10721 | .load_got, | 10867 | .load_got, |
| 10722 | .load_extern_got, | | |
| 10723 | .load_direct, | 10868 | .load_direct, |
| 10724 | .load_tlv, | 10869 | .load_tlv, |
| 10725 | => { | 10870 | => { |
| ... | @@ -11316,7 +11461,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11316,7 +11461,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 11316 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_| | 11461 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_| |
| 11317 | break :arg input_mcv, | 11462 | break :arg input_mcv, |
| 11318 | .indirect, .load_frame => break :arg input_mcv, | 11463 | .indirect, .load_frame => break :arg input_mcv, |
| 11319 | .load_direct, .load_got, .load_extern_got, .load_tlv => {}, | 11464 | .load_symbol, .load_direct, .load_got, .load_tlv => {}, |
| 11320 | else => { | 11465 | else => { |
| 11321 | const temp_mcv = try self.allocTempRegOrMem(ty, false); | 11466 | const temp_mcv = try self.allocTempRegOrMem(ty, false); |
| 11322 | try self.genCopy(ty, temp_mcv, input_mcv); | 11467 | try self.genCopy(ty, temp_mcv, input_mcv); |
| ... | @@ -11578,6 +11723,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11578,6 +11723,10 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 11578 | .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) } | 11723 | .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .lea_got = sym_index }) } |
| 11579 | else | 11724 | else |
| 11580 | return self.fail("invalid modifier: '{s}'", .{modifier}), | 11725 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| | 11726 | .load_symbol => |sym_index| if (mem.eql(u8, modifier, "P")) |
| | 11727 | .{ .reg = try self.copyToTmpRegister(Type.usize, .{ .load_symbol = sym_index }) } |
| | 11728 | else |
| | 11729 | return self.fail("invalid modifier: '{s}'", .{modifier}), |
| 11581 | else => return self.fail("invalid constraint: '{s}'", .{op_str}), | 11730 | else => return self.fail("invalid constraint: '{s}'", .{op_str}), |
| 11582 | }; | 11731 | }; |
| 11583 | } else if (mem.startsWith(u8, op_str, "$")) { | 11732 | } else if (mem.startsWith(u8, op_str, "$")) { |
| ... | @@ -11798,6 +11947,7 @@ const MoveStrategy = union(enum) { | ... | @@ -11798,6 +11947,7 @@ const MoveStrategy = union(enum) { |
| 11798 | .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem), | 11947 | .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem), |
| 11799 | .x87_load_store => { | 11948 | .x87_load_store => { |
| 11800 | try self.asmMemory(.{ .f_, .ld }, src_mem); | 11949 | try self.asmMemory(.{ .f_, .ld }, src_mem); |
| | 11950 | assert(dst_reg != .st7); |
| 11801 | try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1)); | 11951 | try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1)); |
| 11802 | }, | 11952 | }, |
| 11803 | .insert_extract => |ie| try self.asmRegisterMemoryImmediate( | 11953 | .insert_extract => |ie| try self.asmRegisterMemoryImmediate( |
| ... | @@ -11831,188 +11981,284 @@ const MoveStrategy = union(enum) { | ... | @@ -11831,188 +11981,284 @@ const MoveStrategy = union(enum) { |
| 11831 | } | 11981 | } |
| 11832 | } | 11982 | } |
| 11833 | }; | 11983 | }; |
| 11834 | fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy { | 11984 | fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy { |
| 11835 | const mod = self.bin_file.options.module.?; | 11985 | const mod = self.bin_file.options.module.?; |
| 11836 | switch (ty.zigTypeTag(mod)) { | 11986 | switch (class) { |
| 11837 | else => return .{ .move = .{ ._, .mov } }, | 11987 | .general_purpose, .segment => return .{ .move = .{ ._, .mov } }, |
| 11838 | .Float => switch (ty.floatBits(self.target.*)) { | 11988 | .x87 => return .x87_load_store, |
| 11839 | 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 11989 | .mmx => {}, |
| 11840 | .insert = .{ .vp_w, .insr }, | 11990 | .sse => { |
| 11841 | .extract = .{ .vp_w, .extr }, | 11991 | switch (ty.zigTypeTag(mod)) { |
| 11842 | } } else .{ .insert_extract = .{ | 11992 | else => { |
| 11843 | .insert = .{ .p_w, .insr }, | 11993 | const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none); |
| 11844 | .extract = .{ .p_w, .extr }, | 11994 | assert(std.mem.indexOfNone(abi.Class, classes, &.{ |
| 11845 | } }, | 11995 | .integer, .sse, .float, .float_combine, |
| 11846 | 32 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov } }, | 11996 | }) == null); |
| 11847 | 64 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov } }, | 11997 | const abi_size = ty.abiSize(mod); |
| 11848 | 80 => return .x87_load_store, | 11998 | if (abi_size < 4 or |
| 11849 | 128 => return .{ .move = if (self.hasFeature(.avx)) | 11999 | std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) { |
| 11850 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 12000 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ |
| 11851 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 12001 | .insert = .{ .vp_b, .insr }, |
| 11852 | else => {}, | 12002 | .extract = .{ .vp_b, .extr }, |
| 11853 | }, | 12003 | } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{ |
| 11854 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { | 12004 | .insert = .{ .p_b, .insr }, |
| 11855 | .Bool => return .{ .move = .{ ._, .mov } }, | 12005 | .extract = .{ .p_b, .extr }, |
| 11856 | .Int => switch (ty.childType(mod).intInfo(mod).bits) { | 12006 | } }, |
| 11857 | 8 => switch (ty.vectorLen(mod)) { | 12007 | 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| 11858 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ | 12008 | .insert = .{ .vp_w, .insr }, |
| 11859 | .insert = .{ .vp_b, .insr }, | 12009 | .extract = .{ .vp_w, .extr }, |
| 11860 | .extract = .{ .vp_b, .extr }, | 12010 | } } else .{ .insert_extract = .{ |
| 11861 | } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{ | 12011 | .insert = .{ .p_w, .insr }, |
| 11862 | .insert = .{ .p_b, .insr }, | 12012 | .extract = .{ .p_w, .extr }, |
| 11863 | .extract = .{ .p_b, .extr }, | 12013 | } }, |
| 11864 | } }, | 12014 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| 11865 | 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 12015 | .{ .v_d, .mov } |
| 11866 | .insert = .{ .vp_w, .insr }, | 12016 | else |
| 11867 | .extract = .{ .vp_w, .extr }, | 12017 | .{ ._d, .mov } }, |
| 11868 | } } else .{ .insert_extract = .{ | 12018 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) |
| 11869 | .insert = .{ .p_w, .insr }, | 12019 | .{ .v_q, .mov } |
| 11870 | .extract = .{ .p_w, .extr }, | 12020 | else |
| 11871 | } }, | 12021 | .{ ._q, .mov } }, |
| 11872 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | 12022 | 9...16 => return .{ .move = if (self.hasFeature(.avx)) |
| 11873 | .{ .v_d, .mov } | 12023 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 11874 | else | 12024 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 11875 | .{ ._d, .mov } }, | 12025 | 17...32 => if (self.hasFeature(.avx)) |
| 11876 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | 12026 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, |
| 11877 | .{ .v_q, .mov } | 12027 | else => {}, |
| 11878 | else | 12028 | } else switch (abi_size) { |
| 11879 | .{ ._q, .mov } }, | 12029 | 4 => return .{ .move = if (self.hasFeature(.avx)) |
| 11880 | 9...16 => return .{ .move = if (self.hasFeature(.avx)) | 12030 | .{ .v_ss, .mov } |
| 11881 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 12031 | else |
| 11882 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 12032 | .{ ._ss, .mov } }, |
| 11883 | 17...32 => if (self.hasFeature(.avx)) | 12033 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) |
| 11884 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | 12034 | .{ .v_sd, .mov } |
| 11885 | else => {}, | 12035 | else |
| 11886 | }, | 12036 | .{ ._sd, .mov } }, |
| 11887 | 16 => switch (ty.vectorLen(mod)) { | 12037 | 9...16 => return .{ .move = if (self.hasFeature(.avx)) |
| 11888 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | 12038 | if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } |
| 11889 | .insert = .{ .vp_w, .insr }, | 12039 | else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } }, |
| 11890 | .extract = .{ .vp_w, .extr }, | 12040 | 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned) |
| 11891 | } } else .{ .insert_extract = .{ | 12041 | .{ .v_pd, .mova } |
| 11892 | .insert = .{ .p_w, .insr }, | 12042 | else |
| 11893 | .extract = .{ .p_w, .extr }, | 12043 | .{ .v_pd, .movu } }, |
| 11894 | } }, | 12044 | else => {}, |
| 11895 | 2 => return .{ .move = if (self.hasFeature(.avx)) | 12045 | } |
| 11896 | .{ .v_d, .mov } | | |
| 11897 | else | | |
| 11898 | .{ ._d, .mov } }, | | |
| 11899 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11900 | .{ .v_q, .mov } | | |
| 11901 | else | | |
| 11902 | .{ ._q, .mov } }, | | |
| 11903 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11904 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | | |
| 11905 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | | |
| 11906 | 9...16 => if (self.hasFeature(.avx)) | | |
| 11907 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11908 | else => {}, | | |
| 11909 | }, | | |
| 11910 | 32 => switch (ty.vectorLen(mod)) { | | |
| 11911 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11912 | .{ .v_d, .mov } | | |
| 11913 | else | | |
| 11914 | .{ ._d, .mov } }, | | |
| 11915 | 2 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11916 | .{ .v_q, .mov } | | |
| 11917 | else | | |
| 11918 | .{ ._q, .mov } }, | | |
| 11919 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11920 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | | |
| 11921 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | | |
| 11922 | 5...8 => if (self.hasFeature(.avx)) | | |
| 11923 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11924 | else => {}, | | |
| 11925 | }, | | |
| 11926 | 64 => switch (ty.vectorLen(mod)) { | | |
| 11927 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11928 | .{ .v_q, .mov } | | |
| 11929 | else | | |
| 11930 | .{ ._q, .mov } }, | | |
| 11931 | 2 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11932 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | | |
| 11933 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | | |
| 11934 | 3...4 => if (self.hasFeature(.avx)) | | |
| 11935 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11936 | else => {}, | | |
| 11937 | }, | | |
| 11938 | 128 => switch (ty.vectorLen(mod)) { | | |
| 11939 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11940 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | | |
| 11941 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | | |
| 11942 | 2 => if (self.hasFeature(.avx)) | | |
| 11943 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11944 | else => {}, | | |
| 11945 | }, | | |
| 11946 | 256 => switch (ty.vectorLen(mod)) { | | |
| 11947 | 1 => if (self.hasFeature(.avx)) | | |
| 11948 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11949 | else => {}, | | |
| 11950 | }, | 12046 | }, |
| 11951 | else => {}, | 12047 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11952 | }, | 12048 | 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| 11953 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { | | |
| 11954 | 16 => switch (ty.vectorLen(mod)) { | | |
| 11955 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ | | |
| 11956 | .insert = .{ .vp_w, .insr }, | 12049 | .insert = .{ .vp_w, .insr }, |
| 11957 | .extract = .{ .vp_w, .extr }, | 12050 | .extract = .{ .vp_w, .extr }, |
| 11958 | } } else .{ .insert_extract = .{ | 12051 | } } else .{ .insert_extract = .{ |
| 11959 | .insert = .{ .p_w, .insr }, | 12052 | .insert = .{ .p_w, .insr }, |
| 11960 | .extract = .{ .p_w, .extr }, | 12053 | .extract = .{ .p_w, .extr }, |
| 11961 | } }, | 12054 | } }, |
| 11962 | 2 => return .{ .move = if (self.hasFeature(.avx)) | 12055 | 32 => return .{ .move = if (self.hasFeature(.avx)) |
| 11963 | .{ .v_d, .mov } | | |
| 11964 | else | | |
| 11965 | .{ ._d, .mov } }, | | |
| 11966 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11967 | .{ .v_q, .mov } | | |
| 11968 | else | | |
| 11969 | .{ ._q, .mov } }, | | |
| 11970 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11971 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | | |
| 11972 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | | |
| 11973 | 9...16 => if (self.hasFeature(.avx)) | | |
| 11974 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 11975 | else => {}, | | |
| 11976 | }, | | |
| 11977 | 32 => switch (ty.vectorLen(mod)) { | | |
| 11978 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11979 | .{ .v_ss, .mov } | 12056 | .{ .v_ss, .mov } |
| 11980 | else | 12057 | else |
| 11981 | .{ ._ss, .mov } }, | 12058 | .{ ._ss, .mov } }, |
| 11982 | 2 => return .{ .move = if (self.hasFeature(.avx)) | 12059 | 64 => return .{ .move = if (self.hasFeature(.avx)) |
| 11983 | .{ .v_sd, .mov } | | |
| 11984 | else | | |
| 11985 | .{ ._sd, .mov } }, | | |
| 11986 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11987 | if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } | | |
| 11988 | else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } }, | | |
| 11989 | 5...8 => if (self.hasFeature(.avx)) | | |
| 11990 | return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } }, | | |
| 11991 | else => {}, | | |
| 11992 | }, | | |
| 11993 | 64 => switch (ty.vectorLen(mod)) { | | |
| 11994 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 11995 | .{ .v_sd, .mov } | 12060 | .{ .v_sd, .mov } |
| 11996 | else | 12061 | else |
| 11997 | .{ ._sd, .mov } }, | 12062 | .{ ._sd, .mov } }, |
| 11998 | 2 => return .{ .move = if (self.hasFeature(.avx)) | 12063 | 128 => return .{ .move = if (self.hasFeature(.avx)) |
| 11999 | if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } | | |
| 12000 | else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } }, | | |
| 12001 | 3...4 => if (self.hasFeature(.avx)) | | |
| 12002 | return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } }, | | |
| 12003 | else => {}, | | |
| 12004 | }, | | |
| 12005 | 128 => switch (ty.vectorLen(mod)) { | | |
| 12006 | 1 => return .{ .move = if (self.hasFeature(.avx)) | | |
| 12007 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } | 12064 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| 12008 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, | 12065 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| 12009 | 2 => if (self.hasFeature(.avx)) | | |
| 12010 | return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } }, | | |
| 12011 | else => {}, | 12066 | else => {}, |
| 12012 | }, | 12067 | }, |
| 12013 | else => {}, | 12068 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 12014 | }, | 12069 | .Bool => return .{ .move = .{ ._, .mov } }, |
| 12015 | else => {}, | 12070 | .Int => switch (ty.childType(mod).intInfo(mod).bits) { |
| | 12071 | 8 => switch (ty.vectorLen(mod)) { |
| | 12072 | 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{ |
| | 12073 | .insert = .{ .vp_b, .insr }, |
| | 12074 | .extract = .{ .vp_b, .extr }, |
| | 12075 | } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{ |
| | 12076 | .insert = .{ .p_b, .insr }, |
| | 12077 | .extract = .{ .p_b, .extr }, |
| | 12078 | } }, |
| | 12079 | 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| | 12080 | .insert = .{ .vp_w, .insr }, |
| | 12081 | .extract = .{ .vp_w, .extr }, |
| | 12082 | } } else .{ .insert_extract = .{ |
| | 12083 | .insert = .{ .p_w, .insr }, |
| | 12084 | .extract = .{ .p_w, .extr }, |
| | 12085 | } }, |
| | 12086 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12087 | .{ .v_d, .mov } |
| | 12088 | else |
| | 12089 | .{ ._d, .mov } }, |
| | 12090 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12091 | .{ .v_q, .mov } |
| | 12092 | else |
| | 12093 | .{ ._q, .mov } }, |
| | 12094 | 9...16 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12095 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12096 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12097 | 17...32 => if (self.hasFeature(.avx)) |
| | 12098 | return .{ .move = if (aligned) |
| | 12099 | .{ .v_, .movdqa } |
| | 12100 | else |
| | 12101 | .{ .v_, .movdqu } }, |
| | 12102 | else => {}, |
| | 12103 | }, |
| | 12104 | 16 => switch (ty.vectorLen(mod)) { |
| | 12105 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| | 12106 | .insert = .{ .vp_w, .insr }, |
| | 12107 | .extract = .{ .vp_w, .extr }, |
| | 12108 | } } else .{ .insert_extract = .{ |
| | 12109 | .insert = .{ .p_w, .insr }, |
| | 12110 | .extract = .{ .p_w, .extr }, |
| | 12111 | } }, |
| | 12112 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12113 | .{ .v_d, .mov } |
| | 12114 | else |
| | 12115 | .{ ._d, .mov } }, |
| | 12116 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12117 | .{ .v_q, .mov } |
| | 12118 | else |
| | 12119 | .{ ._q, .mov } }, |
| | 12120 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12121 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12122 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12123 | 9...16 => if (self.hasFeature(.avx)) |
| | 12124 | return .{ .move = if (aligned) |
| | 12125 | .{ .v_, .movdqa } |
| | 12126 | else |
| | 12127 | .{ .v_, .movdqu } }, |
| | 12128 | else => {}, |
| | 12129 | }, |
| | 12130 | 32 => switch (ty.vectorLen(mod)) { |
| | 12131 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12132 | .{ .v_d, .mov } |
| | 12133 | else |
| | 12134 | .{ ._d, .mov } }, |
| | 12135 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12136 | .{ .v_q, .mov } |
| | 12137 | else |
| | 12138 | .{ ._q, .mov } }, |
| | 12139 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12140 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12141 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12142 | 5...8 => if (self.hasFeature(.avx)) |
| | 12143 | return .{ .move = if (aligned) |
| | 12144 | .{ .v_, .movdqa } |
| | 12145 | else |
| | 12146 | .{ .v_, .movdqu } }, |
| | 12147 | else => {}, |
| | 12148 | }, |
| | 12149 | 64 => switch (ty.vectorLen(mod)) { |
| | 12150 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12151 | .{ .v_q, .mov } |
| | 12152 | else |
| | 12153 | .{ ._q, .mov } }, |
| | 12154 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12155 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12156 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12157 | 3...4 => if (self.hasFeature(.avx)) |
| | 12158 | return .{ .move = if (aligned) |
| | 12159 | .{ .v_, .movdqa } |
| | 12160 | else |
| | 12161 | .{ .v_, .movdqu } }, |
| | 12162 | else => {}, |
| | 12163 | }, |
| | 12164 | 128 => switch (ty.vectorLen(mod)) { |
| | 12165 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12166 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12167 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12168 | 2 => if (self.hasFeature(.avx)) |
| | 12169 | return .{ .move = if (aligned) |
| | 12170 | .{ .v_, .movdqa } |
| | 12171 | else |
| | 12172 | .{ .v_, .movdqu } }, |
| | 12173 | else => {}, |
| | 12174 | }, |
| | 12175 | 256 => switch (ty.vectorLen(mod)) { |
| | 12176 | 1 => if (self.hasFeature(.avx)) |
| | 12177 | return .{ .move = if (aligned) |
| | 12178 | .{ .v_, .movdqa } |
| | 12179 | else |
| | 12180 | .{ .v_, .movdqu } }, |
| | 12181 | else => {}, |
| | 12182 | }, |
| | 12183 | else => {}, |
| | 12184 | }, |
| | 12185 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| | 12186 | 16 => switch (ty.vectorLen(mod)) { |
| | 12187 | 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| | 12188 | .insert = .{ .vp_w, .insr }, |
| | 12189 | .extract = .{ .vp_w, .extr }, |
| | 12190 | } } else .{ .insert_extract = .{ |
| | 12191 | .insert = .{ .p_w, .insr }, |
| | 12192 | .extract = .{ .p_w, .extr }, |
| | 12193 | } }, |
| | 12194 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12195 | .{ .v_d, .mov } |
| | 12196 | else |
| | 12197 | .{ ._d, .mov } }, |
| | 12198 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12199 | .{ .v_q, .mov } |
| | 12200 | else |
| | 12201 | .{ ._q, .mov } }, |
| | 12202 | 5...8 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12203 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12204 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12205 | 9...16 => if (self.hasFeature(.avx)) |
| | 12206 | return .{ .move = if (aligned) |
| | 12207 | .{ .v_, .movdqa } |
| | 12208 | else |
| | 12209 | .{ .v_, .movdqu } }, |
| | 12210 | else => {}, |
| | 12211 | }, |
| | 12212 | 32 => switch (ty.vectorLen(mod)) { |
| | 12213 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12214 | .{ .v_ss, .mov } |
| | 12215 | else |
| | 12216 | .{ ._ss, .mov } }, |
| | 12217 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12218 | .{ .v_sd, .mov } |
| | 12219 | else |
| | 12220 | .{ ._sd, .mov } }, |
| | 12221 | 3...4 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12222 | if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } |
| | 12223 | else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } }, |
| | 12224 | 5...8 => if (self.hasFeature(.avx)) |
| | 12225 | return .{ .move = if (aligned) |
| | 12226 | .{ .v_ps, .mova } |
| | 12227 | else |
| | 12228 | .{ .v_ps, .movu } }, |
| | 12229 | else => {}, |
| | 12230 | }, |
| | 12231 | 64 => switch (ty.vectorLen(mod)) { |
| | 12232 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12233 | .{ .v_sd, .mov } |
| | 12234 | else |
| | 12235 | .{ ._sd, .mov } }, |
| | 12236 | 2 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12237 | if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } |
| | 12238 | else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } }, |
| | 12239 | 3...4 => if (self.hasFeature(.avx)) |
| | 12240 | return .{ .move = if (aligned) |
| | 12241 | .{ .v_pd, .mova } |
| | 12242 | else |
| | 12243 | .{ .v_pd, .movu } }, |
| | 12244 | else => {}, |
| | 12245 | }, |
| | 12246 | 128 => switch (ty.vectorLen(mod)) { |
| | 12247 | 1 => return .{ .move = if (self.hasFeature(.avx)) |
| | 12248 | if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } |
| | 12249 | else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } }, |
| | 12250 | 2 => if (self.hasFeature(.avx)) |
| | 12251 | return .{ .move = if (aligned) |
| | 12252 | .{ .v_, .movdqa } |
| | 12253 | else |
| | 12254 | .{ .v_, .movdqu } }, |
| | 12255 | else => {}, |
| | 12256 | }, |
| | 12257 | else => {}, |
| | 12258 | }, |
| | 12259 | else => {}, |
| | 12260 | }, |
| | 12261 | } |
| 12016 | }, | 12262 | }, |
| 12017 | } | 12263 | } |
| 12018 | return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)}); | 12264 | return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)}); |
| ... | @@ -12034,9 +12280,9 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError | ... | @@ -12034,9 +12280,9 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 12034 | .register_overflow, | 12280 | .register_overflow, |
| 12035 | .lea_direct, | 12281 | .lea_direct, |
| 12036 | .lea_got, | 12282 | .lea_got, |
| 12037 | .lea_extern_got, | | |
| 12038 | .lea_tlv, | 12283 | .lea_tlv, |
| 12039 | .lea_frame, | 12284 | .lea_frame, |
| | 12285 | .lea_symbol, |
| 12040 | .reserved_frame, | 12286 | .reserved_frame, |
| 12041 | .air_ref, | 12287 | .air_ref, |
| 12042 | => unreachable, // unmodifiable destination | 12288 | => unreachable, // unmodifiable destination |
| ... | @@ -12060,37 +12306,58 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError | ... | @@ -12060,37 +12306,58 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 12060 | } }, | 12306 | } }, |
| 12061 | }), | 12307 | }), |
| 12062 | .register_pair => |dst_regs| { | 12308 | .register_pair => |dst_regs| { |
| 12063 | switch (src_mcv) { | 12309 | const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) { |
| | 12310 | .register_pair, .memory, .indirect, .load_frame => null, |
| | 12311 | .load_symbol, .load_direct, .load_got, .load_tlv => src: { |
| | 12312 | const src_addr_reg = |
| | 12313 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| | 12314 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| | 12315 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| | 12316 | |
| | 12317 | try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address()); |
| | 12318 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| | 12319 | }, |
| 12064 | .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)), | 12320 | .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)), |
| 12065 | else => {}, | 12321 | else => return self.fail("TODO implement genCopy for {s} of {}", .{ |
| 12066 | } | 12322 | @tagName(src_mcv), ty.fmt(mod), |
| | 12323 | }), |
| | 12324 | }; |
| | 12325 | defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock); |
| | 12326 | |
| 12067 | const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none); | 12327 | const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none); |
| 12068 | for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| { | 12328 | for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| { |
| 12069 | const class_ty = switch (class) { | 12329 | const class_ty = switch (class) { |
| 12070 | .integer => Type.usize, | 12330 | .integer => Type.usize, |
| 12071 | .sse => Type.f64, | 12331 | .sse, .float, .float_combine => Type.f64, |
| 12072 | else => unreachable, | 12332 | else => unreachable, |
| 12073 | }; | 12333 | }; |
| | 12334 | const off: i32 = @intCast(dst_reg_i * 8); |
| 12074 | switch (src_mcv) { | 12335 | switch (src_mcv) { |
| 12075 | .register_pair => |src_regs| try self.genSetReg( | 12336 | .register_pair => |src_regs| try self.genSetReg( |
| 12076 | dst_reg, | 12337 | dst_reg, |
| 12077 | class_ty, | 12338 | class_ty, |
| 12078 | .{ .register = src_regs[dst_reg_i] }, | 12339 | .{ .register = src_regs[dst_reg_i] }, |
| 12079 | ), | 12340 | ), |
| 12080 | else => try self.genSetReg( | 12341 | .memory, .indirect, .load_frame => try self.genSetReg( |
| | 12342 | dst_reg, |
| | 12343 | class_ty, |
| | 12344 | src_mcv.address().offset(off).deref(), |
| | 12345 | ), |
| | 12346 | .load_symbol, .load_direct, .load_got, .load_tlv => try self.genSetReg( |
| 12081 | dst_reg, | 12347 | dst_reg, |
| 12082 | class_ty, | 12348 | class_ty, |
| 12083 | src_mcv.address().offset(@intCast(dst_reg_i * 8)).deref(), | 12349 | .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } }, |
| 12084 | ), | 12350 | ), |
| | 12351 | else => unreachable, |
| 12085 | } | 12352 | } |
| 12086 | } | 12353 | } |
| 12087 | }, | 12354 | }, |
| 12088 | .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv), | 12355 | .indirect => |reg_off| try self.genSetMem(.{ .reg = reg_off.reg }, reg_off.off, ty, src_mcv), |
| 12089 | .memory, .load_direct, .load_got, .load_extern_got, .load_tlv => { | 12356 | .memory, .load_symbol, .load_direct, .load_got, .load_tlv => { |
| 12090 | switch (dst_mcv) { | 12357 | switch (dst_mcv) { |
| 12091 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| | 12358 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 12092 | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv), | 12359 | return self.genSetMem(.{ .reg = .ds }, small_addr, ty, src_mcv), |
| 12093 | .load_direct, .load_got, .load_extern_got, .load_tlv => {}, | 12360 | .load_symbol, .load_direct, .load_got, .load_tlv => {}, |
| 12094 | else => unreachable, | 12361 | else => unreachable, |
| 12095 | } | 12362 | } |
| 12096 | | 12363 | |
| ... | @@ -12157,6 +12424,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12157,6 +12424,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12157 | registerAlias(dst_reg, abi_size), | 12424 | registerAlias(dst_reg, abi_size), |
| 12158 | src_reg, | 12425 | src_reg, |
| 12159 | ), | 12426 | ), |
| | 12427 | .x87, .mmx => unreachable, |
| 12160 | .sse => try self.asmRegisterRegister( | 12428 | .sse => try self.asmRegisterRegister( |
| 12161 | switch (abi_size) { | 12429 | switch (abi_size) { |
| 12162 | 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, | 12430 | 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, |
| ... | @@ -12166,17 +12434,30 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12166,17 +12434,30 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12166 | registerAlias(dst_reg, @max(abi_size, 4)), | 12434 | registerAlias(dst_reg, @max(abi_size, 4)), |
| 12167 | src_reg.to128(), | 12435 | src_reg.to128(), |
| 12168 | ), | 12436 | ), |
| 12169 | .x87, .mmx => unreachable, | | |
| 12170 | }, | 12437 | }, |
| 12171 | .segment => try self.asmRegisterRegister( | 12438 | .segment => try self.asmRegisterRegister( |
| 12172 | .{ ._, .mov }, | 12439 | .{ ._, .mov }, |
| 12173 | dst_reg, | 12440 | dst_reg, |
| 12174 | switch (src_reg.class()) { | 12441 | switch (src_reg.class()) { |
| 12175 | .general_purpose, .segment => registerAlias(src_reg, abi_size), | 12442 | .general_purpose, .segment => registerAlias(src_reg, abi_size), |
| 12176 | .sse => try self.copyToTmpRegister(ty, src_mcv), | | |
| 12177 | .x87, .mmx => unreachable, | 12443 | .x87, .mmx => unreachable, |
| | 12444 | .sse => try self.copyToTmpRegister(ty, src_mcv), |
| 12178 | }, | 12445 | }, |
| 12179 | ), | 12446 | ), |
| | 12447 | .x87 => switch (src_reg.class()) { |
| | 12448 | .general_purpose, .segment => unreachable, |
| | 12449 | .x87 => switch (src_reg) { |
| | 12450 | .st0 => try self.asmRegister(.{ .f_, .st }, dst_reg), |
| | 12451 | .st1, .st2, .st3, .st4, .st5, .st6 => { |
| | 12452 | try self.asmRegister(.{ .f_, .ld }, src_reg); |
| | 12453 | assert(dst_reg != .st7); |
| | 12454 | try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1)); |
| | 12455 | }, |
| | 12456 | else => unreachable, |
| | 12457 | }, |
| | 12458 | .mmx, .sse => unreachable, |
| | 12459 | }, |
| | 12460 | .mmx => unreachable, |
| 12180 | .sse => switch (src_reg.class()) { | 12461 | .sse => switch (src_reg.class()) { |
| 12181 | .general_purpose => try self.asmRegisterRegister( | 12462 | .general_purpose => try self.asmRegisterRegister( |
| 12182 | switch (abi_size) { | 12463 | switch (abi_size) { |
| ... | @@ -12192,6 +12473,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12192,6 +12473,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12192 | ty, | 12473 | ty, |
| 12193 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, | 12474 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, |
| 12194 | ), | 12475 | ), |
| | 12476 | .x87, .mmx => unreachable, |
| 12195 | .sse => try self.asmRegisterRegister( | 12477 | .sse => try self.asmRegisterRegister( |
| 12196 | @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) { | 12478 | @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 12197 | else => switch (abi_size) { | 12479 | else => switch (abi_size) { |
| ... | @@ -12217,9 +12499,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12217,9 +12499,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12217 | registerAlias(dst_reg, abi_size), | 12499 | registerAlias(dst_reg, abi_size), |
| 12218 | registerAlias(src_reg, abi_size), | 12500 | registerAlias(src_reg, abi_size), |
| 12219 | ), | 12501 | ), |
| 12220 | .x87, .mmx => unreachable, | | |
| 12221 | }, | 12502 | }, |
| 12222 | .x87, .mmx => unreachable, | | |
| 12223 | }, | 12503 | }, |
| 12224 | .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }), | 12504 | .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }), |
| 12225 | .register_offset, | 12505 | .register_offset, |
| ... | @@ -12231,9 +12511,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12231,9 +12511,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12231 | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }), | 12511 | 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }), |
| 12232 | else => .{ .move = .{ ._, .lea } }, | 12512 | else => .{ .move = .{ ._, .lea } }, |
| 12233 | }, | 12513 | }, |
| 12234 | .indirect => try self.moveStrategy(ty, false), | 12514 | .indirect => try self.moveStrategy(ty, dst_reg.class(), false), |
| 12235 | .load_frame => |frame_addr| try self.moveStrategy( | 12515 | .load_frame => |frame_addr| try self.moveStrategy( |
| 12236 | ty, | 12516 | ty, |
| | 12517 | dst_reg.class(), |
| 12237 | self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)), | 12518 | self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)), |
| 12238 | ), | 12519 | ), |
| 12239 | .lea_frame => .{ .move = .{ ._, .lea } }, | 12520 | .lea_frame => .{ .move = .{ ._, .lea } }, |
| ... | @@ -12252,18 +12533,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12252,18 +12533,19 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12252 | else => unreachable, | 12533 | else => unreachable, |
| 12253 | }, | 12534 | }, |
| 12254 | )), | 12535 | )), |
| 12255 | .memory, .load_direct, .load_got, .load_extern_got, .load_tlv => { | 12536 | .memory, .load_symbol, .load_direct, .load_got, .load_tlv => { |
| 12256 | switch (src_mcv) { | 12537 | switch (src_mcv) { |
| 12257 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| | 12538 | .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr| |
| 12258 | return (try self.moveStrategy( | 12539 | return (try self.moveStrategy( |
| 12259 | ty, | 12540 | ty, |
| | 12541 | dst_reg.class(), |
| 12260 | ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))), | 12542 | ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))), |
| 12261 | )).read(self, registerAlias(dst_reg, abi_size), Memory.sib( | 12543 | )).read(self, registerAlias(dst_reg, abi_size), Memory.sib( |
| 12262 | self.memPtrSize(ty), | 12544 | self.memPtrSize(ty), |
| 12263 | .{ .base = .{ .reg = .ds }, .disp = small_addr }, | 12545 | .{ .base = .{ .reg = .ds }, .disp = small_addr }, |
| 12264 | )), | 12546 | )), |
| 12265 | .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) { | 12547 | .load_direct => |sym_index| switch (dst_reg.class()) { |
| 12266 | else => { | 12548 | .general_purpose => { |
| 12267 | const atom_index = try self.owner.getSymbolIndex(self); | 12549 | const atom_index = try self.owner.getSymbolIndex(self); |
| 12268 | _ = try self.addInst(.{ | 12550 | _ = try self.addInst(.{ |
| 12269 | .tag = .mov, | 12551 | .tag = .mov, |
| ... | @@ -12278,9 +12560,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12278,9 +12560,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12278 | }); | 12560 | }); |
| 12279 | return; | 12561 | return; |
| 12280 | }, | 12562 | }, |
| 12281 | .Float, .Vector => {}, | 12563 | .segment, .mmx => unreachable, |
| | 12564 | .x87, .sse => {}, |
| 12282 | }, | 12565 | }, |
| 12283 | .load_got, .load_extern_got, .load_tlv => {}, | 12566 | .load_symbol, .load_got, .load_tlv => {}, |
| 12284 | else => unreachable, | 12567 | else => unreachable, |
| 12285 | } | 12568 | } |
| 12286 | | 12569 | |
| ... | @@ -12288,34 +12571,47 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -12288,34 +12571,47 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 12288 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 12571 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 12289 | defer self.register_manager.unlockReg(addr_lock); | 12572 | defer self.register_manager.unlockReg(addr_lock); |
| 12290 | | 12573 | |
| 12291 | try (try self.moveStrategy(ty, false)).read( | 12574 | try (try self.moveStrategy(ty, dst_reg.class(), false)).read( |
| 12292 | self, | 12575 | self, |
| 12293 | registerAlias(dst_reg, abi_size), | 12576 | registerAlias(dst_reg, abi_size), |
| 12294 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }), | 12577 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }), |
| 12295 | ); | 12578 | ); |
| 12296 | }, | 12579 | }, |
| 12297 | .lea_direct, .lea_got, .lea_extern_got => |sym_index| { | 12580 | .lea_symbol, .lea_direct, .lea_got => |sym_index| { |
| 12298 | const atom_index = try self.owner.getSymbolIndex(self); | 12581 | const atom_index = try self.owner.getSymbolIndex(self); |
| 12299 | _ = try self.addInst(.{ | 12582 | if (self.bin_file.cast(link.File.Elf)) |_| { |
| 12300 | .tag = switch (src_mcv) { | 12583 | _ = try self.addInst(.{ |
| 12301 | .lea_direct => .lea, | 12584 | .tag = .lea, |
| 12302 | .lea_got, .lea_extern_got => .mov, | 12585 | .ops = .linker_reloc, |
| 12303 | else => unreachable, | 12586 | .data = .{ .rx = .{ |
| 12304 | }, | 12587 | .r1 = dst_reg.to64(), |
| 12305 | .ops = switch (src_mcv) { | 12588 | .payload = try self.addExtra(Mir.Reloc{ |
| 12306 | .lea_direct => .direct_reloc, | 12589 | .atom_index = atom_index, |
| 12307 | .lea_got => .got_reloc, | 12590 | .sym_index = sym_index, |
| 12308 | .lea_extern_got => .extern_got_reloc, | 12591 | }), |
| 12309 | else => unreachable, | 12592 | } }, |
| 12310 | }, | 12593 | }); |
| 12311 | .data = .{ .rx = .{ | 12594 | } else { |
| 12312 | .r1 = dst_reg.to64(), | 12595 | _ = try self.addInst(.{ |
| 12313 | .payload = try self.addExtra(Mir.Reloc{ | 12596 | .tag = switch (src_mcv) { |
| 12314 | .atom_index = atom_index, | 12597 | .lea_direct => .lea, |
| 12315 | .sym_index = sym_index, | 12598 | .lea_got => .mov, |
| 12316 | }), | 12599 | else => unreachable, |
| 12317 | } }, | 12600 | }, |
| 12318 | }); | 12601 | .ops = switch (src_mcv) { |
| | 12602 | .lea_direct => .direct_reloc, |
| | 12603 | .lea_got => .got_reloc, |
| | 12604 | else => unreachable, |
| | 12605 | }, |
| | 12606 | .data = .{ .rx = .{ |
| | 12607 | .r1 = dst_reg.to64(), |
| | 12608 | .payload = try self.addExtra(Mir.Reloc{ |
| | 12609 | .atom_index = atom_index, |
| | 12610 | .sym_index = sym_index, |
| | 12611 | }), |
| | 12612 | } }, |
| | 12613 | }); |
| | 12614 | } |
| 12319 | }, | 12615 | }, |
| 12320 | .lea_tlv => |sym_index| { | 12616 | .lea_tlv => |sym_index| { |
| 12321 | const atom_index = try self.owner.getSymbolIndex(self); | 12617 | const atom_index = try self.owner.getSymbolIndex(self); |
| ... | @@ -12393,7 +12689,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -12393,7 +12689,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 12393 | }, | 12689 | }, |
| 12394 | }, | 12690 | }, |
| 12395 | .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })), | 12691 | .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })), |
| 12396 | .register => |src_reg| try (try self.moveStrategy(ty, switch (base) { | 12692 | .register => |src_reg| try (try self.moveStrategy(ty, src_reg.class(), switch (base) { |
| 12397 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), | 12693 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| 12398 | .reg => |reg| switch (reg) { | 12694 | .reg => |reg| switch (reg) { |
| 12399 | .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), | 12695 | .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| ... | @@ -12408,17 +12704,21 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -12408,17 +12704,21 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 12408 | registerAlias(src_reg, abi_size), | 12704 | registerAlias(src_reg, abi_size), |
| 12409 | ), | 12705 | ), |
| 12410 | .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| { | 12706 | .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| { |
| 12411 | const part_size = @min(abi_size - src_reg_i * 8, 8); | 12707 | const part_size: u16 = @min(abi_size - src_reg_i * 8, 8); |
| 12412 | try (try self.moveStrategy(ty, switch (base) { | 12708 | try (try self.moveStrategy( |
| 12413 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), | 12709 | try mod.intType(.unsigned, part_size * 8), |
| 12414 | .reg => |reg| switch (reg) { | 12710 | src_reg.class(), |
| 12415 | .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), | 12711 | switch (base) { |
| 12416 | else => false, | 12712 | .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| | 12713 | .reg => |reg| switch (reg) { |
| | 12714 | .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))), |
| | 12715 | else => false, |
| | 12716 | }, |
| | 12717 | .frame => |frame_index| self.getFrameAddrAlignment( |
| | 12718 | .{ .index = frame_index, .off = disp }, |
| | 12719 | ).compare(.gte, ty.abiAlignment(mod)), |
| 12417 | }, | 12720 | }, |
| 12418 | .frame => |frame_index| self.getFrameAddrAlignment( | 12721 | )).write(self, Memory.sib( |
| 12419 | .{ .index = frame_index, .off = disp }, | | |
| 12420 | ).compare(.gte, ty.abiAlignment(mod)), | | |
| 12421 | })).write(self, Memory.sib( | | |
| 12422 | Memory.PtrSize.fromSize(part_size), | 12722 | Memory.PtrSize.fromSize(part_size), |
| 12423 | .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) }, | 12723 | .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) }, |
| 12424 | ), registerAlias(src_reg, part_size)); | 12724 | ), registerAlias(src_reg, part_size)); |
| ... | @@ -12460,12 +12760,12 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -12460,12 +12760,12 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 12460 | .lea_direct, | 12760 | .lea_direct, |
| 12461 | .load_got, | 12761 | .load_got, |
| 12462 | .lea_got, | 12762 | .lea_got, |
| 12463 | .load_extern_got, | | |
| 12464 | .lea_extern_got, | | |
| 12465 | .load_tlv, | 12763 | .load_tlv, |
| 12466 | .lea_tlv, | 12764 | .lea_tlv, |
| 12467 | .load_frame, | 12765 | .load_frame, |
| 12468 | .lea_frame, | 12766 | .lea_frame, |
| | 12767 | .load_symbol, |
| | 12768 | .lea_symbol, |
| 12469 | => switch (abi_size) { | 12769 | => switch (abi_size) { |
| 12470 | 0 => {}, | 12770 | 0 => {}, |
| 12471 | 1, 2, 4, 8 => { | 12771 | 1, 2, 4, 8 => { |
| ... | @@ -12482,9 +12782,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal | ... | @@ -12482,9 +12782,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 12482 | } | 12782 | } |
| 12483 | | 12783 | |
| 12484 | fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { | 12784 | fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void { |
| 12485 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); | 12785 | try self.spillRegisters(&.{ .rsi, .rdi, .rcx }); |
| 12486 | try self.genSetReg(.rdi, Type.usize, dst_ptr); | | |
| 12487 | try self.genSetReg(.rsi, Type.usize, src_ptr); | 12786 | try self.genSetReg(.rsi, Type.usize, src_ptr); |
| | 12787 | try self.genSetReg(.rdi, Type.usize, dst_ptr); |
| 12488 | try self.genSetReg(.rcx, Type.usize, len); | 12788 | try self.genSetReg(.rcx, Type.usize, len); |
| 12489 | try self.asmOpOnly(.{ .@"rep _sb", .mov }); | 12789 | try self.asmOpOnly(.{ .@"rep _sb", .mov }); |
| 12490 | } | 12790 | } |
| ... | @@ -12556,8 +12856,8 @@ fn genLazySymbolRef( | ... | @@ -12556,8 +12856,8 @@ fn genLazySymbolRef( |
| 12556 | | 12856 | |
| 12557 | if (self.bin_file.options.pic) { | 12857 | if (self.bin_file.options.pic) { |
| 12558 | switch (tag) { | 12858 | switch (tag) { |
| 12559 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym.esym_index }), | 12859 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }), |
| 12560 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym.esym_index }), | 12860 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_symbol = sym.esym_index }), |
| 12561 | else => unreachable, | 12861 | else => unreachable, |
| 12562 | } | 12862 | } |
| 12563 | switch (tag) { | 12863 | switch (tag) { |
| ... | @@ -12573,7 +12873,7 @@ fn genLazySymbolRef( | ... | @@ -12573,7 +12873,7 @@ fn genLazySymbolRef( |
| 12573 | switch (tag) { | 12873 | switch (tag) { |
| 12574 | .lea, .mov => _ = try self.addInst(.{ | 12874 | .lea, .mov => _ = try self.addInst(.{ |
| 12575 | .tag = .mov, | 12875 | .tag = .mov, |
| 12576 | .ops = .direct_got_reloc, | 12876 | .ops = .linker_reloc, |
| 12577 | .data = .{ .rx = .{ | 12877 | .data = .{ .rx = .{ |
| 12578 | .r1 = reg.to64(), | 12878 | .r1 = reg.to64(), |
| 12579 | .payload = try self.addExtra(reloc), | 12879 | .payload = try self.addExtra(reloc), |
| ... | @@ -12581,20 +12881,11 @@ fn genLazySymbolRef( | ... | @@ -12581,20 +12881,11 @@ fn genLazySymbolRef( |
| 12581 | }), | 12881 | }), |
| 12582 | .call => _ = try self.addInst(.{ | 12882 | .call => _ = try self.addInst(.{ |
| 12583 | .tag = .call, | 12883 | .tag = .call, |
| 12584 | .ops = .direct_got_reloc, | 12884 | .ops = .linker_reloc, |
| 12585 | .data = .{ .reloc = reloc }, | 12885 | .data = .{ .reloc = reloc }, |
| 12586 | }), | 12886 | }), |
| 12587 | else => unreachable, | 12887 | else => unreachable, |
| 12588 | } | 12888 | } |
| 12589 | switch (tag) { | | |
| 12590 | .lea, .call => {}, | | |
| 12591 | .mov => try self.asmRegisterMemory( | | |
| 12592 | .{ ._, tag }, | | |
| 12593 | reg.to64(), | | |
| 12594 | Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }), | | |
| 12595 | ), | | |
| 12596 | else => unreachable, | | |
| 12597 | } | | |
| 12598 | } | 12889 | } |
| 12599 | } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| { | 12890 | } else if (self.bin_file.cast(link.File.Plan9)) |p9_file| { |
| 12600 | const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | 12891 | const atom_index = p9_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| |
| ... | @@ -14481,10 +14772,11 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | ... | @@ -14481,10 +14772,11 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 14481 | } else mcv: { | 14772 | } else mcv: { |
| 14482 | const ip_index = Air.refToInterned(ref).?; | 14773 | const ip_index = Air.refToInterned(ref).?; |
| 14483 | const gop = try self.const_tracking.getOrPut(self.gpa, ip_index); | 14774 | const gop = try self.const_tracking.getOrPut(self.gpa, ip_index); |
| 14484 | if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{ | 14775 | const mcv = try self.genTypedValue(.{ |
| 14485 | .ty = ty, | 14776 | .ty = ty, |
| 14486 | .val = ip_index.toValue(), | 14777 | .val = ip_index.toValue(), |
| 14487 | })); | 14778 | }); |
| | 14779 | if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(mcv); |
| 14488 | break :mcv gop.value_ptr.short; | 14780 | break :mcv gop.value_ptr.short; |
| 14489 | }; | 14781 | }; |
| 14490 | | 14782 | |
| ... | @@ -14531,9 +14823,9 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | ... | @@ -14531,9 +14823,9 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 14531 | .undef => .undef, | 14823 | .undef => .undef, |
| 14532 | .immediate => |imm| .{ .immediate = imm }, | 14824 | .immediate => |imm| .{ .immediate = imm }, |
| 14533 | .memory => |addr| .{ .memory = addr }, | 14825 | .memory => |addr| .{ .memory = addr }, |
| | 14826 | .load_symbol => |sym_index| .{ .load_symbol = sym_index }, |
| 14534 | .load_direct => |sym_index| .{ .load_direct = sym_index }, | 14827 | .load_direct => |sym_index| .{ .load_direct = sym_index }, |
| 14535 | .load_got => |sym_index| .{ .lea_got = sym_index }, | 14828 | .load_got => |sym_index| .{ .lea_got = sym_index }, |
| 14536 | .load_extern_got => |sym_index| .{ .lea_extern_got = sym_index }, | | |
| 14537 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, | 14829 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 14538 | }, | 14830 | }, |
| 14539 | .fail => |msg| { | 14831 | .fail => |msg| { |
| ... | @@ -14730,16 +15022,22 @@ fn resolveCallingConventionValues( | ... | @@ -14730,16 +15022,22 @@ fn resolveCallingConventionValues( |
| 14730 | arg_mcv_i += 1; | 15022 | arg_mcv_i += 1; |
| 14731 | }, | 15023 | }, |
| 14732 | .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse), | 15024 | .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse), |
| 14733 | .x87, .x87up, .complex_x87, .memory => break, | 15025 | .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) { |
| 14734 | .none => unreachable, | 15026 | .SysV => switch (class) { |
| 14735 | .win_i128 => { | 15027 | .x87, .x87up, .complex_x87, .memory => break, |
| 14736 | const param_int_reg = | 15028 | else => unreachable, |
| 14737 | abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64(); | 15029 | }, |
| 14738 | param_int_reg_i += 1; | 15030 | .Win64 => if (ty.abiSize(mod) > 8) { |
| 14739 | | 15031 | const param_int_reg = |
| 14740 | arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } }; | 15032 | abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64(); |
| 14741 | arg_mcv_i += 1; | 15033 | param_int_reg_i += 1; |
| | 15034 | |
| | 15035 | arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } }; |
| | 15036 | arg_mcv_i += 1; |
| | 15037 | } else break, |
| | 15038 | else => unreachable, |
| 14742 | }, | 15039 | }, |
| | 15040 | .none => unreachable, |
| 14743 | } else { | 15041 | } else { |
| 14744 | arg.* = switch (arg_mcv_i) { | 15042 | arg.* = switch (arg_mcv_i) { |
| 14745 | else => unreachable, | 15043 | else => unreachable, |
| ... | @@ -15017,34 +15315,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 { | ... | @@ -15017,34 +15315,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 { |
| 15017 | }; | 15315 | }; |
| 15018 | } | 15316 | } |
| 15019 | | 15317 | |
| 15020 | fn promoteVarArg(self: *Self, ty: Type) Type { | 15318 | fn promoteInt(self: *Self, ty: Type) Type { |
| 15021 | const mod = self.bin_file.options.module.?; | 15319 | const mod = self.bin_file.options.module.?; |
| 15022 | switch (ty.zigTypeTag(mod)) { | 15320 | const int_info: InternPool.Key.IntType = switch (ty.toIntern()) { |
| 15023 | .Bool => return Type.c_int, | 15321 | .bool_type => .{ .signedness = .unsigned, .bits = 1 }, |
| 15024 | else => { | 15322 | else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty, |
| 15025 | const int_info = ty.intInfo(mod); | 15323 | }; |
| 15026 | for ([_]Type{ | 15324 | for ([_]Type{ |
| 15027 | Type.c_int, Type.c_uint, | 15325 | Type.c_int, Type.c_uint, |
| 15028 | Type.c_long, Type.c_ulong, | 15326 | Type.c_long, Type.c_ulong, |
| 15029 | Type.c_longlong, Type.c_ulonglong, | 15327 | Type.c_longlong, Type.c_ulonglong, |
| 15030 | }) |promote_ty| { | 15328 | }) |promote_ty| { |
| 15031 | const promote_info = promote_ty.intInfo(mod); | 15329 | const promote_info = promote_ty.intInfo(mod); |
| 15032 | if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue; | 15330 | if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue; |
| 15033 | if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and | 15331 | if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and |
| 15034 | promote_info.signedness == .signed) <= promote_info.bits) return promote_ty; | 15332 | promote_info.signedness == .signed) <= promote_info.bits) return promote_ty; |
| 15035 | } | 15333 | } |
| 15036 | unreachable; | 15334 | return ty; |
| 15037 | }, | 15335 | } |
| 15038 | .Float => switch (ty.floatBits(self.target.*)) { | 15336 | |
| 15039 | 32, 64 => return Type.f64, | 15337 | fn promoteVarArg(self: *Self, ty: Type) Type { |
| 15040 | else => |float_bits| { | 15338 | if (!ty.isRuntimeFloat()) return self.promoteInt(ty); |
| 15041 | assert(float_bits == self.target.c_type_bit_size(.longdouble)); | 15339 | switch (ty.floatBits(self.target.*)) { |
| 15042 | return Type.c_longdouble; | 15340 | 32, 64 => return Type.f64, |
| 15043 | }, | 15341 | else => |float_bits| { |
| 15044 | }, | 15342 | assert(float_bits == self.target.c_type_bit_size(.longdouble)); |
| 15045 | .Pointer => { | 15343 | return Type.c_longdouble; |
| 15046 | assert(!ty.isSlice(mod)); | | |
| 15047 | return ty; | | |
| 15048 | }, | 15344 | }, |
| 15049 | } | 15345 | } |
| 15050 | } | 15346 | } |