| ... | ... | @@ -163,8 +163,12 @@ const MCValue = union(enum) { |
| 163 | 163 | immediate: u64, |
| 164 | 164 | /// The value doesn't exist in memory yet. |
| 165 | 165 | load_symbol: SymbolOffset, |
| 166 | /// A TLV value. |
| 167 | load_tlv: u32, |
| 166 | 168 | /// The address of the memory location not-yet-allocated by the linker. |
| 167 | 169 | lea_symbol: SymbolOffset, |
| 170 | /// The address of a TLV value. |
| 171 | lea_tlv: u32, |
| 168 | 172 | /// The value is in a target-specific register. |
| 169 | 173 | register: Register, |
| 170 | 174 | /// The value is split across two registers |
| ... | ... | @@ -221,6 +225,7 @@ const MCValue = union(enum) { |
| 221 | 225 | .lea_frame, |
| 222 | 226 | .undef, |
| 223 | 227 | .lea_symbol, |
| 228 | .lea_tlv, |
| 224 | 229 | .air_ref, |
| 225 | 230 | .reserved_frame, |
| 226 | 231 | => false, |
| ... | ... | @@ -230,6 +235,7 @@ const MCValue = union(enum) { |
| 230 | 235 | .register_offset, |
| 231 | 236 | .load_frame, |
| 232 | 237 | .load_symbol, |
| 238 | .load_tlv, |
| 233 | 239 | .indirect, |
| 234 | 240 | => true, |
| 235 | 241 | }; |
| ... | ... | @@ -248,10 +254,12 @@ const MCValue = union(enum) { |
| 248 | 254 | .undef, |
| 249 | 255 | .air_ref, |
| 250 | 256 | .lea_symbol, |
| 257 | .lea_tlv, |
| 251 | 258 | .reserved_frame, |
| 252 | 259 | => unreachable, // not in memory |
| 253 | 260 | |
| 254 | 261 | .load_symbol => |sym_off| .{ .lea_symbol = sym_off }, |
| 262 | .load_tlv => |sym| .{ .lea_tlv = sym }, |
| 255 | 263 | .memory => |addr| .{ .immediate = addr }, |
| 256 | 264 | .load_frame => |off| .{ .lea_frame = off }, |
| 257 | 265 | .indirect => |reg_off| switch (reg_off.off) { |
| ... | ... | @@ -270,17 +278,19 @@ const MCValue = union(enum) { |
| 270 | 278 | .indirect, |
| 271 | 279 | .undef, |
| 272 | 280 | .air_ref, |
| 273 | | .load_frame, |
| 274 | 281 | .register_pair, |
| 282 | .load_frame, |
| 275 | 283 | .load_symbol, |
| 284 | .load_tlv, |
| 276 | 285 | .reserved_frame, |
| 277 | 286 | => unreachable, // not a pointer |
| 278 | 287 | |
| 279 | 288 | .immediate => |addr| .{ .memory = addr }, |
| 280 | | .lea_frame => |off| .{ .load_frame = off }, |
| 281 | 289 | .register => |reg| .{ .indirect = .{ .reg = reg } }, |
| 282 | 290 | .register_offset => |reg_off| .{ .indirect = reg_off }, |
| 291 | .lea_frame => |off| .{ .load_frame = off }, |
| 283 | 292 | .lea_symbol => |sym_off| .{ .load_symbol = sym_off }, |
| 293 | .lea_tlv => |sym| .{ .load_tlv = sym }, |
| 284 | 294 | }; |
| 285 | 295 | } |
| 286 | 296 | |
| ... | ... | @@ -298,6 +308,8 @@ const MCValue = union(enum) { |
| 298 | 308 | .indirect, |
| 299 | 309 | .load_symbol, |
| 300 | 310 | .lea_symbol, |
| 311 | .lea_tlv, |
| 312 | .load_tlv, |
| 301 | 313 | => switch (off) { |
| 302 | 314 | 0 => mcv, |
| 303 | 315 | else => unreachable, |
| ... | ... | @@ -355,6 +367,8 @@ const InstTracking = struct { |
| 355 | 367 | .memory, |
| 356 | 368 | .load_frame, |
| 357 | 369 | .lea_frame, |
| 370 | .load_tlv, |
| 371 | .lea_tlv, |
| 358 | 372 | .load_symbol, |
| 359 | 373 | .lea_symbol, |
| 360 | 374 | => result, |
| ... | ... | @@ -410,6 +424,8 @@ const InstTracking = struct { |
| 410 | 424 | .lea_frame, |
| 411 | 425 | .load_symbol, |
| 412 | 426 | .lea_symbol, |
| 427 | .load_tlv, |
| 428 | .lea_tlv, |
| 413 | 429 | => inst_tracking.long, |
| 414 | 430 | .dead, |
| 415 | 431 | .register, |
| ... | ... | @@ -438,6 +454,8 @@ const InstTracking = struct { |
| 438 | 454 | .lea_frame, |
| 439 | 455 | .load_symbol, |
| 440 | 456 | .lea_symbol, |
| 457 | .load_tlv, |
| 458 | .lea_tlv, |
| 441 | 459 | => assert(std.meta.eql(inst_tracking.long, target.long)), |
| 442 | 460 | .load_frame, |
| 443 | 461 | .reserved_frame, |
| ... | ... | @@ -3510,17 +3528,19 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void { |
| 3510 | 3528 | defer if (pl_lock) |lock| func.register_manager.unlockReg(lock); |
| 3511 | 3529 | |
| 3512 | 3530 | const opt_mcv = try func.allocRegOrMem(opt_ty, inst, true); |
| 3513 | | try func.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 3514 | 3531 | |
| 3515 | 3532 | if (!same_repr) { |
| 3516 | 3533 | const pl_abi_size: i32 = @intCast(pl_ty.abiSize(pt)); |
| 3517 | 3534 | switch (opt_mcv) { |
| 3518 | | .load_frame => |frame_addr| try func.genSetMem( |
| 3519 | | .{ .frame = frame_addr.index }, |
| 3520 | | frame_addr.off + pl_abi_size, |
| 3521 | | Type.u8, |
| 3522 | | .{ .immediate = 1 }, |
| 3523 | | ), |
| 3535 | .load_frame => |frame_addr| { |
| 3536 | try func.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 3537 | try func.genSetMem( |
| 3538 | .{ .frame = frame_addr.index }, |
| 3539 | frame_addr.off + pl_abi_size, |
| 3540 | Type.u8, |
| 3541 | .{ .immediate = 1 }, |
| 3542 | ); |
| 3543 | }, |
| 3524 | 3544 | |
| 3525 | 3545 | .register => |opt_reg| { |
| 3526 | 3546 | try func.genBinOp( |
| ... | ... | @@ -3531,6 +3551,7 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void { |
| 3531 | 3551 | Type.u64, |
| 3532 | 3552 | opt_reg, |
| 3533 | 3553 | ); |
| 3554 | try func.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 3534 | 3555 | }, |
| 3535 | 3556 | else => unreachable, |
| 3536 | 3557 | } |
| ... | ... | @@ -4457,12 +4478,14 @@ fn load(func: *Func, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro |
| 4457 | 4478 | .register_offset, |
| 4458 | 4479 | .lea_frame, |
| 4459 | 4480 | .lea_symbol, |
| 4481 | .lea_tlv, |
| 4460 | 4482 | => try func.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), |
| 4461 | 4483 | |
| 4462 | 4484 | .memory, |
| 4463 | 4485 | .indirect, |
| 4464 | 4486 | .load_symbol, |
| 4465 | 4487 | .load_frame, |
| 4488 | .load_tlv, |
| 4466 | 4489 | => { |
| 4467 | 4490 | const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv); |
| 4468 | 4491 | const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg); |
| ... | ... | @@ -4509,12 +4532,14 @@ fn store(func: *Func, ptr_mcv: MCValue, src_mcv: MCValue, ptr_ty: Type) !void { |
| 4509 | 4532 | .register_offset, |
| 4510 | 4533 | .lea_symbol, |
| 4511 | 4534 | .lea_frame, |
| 4535 | .lea_tlv, |
| 4512 | 4536 | => try func.genCopy(src_ty, ptr_mcv.deref(), src_mcv), |
| 4513 | 4537 | |
| 4514 | 4538 | .memory, |
| 4515 | 4539 | .indirect, |
| 4516 | 4540 | .load_symbol, |
| 4517 | 4541 | .load_frame, |
| 4542 | .load_tlv, |
| 4518 | 4543 | => { |
| 4519 | 4544 | const addr_reg = try func.copyToTmpRegister(ptr_ty, ptr_mcv); |
| 4520 | 4545 | const addr_lock = func.register_manager.lockRegAssumeUnused(addr_reg); |
| ... | ... | @@ -5989,7 +6014,14 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 5989 | 6014 | try func.register_manager.getReg(reg, null); |
| 5990 | 6015 | try func.genSetReg(ty, reg, input_mcv); |
| 5991 | 6016 | break :arg .{ .register = reg }; |
| 5992 | | } else return func.fail("invalid constraint: '{s}'", .{constraint}); |
| 6017 | } else if (mem.eql(u8, constraint, "r")) arg: { |
| 6018 | switch (input_mcv) { |
| 6019 | .register => break :arg input_mcv, |
| 6020 | else => {}, |
| 6021 | } |
| 6022 | const temp_reg = try func.copyToTmpRegister(ty, input_mcv); |
| 6023 | break :arg .{ .register = temp_reg }; |
| 6024 | } else return func.fail("invalid input constraint: '{s}'", .{constraint}); |
| 5993 | 6025 | if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| { |
| 5994 | 6026 | _ = func.register_manager.lockReg(reg); |
| 5995 | 6027 | }; |
| ... | ... | @@ -6071,6 +6103,10 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6071 | 6103 | assert(sym_off.off == 0); |
| 6072 | 6104 | break :blk .{ .sym = sym_off }; |
| 6073 | 6105 | } else return func.fail("invalid modifier: '{s}'", .{modifier}), |
| 6106 | .register => |reg| if (modifier.len == 0) |
| 6107 | .{ .reg = reg } |
| 6108 | else |
| 6109 | return func.fail("invalid modified '{s}'", .{modifier}), |
| 6074 | 6110 | else => return func.fail("invalid constraint: '{s}'", .{op_str}), |
| 6075 | 6111 | }; |
| 6076 | 6112 | } else return func.fail("invalid operand: '{s}'", .{op_str}); |
| ... | ... | @@ -6253,6 +6289,13 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| 6253 | 6289 | ty, |
| 6254 | 6290 | src_mcv, |
| 6255 | 6291 | ), |
| 6292 | .load_tlv => { |
| 6293 | const addr_reg, const addr_lock = try func.allocReg(.int); |
| 6294 | defer func.register_manager.unlockReg(addr_lock); |
| 6295 | |
| 6296 | try func.genSetReg(ty, addr_reg, dst_mcv.address()); |
| 6297 | try func.genCopy(ty, .{ .indirect = .{ .reg = addr_reg } }, src_mcv); |
| 6298 | }, |
| 6256 | 6299 | .memory => return func.fail("TODO: genCopy memory", .{}), |
| 6257 | 6300 | .register_pair => |dst_regs| { |
| 6258 | 6301 | const src_info: ?struct { addr_reg: Register, addr_lock: ?RegisterLock } = switch (src_mcv) { |
| ... | ... | @@ -6774,6 +6817,25 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6774 | 6817 | try func.genSetReg(ty, addr_reg, src_mcv.address()); |
| 6775 | 6818 | try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } }); |
| 6776 | 6819 | }, |
| 6820 | .lea_tlv => |sym| { |
| 6821 | const atom_index = try func.owner.getSymbolIndex(func); |
| 6822 | |
| 6823 | _ = try func.addInst(.{ |
| 6824 | .tag = .pseudo_load_tlv, |
| 6825 | .data = .{ .reloc = .{ |
| 6826 | .register = reg, |
| 6827 | .atom_index = atom_index, |
| 6828 | .sym_index = sym, |
| 6829 | } }, |
| 6830 | }); |
| 6831 | }, |
| 6832 | .load_tlv => { |
| 6833 | const addr_reg, const addr_lock = try func.allocReg(.int); |
| 6834 | defer func.register_manager.unlockReg(addr_lock); |
| 6835 | |
| 6836 | try func.genSetReg(ty, addr_reg, src_mcv.address()); |
| 6837 | try func.genSetReg(ty, reg, .{ .indirect = .{ .reg = addr_reg } }); |
| 6838 | }, |
| 6777 | 6839 | .air_ref => |ref| try func.genSetReg(ty, reg, try func.resolveInst(ref)), |
| 6778 | 6840 | else => return func.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), |
| 6779 | 6841 | } |
| ... | ... | @@ -6793,7 +6855,6 @@ fn genSetMem( |
| 6793 | 6855 | const dst_ptr_mcv: MCValue = switch (base) { |
| 6794 | 6856 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, |
| 6795 | 6857 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, |
| 6796 | | .reloc => |base_symbol| .{ .lea_symbol = .{ .sym = base_symbol.sym_index, .off = disp } }, |
| 6797 | 6858 | }; |
| 6798 | 6859 | switch (src_mcv) { |
| 6799 | 6860 | .none, |
| ... | ... | @@ -6940,6 +7001,7 @@ fn genSetMem( |
| 6940 | 7001 | return func.genSetMem(base, disp, ty, .{ .register = reg }); |
| 6941 | 7002 | }, |
| 6942 | 7003 | .air_ref => |src_ref| try func.genSetMem(base, disp, ty, try func.resolveInst(src_ref)), |
| 7004 | else => return func.fail("TODO: genSetMem {s}", .{@tagName(src_mcv)}), |
| 6943 | 7005 | } |
| 6944 | 7006 | } |
| 6945 | 7007 | |
| ... | ... | @@ -7761,9 +7823,10 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue { |
| 7761 | 7823 | .none => .none, |
| 7762 | 7824 | .undef => unreachable, |
| 7763 | 7825 | .load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } }, |
| 7826 | .load_tlv => |sym_index| .{ .lea_tlv = sym_index }, |
| 7764 | 7827 | .immediate => |imm| .{ .immediate = imm }, |
| 7765 | 7828 | .memory => |addr| .{ .memory = addr }, |
| 7766 | | .load_got, .load_direct, .load_tlv => { |
| 7829 | .load_got, .load_direct => { |
| 7767 | 7830 | return func.fail("TODO: genTypedValue {s}", .{@tagName(mcv)}); |
| 7768 | 7831 | }, |
| 7769 | 7832 | }, |