Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
def TargetSPIRV : TargetArch<["spirv", "spirv32", "spirv64"]>;
def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
def TargetPowerPC : TargetArch<["ppc", "ppcle", "ppc64", "ppc64le"]>;
def TargetWindows : TargetSpec {
let OSes = ["Win32"];
}
Expand All @@ -508,6 +509,10 @@ def TargetMicrosoftRecordLayout : TargetArch<["x86", "x86_64", "arm", "thumb",
let CustomCode = [{ Target.hasMicrosoftRecordLayout() }];
}

def TargetMustTailAvaiable: TargetArch<!listconcat(TargetARM.Arches, TargetAArch64.Arches, TargetAnyX86.Arches, TargetWebAssembly.Arches, TargetPowerPC.Arches)> {
let CustomCode = [{ Target.hasMustTail() }];
}

def TargetELF : TargetSpec {
let ObjectFormats = ["ELF"];
}
Expand Down Expand Up @@ -1896,7 +1901,7 @@ def NoMerge : DeclOrStmtAttr {
"functions, statements and variables">;
}

def MustTail : StmtAttr {
def MustTail : StmtAttr, TargetSpecificAttr<TargetMustTailAvaiable> {
let Spellings = [Clang<"musttail">];
let Documentation = [MustTailDocs];
let Subjects = SubjectList<[ReturnStmt], ErrorDiag, "return statements">;
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,8 @@ def err_ppc_impossible_musttail: Error<
>;
def err_aix_musttail_unsupported: Error<
"'musttail' attribute is not supported on AIX">;
def err_wasm_musttail_unsupported: Error<
"'musttail' attribute is not supported on this target without tail-call feature">;

// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class TargetInfo : public TransferrableTargetInfo,
protected:
// Target values set by the ctor of the actual target implementation. Default
// values are specified by the TargetInfo constructor.
bool HasMustTail;
bool BigEndian;
bool TLSSupported;
bool VLASupported;
Expand Down Expand Up @@ -669,6 +670,8 @@ class TargetInfo : public TransferrableTargetInfo,
: getLongFractScale() + 1;
}

virtual bool hasMustTail() const { return HasMustTail; }

/// Determine whether the __int128 type is supported on this target.
virtual bool hasInt128Type() const {
return (getPointerWidth(LangAS::Default) >= 64) ||
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static const LangASMap FakeAddrSpaceMap = {
TargetInfo::TargetInfo(const llvm::Triple &T) : Triple(T) {
// Set defaults. Defaults are set for a 32-bit RISC platform, like PPC or
// SPARC. These should be overridden by concrete targets as needed.
HasMustTail = true;
BigEndian = !T.isLittleEndian();
TLSSupported = true;
VLASupported = true;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ bool WebAssemblyTargetInfo::initFeatureMap(

bool WebAssemblyTargetInfo::handleTargetFeatures(
std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
HasMustTail = false;
for (const auto &Feature : Features) {
if (Feature == "+atomics") {
HasAtomics = true;
Expand Down Expand Up @@ -345,10 +346,12 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
}
if (Feature == "+tail-call") {
HasTailCall = true;
HasMustTail = true;
continue;
}
if (Feature == "-tail-call") {
HasTailCall = false;
HasMustTail = false;
continue;
}
if (Feature == "+wide-arithmetic") {
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,6 @@ bool Sema::checkMustTailAttr(const Stmt *St, const Attr &MTA) {

const Expr *E = cast<ReturnStmt>(St)->getRetValue();
const auto *CE = dyn_cast_or_null<CallExpr>(IgnoreParenImplicitAsWritten(E));

if (!CE) {
Diag(St->getBeginLoc(), diag::err_musttail_needs_call) << &MTA;
return false;
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Sema/SemaStmtAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,12 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
!(A.existsInTarget(S.Context.getTargetInfo()) ||
(S.Context.getLangOpts().SYCLIsDevice && Aux &&
A.existsInTarget(*Aux)))) {
// Special case: musttail on WebAssembly without tail-call feature
if (A.getKind() == ParsedAttr::AT_MustTail &&
!S.Context.getTargetInfo().hasMustTail()) {
S.Diag(A.getLoc(), diag::err_wasm_musttail_unsupported);
return nullptr;
}
if (A.isRegularKeywordAttribute()) {
S.Diag(A.getLoc(), diag::err_keyword_not_supported_on_target)
<< A << A.getRange();
Expand Down
20 changes: 20 additions & 0 deletions clang/test/CodeGen/WebAssembly/musttail.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -target-feature +tail-call -o /dev/null -emit-llvm -verify=tail
// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -o /dev/null -emit-llvm -verify=notail

int foo(int x) {
return x;
}

#if __has_attribute(musttail)
// tail-warning@+1 {{HAS IT}}
#warning HAS IT
#else
// notail-warning@+1 {{DOES NOT HAVE}}
#warning DOES NOT HAVE
#endif

int bar(int x)
{
// notail-error@+1 {{'musttail' attribute is not supported on this target without tail-call feature}}
[[clang::musttail]] return foo(1);
}