Statepoint: Fix handling of Far Immediate calls

gc.statepoint intrinsics with a far immediate call target 
were lowered incorrectly as pc-rel32 calls.

This change fixes the problem, and generates an indirect call 
via a scratch register.

For example: 

Intrinsic:
  %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* inttoptr (i64 140727162896504 to void ()*), i32 0, i32 0, i32 0, i32 0)

Old Incorrect Lowering:
  callq 140727162896504

New Correct Lowering:
  movabsq $140727162896504, %rax 
  callq *%rax

In lowerCallFromStatepoint(), the callee-target was modified and 
represented as a "TargetConstant" node, rather than a "Constant" node.
Undoing this modification enabled LowerCall() to generate the 
correct CALL instruction.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239114 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Swaroop Sridhar 2015-06-04 23:03:21 +00:00
parent 1ea35c2d52
commit bb3883dfba
2 changed files with 22 additions and 11 deletions

View File

@ -238,17 +238,6 @@ lowerCallFromStatepoint(ImmutableStatepoint ISP, MachineBasicBlock *LandingPad,
SDValue ActualCallee = Builder.getValue(ISP.getActualCallee());
// Handle immediate and symbolic callees.
if (auto *ConstCallee = dyn_cast<ConstantSDNode>(ActualCallee.getNode()))
ActualCallee = Builder.DAG.getIntPtrConstant(ConstCallee->getZExtValue(),
Builder.getCurSDLoc(),
/*isTarget=*/true);
else if (auto *SymbolicCallee =
dyn_cast<GlobalAddressSDNode>(ActualCallee.getNode()))
ActualCallee = Builder.DAG.getTargetGlobalAddress(
SymbolicCallee->getGlobal(), SDLoc(SymbolicCallee),
SymbolicCallee->getValueType(0));
assert(CS.getCallingConv() != CallingConv::AnyReg &&
"anyregcc is not supported on statepoints!");

View File

@ -0,0 +1,22 @@
; RUN: llc < %s | FileCheck %s
; Test to check that Statepoints with X64 far-immediate targets
; are lowered correctly to an indirect call via a scratch register.
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-win64"
define void @test_far_call() gc "statepoint-example" {
; CHECK-LABEL: test_far_call
; CHECK: pushq %rax
; CHECK: movabsq $140727162896504, %rax
; CHECK: callq *%rax
; CHECK: popq %rax
; CHECK: retq
entry:
%safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* inttoptr (i64 140727162896504 to void ()*), i32 0, i32 0, i32 0, i32 0)
ret void
}
declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)