[llvm] r217942 - [x32] Fix function indirect calls
Pavel Chupin
pavel.v.chupin at intel.com
Wed Sep 17 00:09:23 PDT 2014
Author: pvchupin
Date: Wed Sep 17 02:09:23 2014
New Revision: 217942
URL: http://llvm.org/viewvc/llvm-project?rev=217942&view=rev
Log:
[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
Added:
llvm/trunk/test/CodeGen/X86/x32-function_pointer-1.ll
llvm/trunk/test/CodeGen/X86/x32-function_pointer-2.ll
llvm/trunk/test/CodeGen/X86/x32-function_pointer-3.ll
Modified:
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
llvm/trunk/test/CodeGen/X86/x86-64-call.ll
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=217942&r1=217941&r2=217942&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Sep 17 02:09:23 2014
@@ -3119,6 +3119,9 @@ X86TargetLowering::LowerCall(TargetLower
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
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.
Added: llvm/trunk/test/CodeGen/X86/x32-function_pointer-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x32-function_pointer-1.ll?rev=217942&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x32-function_pointer-1.ll (added)
+++ llvm/trunk/test/CodeGen/X86/x32-function_pointer-1.ll Wed Sep 17 02:09:23 2014
@@ -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
+
+ at foo1 = external global void (i8*)*
+ at 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
+}
Added: llvm/trunk/test/CodeGen/X86/x32-function_pointer-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x32-function_pointer-2.ll?rev=217942&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x32-function_pointer-2.ll (added)
+++ llvm/trunk/test/CodeGen/X86/x32-function_pointer-2.ll Wed Sep 17 02:09:23 2014
@@ -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
+}
Added: llvm/trunk/test/CodeGen/X86/x32-function_pointer-3.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x32-function_pointer-3.ll?rev=217942&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x32-function_pointer-3.ll (added)
+++ llvm/trunk/test/CodeGen/X86/x32-function_pointer-3.ll Wed Sep 17 02:09:23 2014
@@ -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
+}
Modified: llvm/trunk/test/CodeGen/X86/x86-64-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-64-call.ll?rev=217942&r1=217941&r2=217942&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x86-64-call.ll (original)
+++ llvm/trunk/test/CodeGen/X86/x86-64-call.ll Wed Sep 17 02:09:23 2014
@@ -6,8 +6,8 @@
define i32 @far() nounwind uwtable {
entry:
-; CHECK: callq
-; IA32: calll
+; CHECK: callq foo
+; IA32: calll foo
tail call void @foo() nounwind
ret i32 0
}
More information about the llvm-commits
mailing list