Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 780f7e2

Browse files
author
Pavel Chupin
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217942 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent cc0c4e7 commit 780f7e2

File tree

5 files changed

+76
-2
lines changed

5 files changed

+76
-2
lines changed

lib/Target/X86/X86ISelLowering.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3119,6 +3119,9 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
31193119

31203120
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(),
31213121
OpFlags);
3122+
} else if (Subtarget->isTarget64BitILP32() && Callee->getValueType(0) == MVT::i32) {
3123+
// Zero-extend the 32-bit Callee address into a 64-bit according to x32 ABI
3124+
Callee = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i64, Callee);
31223125
}
31233126

31243127
// Returns a chain & a flag for retval copy to use.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
2+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
3+
4+
; Test for x32 function pointer tail call
5+
6+
@foo1 = external global void (i8*)*
7+
@foo2 = external global void (i8*)*
8+
9+
define void @bar(i8* %h) nounwind uwtable {
10+
entry:
11+
%0 = load void (i8*)** @foo1, align 4
12+
; CHECK: movl foo1(%rip), %e{{[^,]*}}
13+
tail call void %0(i8* %h) nounwind
14+
; CHECK: callq *%r{{[^,]*}}
15+
%1 = load void (i8*)** @foo2, align 4
16+
; CHECK: movl foo2(%rip), %e{{[^,]*}}
17+
tail call void %1(i8* %h) nounwind
18+
; CHECK: jmpq *%r{{[^,]*}}
19+
ret void
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
2+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
3+
4+
; Test call function pointer with function argument
5+
;
6+
; void bar (void * h, void (*foo) (void *))
7+
; {
8+
; foo (h);
9+
; foo (h);
10+
; }
11+
12+
13+
define void @bar(i8* %h, void (i8*)* nocapture %foo) nounwind {
14+
entry:
15+
tail call void %foo(i8* %h) nounwind
16+
; CHECK: mov{{l|q}} %{{e|r}}si, %{{e|r}}[[REG:.*]]{{d?}}
17+
; CHECK: callq *%r[[REG]]
18+
tail call void %foo(i8* %h) nounwind
19+
; CHECK: jmpq *%r{{[^,]*}}
20+
ret void
21+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 | FileCheck %s
2+
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -fast-isel | FileCheck %s
3+
4+
; Test calling function pointer passed in struct
5+
6+
; The fuction argument `h' in
7+
8+
; struct foo {
9+
; void (*f) (void);
10+
; int i;
11+
; };
12+
; void
13+
; bar (struct foo h)
14+
; {
15+
; h.f ();
16+
; }
17+
18+
; is passed in the 64-bit %rdi register. The `f' field is in the lower 32
19+
; bits of %rdi register and the `i' field is in the upper 32 bits of %rdi
20+
; register. We need to zero-extend %edi to %rdi before branching via %rdi.
21+
22+
define void @bar(i64 %h.coerce) nounwind {
23+
entry:
24+
%h.sroa.0.0.extract.trunc = trunc i64 %h.coerce to i32
25+
%0 = inttoptr i32 %h.sroa.0.0.extract.trunc to void ()*
26+
; CHECK: movl %edi, %e[[REG:.*]]
27+
tail call void %0() nounwind
28+
; CHECK: jmpq *%r[[REG]]
29+
ret void
30+
}

test/CodeGen/X86/x86-64-call.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
define i32 @far() nounwind uwtable {
88
entry:
9-
; CHECK: callq
10-
; IA32: calll
9+
; CHECK: callq foo
10+
; IA32: calll foo
1111
tail call void @foo() nounwind
1212
ret i32 0
1313
}

0 commit comments

Comments
 (0)