[clang] Inject compilation command into __cli_<file> global variable (PR #144622)

via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 20 08:50:39 PDT 2025


https://github.com/Pavithra029 updated https://github.com/llvm/llvm-project/pull/144622

>From d41ac68039e6d654249fbeceb3b77c4b6780f9c0 Mon Sep 17 00:00:00 2001
From: pavithra <pavithra at Ubuntu-22.04.3.myguest.virtualbox.org>
Date: Wed, 18 Jun 2025 05:50:13 +0530
Subject: [PATCH 1/2] Inject compilation command into __cli_<file> global
 variable

---
 clang/lib/CodeGen/CodeGenModule.cpp | 100 ++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index c005d3322ed7a..577cb6f0abd2c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1472,6 +1472,106 @@ void CodeGenModule::Release() {
       }
     }
   }
+  
+      // 1. Get source file name
+  /*  std::string FileName = getModule().getSourceFileName(); // like "foo.c"
+    llvm::StringRef BaseName = llvm::sys::path::filename(FileName);
+
+    // 2. Create variable name like __cli_foo_c
+    std::string VarName = "__cli_" + BaseName.str();
+    std::replace(VarName.begin(), VarName.end(), '.', '_');
+
+    // 3. Get the compilation command line from options
+    std::string CmdLineStr;
+    for (const std::string &Arg : CodeGenOpts.CommandLineArgs) {
+        CmdLineStr += Arg + " ";
+    }
+
+    // 4. Create LLVM IR string global
+    llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true);
+    // 1. Prepare internal string global variable
+auto *GV = new llvm::GlobalVariable(
+    getModule(),
+    CmdStr->getType(),
+    true,
+    llvm::GlobalValue::InternalLinkage,
+    CmdStr,
+    VarName + ".data"
+);
+GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
+// 2. Create external pointer global pointing to internal string
+llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0);
+llvm::Constant *Indices[] = {Zero, Zero};
+llvm::Constant *PtrToStr = llvm::ConstantExpr::getGetElementPtr(CmdStr->getType(), GV, Indices);
+
+auto *ExternGV = new llvm::GlobalVariable(
+    getModule(),
+    PtrToStr->getType(),
+    true,
+    llvm::GlobalValue::ExternalLinkage,
+    PtrToStr,
+    VarName
+);
+ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+(void)ExternGV;
+    llvm::errs() << "✅ Emitting __cli global variable!\n";
+
+  */
+  
+  // === BEGIN: Emit global __cli_<file> variable ===
+
+std::string FileName = getModule().getSourceFileName();
+llvm::StringRef BaseName = llvm::sys::path::filename(FileName);
+std::string VarName = "__cli_" + BaseName.str();
+std::replace(VarName.begin(), VarName.end(), '.', '_');
+
+// Join command line args into one string
+std::string CmdLineStr;
+for (const std::string &Arg : CodeGenOpts.CommandLineArgs) {
+    CmdLineStr += Arg + " ";
+}
+
+// Step 1: Create string constant (char[] data)
+llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true);
+
+// Step 2: Emit internal variable: @__cli_foo_c.data
+auto *DataGV = new llvm::GlobalVariable(
+    getModule(),
+    CmdStr->getType(),                         // [N x i8]
+    true,                                     // constant
+    llvm::GlobalValue::InternalLinkage,
+    CmdStr,
+    VarName + ".data"
+);
+DataGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
+
+// Step 3: Pointer to string
+llvm::Constant *PtrToStr = llvm::ConstantExpr::getPointerCast(
+    DataGV, llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(getLLVMContext()))
+);
+
+
+// Step 4: Remove dummy external if exists
+if (auto *Old = getModule().getNamedGlobal(VarName)) {
+    Old->eraseFromParent();
+}
+
+// ✅ Step 5: Emit the real global variable
+auto *FinalGV = new llvm::GlobalVariable(
+    getModule(),
+    PtrToStr->getType(),                       // i8*
+    true,                                     // constant
+    llvm::GlobalValue::ExternalLinkage,       // important: this makes it visible!
+    PtrToStr,
+    VarName
+);
+//FinalGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
+
+llvm::errs() << "✅ Emitting " << VarName << " global variable!\n";
+
+// === END ===
+
 }
 
 void CodeGenModule::EmitOpenCLMetadata() {

>From 666c6f4130b18aee0fc5cb79cc6678bcb5c72eed Mon Sep 17 00:00:00 2001
From: pavithra <pavithra at Ubuntu-22.04.3.myguest.virtualbox.org>
Date: Fri, 20 Jun 2025 19:24:00 +0530
Subject: [PATCH 2/2] Fix: Inject __cli_<file> global variable with command
 line

---
 clang/lib/CodeGen/CodeGenModule.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 577cb6f0abd2c..b996da98c5de0 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1515,7 +1515,7 @@ auto *ExternGV = new llvm::GlobalVariable(
 );
 ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
 (void)ExternGV;
-    llvm::errs() << "✅ Emitting __cli global variable!\n";
+    llvm::errs() << "Emitting __cli global variable!\n";
 
   */
   
@@ -1557,7 +1557,7 @@ if (auto *Old = getModule().getNamedGlobal(VarName)) {
     Old->eraseFromParent();
 }
 
-// ✅ Step 5: Emit the real global variable
+// Step 5: Emit the real global variable
 auto *FinalGV = new llvm::GlobalVariable(
     getModule(),
     PtrToStr->getType(),                       // i8*
@@ -1568,7 +1568,7 @@ auto *FinalGV = new llvm::GlobalVariable(
 );
 //FinalGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
 
-llvm::errs() << "✅ Emitting " << VarName << " global variable!\n";
+llvm::errs() << "Emitting " << VarName << " global variable!\n";
 
 // === END ===
 



More information about the cfe-commits mailing list