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/2] [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/2] 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> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
