Skip to content
Open
Show file tree
Hide file tree
Changes from all 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() }];
}

Comment on lines +512 to +515
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is close to what I was thinking, but I was going for something more like this:

def TargetMustTailAvaiable:  TargetSpec {
  let CustomCode = [{ Target.hasMustTail() }];
}

(so no need to list the architectures)

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">;
Comment on lines +377 to +378
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to add a new diagnostic, we have automatic checking for whether the attribute is supported by the target (that's the code in Attr.td) which will diagnose the attribute as being unknown.


// 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));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can back out this change (it's the only change to the file).

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;
}
Comment on lines +675 to +680
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to add this code, either existsInTarget() (slightly above) will catch it, or checkCommonAttributeFeatures() (slightly below) will.

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);
}