mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 20:32:21 +00:00
[FastISel][X86] Add support for the frameaddress intrinsic.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@210709 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e4cd27799
commit
a2d36a20fa
@ -1653,6 +1653,58 @@ bool X86FastISel::X86VisitIntrinsicCall(const IntrinsicInst &I) {
|
||||
// FIXME: Handle more intrinsics.
|
||||
switch (I.getIntrinsicID()) {
|
||||
default: return false;
|
||||
case Intrinsic::frameaddress: {
|
||||
Type *RetTy = I.getCalledFunction()->getReturnType();
|
||||
|
||||
MVT VT;
|
||||
if (!isTypeLegal(RetTy, VT))
|
||||
return false;
|
||||
|
||||
unsigned Opc;
|
||||
const TargetRegisterClass *RC = nullptr;
|
||||
|
||||
switch (VT.SimpleTy) {
|
||||
default: llvm_unreachable("Invalid result type for frameaddress.");
|
||||
case MVT::i32: Opc = X86::MOV32rm; RC = &X86::GR32RegClass; break;
|
||||
case MVT::i64: Opc = X86::MOV64rm; RC = &X86::GR64RegClass; break;
|
||||
}
|
||||
|
||||
// This needs to be set before we call getFrameRegister, otherwise we get
|
||||
// the wrong frame register.
|
||||
MachineFrameInfo *MFI = FuncInfo.MF->getFrameInfo();
|
||||
MFI->setFrameAddressIsTaken(true);
|
||||
|
||||
const X86RegisterInfo *RegInfo =
|
||||
static_cast<const X86RegisterInfo*>(TM.getRegisterInfo());
|
||||
unsigned FrameReg = RegInfo->getFrameRegister(*(FuncInfo.MF));
|
||||
assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
|
||||
(FrameReg == X86::EBP && VT == MVT::i32)) &&
|
||||
"Invalid Frame Register!");
|
||||
|
||||
// Always make a copy of the frame register to to a vreg first, so that we
|
||||
// never directly reference the frame register (the TwoAddressInstruction-
|
||||
// Pass doesn't like that).
|
||||
unsigned SrcReg = createResultReg(RC);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(TargetOpcode::COPY), SrcReg).addReg(FrameReg);
|
||||
|
||||
// Now recursively load from the frame address.
|
||||
// movq (%rbp), %rax
|
||||
// movq (%rax), %rax
|
||||
// movq (%rax), %rax
|
||||
// ...
|
||||
unsigned DestReg;
|
||||
unsigned Depth = cast<ConstantInt>(I.getOperand(0))->getZExtValue();
|
||||
while (Depth--) {
|
||||
DestReg = createResultReg(RC);
|
||||
addDirectMem(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(Opc), DestReg), SrcReg);
|
||||
SrcReg = DestReg;
|
||||
}
|
||||
|
||||
UpdateValueMap(&I, SrcReg);
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::memcpy: {
|
||||
const MemCpyInst &MCI = cast<MemCpyInst>(I);
|
||||
// Don't handle volatile or variable length memcpys.
|
||||
|
27
test/CodeGen/X86/frameaddr.ll
Normal file
27
test/CodeGen/X86/frameaddr.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; RUN: llc < %s -march=x86 | FileCheck %s --check-prefix=CHECK-32
|
||||
; RUN: llc < %s -march=x86 -fast-isel -fast-isel-abort | FileCheck %s --check-prefix=CHECK-32
|
||||
; RUN: llc < %s -march=x86-64 | FileCheck %s --check-prefix=CHECK-64
|
||||
; RUN: llc < %s -march=x86-64 -fast-isel -fast-isel-abort | FileCheck %s --check-prefix=CHECK-64
|
||||
|
||||
define i8* @test1() nounwind {
|
||||
entry:
|
||||
; CHECK-32: movl %esp, %ebp
|
||||
; CHECK-32-NEXT: movl %ebp, %eax
|
||||
; CHECK-64: movq %rsp, %rbp
|
||||
; CHECK-64-NEXT: movq %rbp, %rax
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
||||
ret i8* %0
|
||||
}
|
||||
|
||||
define i8* @test2() nounwind {
|
||||
entry:
|
||||
; CHECK-32: movl %esp, %ebp
|
||||
; CHECK-32-NEXT: movl (%ebp), %eax
|
||||
; CHECK-32-NEXT: movl (%eax), %eax
|
||||
; CHECK-64: movq %rsp, %rbp
|
||||
; CHECK-64-NEXT: movq (%rbp), %rax
|
||||
; CHECK-64-NEXT: movq (%rax), %rax
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 2)
|
||||
ret i8* %0
|
||||
}
|
||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
@ -1,15 +0,0 @@
|
||||
; RUN: llc < %s -march=x86-64 | FileCheck %s
|
||||
|
||||
; CHECK: stack_end_address
|
||||
; CHECK: {{movq.+rbp.*$}}
|
||||
; CHECK: {{movq.+rbp.*$}}
|
||||
; CHECK: ret
|
||||
|
||||
define i64* @stack_end_address() nounwind {
|
||||
entry:
|
||||
tail call i8* @llvm.frameaddress( i32 0 )
|
||||
bitcast i8* %0 to i64*
|
||||
ret i64* %1
|
||||
}
|
||||
|
||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
@ -1,9 +0,0 @@
|
||||
; RUN: llc < %s -march=x86 | grep mov | grep ebp
|
||||
|
||||
define i8* @t() nounwind {
|
||||
entry:
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 0)
|
||||
ret i8* %0
|
||||
}
|
||||
|
||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
@ -1,9 +0,0 @@
|
||||
; RUN: llc < %s -march=x86 | grep mov | count 3
|
||||
|
||||
define i8* @t() nounwind {
|
||||
entry:
|
||||
%0 = tail call i8* @llvm.frameaddress(i32 2)
|
||||
ret i8* %0
|
||||
}
|
||||
|
||||
declare i8* @llvm.frameaddress(i32) nounwind readnone
|
Loading…
Reference in New Issue
Block a user