Skip to content

Commit a80f9d7

Browse files
dcharkescommit-bot@chromium.org
authored andcommitted
[vm/ffi] Stop using R8 in FFI calls, callbacks and stubs on arm64
R8 is used for passing the address when returning structs by value in the native ABI. Separated out from https://dart-review.googlesource.com/c/sdk/+/140290 Issue: #36730 Change-Id: I35187d35b8cd1b9fe6852faf0cd02a5f51e9f358 Cq-Include-Trybots: luci.dart.try:vm-ffi-android-debug-arm-try,vm-ffi-android-debug-arm64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-linux-debug-ia32-try,vm-kernel-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163204 Reviewed-by: Tess Strickland <[email protected]> Commit-Queue: Tess Strickland <[email protected]> Auto-Submit: Daco Harkes <[email protected]>
1 parent 475ffb9 commit a80f9d7

File tree

6 files changed

+60
-43
lines changed

6 files changed

+60
-43
lines changed

runtime/vm/compiler/backend/il_arm64.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,8 +1170,8 @@ void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
11701170
THR, compiler::target::Thread::
11711171
call_native_through_safepoint_entry_point_offset()));
11721172

1173-
// Calls R8 and clobbers R19 (along with volatile registers).
1174-
ASSERT(branch == R8 && temp == R19);
1173+
// Calls R9 and clobbers R19 (along with volatile registers).
1174+
ASSERT(branch == R9 && temp == R19);
11751175
__ blr(TMP);
11761176
}
11771177

runtime/vm/compiler/stub_code_compiler_arm64.cc

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
291291
// Calls native code within a safepoint.
292292
//
293293
// On entry:
294-
// R8: target to call
294+
// R9: target to call
295295
// Stack: set up for native call (SP), aligned, CSP < SP
296296
//
297297
// On exit:
@@ -302,29 +302,29 @@ void StubCodeCompiler::GenerateCallNativeThroughSafepointStub(
302302
COMPILE_ASSERT((1 << R19) & kAbiPreservedCpuRegs);
303303

304304
__ mov(R19, LR);
305-
__ LoadImmediate(R9, target::Thread::exit_through_ffi());
306-
__ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/,
305+
__ LoadImmediate(R10, target::Thread::exit_through_ffi());
306+
__ TransitionGeneratedToNative(R9, FPREG, R10 /*volatile*/,
307307
/*enter_safepoint=*/true);
308308
__ mov(R25, CSP);
309309
__ mov(CSP, SP);
310310

311311
#if defined(DEBUG)
312312
// Check CSP alignment.
313-
__ andi(R10 /*volatile*/, SP,
313+
__ andi(R11 /*volatile*/, SP,
314314
Immediate(~(OS::ActivationFrameAlignment() - 1)));
315-
__ cmp(R10, Operand(SP));
315+
__ cmp(R11, Operand(SP));
316316
Label done;
317317
__ b(&done, EQ);
318318
__ Breakpoint();
319319
__ Bind(&done);
320320
#endif
321321

322-
__ blr(R8);
322+
__ blr(R9);
323323

324324
__ mov(SP, CSP);
325325
__ mov(CSP, R25);
326326

327-
__ TransitionNativeToGenerated(R9, /*leave_safepoint=*/true);
327+
__ TransitionNativeToGenerated(R10, /*leave_safepoint=*/true);
328328
__ ret(R19);
329329
}
330330

@@ -338,16 +338,16 @@ void StubCodeCompiler::GenerateJITCallbackTrampolines(
338338
#else
339339
Label done;
340340

341-
// R8 is volatile and not used for passing any arguments.
342-
COMPILE_ASSERT(!IsCalleeSavedRegister(R8) && !IsArgumentRegister(R8));
341+
// R9 is volatile and not used for passing any arguments.
342+
COMPILE_ASSERT(!IsCalleeSavedRegister(R9) && !IsArgumentRegister(R9));
343343
for (intptr_t i = 0;
344344
i < NativeCallbackTrampolines::NumCallbackTrampolinesPerPage(); ++i) {
345345
// We don't use LoadImmediate because we need the trampoline size to be
346346
// fixed independently of the callback ID.
347347
//
348348
// Instead we paste the callback ID directly in the code load it
349349
// PC-relative.
350-
__ ldr(R8, compiler::Address::PC(2 * Instr::kInstrSize));
350+
__ ldr(R9, compiler::Address::PC(2 * Instr::kInstrSize));
351351
__ b(&done);
352352
__ Emit(next_callback_id + i);
353353
}
@@ -362,7 +362,7 @@ void StubCodeCompiler::GenerateJITCallbackTrampolines(
362362

363363
// The load of the callback ID might have incorrect higher-order bits, since
364364
// we only emit a 32-bit callback ID.
365-
__ uxtw(R8, R8);
365+
__ uxtw(R9, R9);
366366

367367
// Save THR (callee-saved) and LR on real real C stack (CSP). Keeps it
368368
// aligned.
@@ -374,8 +374,8 @@ void StubCodeCompiler::GenerateJITCallbackTrampolines(
374374
RegisterSet all_registers;
375375
all_registers.AddAllArgumentRegisters();
376376

377-
// The call below might clobber R8 (volatile, holding callback_id).
378-
all_registers.Add(Location::RegisterLocation(R8));
377+
// The call below might clobber R9 (volatile, holding callback_id).
378+
all_registers.Add(Location::RegisterLocation(R9));
379379

380380
// Load the thread, verify the callback ID and exit the safepoint.
381381
//
@@ -396,7 +396,7 @@ void StubCodeCompiler::GenerateJITCallbackTrampolines(
396396
// loaded anywhere, we use the same trick as before to ensure a predictable
397397
// instruction sequence.
398398
Label call;
399-
__ mov(R0, R8);
399+
__ mov(R0, R9);
400400
__ ldr(R1, compiler::Address::PC(2 * Instr::kInstrSize));
401401
__ b(&call);
402402

@@ -415,29 +415,30 @@ void StubCodeCompiler::GenerateJITCallbackTrampolines(
415415
__ mov(CSP, SP);
416416
}
417417

418-
COMPILE_ASSERT(!IsCalleeSavedRegister(R9) && !IsArgumentRegister(R9));
418+
COMPILE_ASSERT(!IsCalleeSavedRegister(R10) && !IsArgumentRegister(R10));
419419

420420
// Load the code object.
421-
__ LoadFromOffset(R9, THR, compiler::target::Thread::callback_code_offset());
422-
__ LoadFieldFromOffset(R9, R9,
421+
__ LoadFromOffset(R10, THR, compiler::target::Thread::callback_code_offset());
422+
__ LoadFieldFromOffset(R10, R10,
423423
compiler::target::GrowableObjectArray::data_offset());
424-
__ ldr(R9, __ ElementAddressForRegIndex(
425-
/*external=*/false,
426-
/*array_cid=*/kArrayCid,
427-
/*index, smi-tagged=*/compiler::target::kWordSize * 2,
428-
/*index_unboxed=*/false,
429-
/*array=*/R9,
430-
/*index=*/R8,
431-
/*temp=*/TMP));
432-
__ LoadFieldFromOffset(R9, R9, compiler::target::Code::entry_point_offset());
433-
434-
// Clobbers all volatile registers, including the callback ID in R8.
424+
__ ldr(R10, __ ElementAddressForRegIndex(
425+
/*external=*/false,
426+
/*array_cid=*/kArrayCid,
427+
/*index, smi-tagged=*/compiler::target::kWordSize * 2,
428+
/*index_unboxed=*/false,
429+
/*array=*/R10,
430+
/*index=*/R9,
431+
/*temp=*/TMP));
432+
__ LoadFieldFromOffset(R10, R10,
433+
compiler::target::Code::entry_point_offset());
434+
435+
// Clobbers all volatile registers, including the callback ID in R9.
435436
// Resets CSP and SP, important for EnterSafepoint below.
436-
__ blr(R9);
437+
__ blr(R10);
437438

438-
// EnterSafepoint clobbers TMP, TMP2 and R8 -- all volatile and not holding
439+
// EnterSafepoint clobbers TMP, TMP2 and R9 -- all volatile and not holding
439440
// return values.
440-
__ EnterSafepoint(/*scratch=*/R8);
441+
__ EnterSafepoint(/*scratch=*/R9);
441442

442443
// Pop LR and THR from the real stack (CSP).
443444
__ ldp(THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));

runtime/vm/constants_arm.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,11 @@ extern const char* fpu_d_reg_names[kNumberOfDRegisters];
285285
// Register aliases.
286286
const Register TMP = IP; // Used as scratch register by assembler.
287287
const Register TMP2 = kNoRegister; // There is no second assembler temporary.
288-
const Register PP = R5; // Caches object pool pointer in generated code.
288+
const Register PP = R5; // Caches object pool pointer in generated code.
289289
const Register DISPATCH_TABLE_REG = NOTFP; // Dispatch table register.
290-
const Register SPREG = SP; // Stack pointer register.
291-
const Register FPREG = FP; // Frame pointer register.
292-
const Register LRREG = LR; // Link register.
290+
const Register SPREG = SP; // Stack pointer register.
291+
const Register FPREG = FP; // Frame pointer register.
292+
const Register LRREG = LR; // Link register.
293293
const Register ARGS_DESC_REG = R4;
294294
const Register CODE_REG = R6;
295295
const Register THR = R10; // Caches current thread in generated code.
@@ -453,6 +453,7 @@ class CallingConventions {
453453
static const intptr_t kArgumentRegisters = kAbiArgumentCpuRegs;
454454
static const Register ArgumentRegisters[];
455455
static const intptr_t kNumArgRegs = 4;
456+
static const Register kPointerToReturnStructRegister = R0;
456457

457458
static const intptr_t kFpuArgumentRegisters = 0;
458459

@@ -498,6 +499,10 @@ class CallingConventions {
498499
static constexpr Register kSecondNonArgumentRegister = R9;
499500
static constexpr Register kFirstCalleeSavedCpuReg = R4;
500501
static constexpr Register kStackPointerRegister = SPREG;
502+
503+
COMPILE_ASSERT(
504+
((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
505+
(kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
501506
};
502507

503508
#undef R
@@ -974,7 +979,7 @@ float ReciprocalStep(float op1, float op2);
974979
float ReciprocalSqrtEstimate(float op);
975980
float ReciprocalSqrtStep(float op1, float op2);
976981

977-
constexpr uword kBreakInstructionFiller = 0xE1200070; // bkpt #0
982+
constexpr uword kBreakInstructionFiller = 0xE1200070; // bkpt #0
978983
constexpr uword kDataMemoryBarrier = 0xf57ff050 | 0xb; // dmb ish
979984

980985
} // namespace dart

runtime/vm/constants_arm64.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ class CallingConventions {
308308
static const intptr_t kArgumentRegisters = kAbiArgumentCpuRegs;
309309
static const Register ArgumentRegisters[];
310310
static const intptr_t kNumArgRegs = 8;
311+
// The native ABI uses R8 to pass the pointer to the memory preallocated for
312+
// struct return values. Arm64 is the only ABI in which this pointer is _not_
313+
// in ArgumentRegisters[0] or on the stack.
314+
static const Register kPointerToReturnStructRegister = R8;
311315

312316
static const FpuRegister FpuArgumentRegisters[];
313317
static const intptr_t kFpuArgumentRegisters =
@@ -350,9 +354,13 @@ class CallingConventions {
350354
static constexpr FpuRegister kReturnFpuReg = V0;
351355

352356
static constexpr Register kFirstCalleeSavedCpuReg = kAbiFirstPreservedCpuReg;
353-
static constexpr Register kFirstNonArgumentRegister = R8;
354-
static constexpr Register kSecondNonArgumentRegister = R9;
357+
static constexpr Register kFirstNonArgumentRegister = R9;
358+
static constexpr Register kSecondNonArgumentRegister = R10;
355359
static constexpr Register kStackPointerRegister = SPREG;
360+
361+
COMPILE_ASSERT(
362+
((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
363+
(kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
356364
};
357365

358366
#undef R

runtime/vm/constants_ia32.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ class CallingConventions {
215215
static const intptr_t kArgumentRegisters = 0;
216216
static const intptr_t kFpuArgumentRegisters = 0;
217217
static const intptr_t kNumArgRegs = 0;
218+
static const Register kPointerToReturnStructRegister = kNoRegister;
218219

219220
static const XmmRegister FpuArgumentRegisters[];
220221
static const intptr_t kXmmArgumentRegisters = 0;

runtime/vm/constants_x64.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ class CallingConventions {
271271
static const intptr_t kFpuArgumentRegisters =
272272
R(XMM0) | R(XMM1) | R(XMM2) | R(XMM3);
273273
static const intptr_t kNumFpuArgRegs = 4;
274+
static const intptr_t kPointerToReturnStructRegister = kArg1Reg;
274275

275276
// can ArgumentRegisters[i] and XmmArgumentRegisters[i] both be used at the
276277
// same time? (Windows no, rest yes)
@@ -330,6 +331,7 @@ class CallingConventions {
330331
R(kArg3Reg) | R(kArg4Reg) |
331332
R(kArg5Reg) | R(kArg6Reg);
332333
static const intptr_t kNumArgRegs = 6;
334+
static const Register kPointerToReturnStructRegister = kArg1Reg;
333335

334336
static const XmmRegister FpuArgumentRegisters[];
335337
static const intptr_t kFpuArgumentRegisters = R(XMM0) | R(XMM1) | R(XMM2) |
@@ -394,9 +396,9 @@ class CallingConventions {
394396

395397
COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
396398

397-
COMPILE_ASSERT(((R(kFirstNonArgumentRegister) |
398-
R(kSecondNonArgumentRegister)) &
399-
kArgumentRegisters) == 0);
399+
COMPILE_ASSERT(
400+
((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
401+
(kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
400402
};
401403

402404
#undef R

0 commit comments

Comments
 (0)