[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