mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-20 09:30:43 +00:00
336da8cdc5
The PowerPC back-end uses BLA to implement calls to functions at known-constant addresses, which is apparently used for certain system routines on Darwin. However, with the 64-bit SVR4 ABI, this is actually incorrect. An immediate function pointer value on this platform is not directly usable as a target address for BLA: - in the ELFv1 ABI, the function pointer value refers to the *function descriptor*, not the code address - in the ELFv2 ABI, the function pointer value refers to the global entry point, but BL(A) would only be correct when calling the *local* entry point This bug didn't show up since using immediate function pointer values is not usually done in the 64-bit SVR4 ABI in the first place. However, I ran into this issue with a certain use case of LLVM as JIT, where immediate function pointer values were uses to implement callbacks from JITted code to helpers in statically compiled code. Fixed by simply not using BLA with the 64-bit SVR4 ABI. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211174 91177308-0d34-0410-b5e6-96231b3b80d8
55 lines
1.4 KiB
LLVM
55 lines
1.4 KiB
LLVM
; RUN: llc < %s -march=ppc64 | FileCheck %s
|
|
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"
|
|
target triple = "powerpc64-unknown-linux-gnu"
|
|
|
|
define void @foo() nounwind readnone noinline {
|
|
ret void
|
|
}
|
|
|
|
define weak void @foo_weak() nounwind {
|
|
ret void
|
|
}
|
|
|
|
; Calls to local function does not require the TOC restore 'nop'
|
|
define void @test_direct() nounwind readnone {
|
|
; CHECK-LABEL: test_direct:
|
|
tail call void @foo() nounwind
|
|
; CHECK: bl foo
|
|
; CHECK-NOT: nop
|
|
ret void
|
|
}
|
|
|
|
; Calls to weak function requires a TOC restore 'nop' because they
|
|
; may be overridden in a different module.
|
|
define void @test_weak() nounwind readnone {
|
|
; CHECK-LABEL: test_weak:
|
|
tail call void @foo_weak() nounwind
|
|
; CHECK: bl foo
|
|
; CHECK-NEXT: nop
|
|
ret void
|
|
}
|
|
|
|
; Indirect calls requires a full stub creation
|
|
define void @test_indirect(void ()* nocapture %fp) nounwind {
|
|
; CHECK-LABEL: test_indirect:
|
|
tail call void %fp() nounwind
|
|
; CHECK: ld [[FP:[0-9]+]], 0(3)
|
|
; CHECK: ld 11, 16(3)
|
|
; CHECK: ld 2, 8(3)
|
|
; CHECK-NEXT: mtctr [[FP]]
|
|
; CHECK-NEXT: bctrl
|
|
; CHECK-NEXT: ld 2, 40(1)
|
|
ret void
|
|
}
|
|
|
|
declare double @sin(double) nounwind
|
|
|
|
; External functions call should also have a 'nop'
|
|
define double @test_external(double %x) nounwind {
|
|
; CHECK-LABEL: test_external:
|
|
%call = tail call double @sin(double %x) nounwind
|
|
; CHECK: bl sin
|
|
; CHECK-NEXT: nop
|
|
ret double %call
|
|
}
|