https://github.com/steffenlarsen updated 
https://github.com/llvm/llvm-project/pull/214135

>From 8af2e41c4def005000f304343c171946f598eacb Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Tue, 4 Aug 2026 01:04:45 -0500
Subject: [PATCH 1/4] [Clang][PCH] Use metadata for embedding AST

To avoid the size restriction that may be imposed by the address spaces
of the target, this patch changes the embedding of the Clang AST from
placing it inside a global variable to placing it inside a metadata
node. This is done by introducing a new metadata node, namely
`llvm.raw.sections`, which refers to nodes comprised of a section name,
an alignment and the section data. The AsmPrinter lowers this to the
corresponding sections.

Assisted-by: Claude Opus 4.6

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 .../CodeGen/ObjectFilePCHContainerWriter.cpp  | 34 ++++++++++---------
 clang/test/Modules/lsv-debuginfo.cpp          |  9 +++--
 clang/test/PCH/pch-clangast-raw-section.c     |  6 ++++
 .../CodeGen/TargetLoweringObjectFileImpl.h    |  8 +++++
 .../llvm/Target/TargetLoweringObjectFile.h    |  7 ++++
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    | 21 ++++++++++++
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  | 23 +++++++++++++
 .../CodeGen/WebAssembly/raw-sections-wasm.ll  |  7 ++++
 llvm/test/CodeGen/X86/raw-sections-coff.ll    | 12 +++++++
 llvm/test/CodeGen/X86/raw-sections-elf.ll     |  7 ++++
 llvm/test/CodeGen/X86/raw-sections-macho.ll   |  9 +++++
 11 files changed, 124 insertions(+), 19 deletions(-)
 create mode 100644 clang/test/PCH/pch-clangast-raw-section.c
 create mode 100644 llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
 create mode 100644 llvm/test/CodeGen/X86/raw-sections-coff.ll
 create mode 100644 llvm/test/CodeGen/X86/raw-sections-elf.ll
 create mode 100644 llvm/test/CodeGen/X86/raw-sections-macho.ll

diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp 
b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
index 074f2a520704d..3a507782bb66e 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
@@ -297,25 +297,27 @@ class PCHContainerGenerator : public ASTConsumer {
       auto *NameAndContent = llvm::MDTuple::get(*VMContext, Ops);
       MD->addOperand(NameAndContent);
     } else {
-      auto Int8Ty = llvm::Type::getInt8Ty(*VMContext);
-      auto *Ty = llvm::ArrayType::get(Int8Ty, Size);
-      auto *Data = llvm::ConstantDataArray::getString(
-          *VMContext, StringRef(SerializedAST.data(), Size),
-          /*AddNull=*/false);
-      auto *ASTSym = new llvm::GlobalVariable(
-          *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage,
-          Data, "__clang_ast");
-      // The on-disk hashtable needs to be aligned.
-      ASTSym->setAlignment(llvm::Align(8));
-
-      // Mach-O also needs a segment name.
+      // Emit the serialized AST into a named section via llvm.raw.sections
+      // metadata, which the AsmPrinter emits directly at the MC layer.
+      // This avoids IR-level size constraints from the target's address space.
+      llvm::NamedMDNode *RawSections =
+          M->getOrInsertNamedMetadata("llvm.raw.sections");
+
+      StringRef SectionName;
       if (Triple.isOSBinFormatMachO())
-        ASTSym->setSection("__CLANG,__clangast");
-      // COFF has an eight character length limit.
+        SectionName = "__CLANG,__clangast";
       else if (Triple.isOSBinFormatCOFF())
-        ASTSym->setSection("clangast");
+        SectionName = "clangast";
       else
-        ASTSym->setSection("__clangast");
+        SectionName = "__clangast";
+
+      llvm::Metadata *Ops[] = {
+          llvm::MDString::get(*VMContext, SectionName),
+          llvm::ConstantAsMetadata::get(
+              llvm::ConstantInt::get(llvm::Type::getInt32Ty(*VMContext), 8)),
+          llvm::MDString::get(*VMContext,
+                              StringRef(SerializedAST.data(), Size))};
+      RawSections->addOperand(llvm::MDTuple::get(*VMContext, Ops));
     }
 
     LLVM_DEBUG({
diff --git a/clang/test/Modules/lsv-debuginfo.cpp 
b/clang/test/Modules/lsv-debuginfo.cpp
index 40455727ecdda..61d2ff9514ed3 100644
--- a/clang/test/Modules/lsv-debuginfo.cpp
+++ b/clang/test/Modules/lsv-debuginfo.cpp
@@ -21,17 +21,20 @@
 // RUN: cat %t-mod.ll | FileCheck %s
 
 // ADT
-// CHECK: @__clang_ast =
+// CHECK: !llvm.raw.sections = !{[[ADT_SEC:![0-9]+]]}
+// CHECK: [[ADT_SEC]] = !{!"__clangast",
 
 // B
-// CHECK: @__clang_ast =
+// CHECK: !llvm.raw.sections = !{[[B_SEC:![0-9]+]]}
+// CHECK: [[B_SEC]] = !{!"__clangast",
 
 // This type isn't anchored anywhere, expect a full definition.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
 // CHECK-SAME:             elements:
 
 // C
-// CHECK: @__clang_ast =
+// CHECK: !llvm.raw.sections = !{[[C_SEC:![0-9]+]]}
+// CHECK: [[C_SEC]] = !{!"__clangast",
 
 // Here, too.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
diff --git a/clang/test/PCH/pch-clangast-raw-section.c 
b/clang/test/PCH/pch-clangast-raw-section.c
new file mode 100644
index 0000000000000..2ef54cf640e1c
--- /dev/null
+++ b/clang/test/PCH/pch-clangast-raw-section.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-pch -fmodule-format=obj 
%S/pchpch1.h -o - | llvm-readelf --sections - | FileCheck %s
+
+// Ensure the serialized AST is emitted via llvm.raw.sections metadata into
+// a __clangast section with 8-byte alignment.
+
+// CHECK: __clangast        PROGBITS  {{[0-9a-f]+}} {{[0-9a-f]+}} 
{{[0-9a-f]+}} 00   A  0   0  8
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h 
b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 78954a8bb2121..a56e8ed6e0879 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -49,6 +49,8 @@ class LLVM_ABI TargetLoweringObjectFileELF : public 
TargetLoweringObjectFile {
   /// Emit Obj-C garbage collection and linker options.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
+  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+
   void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
                             const MCSymbol *Sym,
                             const MachineModuleInfo *MMI) const override;
@@ -144,6 +146,8 @@ class LLVM_ABI TargetLoweringObjectFileMachO : public 
TargetLoweringObjectFile {
   /// Emit the module flags that specify the garbage collection information.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
+  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+
   void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const override;
 
   MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
@@ -207,6 +211,8 @@ class LLVM_ABI TargetLoweringObjectFileCOFF : public 
TargetLoweringObjectFile {
   /// Emit Obj-C garbage collection and linker options.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
+  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+
   void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const override;
 
   MCSection *getStaticCtorSection(unsigned Priority,
@@ -245,6 +251,8 @@ class LLVM_ABI TargetLoweringObjectFileWasm : public 
TargetLoweringObjectFile {
   bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
                                            const Function &F) const override;
 
+  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+
   void InitializeWasm();
   MCSection *getStaticCtorSection(unsigned Priority,
                                   const MCSymbol *KeySym) const override;
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h 
b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index 3cce5974e6705..df8dd3466451e 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -90,6 +90,13 @@ class LLVM_ABI TargetLoweringObjectFile : public 
MCObjectFileInfo {
   /// Emit the module-level metadata that the platform cares about.
   virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
 
+  /// Get a read-only data section with the given name, using 
format-appropriate
+  /// defaults.
+  /// Returns nullptr if not supported by this object file format.
+  virtual MCSection *getNamedReadOnlySection(StringRef Name) const {
+    return nullptr;
+  }
+
   /// Emit Call Graph Profile metadata.
   void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const;
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp 
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0580fc0f3a034..af48b444b7991 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2980,6 +2980,27 @@ bool AsmPrinter::doFinalization(Module &M) {
 
   TLOF.emitModuleMetadata(*OutStreamer, M);
 
+  // Emit raw section data from llvm.raw.sections metadata.
+  if (const NamedMDNode *RawSections =
+          M.getNamedMetadata("llvm.raw.sections")) {
+    for (const MDNode *Op : RawSections->operands()) {
+      assert(Op->getNumOperands() == 3 &&
+             "llvm.raw.sections metadata entry must have three operands");
+      auto *SectionName = cast<MDString>(Op->getOperand(0));
+      auto *AlignCI = mdconst::extract<ConstantInt>(Op->getOperand(1));
+      auto *Data = cast<MDString>(Op->getOperand(2));
+
+      if (MCSection *Section =
+              TLOF.getNamedReadOnlySection(SectionName->getString())) {
+        OutStreamer->pushSection();
+        OutStreamer->switchSection(Section);
+        OutStreamer->emitValueToAlignment(Align(AlignCI->getZExtValue()));
+        OutStreamer->emitBytes(Data->getString());
+        OutStreamer->popSection();
+      }
+    }
+  }
+
   if (Target.isOSBinFormatELF()) {
     MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
 
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp 
b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 84b72321b1f55..bcdb2c3d63715 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -377,6 +377,11 @@ void 
TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
   emitCGProfileMetadata(Streamer, M);
 }
 
+MCSection *
+TargetLoweringObjectFileELF::getNamedReadOnlySection(StringRef Name) const {
+  return getContext().getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
+}
+
 void TargetLoweringObjectFileELF::emitLinkerDirectives(MCStreamer &Streamer,
                                                        Module &M) const {
   auto &C = getContext();
@@ -1350,6 +1355,13 @@ void 
TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
   Streamer.addBlankLine();
 }
 
+MCSection *
+TargetLoweringObjectFileMachO::getNamedReadOnlySection(StringRef Name) const {
+  auto [Segment, SecName] = Name.split(',');
+  return getContext().getMachOSection(Segment, SecName, 0,
+                                      SectionKind::getReadOnly());
+}
+
 void TargetLoweringObjectFileMachO::emitLinkerDirectives(MCStreamer &Streamer,
                                                          Module &M) const {
   if (auto *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
@@ -1944,6 +1956,12 @@ void 
TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
   });
 }
 
+MCSection *
+TargetLoweringObjectFileCOFF::getNamedReadOnlySection(StringRef Name) const {
+  return getContext().getCOFFSection(
+      Name, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ);
+}
+
 void TargetLoweringObjectFileCOFF::emitLinkerDirectives(
     MCStreamer &Streamer, Module &M) const {
   if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
@@ -2258,6 +2276,11 @@ void 
TargetLoweringObjectFileWasm::getModuleMetadata(Module &M) {
       Used.insert(GO);
 }
 
+MCSection *
+TargetLoweringObjectFileWasm::getNamedReadOnlySection(StringRef Name) const {
+  return getContext().getWasmSection(Name, SectionKind::getReadOnly());
+}
+
 MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
   // We don't support explict section names for functions in the wasm object
diff --git a/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll 
b/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
new file mode 100644
index 0000000000000..a326a5e912508
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
@@ -0,0 +1,7 @@
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown %s -o %t.o
+; RUN: llvm-readobj --sections %t.o | FileCheck %s
+
+; CHECK: Name: __clangast
+
+!0 = !{!"__clangast", i32 8, !"\de\ad\be\ef"}
+!llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-coff.ll 
b/llvm/test/CodeGen/X86/raw-sections-coff.ll
new file mode 100644
index 0000000000000..fc9d2e7515f94
--- /dev/null
+++ b/llvm/test/CodeGen/X86/raw-sections-coff.ll
@@ -0,0 +1,12 @@
+; RUN: llc -filetype=obj -mtriple=x86_64-windows-msvc %s -o %t.o
+; RUN: llvm-readobj --sections %t.o | FileCheck %s
+
+; CHECK:      Name: clangast
+; CHECK:      RawDataSize:
+; CHECK:      Characteristics [
+; CHECK-DAG:    IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG:    IMAGE_SCN_MEM_READ
+; CHECK:      ]
+
+!0 = !{!"clangast", i32 8, !"\de\ad\be\ef"}
+!llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-elf.ll 
b/llvm/test/CodeGen/X86/raw-sections-elf.ll
new file mode 100644
index 0000000000000..c1afbb043066b
--- /dev/null
+++ b/llvm/test/CodeGen/X86/raw-sections-elf.ll
@@ -0,0 +1,7 @@
+; RUN: llc -filetype=obj -mtriple=x86_64-linux-gnu %s -o %t.o
+; RUN: llvm-readelf --sections %t.o | FileCheck %s
+
+; CHECK: __clangast        PROGBITS  {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 
00   A  0   0  8
+
+!0 = !{!"__clangast", i32 8, !"\de\ad\be\ef"}
+!llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-macho.ll 
b/llvm/test/CodeGen/X86/raw-sections-macho.ll
new file mode 100644
index 0000000000000..54d16b45529c4
--- /dev/null
+++ b/llvm/test/CodeGen/X86/raw-sections-macho.ll
@@ -0,0 +1,9 @@
+; RUN: llc -filetype=obj -mtriple=x86_64-apple-darwin %s -o %t.o
+; RUN: llvm-readobj --sections %t.o | FileCheck %s
+
+; CHECK:      Name: __clangast
+; CHECK-NEXT: Segment: __CLANG
+; CHECK:      Size:
+
+!0 = !{!"__CLANG,__clangast", i32 8, !"\de\ad\be\ef"}
+!llvm.raw.sections = !{!0}

>From 139c6119893b9bc991feff84a9394cadff8bcd5a Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 5 Aug 2026 04:09:58 -0500
Subject: [PATCH 2/4] Fix test expectations

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/test/Modules/gmodules-nodebug.cpp | 1 +
 clang/test/Modules/lsv-debuginfo.cpp    | 8 ++++----
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/clang/test/Modules/gmodules-nodebug.cpp 
b/clang/test/Modules/gmodules-nodebug.cpp
index d83103768e838..da05d35667d52 100644
--- a/clang/test/Modules/gmodules-nodebug.cpp
+++ b/clang/test/Modules/gmodules-nodebug.cpp
@@ -12,3 +12,4 @@ __void_t<> func() {}
 
 // CHECK: !DICompileUnit
 // CHECK-NOT: __void_t
+// CHECK: !{!"__clangast",
diff --git a/clang/test/Modules/lsv-debuginfo.cpp 
b/clang/test/Modules/lsv-debuginfo.cpp
index 61d2ff9514ed3..fc05fce5c6d5d 100644
--- a/clang/test/Modules/lsv-debuginfo.cpp
+++ b/clang/test/Modules/lsv-debuginfo.cpp
@@ -24,20 +24,20 @@
 // CHECK: !llvm.raw.sections = !{[[ADT_SEC:![0-9]+]]}
 // CHECK: [[ADT_SEC]] = !{!"__clangast",
 
-// B
+// B — named metadata first, then numbered nodes (DICompositeType before blob)
 // CHECK: !llvm.raw.sections = !{[[B_SEC:![0-9]+]]}
-// CHECK: [[B_SEC]] = !{!"__clangast",
 
 // This type isn't anchored anywhere, expect a full definition.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
 // CHECK-SAME:             elements:
+// CHECK: [[B_SEC]] = !{!"__clangast",
 
-// C
+// C — same ordering
 // CHECK: !llvm.raw.sections = !{[[C_SEC:![0-9]+]]}
-// CHECK: [[C_SEC]] = !{!"__clangast",
 
 // Here, too.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
 // CHECK-SAME:             elements:
+// CHECK: [[C_SEC]] = !{!"__clangast",
 
 #include <B/B.h>

>From 8f0d295f95cc9887d7909b65d543137f51e283a4 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Wed, 5 Aug 2026 06:26:02 -0500
Subject: [PATCH 3/4] Change expectations to be target-independent

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 clang/test/Modules/gmodules-nodebug.cpp |  2 +-
 clang/test/Modules/lsv-debuginfo.cpp    | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/test/Modules/gmodules-nodebug.cpp 
b/clang/test/Modules/gmodules-nodebug.cpp
index da05d35667d52..1be0dddfa149b 100644
--- a/clang/test/Modules/gmodules-nodebug.cpp
+++ b/clang/test/Modules/gmodules-nodebug.cpp
@@ -12,4 +12,4 @@ __void_t<> func() {}
 
 // CHECK: !DICompileUnit
 // CHECK-NOT: __void_t
-// CHECK: !{!"__clangast",
+// CHECK: !{!"{{(__CLANG,)?(__)?}}clangast",
diff --git a/clang/test/Modules/lsv-debuginfo.cpp 
b/clang/test/Modules/lsv-debuginfo.cpp
index fc05fce5c6d5d..189266f4ae324 100644
--- a/clang/test/Modules/lsv-debuginfo.cpp
+++ b/clang/test/Modules/lsv-debuginfo.cpp
@@ -22,22 +22,22 @@
 
 // ADT
 // CHECK: !llvm.raw.sections = !{[[ADT_SEC:![0-9]+]]}
-// CHECK: [[ADT_SEC]] = !{!"__clangast",
+// CHECK: [[ADT_SEC]] = !{!"{{(__CLANG,)?(__)?}}clangast",
 
-// B — named metadata first, then numbered nodes (DICompositeType before blob)
+// B
 // CHECK: !llvm.raw.sections = !{[[B_SEC:![0-9]+]]}
 
 // This type isn't anchored anywhere, expect a full definition.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
 // CHECK-SAME:             elements:
-// CHECK: [[B_SEC]] = !{!"__clangast",
+// CHECK: [[B_SEC]] = !{!"{{(__CLANG,)?(__)?}}clangast",
 
-// C — same ordering
+// C
 // CHECK: !llvm.raw.sections = !{[[C_SEC:![0-9]+]]}
 
 // Here, too.
 // CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4U, 16U>",
 // CHECK-SAME:             elements:
-// CHECK: [[C_SEC]] = !{!"__clangast",
+// CHECK: [[C_SEC]] = !{!"{{(__CLANG,)?(__)?}}clangast",
 
 #include <B/B.h>

>From db80d8641bdd74f5376ff8f6b1f473a2b093c299 Mon Sep 17 00:00:00 2001
From: Steffen Holst Larsen <[email protected]>
Date: Thu, 6 Aug 2026 01:34:09 -0500
Subject: [PATCH 4/4] Add section kind field, verify in verifier and document

Signed-off-by: Steffen Holst Larsen <[email protected]>
---
 .../CodeGen/ObjectFilePCHContainerWriter.cpp  |  7 +++--
 llvm/docs/LangRef.md                          | 29 +++++++++++++++++
 .../CodeGen/TargetLoweringObjectFileImpl.h    |  8 ++---
 llvm/include/llvm/MC/SectionKind.h            |  5 +++
 .../llvm/Target/TargetLoweringObjectFile.h    |  6 ++--
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    | 11 ++++---
 .../CodeGen/TargetLoweringObjectFileImpl.cpp  | 30 ++++++++++--------
 llvm/lib/IR/Verifier.cpp                      | 31 +++++++++++++++++++
 .../CodeGen/WebAssembly/raw-sections-wasm.ll  |  2 +-
 llvm/test/CodeGen/X86/raw-sections-coff.ll    |  2 +-
 llvm/test/CodeGen/X86/raw-sections-elf.ll     |  2 +-
 llvm/test/CodeGen/X86/raw-sections-macho.ll   |  2 +-
 llvm/test/Verifier/raw-sections.ll            |  9 ++++++
 13 files changed, 113 insertions(+), 31 deletions(-)
 create mode 100644 llvm/test/Verifier/raw-sections.ll

diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp 
b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
index 3a507782bb66e..fffc28721e825 100644
--- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
+++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp
@@ -25,6 +25,7 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
+#include "llvm/MC/SectionKind.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Support/Path.h"
@@ -311,10 +312,12 @@ class PCHContainerGenerator : public ASTConsumer {
       else
         SectionName = "__clangast";
 
+      auto *Int32Ty = llvm::Type::getInt32Ty(*VMContext);
       llvm::Metadata *Ops[] = {
           llvm::MDString::get(*VMContext, SectionName),
-          llvm::ConstantAsMetadata::get(
-              llvm::ConstantInt::get(llvm::Type::getInt32Ty(*VMContext), 8)),
+          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int32Ty, 8)),
+          llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+              Int32Ty, llvm::SectionKind::getReadOnly().getValue())),
           llvm::MDString::get(*VMContext,
                               StringRef(SerializedAST.data(), Size))};
       RawSections->addOperand(llvm::MDTuple::get(*VMContext, Ops));
diff --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 6a3194271b838..bd484213eff73 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -9623,6 +9623,35 @@ for an integer access:
 Multiple TBAA operands are allowed to support merging of modules that may use
 different TBAA hierarchies (e.g., when mixing C and C++).
 
+## '`llvm.raw.sections`' Named Metadata
+
+The module-level `!llvm.raw.sections` metadata allows embedding arbitrary
+binary data into named sections of the output object file. A
+`!llvm.raw.sections` metadata node is a list of metadata nodes with the
+following fields:
+
+```
+!0 = !{!"section_name", i32 alignment, i32 section_kind, !"raw data"}
+```
+
+- **section_name**: The name of the output section.
+- **alignment**: The byte alignment of the section data.
+- **section_kind**: An integer value corresponding to the `SectionKind` type
+  declared in the `<include/llvm/MC/SectionKind.h>` header file. This field
+  specifies the nature of the section (e.g. read-only, data, metadata). Each
+  target maps this to format-appropriate section flags.
+- **raw data**: The binary contents of the section.
+
+Example:
+```
+!llvm.raw.sections = !{!0}
+!0 = !{!"__mydata", i32 8, i32 4, !"\DE\AD\BE\EF"}
+```
+
+Each of the nodes inside a `!llvm.raw.sections` metadata node gets lowered to
+a target-specific named data section. Targets that do not support arbitrary
+named sections silently skip `!llvm.raw.sections` metadata nodes.
+
 (summary)=
 
 ## ThinLTO Summary
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h 
b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index a56e8ed6e0879..f334e5e454454 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -49,7 +49,7 @@ class LLVM_ABI TargetLoweringObjectFileELF : public 
TargetLoweringObjectFile {
   /// Emit Obj-C garbage collection and linker options.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
-  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+  MCSection *getNamedSection(StringRef Name, SectionKind Kind) const override;
 
   void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &DL,
                             const MCSymbol *Sym,
@@ -146,7 +146,7 @@ class LLVM_ABI TargetLoweringObjectFileMachO : public 
TargetLoweringObjectFile {
   /// Emit the module flags that specify the garbage collection information.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
-  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+  MCSection *getNamedSection(StringRef Name, SectionKind Kind) const override;
 
   void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const override;
 
@@ -211,7 +211,7 @@ class LLVM_ABI TargetLoweringObjectFileCOFF : public 
TargetLoweringObjectFile {
   /// Emit Obj-C garbage collection and linker options.
   void emitModuleMetadata(MCStreamer &Streamer, Module &M) const override;
 
-  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+  MCSection *getNamedSection(StringRef Name, SectionKind Kind) const override;
 
   void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const override;
 
@@ -251,7 +251,7 @@ class LLVM_ABI TargetLoweringObjectFileWasm : public 
TargetLoweringObjectFile {
   bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
                                            const Function &F) const override;
 
-  MCSection *getNamedReadOnlySection(StringRef Name) const override;
+  MCSection *getNamedSection(StringRef Name, SectionKind Kind) const override;
 
   void InitializeWasm();
   MCSection *getStaticCtorSection(unsigned Priority,
diff --git a/llvm/include/llvm/MC/SectionKind.h 
b/llvm/include/llvm/MC/SectionKind.h
index 61e400fe9edee..5c10f8f25d64d 100644
--- a/llvm/include/llvm/MC/SectionKind.h
+++ b/llvm/include/llvm/MC/SectionKind.h
@@ -212,6 +212,11 @@ class SectionKind {
   static SectionKind getCommon() { return get(Common); }
   static SectionKind getData() { return get(Data); }
   static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); }
+
+  unsigned getValue() const { return static_cast<unsigned>(K); }
+  static SectionKind fromValue(unsigned Val) {
+    return get(static_cast<Kind>(Val));
+  }
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h 
b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
index df8dd3466451e..437279501af53 100644
--- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h
@@ -90,10 +90,10 @@ class LLVM_ABI TargetLoweringObjectFile : public 
MCObjectFileInfo {
   /// Emit the module-level metadata that the platform cares about.
   virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M) const {}
 
-  /// Get a read-only data section with the given name, using 
format-appropriate
-  /// defaults.
+  /// Get a section with the given name and kind, using format-appropriate
+  /// defaults for section flags.
   /// Returns nullptr if not supported by this object file format.
-  virtual MCSection *getNamedReadOnlySection(StringRef Name) const {
+  virtual MCSection *getNamedSection(StringRef Name, SectionKind Kind) const {
     return nullptr;
   }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp 
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index af48b444b7991..febedf3b49a41 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2980,18 +2980,19 @@ bool AsmPrinter::doFinalization(Module &M) {
 
   TLOF.emitModuleMetadata(*OutStreamer, M);
 
-  // Emit raw section data from llvm.raw.sections metadata.
+  // Emit raw section data from llvm.raw.sections metadata. Each operand is
+  // a tuple of {section_name, alignment, section_kind, data}.
   if (const NamedMDNode *RawSections =
           M.getNamedMetadata("llvm.raw.sections")) {
     for (const MDNode *Op : RawSections->operands()) {
-      assert(Op->getNumOperands() == 3 &&
-             "llvm.raw.sections metadata entry must have three operands");
       auto *SectionName = cast<MDString>(Op->getOperand(0));
       auto *AlignCI = mdconst::extract<ConstantInt>(Op->getOperand(1));
-      auto *Data = cast<MDString>(Op->getOperand(2));
+      auto *KindCI = mdconst::extract<ConstantInt>(Op->getOperand(2));
+      auto *Data = cast<MDString>(Op->getOperand(3));
 
+      SectionKind Kind = SectionKind::fromValue(KindCI->getZExtValue());
       if (MCSection *Section =
-              TLOF.getNamedReadOnlySection(SectionName->getString())) {
+              TLOF.getNamedSection(SectionName->getString(), Kind)) {
         OutStreamer->pushSection();
         OutStreamer->switchSection(Section);
         OutStreamer->emitValueToAlignment(Align(AlignCI->getZExtValue()));
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp 
b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index bcdb2c3d63715..df87c8bdbda10 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -377,11 +377,6 @@ void 
TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
   emitCGProfileMetadata(Streamer, M);
 }
 
-MCSection *
-TargetLoweringObjectFileELF::getNamedReadOnlySection(StringRef Name) const {
-  return getContext().getELFSection(Name, ELF::SHT_PROGBITS, ELF::SHF_ALLOC);
-}
-
 void TargetLoweringObjectFileELF::emitLinkerDirectives(MCStreamer &Streamer,
                                                        Module &M) const {
   auto &C = getContext();
@@ -576,6 +571,14 @@ static unsigned getELFSectionFlags(SectionKind K, const 
Triple &T) {
   return Flags;
 }
 
+MCSection *
+TargetLoweringObjectFileELF::getNamedSection(StringRef Name,
+                                             SectionKind Kind) const {
+  unsigned Type = getELFSectionType(Name, Kind);
+  unsigned Flags = getELFSectionFlags(Kind, getContext().getTargetTriple());
+  return getContext().getELFSection(Name, Type, Flags);
+}
+
 static const Comdat *getELFComdat(const GlobalValue *GV) {
   const Comdat *C = GV->getComdat();
   if (!C)
@@ -1356,10 +1359,10 @@ void 
TargetLoweringObjectFileMachO::emitModuleMetadata(MCStreamer &Streamer,
 }
 
 MCSection *
-TargetLoweringObjectFileMachO::getNamedReadOnlySection(StringRef Name) const {
+TargetLoweringObjectFileMachO::getNamedSection(StringRef Name,
+                                               SectionKind Kind) const {
   auto [Segment, SecName] = Name.split(',');
-  return getContext().getMachOSection(Segment, SecName, 0,
-                                      SectionKind::getReadOnly());
+  return getContext().getMachOSection(Segment, SecName, 0, Kind);
 }
 
 void TargetLoweringObjectFileMachO::emitLinkerDirectives(MCStreamer &Streamer,
@@ -1957,9 +1960,9 @@ void 
TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
 }
 
 MCSection *
-TargetLoweringObjectFileCOFF::getNamedReadOnlySection(StringRef Name) const {
-  return getContext().getCOFFSection(
-      Name, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ);
+TargetLoweringObjectFileCOFF::getNamedSection(StringRef Name,
+                                              SectionKind Kind) const {
+  return getContext().getCOFFSection(Name, getCOFFSectionFlags(Kind, *TM));
 }
 
 void TargetLoweringObjectFileCOFF::emitLinkerDirectives(
@@ -2277,8 +2280,9 @@ void 
TargetLoweringObjectFileWasm::getModuleMetadata(Module &M) {
 }
 
 MCSection *
-TargetLoweringObjectFileWasm::getNamedReadOnlySection(StringRef Name) const {
-  return getContext().getWasmSection(Name, SectionKind::getReadOnly());
+TargetLoweringObjectFileWasm::getNamedSection(StringRef Name,
+                                              SectionKind Kind) const {
+  return getContext().getWasmSection(Name, Kind);
 }
 
 MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 44d1843aa56a9..e5ec2ac833338 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -308,6 +308,7 @@ class Verifier : public InstVisitor<Verifier>, 
VerifierSupport {
     visitModuleIdents();
     visitModuleCommandLines();
     visitModuleErrnoTBAA();
+    visitModuleRawSections();
 
     verifyCompileUnits();
 
@@ -345,6 +346,7 @@ class Verifier : public InstVisitor<Verifier>, 
VerifierSupport {
   void visitModuleIdents();
   void visitModuleCommandLines();
   void visitModuleErrnoTBAA();
+  void visitModuleRawSections();
   void visitModuleFlags();
   void visitModuleFlag(const MDNode *Op,
                        DenseMap<const MDString *, const MDNode *> &SeenIDs,
@@ -1844,6 +1846,35 @@ void Verifier::visitModuleErrnoTBAA() {
     TBAAVerifyHelper.visitTBAAMetadata(nullptr, N);
 }
 
+void Verifier::visitModuleRawSections() {
+  const NamedMDNode *RawSections = M.getNamedMetadata("llvm.raw.sections");
+  if (!RawSections)
+    return;
+
+  for (const MDNode *N : RawSections->operands()) {
+    if (N->getNumOperands() != 4) {
+      CheckFailed("llvm.raw.sections entry must have four operands", N);
+      continue;
+    }
+    Check(dyn_cast_or_null<MDString>(N->getOperand(0)),
+          "llvm.raw.sections entry operand 0 must be a string "
+          "(section name)",
+          N);
+    Check(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(1)),
+          "llvm.raw.sections entry operand 1 must be an integer "
+          "(alignment)",
+          N);
+    Check(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(2)),
+          "llvm.raw.sections entry operand 2 must be an integer "
+          "(section kind)",
+          N);
+    Check(dyn_cast_or_null<MDString>(N->getOperand(3)),
+          "llvm.raw.sections entry operand 3 must be a string "
+          "(section data)",
+          N);
+  }
+}
+
 void Verifier::visitModuleFlags() {
   const NamedMDNode *Flags = M.getModuleFlagsMetadata();
   if (!Flags) return;
diff --git a/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll 
b/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
index a326a5e912508..8bcad587a0e01 100644
--- a/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
+++ b/llvm/test/CodeGen/WebAssembly/raw-sections-wasm.ll
@@ -3,5 +3,5 @@
 
 ; CHECK: Name: __clangast
 
-!0 = !{!"__clangast", i32 8, !"\de\ad\be\ef"}
+!0 = !{!"__clangast", i32 8, i32 4, !"\de\ad\be\ef"}
 !llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-coff.ll 
b/llvm/test/CodeGen/X86/raw-sections-coff.ll
index fc9d2e7515f94..4b83e5145a422 100644
--- a/llvm/test/CodeGen/X86/raw-sections-coff.ll
+++ b/llvm/test/CodeGen/X86/raw-sections-coff.ll
@@ -8,5 +8,5 @@
 ; CHECK-DAG:    IMAGE_SCN_MEM_READ
 ; CHECK:      ]
 
-!0 = !{!"clangast", i32 8, !"\de\ad\be\ef"}
+!0 = !{!"clangast", i32 8, i32 4, !"\de\ad\be\ef"}
 !llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-elf.ll 
b/llvm/test/CodeGen/X86/raw-sections-elf.ll
index c1afbb043066b..8ac065224ce9a 100644
--- a/llvm/test/CodeGen/X86/raw-sections-elf.ll
+++ b/llvm/test/CodeGen/X86/raw-sections-elf.ll
@@ -3,5 +3,5 @@
 
 ; CHECK: __clangast        PROGBITS  {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 
00   A  0   0  8
 
-!0 = !{!"__clangast", i32 8, !"\de\ad\be\ef"}
+!0 = !{!"__clangast", i32 8, i32 4, !"\de\ad\be\ef"}
 !llvm.raw.sections = !{!0}
diff --git a/llvm/test/CodeGen/X86/raw-sections-macho.ll 
b/llvm/test/CodeGen/X86/raw-sections-macho.ll
index 54d16b45529c4..cff3272c9ad83 100644
--- a/llvm/test/CodeGen/X86/raw-sections-macho.ll
+++ b/llvm/test/CodeGen/X86/raw-sections-macho.ll
@@ -5,5 +5,5 @@
 ; CHECK-NEXT: Segment: __CLANG
 ; CHECK:      Size:
 
-!0 = !{!"__CLANG,__clangast", i32 8, !"\de\ad\be\ef"}
+!0 = !{!"__CLANG,__clangast", i32 8, i32 4, !"\de\ad\be\ef"}
 !llvm.raw.sections = !{!0}
diff --git a/llvm/test/Verifier/raw-sections.ll 
b/llvm/test/Verifier/raw-sections.ll
new file mode 100644
index 0000000000000..77bc01f89b06c
--- /dev/null
+++ b/llvm/test/Verifier/raw-sections.ll
@@ -0,0 +1,9 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+; CHECK: llvm.raw.sections entry must have four operands
+; CHECK: llvm.raw.sections entry operand 0 must be a string (section name)
+
+!llvm.raw.sections = !{!0, !1, !2}
+!0 = !{!"__clangast", i32 8, i32 4, !"data"}
+!1 = !{!"__clangast", i32 8, !"data"}
+!2 = !{i32 0, i32 8, i32 4, !"data"}

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

Reply via email to