mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-18 13:34:04 +00:00
[PowerPC] Support symbolic targets in patchpoints
Follow-up r235483, with the corresponding support in PPC. We use a regular call for symbolic targets (because they're much cheaper than indirect calls). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242239 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
96b5986e38
commit
a67262f6bc
@ -363,71 +363,85 @@ void PPCAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
|
||||
SM.recordPatchPoint(MI);
|
||||
PatchPointOpers Opers(&MI);
|
||||
|
||||
int64_t CallTarget = Opers.getMetaOper(PatchPointOpers::TargetPos).getImm();
|
||||
unsigned EncodedBytes = 0;
|
||||
if (CallTarget) {
|
||||
assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
|
||||
"High 16 bits of call target should be zero.");
|
||||
unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
|
||||
EncodedBytes = 0;
|
||||
// Materialize the jump address:
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LI8)
|
||||
.addReg(ScratchReg)
|
||||
.addImm((CallTarget >> 32) & 0xFFFF));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::RLDIC)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(32).addImm(16));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORIS8)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm((CallTarget >> 16) & 0xFFFF));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORI8)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(CallTarget & 0xFFFF));
|
||||
const MachineOperand &CalleeMO =
|
||||
Opers.getMetaOper(PatchPointOpers::TargetPos);
|
||||
|
||||
// Save the current TOC pointer before the remote call.
|
||||
int TOCSaveOffset = Subtarget->isELFv2ABI() ? 24 : 40;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::STD)
|
||||
.addReg(PPC::X2)
|
||||
.addImm(TOCSaveOffset)
|
||||
.addReg(PPC::X1));
|
||||
++EncodedBytes;
|
||||
if (CalleeMO.isImm()) {
|
||||
int64_t CallTarget = Opers.getMetaOper(PatchPointOpers::TargetPos).getImm();
|
||||
if (CallTarget) {
|
||||
assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
|
||||
"High 16 bits of call target should be zero.");
|
||||
unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
|
||||
EncodedBytes = 0;
|
||||
// Materialize the jump address:
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LI8)
|
||||
.addReg(ScratchReg)
|
||||
.addImm((CallTarget >> 32) & 0xFFFF));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::RLDIC)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(32).addImm(16));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORIS8)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm((CallTarget >> 16) & 0xFFFF));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::ORI8)
|
||||
.addReg(ScratchReg)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(CallTarget & 0xFFFF));
|
||||
|
||||
// Save the current TOC pointer before the remote call.
|
||||
int TOCSaveOffset = Subtarget->isELFv2ABI() ? 24 : 40;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::STD)
|
||||
.addReg(PPC::X2)
|
||||
.addImm(TOCSaveOffset)
|
||||
.addReg(PPC::X1));
|
||||
++EncodedBytes;
|
||||
|
||||
|
||||
// If we're on ELFv1, then we need to load the actual function pointer from
|
||||
// the function descriptor.
|
||||
if (!Subtarget->isELFv2ABI()) {
|
||||
// Load the new TOC pointer and the function address, but not r11
|
||||
// (needing this is rare, and loading it here would prevent passing it
|
||||
// via a 'nest' parameter.
|
||||
// If we're on ELFv1, then we need to load the actual function pointer
|
||||
// from the function descriptor.
|
||||
if (!Subtarget->isELFv2ABI()) {
|
||||
// Load the new TOC pointer and the function address, but not r11
|
||||
// (needing this is rare, and loading it here would prevent passing it
|
||||
// via a 'nest' parameter.
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LD)
|
||||
.addReg(PPC::X2)
|
||||
.addImm(8)
|
||||
.addReg(ScratchReg));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LD)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(0)
|
||||
.addReg(ScratchReg));
|
||||
++EncodedBytes;
|
||||
}
|
||||
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTCTR8)
|
||||
.addReg(ScratchReg));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCTRL8));
|
||||
++EncodedBytes;
|
||||
|
||||
// Restore the TOC pointer after the call.
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LD)
|
||||
.addReg(PPC::X2)
|
||||
.addImm(8)
|
||||
.addReg(ScratchReg));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LD)
|
||||
.addReg(ScratchReg)
|
||||
.addImm(0)
|
||||
.addReg(ScratchReg));
|
||||
.addImm(TOCSaveOffset)
|
||||
.addReg(PPC::X1));
|
||||
++EncodedBytes;
|
||||
}
|
||||
} else if (CalleeMO.isGlobal()) {
|
||||
const GlobalValue *GValue = CalleeMO.getGlobal();
|
||||
MCSymbol *MOSymbol = getSymbol(GValue);
|
||||
const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext);
|
||||
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::MTCTR8).addReg(ScratchReg));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BCTRL8));
|
||||
++EncodedBytes;
|
||||
|
||||
// Restore the TOC pointer after the call.
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::LD)
|
||||
.addReg(PPC::X2)
|
||||
.addImm(TOCSaveOffset)
|
||||
.addReg(PPC::X1));
|
||||
++EncodedBytes;
|
||||
EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL8_NOP)
|
||||
.addExpr(SymVar));
|
||||
EncodedBytes += 2;
|
||||
}
|
||||
|
||||
// Each instruction is 4 bytes.
|
||||
|
@ -103,6 +103,21 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Trivial symbolic patchpoint codegen.
|
||||
|
||||
declare i64 @foo(i64 %p1, i64 %p2)
|
||||
define i64 @trivial_symbolic_patchpoint_codegen(i64 %p1, i64 %p2) {
|
||||
entry:
|
||||
; CHECK-LABEL: trivial_symbolic_patchpoint_codegen:
|
||||
; CHECK: bl foo
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NEXT: nop
|
||||
; CHECK-NOT: nop
|
||||
; CHECK: blr
|
||||
%result = tail call i64 (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.i64(i64 9, i32 12, i8* bitcast (i64 (i64, i64)* @foo to i8*), i32 2, i64 %p1, i64 %p2)
|
||||
ret i64 %result
|
||||
}
|
||||
|
||||
declare void @llvm.experimental.stackmap(i64, i32, ...)
|
||||
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
|
||||
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
|
||||
|
Loading…
x
Reference in New Issue
Block a user