[clang] [clang] Add per-global code model attribute (PR #72078)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 4 18:00:57 PST 2023
https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/72078
>From 5333233261a3563f80ed58250c40791bd44a9901 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Fri, 10 Nov 2023 21:07:48 -0600
Subject: [PATCH] [clang] Add per-global code model attribute
This adds a per-global code model attribute, which can override
the target's code model to access global variables.
Suggested-by: Arthur Eubanks <aeubanks at google.com>
Signed-off-by: WANG Rui <wangrui at loongson.cn>
Link: https://discourse.llvm.org/t/how-to-best-implement-code-model-overriding-for-certain-values/71816
Link: https://discourse.llvm.org/t/rfc-add-per-global-code-model-attribute/74944
---
clang/include/clang/Basic/Attr.td | 8 ++++++++
clang/include/clang/Basic/AttrDocs.td | 9 +++++++++
.../clang/Basic/DiagnosticSemaKinds.td | 3 +++
clang/lib/CodeGen/CodeGenModule.cpp | 13 ++++++++++++
clang/lib/Sema/SemaDeclAttr.cpp | 20 +++++++++++++++++++
clang/test/CodeGen/attributes.c | 15 ++++++++++++++
...a-attribute-supported-attributes-list.test | 1 +
clang/test/Sema/attr-model.c | 12 +++++++++++
8 files changed, 81 insertions(+)
create mode 100644 clang/test/Sema/attr-model.c
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 1800f584c7e10..d5b5717f3d77c 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2718,6 +2718,14 @@ def PragmaClangTextSection : InheritableAttr {
let Documentation = [InternalOnly];
}
+def CodeModel : InheritableAttr {
+ let Spellings = [GCC<"model">];
+ let Args = [StringArgument<"Model">];
+ let Subjects =
+ SubjectList<[ GlobalVar ], ErrorDiag>;
+ let Documentation = [CodeModelDocs];
+}
+
def Sentinel : InheritableAttr {
let Spellings = [GCC<"sentinel">];
let Args = [DefaultIntArgument<"Sentinel", 0>,
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b45ec6bbb8d37..1d37c2da6bec0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -57,6 +57,15 @@ global variable or function should be in after translation.
let Heading = "section, __declspec(allocate)";
}
+def CodeModelDocs : Documentation {
+ let Category = DocCatVariable;
+ let Content = [{
+The ``model`` attribute allows you to specify a specific code model a
+global variable should be in after translation.
+ }];
+ let Heading = "model";
+}
+
def UsedDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6dfb2d7195203..2c48627a15929 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3408,6 +3408,9 @@ def warn_objc_redundant_literal_use : Warning<
def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", "
"\"local-dynamic\", \"initial-exec\" or \"local-exec\"">;
+def err_attr_codemodel_arg : Error<"code_model must be \"tiny\", "
+ "\"small\", \"kernel\", \"medium\" or \"large\"">;
+
def err_aix_attr_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">;
def err_tls_var_aligned_over_maximum : Error<
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index dea58a7ff4146..1f49721e79ddc 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4841,6 +4841,19 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty,
isExternallyVisible(D->getLinkageAndVisibility().getLinkage()))
GV->setSection(".cp.rodata");
+ // Handle code model attribute
+ if (D->hasAttr<CodeModelAttr>()) {
+ if (const CodeModelAttr *CMA = D->getAttr<CodeModelAttr>()) {
+ auto CM = llvm::StringSwitch<llvm::CodeModel::Model>(CMA->getModel())
+ .Case("tiny", llvm::CodeModel::Tiny)
+ .Case("kernel", llvm::CodeModel::Kernel)
+ .Case("medium", llvm::CodeModel::Medium)
+ .Case("large", llvm::CodeModel::Large)
+ .Default(llvm::CodeModel::Small);
+ GV->setCodeModel(CM);
+ }
+ }
+
// Check if we a have a const declaration with an initializer, we may be
// able to emit it as available_externally to expose it's value to the
// optimizer.
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 87c78d742d0ff..b0d25a17db289 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3369,6 +3369,23 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
}
+static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ StringRef Model;
+ SourceLocation LiteralLoc;
+ // Check that it is a string.
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, Model, &LiteralLoc))
+ return;
+
+ // Check that the value.
+ if (Model != "tiny" && Model != "small" && Model != "kernel" &&
+ Model != "medium" && Model != "large") {
+ S.Diag(LiteralLoc, diag::err_attr_codemodel_arg);
+ return;
+ }
+
+ D->addAttr(::new (S.Context) CodeModelAttr(S.Context, AL, Model));
+}
+
// This is used for `__declspec(code_seg("segname"))` on a decl.
// `#pragma code_seg("segname")` uses checkSectionName() instead.
static bool checkCodeSegName(Sema &S, SourceLocation LiteralLoc,
@@ -9309,6 +9326,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_Section:
handleSectionAttr(S, D, AL);
break;
+ case ParsedAttr::AT_CodeModel:
+ handleCodeModelAttr(S, D, AL);
+ break;
case ParsedAttr::AT_RandomizeLayout:
handleRandomizeLayoutAttr(S, D, AL);
break;
diff --git a/clang/test/CodeGen/attributes.c b/clang/test/CodeGen/attributes.c
index 5afef72b747af..7783d87b84c29 100644
--- a/clang/test/CodeGen/attributes.c
+++ b/clang/test/CodeGen/attributes.c
@@ -25,6 +25,21 @@ int t6 __attribute__((visibility("protected")));
// CHECK: @t12 ={{.*}} global i32 0, section "SECT"
int t12 __attribute__((section("SECT")));
+// CHECK: @tiny ={{.*}} global i32 0, code_model "tiny"
+int tiny __attribute__((model("tiny")));
+
+// CHECK: @small ={{.*}} global i32 0, code_model "small"
+int small __attribute__((model("small")));
+
+// CHECK: @kernel ={{.*}} global i32 0, code_model "kernel"
+int kernel __attribute__((model("kernel")));
+
+// CHECK: @medium ={{.*}} global i32 0, code_model "medium"
+int medium __attribute__((model("medium")));
+
+// CHECK: @large ={{.*}} global i32 0, code_model "large"
+int large __attribute__((model("large")));
+
// CHECK: @t9 = weak{{.*}} alias void (...), ptr @__t8
void __t8() {}
void t9() __attribute__((weak, alias("__t8")));
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index dd91f4f88ad68..2b191abdac8b5 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -48,6 +48,7 @@
// CHECK-NEXT: CarriesDependency (SubjectMatchRule_variable_is_parameter, SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: Cleanup (SubjectMatchRule_variable_is_local)
// CHECK-NEXT: CmseNSEntry (SubjectMatchRule_function)
+// CHECK-NEXT: CodeModel (SubjectMatchRule_variable_is_global)
// CHECK-NEXT: Cold (SubjectMatchRule_function)
// CHECK-NEXT: Common (SubjectMatchRule_variable)
// CHECK-NEXT: ConstInit (SubjectMatchRule_variable_is_global)
diff --git a/clang/test/Sema/attr-model.c b/clang/test/Sema/attr-model.c
new file mode 100644
index 0000000000000..90b9713f5f32c
--- /dev/null
+++ b/clang/test/Sema/attr-model.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64 -verify -fsyntax-only %s
+
+#if !__has_attribute(model)
+#error "Should support model attribute"
+#endif
+
+int a __attribute((model("tiny"))); // no-warning
+int b __attribute((model("small"))); // no-warning
+int c __attribute((model("kernel"))); // no-warning
+int d __attribute((model("medium"))); // no-warning
+int e __attribute((model("large"))); // no-warning
+int f __attribute((model("normal"))); // expected-error {{code_model must be "tiny", "small", "kernel", "medium" or "large"}}
More information about the cfe-commits
mailing list