mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[x32] Fix function indirect calls
Summary: Zero-extend register to 64-bit for callq/jmpq. Test Plan: 3 tests added Reviewers: nadav, dschuff Subscribers: llvm-commits, zinovy.nis Differential Revision: http://reviews.llvm.org/D5355 llvm-svn: 217942
This commit is contained in:
parent
270ad5d7f6
commit
b9a0bd8c7b
@ -3119,6 +3119,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|||||||
|
|
||||||
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
|
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
|
||||||
OpFlags);
|
OpFlags);
|
||||||
|
} else if (Subtarget->isTarget64BitILP32() && Callee->getValueType(0) == MVT::i32) {
|
||||||
|
// Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
|
||||||
|
Callee = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Callee);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a chain & a flag for retval copy to use.
|
// Returns a chain & a flag for retval copy to use.
|
||||||
|
20
test/CodeGen/X86/x32-function_pointer-1.ll
Normal file
20
test/CodeGen/X86/x32-function_pointer-1.ll
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
|
||||||
|
|
||||||
|
; Test for x32 function pointer tail call
|
||||||
|
|
||||||
|
@foo1 = external global void (i8*)*
|
||||||
|
@foo2 = external global void (i8*)*
|
||||||
|
|
||||||
|
define void @bar(i8* %h) nounwind uwtable {
|
||||||
|
entry:
|
||||||
|
%0 = load void (i8*)** @foo1, align 4
|
||||||
|
; CHECK: movl foo1(%rip), %e{{[^,]*}}
|
||||||
|
tail call void %0(i8* %h) nounwind
|
||||||
|
; CHECK: callq *%r{{[^,]*}}
|
||||||
|
%1 = load void (i8*)** @foo2, align 4
|
||||||
|
; CHECK: movl foo2(%rip), %e{{[^,]*}}
|
||||||
|
tail call void %1(i8* %h) nounwind
|
||||||
|
; CHECK: jmpq *%r{{[^,]*}}
|
||||||
|
ret void
|
||||||
|
}
|
21
test/CodeGen/X86/x32-function_pointer-2.ll
Normal file
21
test/CodeGen/X86/x32-function_pointer-2.ll
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
|
||||||
|
|
||||||
|
; Test call function pointer with function argument
|
||||||
|
;
|
||||||
|
; void bar (void * h, void (*foo) (void *))
|
||||||
|
; {
|
||||||
|
; foo (h);
|
||||||
|
; foo (h);
|
||||||
|
; }
|
||||||
|
|
||||||
|
|
||||||
|
define void @bar(i8* %h, void (i8*)* nocapture %foo) nounwind {
|
||||||
|
entry:
|
||||||
|
tail call void %foo(i8* %h) nounwind
|
||||||
|
; CHECK: mov{{l|q}} %{{e|r}}si, %{{e|r}}[[REG:.*]]{{d?}}
|
||||||
|
; CHECK: callq *%r[[REG]]
|
||||||
|
tail call void %foo(i8* %h) nounwind
|
||||||
|
; CHECK: jmpq *%r{{[^,]*}}
|
||||||
|
ret void
|
||||||
|
}
|
30
test/CodeGen/X86/x32-function_pointer-3.ll
Normal file
30
test/CodeGen/X86/x32-function_pointer-3.ll
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
|
||||||
|
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
|
||||||
|
|
||||||
|
; Test calling function pointer passed in struct
|
||||||
|
|
||||||
|
; The fuction argument `h' in
|
||||||
|
|
||||||
|
; struct foo {
|
||||||
|
; void (*f) (void);
|
||||||
|
; int i;
|
||||||
|
; };
|
||||||
|
; void
|
||||||
|
; bar (struct foo h)
|
||||||
|
; {
|
||||||
|
; h.f ();
|
||||||
|
; }
|
||||||
|
|
||||||
|
; is passed in the 64-bit %rdi register. The `f' field is in the lower 32
|
||||||
|
; bits of %rdi register and the `i' field is in the upper 32 bits of %rdi
|
||||||
|
; register. We need to zero-extend %edi to %rdi before branching via %rdi.
|
||||||
|
|
||||||
|
define void @bar(i64 %h.coerce) nounwind {
|
||||||
|
entry:
|
||||||
|
%h.sroa.0.0.extract.trunc = trunc i64 %h.coerce to i32
|
||||||
|
%0 = inttoptr i32 %h.sroa.0.0.extract.trunc to void ()*
|
||||||
|
; CHECK: movl %edi, %e[[REG:.*]]
|
||||||
|
tail call void %0() nounwind
|
||||||
|
; CHECK: jmpq *%r[[REG]]
|
||||||
|
ret void
|
||||||
|
}
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
define i32 @far() nounwind uwtable {
|
define i32 @far() nounwind uwtable {
|
||||||
entry:
|
entry:
|
||||||
; CHECK: callq
|
; CHECK: callq foo
|
||||||
; IA32: calll
|
; IA32: calll foo
|
||||||
tail call void @foo() nounwind
|
tail call void @foo() nounwind
|
||||||
ret i32 0
|
ret i32 0
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user