Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] Add per-global code model attribute #72078

Merged
merged 10 commits into from
Jan 6, 2024
Merged

Conversation

heiher
Copy link
Member

@heiher heiher commented Nov 13, 2023

This patch adds a per-global code model attribute, which can override the target's code model to access global variables.

Currently, the code model attribute is only supported on LoongArch. This patch also maps GCC's code model names to LLVM's, which allows for better compatibility between the two compilers.

Suggested-by: Arthur Eubanks aeubanks@google.com
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

@heiher heiher requested a review from aeubanks November 13, 2023 02:48
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen labels Nov 13, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 13, 2023

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-clang

Author: hev (heiher)

Changes

This adds a per-global code model attribute, which can override the target's code model to access global variables.

Link: https://discourse.llvm.org/t/how-to-best-implement-code-model-overriding-for-certain-values/71816

Suggested-by: Arthur Eubanks <aeubanks@google.com>


Full diff: https://github.com/llvm/llvm-project/pull/72078.diff

8 Files Affected:

  • (modified) clang/include/clang/Basic/Attr.td (+8)
  • (modified) clang/include/clang/Basic/AttrDocs.td (+9)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (+13)
  • (modified) clang/lib/Sema/SemaDeclAttr.cpp (+20)
  • (modified) clang/test/CodeGen/attributes.c (+15)
  • (modified) clang/test/Misc/pragma-attribute-supported-attributes-list.test (+1)
  • (added) clang/test/Sema/attr-model.c (+12)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 31434565becaec67..0d3742080435142f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2694,6 +2694,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 fa6f6acd0c30e883..ca09e4acb113003b 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 4614324babb1c917..f9305e21bd6a39b3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3401,6 +3401,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 4c7f516e308ca003..f783130e3cbfd12e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4774,6 +4774,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 cdb769a883550d0f..8646c494602a3ea4 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,
@@ -9274,6 +9291,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 5afef72b747afb11..7783d87b84c29c9b 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 969794073a5f2e80..7a0b4f20cb88a5c7 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 0000000000000000..90b9713f5f32cd26
--- /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"}}

Copy link

github-actions bot commented Nov 13, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@heiher
Copy link
Member Author

heiher commented Nov 13, 2023

Part 1/3: #72077
Part 3/3: #72079

@heiher
Copy link
Member Author

heiher commented Nov 13, 2023

cc @xen0n @xry111

@heiher heiher marked this pull request as ready for review December 5, 2023 02:03
@heiher heiher marked this pull request as draft December 5, 2023 02:14
@heiher heiher marked this pull request as ready for review December 5, 2023 03:50
This patch adds a per-global code model attribute, which can override
the target's code model to access global variables.

Currently, the code model attribute is only supported on LoongArch.
This patch also maps GCC's code model names to LLVM's, which allows
for better compatibility between the two compilers.

Suggested-by: Arthur Eubanks <aeubanks@google.com>
Signed-off-by: WANG Rui <wangrui@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
Copy link
Contributor

@xen0n xen0n left a comment

Choose a reason for hiding this comment

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

There should also be a test case that shows the attribute is not supported on a non-LoongArch target. Otherwise this mostly looks fine to me, thanks for pushing this forward!

clang/lib/Sema/SemaDeclAttr.cpp Outdated Show resolved Hide resolved
clang/include/clang/Basic/AttrDocs.td Outdated Show resolved Hide resolved
@rnk
Copy link
Collaborator

rnk commented Dec 5, 2023

Do folks feel like the attribute name is sufficiently descriptive? i.e. should it be __attribute__((code_model("asdf")))? Are we aiming for GCC compat here? What guides the naming choice?

@xry111
Copy link
Contributor

xry111 commented Dec 5, 2023

Do folks feel like the attribute name is sufficiently descriptive? i.e. should it be __attribute__((code_model("asdf")))? Are we aiming for GCC compat here? What guides the naming choice?

Yes, for GCC compat, so we don't need to add more #ifdef's in kernel.

As the author of the GCC attribute: the name choice was "borrowed" from IA64. I have to admit that maybe I learnt from a bad example (anyway IA64 is in a zombie state now since it's removed from the kernel), but for now I don't see too much benefit to rename this.

@aeubanks
Copy link
Contributor

aeubanks commented Dec 5, 2023

is it too late to change the gcc attribute name?

@xry111
Copy link
Contributor

xry111 commented Dec 5, 2023

is it too late to change the gcc attribute name?

It has been released in GCC 13, and GCC 14 is in stage 3 so a change must be deferred into GCC 15. And the kernel code already relies on it. So a change will render all previous kernel releases (and some future kernel releases) impossible to build with GCC 15+.

@heiher heiher requested a review from xen0n December 11, 2023 14:35
@heiher heiher requested a review from MaskRay December 12, 2023 07:48
@MaskRay MaskRay requested review from erichkeane and removed request for xen0n December 13, 2023 07:45
@MaskRay
Copy link
Member

MaskRay commented Dec 13, 2023

Add @erichkeane for the attribute change.

Copy link
Contributor

@xen0n xen0n left a comment

Choose a reason for hiding this comment

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

Overall this seems fine, thanks!

But I'm not sure if reporting a more generic "the model attribute is not supported on this target" for non-LoongArch would be better: it doesn't give the false impression that the target doesn't support the specified code model.

clang/include/clang/Basic/DiagnosticSemaKinds.td Outdated Show resolved Hide resolved
@heiher
Copy link
Member Author

heiher commented Dec 13, 2023

Overall this seems fine, thanks!

But I'm not sure if reporting a more generic "the model attribute is not supported on this target" for non-LoongArch would be better: it doesn't give the false impression that the target doesn't support the specified code model.

In my opinion I think this is better. I put it in a separate commit so we can easily revert it if someone thinks otherwise. thanks

@heiher
Copy link
Member Author

heiher commented Jan 4, 2024

@erichkeane gentle ping

@heiher heiher requested a review from erichkeane January 5, 2024 07:26
@heiher heiher merged commit 4df5662 into llvm:main Jan 6, 2024
5 checks passed
@heiher heiher deleted the model-attr-clang branch January 6, 2024 00:52
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
This patch adds a per-global code model attribute, which can override
the target's code model to access global variables.

Currently, the code model attribute is only supported on LoongArch. This
patch also maps GCC's code model names to LLVM's, which allows for
better compatibility between the two compilers.


Suggested-by: Arthur Eubanks <aeubanks@google.com>
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

---------

Signed-off-by: WANG Rui <wangrui@loongson.cn>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants