Skip to content

Commit 7c40169

Browse files
committed
[clang][X86] Support __attribute__((model("small"/"large")))
Following up #72078, on x86-64 this allows a global to be considered small or large regardless of the code model. For example, x86-64's medium code model by default classifies globals as small or large depending on their size relative to -mlarge-data-threshold.
1 parent ef232a7 commit 7c40169

File tree

5 files changed

+61
-17
lines changed

5 files changed

+61
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,11 @@ Attribute Changes in Clang
657657

658658
- Clang now disallows the use of attributes after the namespace name. (#GH121407)
659659

660+
- Clang now allows ``__attribute__((model("small")))`` and
661+
``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.
662+
This forces the global to be considered small or large in regards to the
663+
x86-64 code model, regardless of the code model specified for the compilation.
664+
660665
Improvements to Clang's diagnostics
661666
-----------------------------------
662667

clang/include/clang/Basic/Attr.td

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ def TargetMSP430 : TargetArch<["msp430"]>;
462462
def TargetM68k : TargetArch<["m68k"]>;
463463
def TargetRISCV : TargetArch<["riscv32", "riscv64"]>;
464464
def TargetX86 : TargetArch<["x86"]>;
465+
def TargetX86_64 : TargetArch<["x86_64"]>;
465466
def TargetAnyX86 : TargetArch<["x86", "x86_64"]>;
466467
def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>;
467468
def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>;
@@ -3117,11 +3118,15 @@ def PragmaClangTextSection : InheritableAttr {
31173118
let Documentation = [InternalOnly];
31183119
}
31193120

3120-
def CodeModel : InheritableAttr, TargetSpecificAttr<TargetLoongArch> {
3121+
def CodeModel : InheritableAttr,
3122+
TargetSpecificAttr<TargetArch<!listconcat(
3123+
TargetLoongArch.Arches, TargetX86_64.Arches)>> {
31213124
let Spellings = [GCC<"model">];
3122-
let Args = [EnumArgument<"Model", "llvm::CodeModel::Model", /*is_string=*/1,
3123-
["normal", "medium", "extreme"], ["Small", "Medium", "Large"],
3124-
/*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>];
3125+
let Args = [EnumArgument<
3126+
"Model", "llvm::CodeModel::Model",
3127+
/*is_string=*/1, ["small", "normal", "medium", "large", "extreme"],
3128+
["Small", "Small", "Medium", "Large", "Large"],
3129+
/*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>];
31253130
let Subjects = SubjectList<[NonTLSGlobalVar], ErrorDiag>;
31263131
let Documentation = [CodeModelDocs];
31273132
}

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "llvm/IR/DerivedTypes.h"
6565
#include "llvm/MC/MCSectionMachO.h"
6666
#include "llvm/Support/Error.h"
67+
#include "llvm/Support/ErrorHandling.h"
6768
#include "llvm/Support/MathExtras.h"
6869
#include "llvm/Support/raw_ostream.h"
6970
#include "llvm/TargetParser/Triple.h"
@@ -2949,6 +2950,13 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
29492950
}
29502951
}
29512952

2953+
static bool isValidCodeModelAttr(Sema &S, StringRef Str) {
2954+
bool IsX8664Target =
2955+
S.Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86_64;
2956+
bool IsX8664Spelling = Str == "small" || Str == "large";
2957+
return IsX8664Target == IsX8664Spelling;
2958+
}
2959+
29522960
static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
29532961
StringRef Str;
29542962
SourceLocation LiteralLoc;
@@ -2957,7 +2965,8 @@ static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
29572965
return;
29582966

29592967
llvm::CodeModel::Model CM;
2960-
if (!CodeModelAttr::ConvertStrToModel(Str, CM)) {
2968+
if (!CodeModelAttr::ConvertStrToModel(Str, CM) ||
2969+
!isValidCodeModelAttr(S, Str)) {
29612970
S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str;
29622971
return;
29632972
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown %s -o - | FileCheck %s
2+
3+
// CHECK: @_ZL2v1 ={{.*}} global i32 0, code_model "small"
4+
static int v1 __attribute__((model("small")));
5+
6+
void use1() {
7+
v1 = 1;
8+
}
9+
10+
// CHECK: @v2 ={{.*}} global float 0.000000e+00, code_model "large"
11+
float v2 __attribute__((model("large")));
12+
13+
// CHECK: @_ZL2v3IiE ={{.*}} global i32 0, code_model "small"
14+
template <typename T>
15+
static T v3 __attribute__((model("small")));
16+
17+
void use2() {
18+
v3<int> = 1;
19+
}
20+
struct S {
21+
double d;
22+
};
23+
24+
typedef void (*F)();
25+
26+
// CHECK: @v4 ={{.*}} global ptr null, code_model "large"
27+
F v4 __attribute__((model("large")));

clang/test/Sema/attr-model.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// RUN: %clang_cc1 -triple riscv64 -verify=expected,riscv64 -fsyntax-only %s
66
// RUN: %clang_cc1 -triple x86_64 -verify=expected,x86_64 -fsyntax-only %s
77

8-
#if defined(__loongarch__) && !__has_attribute(model)
8+
#if (defined(__loongarch__) || defined(__x86_64__)) && !__has_attribute(model)
99
#error "Should support model attribute"
1010
#endif
1111

@@ -14,51 +14,49 @@ int a __attribute((model("tiny"))); // aarch64-warning {{unknown attribute 'm
1414
// mips64-warning {{unknown attribute 'model' ignored}} \
1515
// powerpc64-warning {{unknown attribute 'model' ignored}} \
1616
// riscv64-warning {{unknown attribute 'model' ignored}} \
17-
// x86_64-warning {{unknown attribute 'model' ignored}}
17+
// x86_64-error {{code model 'tiny' is not supported on this target}}
1818
int b __attribute((model("small"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
1919
// loongarch64-error {{code model 'small' is not supported on this target}} \
2020
// mips64-warning {{unknown attribute 'model' ignored}} \
2121
// powerpc64-warning {{unknown attribute 'model' ignored}} \
22-
// riscv64-warning {{unknown attribute 'model' ignored}} \
23-
// x86_64-warning {{unknown attribute 'model' ignored}}
22+
// riscv64-warning {{unknown attribute 'model' ignored}}
2423
int c __attribute((model("normal"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
2524
// mips64-warning {{unknown attribute 'model' ignored}} \
2625
// powerpc64-warning {{unknown attribute 'model' ignored}} \
2726
// riscv64-warning {{unknown attribute 'model' ignored}} \
28-
// x86_64-warning {{unknown attribute 'model' ignored}}
27+
// x86_64-error {{code model 'normal' is not supported on this target}}
2928
int d __attribute((model("kernel"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
3029
// loongarch64-error {{code model 'kernel' is not supported on this target}} \
3130
// mips64-warning {{unknown attribute 'model' ignored}} \
3231
// powerpc64-warning {{unknown attribute 'model' ignored}} \
3332
// riscv64-warning {{unknown attribute 'model' ignored}} \
34-
// x86_64-warning {{unknown attribute 'model' ignored}}
33+
// x86_64-error {{code model 'kernel' is not supported on this target}}
3534
int e __attribute((model("medium"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
3635
// mips64-warning {{unknown attribute 'model' ignored}} \
3736
// powerpc64-warning {{unknown attribute 'model' ignored}} \
3837
// riscv64-warning {{unknown attribute 'model' ignored}} \
39-
// x86_64-warning {{unknown attribute 'model' ignored}}
38+
// x86_64-error {{code model 'medium' is not supported on this target}}
4039
int f __attribute((model("large"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
4140
// loongarch64-error {{code model 'large' is not supported on this target}} \
4241
// mips64-warning {{unknown attribute 'model' ignored}} \
4342
// powerpc64-warning {{unknown attribute 'model' ignored}} \
44-
// riscv64-warning {{unknown attribute 'model' ignored}} \
45-
// x86_64-warning {{unknown attribute 'model' ignored}}
43+
// riscv64-warning {{unknown attribute 'model' ignored}}
4644
int g __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
4745
// mips64-warning {{unknown attribute 'model' ignored}} \
4846
// powerpc64-warning {{unknown attribute 'model' ignored}} \
4947
// riscv64-warning {{unknown attribute 'model' ignored}} \
50-
// x86_64-warning {{unknown attribute 'model' ignored}}
48+
// x86_64-error {{code model 'extreme' is not supported on this target}}
5149

5250
void __attribute((model("extreme"))) h() {} // aarch64-warning {{unknown attribute 'model' ignored}} \
5351
// loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
5452
// mips64-warning {{unknown attribute 'model' ignored}} \
5553
// powerpc64-warning {{unknown attribute 'model' ignored}} \
5654
// riscv64-warning {{unknown attribute 'model' ignored}} \
57-
// x86_64-warning {{unknown attribute 'model' ignored}}
55+
// x86_64-error {{'model' attribute only applies to non-TLS global variables}}
5856

5957
thread_local int i __attribute((model("extreme"))); // aarch64-warning {{unknown attribute 'model' ignored}} \
6058
// loongarch64-error {{'model' attribute only applies to non-TLS global variables}} \
6159
// mips64-warning {{unknown attribute 'model' ignored}} \
6260
// powerpc64-warning {{unknown attribute 'model' ignored}} \
6361
// riscv64-warning {{unknown attribute 'model' ignored}} \
64-
// x86_64-warning {{unknown attribute 'model' ignored}}
62+
// x86_64-error {{'model' attribute only applies to non-TLS global variables}}

0 commit comments

Comments
 (0)