Skip to content
Merged
35 changes: 25 additions & 10 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2950,12 +2950,11 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}

static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
if (S.Context.getTargetInfo().getTriple().isLoongArch()) {
static bool isValidCodeModelAttr(llvm::Triple Triple, StringRef Str) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Triple contains a std::string, I wouldn't treat it as a cheap-to-copy value type:
https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/TargetParser/Triple.h#L321

Copy link
Contributor

Choose a reason for hiding this comment

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

Right. This should be fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

if (Triple.isLoongArch()) {
return Str == "normal" || Str == "medium" || Str == "extreme";
} else {
assert(S.Context.getTargetInfo().getTriple().getArch() ==
llvm::Triple::x86_64 &&
assert(Triple.getArch() == llvm::Triple::x86_64 &&
"only loongarch/x86-64 supported");
return Str == "small" || Str == "large";
}
Expand All @@ -2964,20 +2963,36 @@ static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
StringRef Str;
SourceLocation LiteralLoc;
auto IsTripleSupported = [](const llvm::Triple Triple) {
return Triple.getArch() == llvm::Triple::ArchType::x86_64 ||
Triple.isLoongArch();
};

// Check that it is a string.
if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc))
return;

// Ignore the attribute for GPU device compiles since it only applies to host
// globals.
if (S.Context.getTargetInfo().getTriple().isNVPTX() ||
S.Context.getTargetInfo().getTriple().isAMDGPU() ||
S.Context.getTargetInfo().getTriple().isSPIRV())
SmallVector<llvm::Triple, 2> Triples = {
S.Context.getTargetInfo().getTriple()};
if (auto *aux = S.Context.getAuxTargetInfo()) {
Triples.push_back(aux->getTriple());
} else if (S.Context.getTargetInfo().getTriple().isNVPTX() ||
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 not actionable in this patch, but this points to the need for some kind of isGPU / isVirtualISA predicate.

Copy link
Contributor

Choose a reason for hiding this comment

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

i agree.

S.Context.getTargetInfo().getTriple().isAMDGPU() ||
S.Context.getTargetInfo().getTriple().isSPIRV()) {
// Ignore the attribute for pure GPU device compiles since it only applies
// to host globals.
return;
}

auto SupportedTripleIt = llvm::find_if(Triples, IsTripleSupported);
if (SupportedTripleIt == Triples.end()) {
Comment on lines +2987 to +2988
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this be if (llvm::none_of(Triple, IsTripleSupported))?

Copy link
Contributor

Choose a reason for hiding this comment

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

this was done this way because we also need the SupportedTripleIt later in line 2995

S.Diag(LiteralLoc, diag::warn_unknown_attribute_ignored) << AL;
return;
}

llvm::CodeModel::Model CM;
if (!CodeModelAttr::ConvertStrToModel(Str, CM) ||
!isValidCodeModelAttr(S, Str)) {
!isValidCodeModelAttr(*SupportedTripleIt, Str)) {
S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str;
return;
}
Expand Down
46 changes: 35 additions & 11 deletions clang/test/Sema/attr-model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,60 @@
// RUN: %clang_cc1 -triple spirv32-unknown-unknown -verify=ignored -fsyntax-only %s
// RUN: %clang_cc1 -triple spirv64-unknown-unknown -verify=ignored -fsyntax-only %s

// RUN: %clang_cc1 -triple x86_64 -aux-triple nvptx64 -x cuda -verify=x86_64 -fsyntax-only %s
// RUN: %clang_cc1 -triple nvptx64 -aux-triple x86_64 -x cuda -fcuda-is-device -verify=nvptx64-x86_64 -fsyntax-only %s
// RUN: %clang_cc1 -triple aarch64 -aux-triple nvptx64 -x cuda -verify=unsupported -fsyntax-only %s
// RUN: %clang_cc1 -triple nvptx64 -aux-triple aarch64 -x cuda -fcuda-is-device -verify=nvptx64-unsupported -fsyntax-only %s

#if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
#error "Should support model attribute"
#endif

int a __attribute((model("tiny"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// loongarch64-error {{code model 'tiny' is not supported on this target}} \
// x86_64-error {{code model 'tiny' is not supported on this target}}
// x86_64-error {{code model 'tiny' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'tiny' is not supported on this target}}
int b __attribute((model("small"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// loongarch64-error {{code model 'small' is not supported on this target}}
// loongarch64-error {{code model 'small' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}}
int c __attribute((model("normal"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// x86_64-error {{code model 'normal' is not supported on this target}}
// x86_64-error {{code model 'normal' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'normal' is not supported on this target}}
int d __attribute((model("kernel"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// loongarch64-error {{code model 'kernel' is not supported on this target}} \
// x86_64-error {{code model 'kernel' is not supported on this target}}
// x86_64-error {{code model 'kernel' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'kernel' is not supported on this target}}
int e __attribute((model("medium"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// x86_64-error {{code model 'medium' is not supported on this target}}
// x86_64-error {{code model 'medium' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'medium' is not supported on this target}}
int f __attribute((model("large"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// loongarch64-error {{code model 'large' is not supported on this target}}
// loongarch64-error {{code model 'large' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}}
int g __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// x86_64-error {{code model 'extreme' is not supported on this target}}
// x86_64-error {{code model 'extreme' is not supported on this target}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'extreme' is not supported on this target}}

void __attribute((model("extreme"))) h() {} // unsupported-warning {{unknown attribute 'model' ignored}} \
// ignored-error {{'model' attribute only applies to non-TLS global variables}} \
// loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
// x86_64-error {{'model' attribute only applies to non-TLS global variables}}
// x86_64-error {{'model' attribute only applies to non-TLS global variables}} \
// nvptx64-unsupported-error {{'model' attribute only applies to non-TLS global variables}} \
// nvptx64-x86_64-error {{'model' attribute only applies to non-TLS global variables}}

// NVPTX doesn't support thread_local at all.
#if !defined(__NVPTX__) && !defined(__AMDGCN__) && !defined(__R600__) && !defined(__SPIRV__)
#if !defined(__CUDA__) || !defined(__CUDA_ARCH__)
// if we are compiling for non-cuda host, or host mode in a CUDA compile
#if !defined(__AMDGCN__) && !defined(__R600__) && !defined(__SPIRV__)
// for all non-cuda hosts, above targets don't support thread_local
thread_local
#endif
#endif
int i __attribute((model("extreme"))); // unsupported-warning {{unknown attribute 'model' ignored}} \
// loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
// x86_64-error {{'model' attribute only applies to non-TLS global variables}}
// x86_64-error {{'model' attribute only applies to non-TLS global variables}} \
// nvptx64-unsupported-warning {{unknown attribute 'model' ignored}} \
// nvptx64-x86_64-error {{code model 'extreme' is not supported on this target}}