Skip to content

Commit

Permalink
Misc: Replace offsetof with constexpr-friendly OFFSETOF
Browse files Browse the repository at this point in the history
Fixes build with clang-18.
  • Loading branch information
stenzek committed Apr 28, 2024
1 parent dc84c58 commit 295081f
Show file tree
Hide file tree
Showing 14 changed files with 144 additions and 138 deletions.
12 changes: 9 additions & 3 deletions src/common/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,15 @@ char (&__countof_ArraySizeHelper(T (&array)[N]))[N];
#endif
#endif

// offsetof macro
#ifndef offsetof
#define offsetof(st, m) ((size_t)((char*)&((st*)(0))->m - (char*)0))
// offsetof macro. Need to use __builtin_offsetof(), otherwise it doesn't work in constant expressions.
#if defined(__clang__) || defined(__GNUC__)
#define OFFSETOF(st, m) __builtin_offsetof(st, m)
#else
#ifdef offsetof
#define OFFSETOF(st, m) offsetof(st, m)
#else
#define OFFSETOF(st, m) ((size_t)((char*)&((st*)(0))->m - (char*)0))
#endif
#endif

#ifdef __GNUC__
Expand Down
4 changes: 2 additions & 2 deletions src/core/cpu_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ struct State

std::array<u8, SCRATCHPAD_SIZE> scratchpad = {};

static constexpr u32 GPRRegisterOffset(u32 index) { return offsetof(State, regs.r) + (sizeof(u32) * index); }
static constexpr u32 GTERegisterOffset(u32 index) { return offsetof(State, gte_regs.r32) + (sizeof(u32) * index); }
static constexpr u32 GPRRegisterOffset(u32 index) { return OFFSETOF(State, regs.r) + (sizeof(u32) * index); }
static constexpr u32 GTERegisterOffset(u32 index) { return OFFSETOF(State, gte_regs.r32) + (sizeof(u32) * index); }
};

extern State g_state;
Expand Down
4 changes: 2 additions & 2 deletions src/core/cpu_newrec_compiler_aarch32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ void CPU::NewRec::AArch32Compiler::GenerateICacheCheckAndUpdate()
continue;

const u32 line = GetICacheLine(current_pc);
const u32 offset = offsetof(State, icache_tags) + (line * sizeof(u32));
const u32 offset = OFFSETOF(State, icache_tags) + (line * sizeof(u32));

Label cache_hit;
armAsm->ldr(existing_tag_reg, MemOperand(RSTATE, offset));
Expand Down Expand Up @@ -654,7 +654,7 @@ void CPU::NewRec::AArch32Compiler::Flush(u32 flags)
// TODO: make it a function?
armAsm->ldrb(RARG1, PTR(&g_state.load_delay_reg));
armAsm->ldr(RARG2, PTR(&g_state.load_delay_value));
EmitMov(RSCRATCH, offsetof(CPU::State, regs.r[0]));
EmitMov(RSCRATCH, OFFSETOF(CPU::State, regs.r[0]));
armAsm->add(RARG1, RSCRATCH, vixl::aarch32::Operand(RARG1, LSL, 2));
armAsm->str(RARG2, MemOperand(RSTATE, RARG1));
EmitMov(RSCRATCH, static_cast<u8>(Reg::count));
Expand Down
4 changes: 2 additions & 2 deletions src/core/cpu_newrec_compiler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void CPU::NewRec::AArch64Compiler::GenerateICacheCheckAndUpdate()
continue;

const u32 line = GetICacheLine(current_pc);
const u32 offset = offsetof(State, icache_tags) + (line * sizeof(u32));
const u32 offset = OFFSETOF(State, icache_tags) + (line * sizeof(u32));

Label cache_hit;
armAsm->ldr(existing_tag_reg, MemOperand(RSTATE, offset));
Expand Down Expand Up @@ -624,7 +624,7 @@ void CPU::NewRec::AArch64Compiler::Flush(u32 flags)
// TODO: make it a function?
armAsm->ldrb(RWARG1, PTR(&g_state.load_delay_reg));
armAsm->ldr(RWARG2, PTR(&g_state.load_delay_value));
EmitMov(RWSCRATCH, offsetof(CPU::State, regs.r[0]));
EmitMov(RWSCRATCH, OFFSETOF(CPU::State, regs.r[0]));
armAsm->add(RWARG1, RWSCRATCH, vixl::aarch64::Operand(RWARG1, LSL, 2));
armAsm->str(RWARG2, MemOperand(RSTATE, RXARG1));
EmitMov(RWSCRATCH, static_cast<u8>(Reg::count));
Expand Down
6 changes: 3 additions & 3 deletions src/core/cpu_newrec_compiler_riscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ u32 CPU::CodeCache::EmitASMFunctions(void* code, u32 code_size)
// Downcount isn't set on entry, so we need to initialize it
rvMoveAddressToReg(rvAsm, RARG1, TimingEvents::GetHeadEventPtr());
rvAsm->LD(RARG1, 0, RARG1);
rvAsm->LW(RARG1, offsetof(TimingEvent, m_downcount), RARG1);
rvAsm->LW(RARG1, OFFSETOF(TimingEvent, m_downcount), RARG1);
rvAsm->SW(RARG1, PTR(&g_state.downcount));

// Fall through to event dispatcher
Expand Down Expand Up @@ -545,7 +545,7 @@ void CPU::NewRec::RISCV64Compiler::GenerateICacheCheckAndUpdate()
continue;

const u32 line = GetICacheLine(current_pc);
const u32 offset = offsetof(State, icache_tags) + (line * sizeof(u32));
const u32 offset = OFFSETOF(State, icache_tags) + (line * sizeof(u32));

// TODO: Verify sign extension here...
Label cache_hit;
Expand Down Expand Up @@ -900,7 +900,7 @@ void CPU::NewRec::RISCV64Compiler::Flush(u32 flags)
rvAsm->LW(RARG2, PTR(&g_state.load_delay_value));
rvAsm->SLLI(RARG1, RARG1, 2); // *4
rvAsm->ADD(RARG1, RARG1, RSTATE);
rvAsm->SW(RARG2, offsetof(CPU::State, regs.r[0]), RARG1);
rvAsm->SW(RARG2, OFFSETOF(CPU::State, regs.r[0]), RARG1);
rvAsm->LI(RSCRATCH, static_cast<u8>(Reg::count));
rvAsm->SB(RSCRATCH, PTR(&g_state.load_delay_reg));
m_load_delay_dirty = false;
Expand Down
78 changes: 39 additions & 39 deletions src/core/cpu_recompiler_code_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -986,7 +986,7 @@ void CodeGenerator::BlockPrologue()
EmitBlockProtectCheck(ram_ptr, shadow_ptr, m_block->size * sizeof(Instruction));
}

EmitStoreCPUStructField(offsetof(State, exception_raised), Value::FromConstantU8(0));
EmitStoreCPUStructField(OFFSETOF(State, exception_raised), Value::FromConstantU8(0));

if (g_settings.bios_tty_logging)
{
Expand Down Expand Up @@ -1036,21 +1036,21 @@ void CodeGenerator::InstructionPrologue(Instruction instruction, const CodeCache
if (m_branch_was_taken_dirty)
{
Value temp = m_register_cache.AllocateScratch(RegSize_8);
EmitLoadCPUStructField(temp.host_reg, RegSize_8, offsetof(State, branch_was_taken));
EmitStoreCPUStructField(offsetof(State, current_instruction_was_branch_taken), temp);
EmitStoreCPUStructField(offsetof(State, branch_was_taken), Value::FromConstantU8(0));
EmitLoadCPUStructField(temp.host_reg, RegSize_8, OFFSETOF(State, branch_was_taken));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction_was_branch_taken), temp);
EmitStoreCPUStructField(OFFSETOF(State, branch_was_taken), Value::FromConstantU8(0));
m_current_instruction_was_branch_taken_dirty = true;
m_branch_was_taken_dirty = false;
}
else if (m_current_instruction_was_branch_taken_dirty)
{
EmitStoreCPUStructField(offsetof(State, current_instruction_was_branch_taken), Value::FromConstantU8(0));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction_was_branch_taken), Value::FromConstantU8(0));
m_current_instruction_was_branch_taken_dirty = false;
}

if (m_current_instruction_in_branch_delay_slot_dirty && !info.is_branch_delay_slot)
{
EmitStoreCPUStructField(offsetof(State, current_instruction_in_branch_delay_slot), Value::FromConstantU8(0));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction_in_branch_delay_slot), Value::FromConstantU8(0));
m_current_instruction_in_branch_delay_slot_dirty = false;
}

Expand All @@ -1064,7 +1064,7 @@ void CodeGenerator::InstructionPrologue(Instruction instruction, const CodeCache
if (info.is_branch_delay_slot && g_settings.cpu_recompiler_memory_exceptions)
{
// m_current_instruction_in_branch_delay_slot = true
EmitStoreCPUStructField(offsetof(State, current_instruction_in_branch_delay_slot), Value::FromConstantU8(1));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction_in_branch_delay_slot), Value::FromConstantU8(1));
m_current_instruction_in_branch_delay_slot_dirty = true;
}

Expand Down Expand Up @@ -1111,24 +1111,24 @@ void CodeGenerator::AddPendingCycles(bool commit)
if (m_gte_done_cycle > m_delayed_cycles_add)
{
Value temp = m_register_cache.AllocateScratch(RegSize_32);
EmitLoadCPUStructField(temp.GetHostRegister(), RegSize_32, offsetof(State, pending_ticks));
EmitLoadCPUStructField(temp.GetHostRegister(), RegSize_32, OFFSETOF(State, pending_ticks));
if (m_delayed_cycles_add > 0)
{
EmitAdd(temp.GetHostRegister(), temp.GetHostRegister(), Value::FromConstantU32(m_delayed_cycles_add), false);
EmitStoreCPUStructField(offsetof(State, pending_ticks), temp);
EmitStoreCPUStructField(OFFSETOF(State, pending_ticks), temp);
EmitAdd(temp.GetHostRegister(), temp.GetHostRegister(),
Value::FromConstantU32(m_gte_done_cycle - m_delayed_cycles_add), false);
EmitStoreCPUStructField(offsetof(State, gte_completion_tick), temp);
EmitStoreCPUStructField(OFFSETOF(State, gte_completion_tick), temp);
}
else
{
EmitAdd(temp.GetHostRegister(), temp.GetHostRegister(), Value::FromConstantU32(m_gte_done_cycle), false);
EmitStoreCPUStructField(offsetof(State, gte_completion_tick), temp);
EmitStoreCPUStructField(OFFSETOF(State, gte_completion_tick), temp);
}
}
else
{
EmitAddCPUStructField(offsetof(State, pending_ticks), Value::FromConstantU32(m_delayed_cycles_add));
EmitAddCPUStructField(OFFSETOF(State, pending_ticks), Value::FromConstantU32(m_delayed_cycles_add));
}

if (commit)
Expand Down Expand Up @@ -1180,7 +1180,7 @@ Value CodeGenerator::GetCurrentInstructionPC(u32 offset /* = 0 */)
void CodeGenerator::WriteNewPC(const Value& value, bool commit)
{
// TODO: This _could_ be moved into the register cache, but would it gain anything?
EmitStoreCPUStructField(offsetof(CPU::State, pc), value);
EmitStoreCPUStructField(OFFSETOF(CPU::State, pc), value);
if (commit)
{
m_pc_valid = value.IsConstant();
Expand All @@ -1201,8 +1201,8 @@ bool CodeGenerator::Compile_Fallback(Instruction instruction, const CodeCache::I
m_register_cache.WriteLoadDelayToCPU(true);
}

EmitStoreCPUStructField(offsetof(State, current_instruction_pc), Value::FromConstantU32(info.pc));
EmitStoreCPUStructField(offsetof(State, current_instruction.bits), Value::FromConstantU32(instruction.bits));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction_pc), Value::FromConstantU32(info.pc));
EmitStoreCPUStructField(OFFSETOF(State, current_instruction.bits), Value::FromConstantU32(instruction.bits));

// emit the function call
if (CanInstructionTrap(instruction, false /*m_block->key.user_mode*/))
Expand Down Expand Up @@ -2404,7 +2404,7 @@ bool CodeGenerator::Compile_Branch(Instruction instruction, const CodeCache::Ins
EmitBindLabel(&branch_okay);

SwitchToFarCode();
EmitStoreCPUStructField(offsetof(State, cop0_regs.BadVaddr), branch_target);
EmitStoreCPUStructField(OFFSETOF(State, cop0_regs.BadVaddr), branch_target);
EmitFunctionCall(
nullptr, static_cast<void (*)(u32, u32)>(&CPU::RaiseException),
Value::FromConstantU32(Cop0Registers::CAUSE::MakeValueForException(Exception::AdEL, false, false, 0)),
Expand Down Expand Up @@ -2433,8 +2433,8 @@ bool CodeGenerator::Compile_Branch(Instruction instruction, const CodeCache::Ins
// check downcount
Value pending_ticks = m_register_cache.AllocateScratch(RegSize_32);
Value downcount = m_register_cache.AllocateScratch(RegSize_32);
EmitLoadCPUStructField(pending_ticks.GetHostRegister(), RegSize_32, offsetof(State, pending_ticks));
EmitLoadCPUStructField(downcount.GetHostRegister(), RegSize_32, offsetof(State, downcount));
EmitLoadCPUStructField(pending_ticks.GetHostRegister(), RegSize_32, OFFSETOF(State, pending_ticks));
EmitLoadCPUStructField(downcount.GetHostRegister(), RegSize_32, OFFSETOF(State, downcount));

// pending < downcount
LabelType return_to_dispatcher;
Expand Down Expand Up @@ -2666,53 +2666,53 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr
switch (reg)
{
case Cop0Reg::BPC:
offset = offsetof(State, cop0_regs.BPC);
offset = OFFSETOF(State, cop0_regs.BPC);
break;

case Cop0Reg::BPCM:
offset = offsetof(State, cop0_regs.BPCM);
offset = OFFSETOF(State, cop0_regs.BPCM);
break;

case Cop0Reg::BDA:
offset = offsetof(State, cop0_regs.BDA);
offset = OFFSETOF(State, cop0_regs.BDA);
break;

case Cop0Reg::BDAM:
offset = offsetof(State, cop0_regs.BDAM);
offset = OFFSETOF(State, cop0_regs.BDAM);
break;

case Cop0Reg::DCIC:
offset = offsetof(State, cop0_regs.dcic.bits);
offset = OFFSETOF(State, cop0_regs.dcic.bits);
write_mask = Cop0Registers::DCIC::WRITE_MASK;
break;

case Cop0Reg::JUMPDEST:
offset = offsetof(State, cop0_regs.TAR);
offset = OFFSETOF(State, cop0_regs.TAR);
write_mask = 0;
break;

case Cop0Reg::BadVaddr:
offset = offsetof(State, cop0_regs.BadVaddr);
offset = OFFSETOF(State, cop0_regs.BadVaddr);
write_mask = 0;
break;

case Cop0Reg::SR:
offset = offsetof(State, cop0_regs.sr.bits);
offset = OFFSETOF(State, cop0_regs.sr.bits);
write_mask = Cop0Registers::SR::WRITE_MASK;
break;

case Cop0Reg::CAUSE:
offset = offsetof(State, cop0_regs.cause.bits);
offset = OFFSETOF(State, cop0_regs.cause.bits);
write_mask = Cop0Registers::CAUSE::WRITE_MASK;
break;

case Cop0Reg::EPC:
offset = offsetof(State, cop0_regs.EPC);
offset = OFFSETOF(State, cop0_regs.EPC);
write_mask = 0;
break;

case Cop0Reg::PRID:
offset = offsetof(State, cop0_regs.PRID);
offset = OFFSETOF(State, cop0_regs.PRID);
write_mask = 0;
break;

Expand Down Expand Up @@ -2804,8 +2804,8 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr

// m_cop0_regs.sr.IEc && ((m_cop0_regs.cause.Ip & m_cop0_regs.sr.Im) != 0)
LabelType no_interrupt;
EmitLoadCPUStructField(sr_value.host_reg, sr_value.size, offsetof(State, cop0_regs.sr.bits));
EmitLoadCPUStructField(cause_value.host_reg, cause_value.size, offsetof(State, cop0_regs.cause.bits));
EmitLoadCPUStructField(sr_value.host_reg, sr_value.size, OFFSETOF(State, cop0_regs.sr.bits));
EmitLoadCPUStructField(cause_value.host_reg, cause_value.size, OFFSETOF(State, cop0_regs.cause.bits));
EmitBranchIfBitClear(sr_value.host_reg, sr_value.size, 0, &no_interrupt);
EmitAnd(sr_value.host_reg, sr_value.host_reg, cause_value);
EmitTest(sr_value.host_reg, Value::FromConstantU32(0xFF00));
Expand All @@ -2817,7 +2817,7 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr
m_register_cache.PushState();
if (!info.is_last_instruction)
WriteNewPC(CalculatePC(), false);
EmitStoreCPUStructField(offsetof(State, downcount), Value::FromConstantU32(0));
EmitStoreCPUStructField(OFFSETOF(State, downcount), Value::FromConstantU32(0));
EmitExceptionExit();
m_register_cache.PopState();
SwitchToNearCode();
Expand All @@ -2831,21 +2831,21 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr

// if ((dcic & master_enable_bits) != master_enable_bits) goto not_enabled;
LabelType not_enabled;
EmitLoadCPUStructField(dcic_value.GetHostRegister(), dcic_value.size, offsetof(State, cop0_regs.dcic.bits));
EmitLoadCPUStructField(dcic_value.GetHostRegister(), dcic_value.size, OFFSETOF(State, cop0_regs.dcic.bits));
EmitAnd(dcic_value.GetHostRegister(), dcic_value.GetHostRegister(),
Value::FromConstantU32(Cop0Registers::DCIC::MASTER_ENABLE_BITS));
EmitConditionalBranch(Condition::NotEqual, false, dcic_value.host_reg,
Value::FromConstantU32(Cop0Registers::DCIC::MASTER_ENABLE_BITS), &not_enabled);

// if ((dcic & breakpoint_bits) == 0) goto not_enabled;
EmitLoadCPUStructField(dcic_value.GetHostRegister(), dcic_value.size, offsetof(State, cop0_regs.dcic.bits));
EmitLoadCPUStructField(dcic_value.GetHostRegister(), dcic_value.size, OFFSETOF(State, cop0_regs.dcic.bits));
EmitTest(dcic_value.GetHostRegister(),
Value::FromConstantU32(Cop0Registers::DCIC::ANY_BREAKPOINTS_ENABLED_BITS));
EmitConditionalBranch(Condition::Zero, false, &not_enabled);

// update dispatcher flag, if enabled, exit block
EmitFunctionCall(nullptr, &UpdateDebugDispatcherFlag);
EmitLoadCPUStructField(dcic_value.GetHostRegister(), RegSize_8, offsetof(State, use_debug_dispatcher));
EmitLoadCPUStructField(dcic_value.GetHostRegister(), RegSize_8, OFFSETOF(State, use_debug_dispatcher));
EmitBranchIfBitClear(dcic_value.GetHostRegister(), RegSize_8, 0, &not_enabled);

m_register_cache.UninhibitAllocation();
Expand Down Expand Up @@ -2883,7 +2883,7 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr
// shift mode bits right two, preserving upper bits
static constexpr u32 mode_bits_mask = UINT32_C(0b1111);
Value sr = m_register_cache.AllocateScratch(RegSize_32);
EmitLoadCPUStructField(sr.host_reg, RegSize_32, offsetof(State, cop0_regs.sr.bits));
EmitLoadCPUStructField(sr.host_reg, RegSize_32, OFFSETOF(State, cop0_regs.sr.bits));
{
Value new_mode_bits = m_register_cache.AllocateScratch(RegSize_32);
EmitShr(new_mode_bits.host_reg, sr.host_reg, new_mode_bits.size, Value::FromConstantU32(2));
Expand All @@ -2892,17 +2892,17 @@ bool CodeGenerator::Compile_cop0(Instruction instruction, const CodeCache::Instr
EmitOr(sr.host_reg, sr.host_reg, new_mode_bits);
}

EmitStoreCPUStructField(offsetof(State, cop0_regs.sr.bits), sr);
EmitStoreCPUStructField(OFFSETOF(State, cop0_regs.sr.bits), sr);

Value cause_value = m_register_cache.AllocateScratch(RegSize_32);
EmitLoadCPUStructField(cause_value.host_reg, cause_value.size, offsetof(State, cop0_regs.cause.bits));
EmitLoadCPUStructField(cause_value.host_reg, cause_value.size, OFFSETOF(State, cop0_regs.cause.bits));

LabelType no_interrupt;
EmitAnd(sr.host_reg, sr.host_reg, cause_value);
EmitTest(sr.host_reg, Value::FromConstantU32(0xFF00));
EmitConditionalBranch(Condition::Zero, false, &no_interrupt);
m_register_cache.InhibitAllocation();
EmitStoreCPUStructField(offsetof(State, downcount), Value::FromConstantU32(0));
EmitStoreCPUStructField(OFFSETOF(State, downcount), Value::FromConstantU32(0));
EmitBindLabel(&no_interrupt);
m_register_cache.UninhibitAllocation();

Expand Down
Loading

0 comments on commit 295081f

Please sign in to comment.