Skip to content

Commit 6047403

Browse files
author
Chen Zheng
committed
[PowerPC] Diagnose musttail instead of crash inside backend
musttail does not often possible to generate on PPC targets as when calling to a function defined in another model, PPC needs to restore the TOC pointer. To restore the TOC pointer, compiler needs to emit a nop after the function call to let linker generate codes to restore TOC pointer. Tail call does not generate expected call sequence for this case. To avoid the crash inside the compiler backend, a diagnosis is added in the frontend and in the backend, PPC will change the musttail to tail. Fixes #63214
1 parent 8f49dab commit 6047403

File tree

5 files changed

+70
-4
lines changed

5 files changed

+70
-4
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3841,6 +3841,11 @@ def note_cannot_use_trivial_abi_reason : Note<
38413841
"it is polymorphic|"
38423842
"it has a base of a non-trivial class type|it has a virtual base|"
38433843
"it has a __weak field|it has a field of a non-trivial class type}1">;
3844+
def warn_ppc_musttail_maybe_ignored: Warning<
3845+
"'musttail' attribute may be ignored on ppc targets">,
3846+
InGroup<IgnoredAttributes>;
3847+
def err_aix_musttail_unsupported: Error<
3848+
"'musttail' attribute is not supported on AIX">;
38443849

38453850
// Availability attribute
38463851
def warn_availability_unknown_platform : Warning<

clang/lib/CodeGen/CGCall.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "clang/AST/DeclCXX.h"
2727
#include "clang/AST/DeclObjC.h"
2828
#include "clang/Basic/CodeGenOptions.h"
29+
#include "clang/Basic/DiagnosticSema.h"
2930
#include "clang/Basic/TargetInfo.h"
3031
#include "clang/CodeGen/CGFunctionInfo.h"
3132
#include "clang/CodeGen/SwiftCallingConv.h"
@@ -5751,8 +5752,15 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
57515752
if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) {
57525753
if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>())
57535754
Call->setTailCallKind(llvm::CallInst::TCK_NoTail);
5754-
else if (IsMustTail)
5755+
else if (IsMustTail) {
5756+
if (getTarget().getTriple().isPPC()) {
5757+
if (getTarget().getTriple().isOSAIX())
5758+
CGM.getDiags().Report(Loc, diag::err_aix_musttail_unsupported);
5759+
else
5760+
CGM.getDiags().Report(Loc, diag::warn_ppc_musttail_maybe_ignored);
5761+
}
57555762
Call->setTailCallKind(llvm::CallInst::TCK_MustTail);
5763+
}
57565764
}
57575765

57585766
// Add metadata for calls to MSAllocator functions
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix-xcoff -o /dev/null -emit-llvm -verify=aix
2+
// RUN: %clang_cc1 %s -triple powerpc-ibm-aix-xcoff -o /dev/null -emit-llvm -verify=aix
3+
// RUN: %clang_cc1 %s -triple powerpc64-unknown-linux-gnu -o /dev/null -emit-llvm -verify=linux
4+
// RUN: %clang_cc1 %s -triple powerpc-unknown-linux-gnu -o /dev/null -emit-llvm -verify=linux
5+
// RUN: %clang_cc1 %s -triple powerpc64le-unknown-linux-gnu -o /dev/null -emit-llvm -verify=linux
6+
7+
int Func();
8+
int Func1() {
9+
// linux-warning@+2 {{'musttail' attribute may be ignored on ppc targets}}
10+
// aix-error@+1 {{'musttail' attribute is not supported on AIX}}
11+
[[clang::musttail]] return Func();
12+
}

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ static cl::opt<unsigned> PPCAIXTLSModelOptUseIEForLDLimit(
146146
cl::desc("Set inclusive limit count of TLS local-dynamic access(es) in a "
147147
"function to use initial-exec"));
148148

149+
static cl::opt<bool> AbortOnImpossibleMusttailCall(
150+
"ppc-abort-on-impossible-musttailcall", cl::init(false), cl::Hidden,
151+
cl::desc("Abort if any call marked as musttail is impossible."));
152+
149153
STATISTIC(NumTailCalls, "Number of tail calls");
150154
STATISTIC(NumSiblingCalls, "Number of sibling calls");
151155
STATISTIC(ShufflesHandledWithVPERM,
@@ -5945,9 +5949,14 @@ PPCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
59455949
}
59465950
}
59475951

5948-
if (!isTailCall && CB && CB->isMustTailCall())
5949-
report_fatal_error("failed to perform tail call elimination on a call "
5950-
"site marked musttail");
5952+
if (!isTailCall && CB && CB->isMustTailCall()) {
5953+
if (AbortOnImpossibleMusttailCall)
5954+
report_fatal_error("failed to perform tail call elimination on a call "
5955+
"site marked musttail");
5956+
else
5957+
cast<CallInst>(const_cast<CallBase *>(CB))
5958+
->setTailCallKind(llvm::CallInst::TCK_Tail);
5959+
}
59515960

59525961
// When long calls (i.e. indirect calls) are always used, calls are always
59535962
// made via function pointer. If we have a function name, first translate it
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: not --crash llc -mtriple=powerpc64-ibm-aix-xcoff %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=true | \
2+
; RUN: FileCheck %s --check-prefix=CRASH
3+
; RUN: not --crash llc -mtriple=powerpc-ibm-aix-xcoff %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=true | \
4+
; RUN: FileCheck %s --check-prefix=CRASH
5+
; RUN: not --crash llc -mtriple=powerpc64-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=true | \
6+
; RUN: FileCheck %s --check-prefix=CRASH
7+
; RUN: not --crash llc -mtriple=powerpc-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=true | \
8+
; RUN: FileCheck %s --check-prefix=CRASH
9+
; RUN: not --crash llc -mtriple=powerpc64le-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=true | \
10+
; RUN: FileCheck %s --check-prefix=CRASH
11+
; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=false | \
12+
; RUN: FileCheck %s --check-prefix=NOCRASH
13+
; RUN: llc -mtriple=powerpc-ibm-aix-xcoff %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=false | \
14+
; RUN: FileCheck %s --check-prefix=NOCRASH
15+
; RUN: llc -mtriple=powerpc64-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=false | \
16+
; RUN: FileCheck %s --check-prefix=NOCRASH
17+
; RUN: llc -mtriple=powerpc-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=false | \
18+
; RUN: FileCheck %s --check-prefix=NOCRASH
19+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu %s -o - 2>&1 -ppc-abort-on-impossible-musttailcall=false | \
20+
; RUN: FileCheck %s --check-prefix=NOCRASH
21+
22+
; CRASH: LLVM ERROR: failed to perform tail call elimination on a call site marked musttail
23+
; NOCRASH-NOT: LLVM ERROR: failed to perform tail call elimination on a call site marked musttail
24+
; NOCRASH-LABEL: caller
25+
; NOCRASH: bl {{callee|.callee}}
26+
27+
28+
declare i32 @callee()
29+
define i32 @caller() {
30+
%res = musttail call i32 @callee()
31+
ret i32 %res
32+
}

0 commit comments

Comments
 (0)