https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/119533
Backport ac5dd455caaf286625f61b604291f2eaed9702f0 ed91843d435d0cd2c39ebb1a50f2907c621f07ed Requested by: @nikic >From 43e9788703a7fd79c616602a35c1eea586dfc99b Mon Sep 17 00:00:00 2001 From: George Stagg <georgest...@gmail.com> Date: Wed, 4 Dec 2024 21:12:15 +0000 Subject: [PATCH 1/2] [WebAssembly] Support multiple `.init_array` fragments when writing Wasm objects (#111008) (cherry picked from commit ac5dd455caaf286625f61b604291f2eaed9702f0) --- llvm/lib/MC/WasmObjectWriter.cpp | 89 ++++++++++++++------------- llvm/test/MC/WebAssembly/init-array.s | 49 +++++++++++++++ 2 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 llvm/test/MC/WebAssembly/init-array.s diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index f25dc92fa235a2..a66c5713ff8a6e 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1853,49 +1853,54 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, if (EmptyFrag.getKind() != MCFragment::FT_Data) report_fatal_error(".init_array section should be aligned"); - const MCFragment &AlignFrag = *EmptyFrag.getNext(); - if (AlignFrag.getKind() != MCFragment::FT_Align) - report_fatal_error(".init_array section should be aligned"); - if (cast<MCAlignFragment>(AlignFrag).getAlignment() != - Align(is64Bit() ? 8 : 4)) - report_fatal_error(".init_array section should be aligned for pointers"); - - const MCFragment &Frag = *AlignFrag.getNext(); - if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) - report_fatal_error("only data supported in .init_array section"); - - uint16_t Priority = UINT16_MAX; - unsigned PrefixLength = strlen(".init_array"); - if (WS.getName().size() > PrefixLength) { - if (WS.getName()[PrefixLength] != '.') + const MCFragment *nextFrag = EmptyFrag.getNext(); + while (nextFrag != nullptr) { + const MCFragment &AlignFrag = *nextFrag; + if (AlignFrag.getKind() != MCFragment::FT_Align) + report_fatal_error(".init_array section should be aligned"); + if (cast<MCAlignFragment>(AlignFrag).getAlignment() != + Align(is64Bit() ? 8 : 4)) report_fatal_error( - ".init_array section priority should start with '.'"); - if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) - report_fatal_error("invalid .init_array section priority"); - } - const auto &DataFrag = cast<MCDataFragment>(Frag); - const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - for (const uint8_t * - P = (const uint8_t *)Contents.data(), - *End = (const uint8_t *)Contents.data() + Contents.size(); - P != End; ++P) { - if (*P != 0) - report_fatal_error("non-symbolic data in .init_array section"); - } - for (const MCFixup &Fixup : DataFrag.getFixups()) { - assert(Fixup.getKind() == - MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); - const MCExpr *Expr = Fixup.getValue(); - auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr); - if (!SymRef) - report_fatal_error("fixups in .init_array should be symbol references"); - const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol()); - if (TargetSym.getIndex() == InvalidIndex) - report_fatal_error("symbols in .init_array should exist in symtab"); - if (!TargetSym.isFunction()) - report_fatal_error("symbols in .init_array should be for functions"); - InitFuncs.push_back( - std::make_pair(Priority, TargetSym.getIndex())); + ".init_array section should be aligned for pointers"); + + const MCFragment &Frag = *AlignFrag.getNext(); + nextFrag = Frag.getNext(); + if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data) + report_fatal_error("only data supported in .init_array section"); + + uint16_t Priority = UINT16_MAX; + unsigned PrefixLength = strlen(".init_array"); + if (WS.getName().size() > PrefixLength) { + if (WS.getName()[PrefixLength] != '.') + report_fatal_error( + ".init_array section priority should start with '.'"); + if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority)) + report_fatal_error("invalid .init_array section priority"); + } + const auto &DataFrag = cast<MCDataFragment>(Frag); + const SmallVectorImpl<char> &Contents = DataFrag.getContents(); + for (const uint8_t * + P = (const uint8_t *)Contents.data(), + *End = (const uint8_t *)Contents.data() + Contents.size(); + P != End; ++P) { + if (*P != 0) + report_fatal_error("non-symbolic data in .init_array section"); + } + for (const MCFixup &Fixup : DataFrag.getFixups()) { + assert(Fixup.getKind() == + MCFixup::getKindForSize(is64Bit() ? 8 : 4, false)); + const MCExpr *Expr = Fixup.getValue(); + auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr); + if (!SymRef) + report_fatal_error( + "fixups in .init_array should be symbol references"); + const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol()); + if (TargetSym.getIndex() == InvalidIndex) + report_fatal_error("symbols in .init_array should exist in symtab"); + if (!TargetSym.isFunction()) + report_fatal_error("symbols in .init_array should be for functions"); + InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex())); + } } } diff --git a/llvm/test/MC/WebAssembly/init-array.s b/llvm/test/MC/WebAssembly/init-array.s new file mode 100644 index 00000000000000..e79fb453ec12a3 --- /dev/null +++ b/llvm/test/MC/WebAssembly/init-array.s @@ -0,0 +1,49 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s + +init1: + .functype init1 () -> () + end_function + +init2: + .functype init2 () -> () + end_function + + .section .init_array,"",@ + .p2align 2, 0 + .int32 init1 + + .section .init_array,"",@ + .p2align 2 + .int32 init2 + +# CHECK: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 0 ] +# CHECK-NEXT: - Type: CODE +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 0B +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 0B +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: linking +# CHECK-NEXT: Version: 2 +# CHECK-NEXT: SymbolTable: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: init1 +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 0 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: init2 +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 1 +# CHECK-NEXT: InitFunctions: +# CHECK-NEXT: - Priority: 65535 +# CHECK-NEXT: Symbol: 0 +# CHECK-NEXT: - Priority: 65535 +# CHECK-NEXT: Symbol: 1 +# CHECK-NEXT: ... +# >From f2eb7829baebcdd34fd5225e60ed89cd00f21d16 Mon Sep 17 00:00:00 2001 From: George Stagg <george.st...@posit.co> Date: Tue, 10 Dec 2024 16:28:18 +0000 Subject: [PATCH 2/2] [WebAssembly] Handle symbols in `.init_array` sections (#119127) Follow on from #111008. (cherry picked from commit ed91843d435d0cd2c39ebb1a50f2907c621f07ed) --- llvm/lib/MC/WasmObjectWriter.cpp | 22 ++++- llvm/test/MC/WebAssembly/init-array-label.s | 91 +++++++++++++++++++++ 2 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MC/WebAssembly/init-array-label.s diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index a66c5713ff8a6e..85264692456767 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1326,6 +1326,22 @@ static bool isInSymtab(const MCSymbolWasm &Sym) { return true; } +static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section) { + StringRef SectionName = Section.getName(); + + for (const MCSymbol &S : Asm.symbols()) { + const auto &WS = static_cast<const MCSymbolWasm &>(S); + if (WS.isData() && WS.isInSection()) { + auto &RefSection = static_cast<MCSectionWasm &>(WS.getSection()); + if (RefSection.getName() == SectionName) { + return true; + } + } + } + + return false; +} + void WasmObjectWriter::prepareImports( SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm) { // For now, always emit the memory import, since loads and stores are not @@ -1482,8 +1498,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group " << Section.getGroup() << "\n";); - // .init_array sections are handled specially elsewhere. - if (SectionName.starts_with(".init_array")) + // .init_array sections are handled specially elsewhere, include them in + // data segments if and only if referenced by a symbol. + if (SectionName.starts_with(".init_array") && + !isSectionReferenced(Asm, Section)) continue; // Code is handled separately diff --git a/llvm/test/MC/WebAssembly/init-array-label.s b/llvm/test/MC/WebAssembly/init-array-label.s new file mode 100644 index 00000000000000..0b4a5ea2da0b59 --- /dev/null +++ b/llvm/test/MC/WebAssembly/init-array-label.s @@ -0,0 +1,91 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s + +init1: + .functype init1 () -> () + end_function + +init2: + .functype init2 () -> () + end_function + + .section .init_array.42,"",@ + .p2align 2, 0x0 + .int32 init1 + + .section .init_array,"",@ + .globl p_init1 + .p2align 2, 0x0 +p_init1: + .int32 init1 + .size p_init1, 4 + + .section .init_array,"",@ + .globl p_init2 + .p2align 2, 0x0 +p_init2: + .int32 init1 + .int32 init2 + .size p_init2, 8 + +# CHECK: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 0 ] +# CHECK-NEXT: - Type: DATACOUNT +# CHECK-NEXT: Count: 1 +# CHECK-NEXT: - Type: CODE +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 0B +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 0B +# CHECK-NEXT: - Type: DATA +# CHECK-NEXT: Segments: +# CHECK-NEXT: - SectionOffset: 6 +# CHECK-NEXT: InitFlags: 0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 0 +# CHECK-NEXT: Content: '000000000000000000000000' +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: linking +# CHECK-NEXT: Version: 2 +# CHECK-NEXT: SymbolTable: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: init1 +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 0 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: init2 +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 1 +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: p_init1 +# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: Segment: 0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: p_init2 +# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: Segment: 0 +# CHECK-NEXT: Offset: 4 +# CHECK-NEXT: Size: 8 +# CHECK-NEXT: SegmentInfo: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: .init_array +# CHECK-NEXT: Alignment: 2 +# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: InitFunctions: +# CHECK-NEXT: - Priority: 42 +# CHECK-NEXT: Symbol: 0 +# CHECK-NEXT: - Priority: 65535 +# CHECK-NEXT: Symbol: 0 +# CHECK-NEXT: - Priority: 65535 +# CHECK-NEXT: Symbol: 0 +# CHECK-NEXT: - Priority: 65535 +# CHECK-NEXT: Symbol: 1 +# CHECK-NEXT: ... _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits