================
@@ -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();
+}
+
+PreservedAnalyses LowerCommentStringPass::run(Module &M,
+                                              ModuleAnalysisManager &AM) {
+  if (DisableCopyrightMetadata || !isAIXTriple(M))
+    return PreservedAnalyses::all();
+
+  LLVMContext &Ctx = M.getContext();
+
+  // Single-metadata: !comment_string.loadtime = !{!0}
+  // Each operand node is expected to have one MDString operand.
+  NamedMDNode *MD = M.getNamedMetadata("comment_string.loadtime");
+  if (!MD || MD->getNumOperands() == 0)
+    return PreservedAnalyses::all();
+
+  // At this point we are guarateed that one TU contains a single copyright
+  // metadata entry. Create TU-local string global for that metadata entry.
+  MDNode *MdNode = MD->getOperand(0);
+  if (!MdNode || MdNode->getNumOperands() == 0)
+    return PreservedAnalyses::all();
+
+  auto *MdString = dyn_cast_or_null<MDString>(MdNode->getOperand(0));
+  if (!MdString)
+    return PreservedAnalyses::all();
+
+  StringRef Text = MdString->getString();
+  if (Text.empty())
+    return PreservedAnalyses::all();
+
+  // 1. Create a single NULL-terminated string global
+  Constant *StrInit = ConstantDataArray::getString(Ctx, Text, 
/*AddNull=*/true);
+
+  // Internal, constant, TU-local--avoids duplicate symbol issues across TUs.
+  auto *StrGV = new GlobalVariable(M, StrInit->getType(),
+                                   /*isConstant=*/true,
+                                   GlobalValue::InternalLinkage, StrInit,
+                                   /*Name=*/"__loadtime_comment_str");
+  // Set unnamed_addr to allow the linker to merge identical strings
+  StrGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
+  StrGV->setAlignment(Align(1));
+  // Place in the "__loadtime_comment" section.
+  // The GV is constant, so we expect a read-only section.
+  StrGV->setSection("__loadtime_comment");
+
+  // 2. Add the string to llvm.used to prevent LLVM optimization/LTO passes 
from
+  // removing it.
+  appendToUsed(M, {StrGV});
+
+  // 3. Attach !implicit ref to every defined function
+  // Create a metadata node pointing to the copyright string:
+  //   !N = !{ptr @__loadtime_comment_str}
+  Metadata *Ops[] = {ConstantAsMetadata::get(StrGV)};
+  MDNode *ImplicitRefMD = MDNode::get(Ctx, Ops);
+
+  // Lambda to attach implicit.ref metadata to a function.
+  auto AddImplicitRef = [&](Function &F) {
+    if (F.isDeclaration())
+      return;
+    // Attach the implicit.ref metadata to the function
+    F.setMetadata("implicit.ref", ImplicitRefMD);
----------------
tonykuttai wrote:

addressed

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