llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Tony Varghese (tonykuttai)

<details>
<summary>Changes</summary>

- Emit `!aix.copyright.comment` from Clang for the pragma.
- Lower it in LLVM to a TU-local string + llvm.used + `!implicit.ref`.
- Add module-import and backend relocation tests.

This change builds on top of [XCOFF associated 
metadata](https://github.com/llvm/llvm-project/pull/159096) and was reviewed at 
[\[PowerPC\]\[AIX\] Support #pragma comment copyright for AIX 
](https://github.com/mandlebug/llvm-project/pull/1)

---

Patch is 29.81 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/178184.diff


22 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4) 
- (modified) clang/include/clang/Basic/PragmaKinds.h (+2-1) 
- (modified) clang/lib/AST/TextNodeDumper.cpp (+3) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+37) 
- (modified) clang/lib/CodeGen/CodeGenModule.h (+5) 
- (modified) clang/lib/Parse/ParsePragma.cpp (+36-9) 
- (added) clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix-modules.cpp 
(+28) 
- (added) clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix.c (+34) 
- (modified) clang/test/CodeGen/lto-newpm-pipeline.c (+2) 
- (added) llvm/include/llvm/Transforms/Utils/LowerCommentStringPass.h (+24) 
- (modified) llvm/lib/Passes/PassBuilder.cpp (+1) 
- (modified) llvm/lib/Passes/PassBuilderPipelines.cpp (+7) 
- (modified) llvm/lib/Passes/PassRegistry.def (+1) 
- (modified) llvm/lib/Transforms/Utils/CMakeLists.txt (+1) 
- (added) llvm/lib/Transforms/Utils/LowerCommentStringPass.cpp (+148) 
- (modified) llvm/test/CodeGen/AArch64/print-pipeline-passes.ll (+1-1) 
- (modified) llvm/test/CodeGen/Hexagon/print-pipeline-passes.ll (+1-1) 
- (modified) llvm/test/Other/new-pm-defaults.ll (+1) 
- (modified) llvm/test/Other/new-pm-thinlto-postlink-defaults.ll (+1) 
- (modified) llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll (+1) 
- (modified) llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll (+1) 
- (added) llvm/test/Transforms/LowerCommentString/lower-comment-string.ll (+59) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 457d3644de35a..ede6a90a31cc6 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1358,6 +1358,10 @@ def err_pragma_comment_unknown_kind : Error<"unknown 
kind of pragma comment">;
 // PS4 recognizes only #pragma comment(lib)
 def warn_pragma_comment_ignored : Warning<"'#pragma comment %0' ignored">,
   InGroup<IgnoredPragmas>;
+def warn_pragma_comment_once
+    : Warning<"'#pragma comment %0' "
+              "can be specified only once per translation unit - ignored">,
+      InGroup<IgnoredPragmas>;
 // - #pragma detect_mismatch
 def err_pragma_detect_mismatch_malformed : Error<
   "pragma detect_mismatch is malformed; it requires two comma-separated "
diff --git a/clang/include/clang/Basic/PragmaKinds.h 
b/clang/include/clang/Basic/PragmaKinds.h
index 42f049f7323d2..52ca58855d460 100644
--- a/clang/include/clang/Basic/PragmaKinds.h
+++ b/clang/include/clang/Basic/PragmaKinds.h
@@ -17,7 +17,8 @@ enum PragmaMSCommentKind {
   PCK_Lib,      // #pragma comment(lib, ...)
   PCK_Compiler, // #pragma comment(compiler, ...)
   PCK_ExeStr,   // #pragma comment(exestr, ...)
-  PCK_User      // #pragma comment(user, ...)
+  PCK_User,     // #pragma comment(user, ...)
+  PCK_Copyright // #pragma comment(copyright, ...)
 };
 
 enum PragmaMSStructKind {
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 7bc0404db1bee..c58c33f95c193 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -2526,6 +2526,9 @@ void TextNodeDumper::VisitPragmaCommentDecl(const 
PragmaCommentDecl *D) {
   case PCK_User:
     OS << "user";
     break;
+  case PCK_Copyright:
+    OS << "copyright";
+    break;
   }
   StringRef Arg = D->getArg();
   if (!Arg.empty())
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index d50c9605a30b3..e63adc98a95aa 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1588,6 +1588,12 @@ void CodeGenModule::Release() {
 
   EmitBackendOptionsMetadata(getCodeGenOpts());
 
+  // Emit copyright metadata
+  if (LoadTimeComment) {
+    auto *NMD = 
getModule().getOrInsertNamedMetadata("comment_string.loadtime");
+    NMD->addOperand(LoadTimeComment);
+  }
+
   // If there is device offloading code embed it in the host now.
   EmbedObject(&getModule(), CodeGenOpts, *getFileSystem(), getDiags());
 
@@ -3481,6 +3487,31 @@ void CodeGenModule::AddDependentLib(StringRef Lib) {
   LinkerOptionsMetadata.push_back(llvm::MDNode::get(C, MDOpts));
 }
 
+/// Process AIX copyright pragma and create LLVM metadata.
+/// #pragma comment(copyright, "string") embed copyright
+/// information into the object file's loader section.
+///
+/// Example: #pragma comment(copyright, "Copyright IBM Corp. 2024")
+///
+/// This should only be called once per translation unit.
+void CodeGenModule::ProcessPragmaComment(PragmaMSCommentKind Kind,
+                                         StringRef Comment) {
+  // Ensure we are only processing Copyright Pragmas
+  assert(Kind == PCK_Copyright &&
+         "Unexpected pragma comment kind, ProcessPragmaComment should only be "
+         "called for PCK_Copyright");
+
+  // Only one copyright pragma allowed per translation unit
+  if (LoadTimeComment) {
+    return;
+  }
+
+  // Create llvm metadata with the comment string
+  auto &C = getLLVMContext();
+  llvm::Metadata *Ops[] = {llvm::MDString::get(C, Comment)};
+  LoadTimeComment = llvm::MDNode::get(C, Ops);
+}
+
 /// Add link options implied by the given module, including modules
 /// it depends on, using a postorder walk.
 static void addLinkOptionsPostorder(CodeGenModule &CGM, Module *Mod,
@@ -7683,6 +7714,12 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
     case PCK_Lib:
         AddDependentLib(PCD->getArg());
       break;
+    case PCK_Copyright:
+      // Skip pragmas deserialized from modules/PCHs. Process the pragma 
comment
+      // only if it originated in this TU and the target OS is AIX.
+      if (!PCD->isFromASTFile() && getTriple().isOSAIX())
+        ProcessPragmaComment(PCD->getCommentKind(), PCD->getArg());
+      break;
     case PCK_Compiler:
     case PCK_ExeStr:
     case PCK_User:
diff --git a/clang/lib/CodeGen/CodeGenModule.h 
b/clang/lib/CodeGen/CodeGenModule.h
index cc18e21d45759..21a75958dcc9d 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -587,6 +587,9 @@ class CodeGenModule : public CodeGenTypeCache {
   /// A vector of metadata strings for dependent libraries for ELF.
   SmallVector<llvm::MDNode *, 16> ELFDependentLibraries;
 
+  /// Metadata for copyright pragma comment (if present).
+  llvm::MDNode *LoadTimeComment = nullptr;
+
   /// @name Cache for Objective-C runtime types
   /// @{
 
@@ -1490,6 +1493,8 @@ class CodeGenModule : public CodeGenTypeCache {
   /// Appends a dependent lib to the appropriate metadata value.
   void AddDependentLib(StringRef Lib);
 
+  /// Process pragma comment
+  void ProcessPragmaComment(PragmaMSCommentKind Kind, StringRef Comment);
 
   llvm::GlobalVariable::LinkageTypes getFunctionLinkage(GlobalDecl GD);
 
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index def2817c930b2..5865319470511 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -237,6 +237,7 @@ struct PragmaCommentHandler : public PragmaHandler {
 
 private:
   Sema &Actions;
+  bool SeenCopyrightInTU = false; // TU-scoped
 };
 
 struct PragmaDetectMismatchHandler : public PragmaHandler {
@@ -480,7 +481,8 @@ void Parser::initializePragmaHandlers() {
   PP.AddPragmaHandler(OpenACCHandler.get());
 
   if (getLangOpts().MicrosoftExt ||
-      getTargetInfo().getTriple().isOSBinFormatELF()) {
+      getTargetInfo().getTriple().isOSBinFormatELF() ||
+      getTargetInfo().getTriple().isOSAIX()) {
     MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
     PP.AddPragmaHandler(MSCommentHandler.get());
   }
@@ -607,7 +609,8 @@ void Parser::resetPragmaHandlers() {
   OpenACCHandler.reset();
 
   if (getLangOpts().MicrosoftExt ||
-      getTargetInfo().getTriple().isOSBinFormatELF()) {
+      getTargetInfo().getTriple().isOSBinFormatELF() ||
+      getTargetInfo().getTriple().isOSAIX()) {
     PP.RemovePragmaHandler(MSCommentHandler.get());
     MSCommentHandler.reset();
   }
@@ -3287,13 +3290,21 @@ void PragmaCommentHandler::HandlePragma(Preprocessor 
&PP,
   // Verify that this is one of the 5 explicitly listed options.
   IdentifierInfo *II = Tok.getIdentifierInfo();
   PragmaMSCommentKind Kind =
-    llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
-    .Case("linker",   PCK_Linker)
-    .Case("lib",      PCK_Lib)
-    .Case("compiler", PCK_Compiler)
-    .Case("exestr",   PCK_ExeStr)
-    .Case("user",     PCK_User)
-    .Default(PCK_Unknown);
+      llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
+          .Case("linker", PCK_Linker)
+          .Case("lib", PCK_Lib)
+          .Case("compiler", PCK_Compiler)
+          .Case("exestr", PCK_ExeStr)
+          .Case("user", PCK_User)
+          .Case("copyright", PCK_Copyright)
+          .Default(PCK_Unknown);
+
+  // Restrict copyright to AIX targets only. This could be applied for z/OS
+  // and extended with other IBM pragma comment kinds.
+  if (!PP.getTargetInfo().getTriple().isOSAIX() && Kind == PCK_Copyright) {
+    Kind = PCK_Unknown;
+  }
+
   if (Kind == PCK_Unknown) {
     PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
     return;
@@ -3305,6 +3316,18 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
     return;
   }
 
+  // On AIX, pragma comment copyright can each appear only once in a TU.
+  if (Kind == PCK_Copyright) {
+    assert(PP.getTargetInfo().getTriple().isOSAIX() &&
+           "Pragma Comment Copyright is supported only on AIX");
+    if (SeenCopyrightInTU) {
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_once)
+          << II->getName();
+      return;
+    }
+    SeenCopyrightInTU = true;
+  }
+
   // Read the optional string if present.
   PP.Lex(Tok);
   std::string ArgumentString;
@@ -3331,6 +3354,10 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
     return;
   }
 
+  // Accept and ignore well-formed copyright with empty string.
+  if (Kind == PCK_Copyright && ArgumentString.empty())
+    return;
+
   // If the pragma is lexically sound, notify any interested PPCallbacks.
   if (PP.getPPCallbacks())
     PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
diff --git 
a/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix-modules.cpp 
b/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix-modules.cpp
new file mode 100644
index 0000000000000..9020df6e737d6
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix-modules.cpp
@@ -0,0 +1,28 @@
+// RUN: split-file %s %t
+
+// Build the module interface to a PCM
+// RUN: %clang_cc1 -std=c++20 -triple powerpc-ibm-aix \
+// RUN:   -emit-module-interface %t/copymod.cppm -o %t/copymod.pcm
+
+// Verify that module interface emits copyright global when compiled to IR
+// RUN: %clang_cc1 -std=c++20 -triple powerpc-ibm-aix -emit-llvm 
%t/copymod.cppm -o - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-MOD
+// CHECK-MOD: @__loadtime_comment_str = internal unnamed_addr constant [10 x 
i8] c"module me\00", section "__loadtime_comment"
+// CHECK-MOD: @llvm.used = appending global {{.*}} @__loadtime_comment_str
+
+// Compile an importing TU that uses the prebuilt module and verify that it
+// does NOT re-emit the module's copyright global.
+// RUN: %clang_cc1 -std=c++20 -triple powerpc-ibm-aix \
+// RUN:   -fprebuilt-module-path=%t -emit-llvm %t/importmod.cc -o - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-IMPORT
+// CHECK-IMPORT-NOT: @__loadtime_comment_str
+// CHECK-IMPORT-NOT: c"module me\00"
+
+//--- copymod.cppm
+export module copymod;
+#pragma comment(copyright, "module me")
+export inline void f() {}
+
+//--- importmod.cc
+import copymod;
+void g() { f(); }
diff --git a/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix.c 
b/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix.c
new file mode 100644
index 0000000000000..98d2db416496e
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/pragma-comment-copyright-aix.c
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 %s -triple powerpc-ibm-aix -O0 -disable-llvm-passes 
-emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix -O0 -disable-llvm-passes 
-emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -triple powerpc-ibm-aix -verify
+// RUN: %clang_cc1 %s -triple powerpc64-ibm-aix -verify
+// RUN: %clang_cc1 %s -DTEST_EMPTY_COPYRIGHT -triple powerpc-ibm-aix -verify
+
+// RUN: %clang_cc1 %s -x c++ -triple powerpc-ibm-aix -O0 -disable-llvm-passes 
-emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -x c++ -triple powerpc64-ibm-aix -O0 
-disable-llvm-passes -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -x c++ -triple powerpc-ibm-aix -verify
+// RUN: %clang_cc1 %s -x c++ -triple powerpc64-ibm-aix -verify
+// RUN: %clang_cc1 %s -x c++ -DTEST_EMPTY_COPYRIGHT -triple powerpc-ibm-aix 
-verify
+
+#ifndef TEST_EMPTY_COPYRIGHT
+// Test basic pragma comment types
+#pragma comment(copyright, "@(#) Copyright")
+
+// Test duplicate copyright - should warn and ignore
+#pragma comment(copyright, "Duplicate Copyright") // expected-warning 
{{'#pragma comment copyright' can be specified only once per translation unit - 
ignored}}
+
+int main() { return 0; }
+
+// Check that both metadata sections are present
+// CHECK: !comment_string.loadtime = !{![[copyright:[0-9]+]]}
+
+// Check individual metadata content
+// CHECK: ![[copyright]] = !{!"@(#) Copyright"}
+
+#else
+// Test empty copyright string - valid with no warning
+#pragma comment(copyright, "") // expected-no-diagnostics
+
+int main() { return 0; }
+
+#endif
diff --git a/clang/test/CodeGen/lto-newpm-pipeline.c 
b/clang/test/CodeGen/lto-newpm-pipeline.c
index ea9784a76f923..b9466b9558b06 100644
--- a/clang/test/CodeGen/lto-newpm-pipeline.c
+++ b/clang/test/CodeGen/lto-newpm-pipeline.c
@@ -27,6 +27,7 @@
 
 // CHECK-FULL-O0: Running pass: VerifierPass
 // CHECK-FULL-O0-NEXT: Running analysis: VerifierAnalysis
+// CHECK-FULL-O0-NEXT: Running pass: LowerCommentStringPass
 // CHECK-FULL-O0-NEXT: Running analysis: InnerAnalysisManagerProxy
 // CHECK-FULL-O0-NEXT: Running pass: EntryExitInstrumenterPass
 // CHECK-FULL-O0-NEXT: Running pass: AlwaysInlinerPass
@@ -41,6 +42,7 @@
 
 // CHECK-THIN-O0: Running pass: VerifierPass
 // CHECK-THIN-O0-NEXT: Running analysis: VerifierAnalysis
+// CHECK-THIN-O0-NEXT: Running pass: LowerCommentStringPass
 // CHECK-THIN-O0-NEXT: Running analysis: InnerAnalysisManagerProxy
 // CHECK-THIN-O0-NEXT: Running pass: EntryExitInstrumenterPass
 // CHECK-THIN-O0-NEXT: Running pass: AlwaysInlinerPass
diff --git a/llvm/include/llvm/Transforms/Utils/LowerCommentStringPass.h 
b/llvm/include/llvm/Transforms/Utils/LowerCommentStringPass.h
new file mode 100644
index 0000000000000..4c6109e1176d3
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/LowerCommentStringPass.h
@@ -0,0 +1,24 @@
+//===-- LowerCommentStringPass.h - Lower Comment string metadata        --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_LOWERCOMMENTSTRINGPASS_H
+#define LLVM_TRANSFORMS_UTILS_LOWERCOMMENTSTRINGPASS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class LowerCommentStringPass : public PassInfoMixin<LowerCommentStringPass> {
+public:
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+
+  static bool isRequired() { return true; }
+};
+
+} // namespace llvm
+
+#endif // LLVM_TRANSFORMS_UTILS_LOWERCOMMENTSTRINGPASS_H
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 45955426d66a0..5c014644a6150 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -361,6 +361,7 @@
 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
 #include "llvm/Transforms/Utils/LoopSimplify.h"
 #include "llvm/Transforms/Utils/LoopVersioning.h"
+#include "llvm/Transforms/Utils/LowerCommentStringPass.h"
 #include "llvm/Transforms/Utils/LowerGlobalDtors.h"
 #include "llvm/Transforms/Utils/LowerIFunc.h"
 #include "llvm/Transforms/Utils/LowerInvoke.h"
diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp 
b/llvm/lib/Passes/PassBuilderPipelines.cpp
index 1584d30875570..e48833528c85a 100644
--- a/llvm/lib/Passes/PassBuilderPipelines.cpp
+++ b/llvm/lib/Passes/PassBuilderPipelines.cpp
@@ -142,6 +142,7 @@
 #include "llvm/Transforms/Utils/ExtraPassManager.h"
 #include "llvm/Transforms/Utils/InjectTLIMappings.h"
 #include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
+#include "llvm/Transforms/Utils/LowerCommentStringPass.h"
 #include "llvm/Transforms/Utils/Mem2Reg.h"
 #include "llvm/Transforms/Utils/MoveAutoInit.h"
 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
@@ -1470,6 +1471,9 @@ 
PassBuilder::buildModuleOptimizationPipeline(OptimizationLevel Level,
   const bool LTOPreLink = isLTOPreLink(LTOPhase);
   ModulePassManager MPM;
 
+  // Process copyright metadata early, before any optimizations
+  MPM.addPass(LowerCommentStringPass());
+
   // Run partial inlining pass to partially inline functions that have
   // large bodies.
   if (RunPartialInlining)
@@ -2318,6 +2322,9 @@ PassBuilder::buildO0DefaultPipeline(OptimizationLevel 
Level,
 
   ModulePassManager MPM;
 
+  // Process copyright metadata at O0 before any other transformations
+  MPM.addPass(LowerCommentStringPass());
+
   // Perform pseudo probe instrumentation in O0 mode. This is for the
   // consistency between different build modes. For example, a LTO build can be
   // mixed with an O0 prelink and an O2 postlink. Loading a sample profile in
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 2cfb5b2592601..05cc8775b8d71 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -62,6 +62,7 @@ MODULE_PASS("check-debugify", NewPMCheckDebugifyPass())
 MODULE_PASS("constmerge", ConstantMergePass())
 MODULE_PASS("coro-cleanup", CoroCleanupPass())
 MODULE_PASS("coro-early", CoroEarlyPass())
+MODULE_PASS("lower-comment-string", LowerCommentStringPass())
 MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass())
 MODULE_PASS("ctx-instr-gen",
             PGOInstrumentationGen(PGOInstrumentationType::CTXPROF))
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt 
b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 2b5f5cf344e60..28f86c5e96010 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -53,6 +53,7 @@ add_llvm_component_library(LLVMTransformUtils
   LoopUtils.cpp
   LoopVersioning.cpp
   LowerAtomic.cpp
+  LowerCommentStringPass.cpp
   LowerGlobalDtors.cpp
   LowerIFunc.cpp
   LowerInvoke.cpp
diff --git a/llvm/lib/Transforms/Utils/LowerCommentStringPass.cpp 
b/llvm/lib/Transforms/Utils/LowerCommentStringPass.cpp
new file mode 100644
index 0000000000000..6deef2f75e0a3
--- /dev/null
+++ b/llvm/lib/Transforms/Utils/LowerCommentStringPass.cpp
@@ -0,0 +1,148 @@
+//===-- LowerCommentStringPass.cpp - Lower Comment string metadata -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+//
+// LowerCommentStringPass pass lowers module-level comment string metadata
+// emitted by Clang:
+//
+//     !comment_string.loadtime = !{!"Copyright ..."}
+//
+// into concrete, translation-unit–local globals.
+// This Pass is enabled only for AIX.
+// For each module (translation unit), the pass performs the following:
+//
+//   1. Creates a null-terminated, internal constant string global
+//      (`__loadtime_comment_str`) containing the copyright text in
+//      `__loadtime_comment` section.
+//
+//   2. Marks the string in `llvm.used` so it cannot be dropped by
+//      optimization or LTO.
+//
+//   3. Attaches `!implicit.ref` metadata referencing the string to every
+//      defined function in the module. The PowerPC AIX backend recognizes
+//      this metadata and emits a `.ref` directive from the function to the
+//      string, creating a concrete relocation that prevents the linker from
+//      discarding it (as long as the referencing symbol is kept).
+//
+//  Input IR:
+//     !comment_string.loadtime = !{!"Copyright"}
+//  Output IR:
+//     @__loadtime_comment_str = internal constant [N x i8] c"Copyright\00",
+//                          section "__loadtime_comment"
+//     @llvm.used = appending global [1 x ptr] [ptr @__loadtime_comment_str]
+//
+//     define i32 @func() !implicit.ref !5 { ... }
+//     !5 = !{ptr @__loadtime_comment_str}
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/LowerCommentStringPass.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TargetParser/Triple.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+#define DEBUG_TYPE "lower-comment-string"
+
+using namespace llvm;
+
+static cl::opt<bool>
+    DisableCopyrightMetadata("disable-lower-comment-string", cl::ReallyHidden,
+                             cl::desc("Disable LowerCommentString pass."),
+                             cl::init(false));
+
+static bool isAIXTriple(const Module &M) {
+  return Triple(M.getTargetTriple()).isOSAIX();
+}
+
+P...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/178184
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to