[llvm] 73332d7 - [lld][WebAssembly] Do not merge comdat data segments

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Mon May 3 16:43:46 PDT 2021


Author: Sam Clegg
Date: 2021-05-03T16:43:29-07:00
New Revision: 73332d73e15f4fdf8e4240c585d0a334f23926f3

URL: https://github.com/llvm/llvm-project/commit/73332d73e15f4fdf8e4240c585d0a334f23926f3
DIFF: https://github.com/llvm/llvm-project/commit/73332d73e15f4fdf8e4240c585d0a334f23926f3.diff

LOG: [lld][WebAssembly] Do not merge comdat data segments

When running in relocatable mode any input data segments that are part
of a comdat group should not be merged with other segments of the same
name.  This is because the final linker needs to keep the separate so
they can be included/excluded individually.

Often this is not a problem since normally only one section with a given
name `foo` ends up in the output object file.  However, the problem
occurs when one input contains `foo` which part of a comdat and another
object contains a local symbol `foo` we were attempting to merge them.

This behaviour matches (I believe) that of the ELF linker.  See
`LinkerScript.cpp:addInputSec`.

Fixes: https://github.com/emscripten-core/emscripten/issues/9726

Differential Revision: https://reviews.llvm.org/D101703

Added: 
    lld/test/wasm/Inputs/comdat-data.s
    lld/test/wasm/relocatable-comdat.s

Modified: 
    lld/wasm/Writer.cpp
    llvm/lib/Object/WasmObjectFile.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/Inputs/comdat-data.s b/lld/test/wasm/Inputs/comdat-data.s
new file mode 100644
index 0000000000000..d25258c91c163
--- /dev/null
+++ b/lld/test/wasm/Inputs/comdat-data.s
@@ -0,0 +1,6 @@
+.globl foo
+.section .data.foo,"G",@,foo,comdat
+foo:
+        .int32 42
+        .int32 43
+        .size foo, 8

diff  --git a/lld/test/wasm/relocatable-comdat.s b/lld/test/wasm/relocatable-comdat.s
new file mode 100644
index 0000000000000..e2b45d46ddcbd
--- /dev/null
+++ b/lld/test/wasm/relocatable-comdat.s
@@ -0,0 +1,46 @@
+# RUN: llvm-mc -triple=wasm32 -filetype=obj %p/Inputs/comdat-data.s -o %t1.o
+# RUN: llvm-mc -triple=wasm32 -filetype=obj %s -o %t.o
+# RUN: wasm-ld --relocatable -o %t.wasm %t.o %t1.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+
+        .globl  _start
+        .type  _start, at function
+_start:
+        .functype _start () -> ()
+        i32.load foo
+        end_function
+
+
+.section  .data.foo,"",@
+foo:
+        .int32 42
+        .size foo, 4
+
+# Verify that .data.foo in this file is not merged with comdat .data.foo
+# section in Inputs/comdat-data.s.
+
+#      CHECK:   - 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:         2A000000
+# CHECK-NEXT:       - SectionOffset:   15
+# CHECK-NEXT:         InitFlags:       0
+# CHECK-NEXT:         Offset:
+# CHECK-NEXT:           Opcode:          I32_CONST
+# CHECK-NEXT:           Value:           4
+# CHECK-NEXT:         Content:         2A0000002B000000
+
+#      CHECK:    SegmentInfo:
+# CHECK-NEXT:      - Index:           0
+# CHECK-NEXT:        Name:            .data.foo
+# CHECK-NEXT:        Alignment:       0
+# CHECK-NEXT:        Flags:           [  ]
+# CHECK-NEXT:      - Index:           1
+# CHECK-NEXT:        Name:            .data.foo
+# CHECK-NEXT:        Alignment:       0
+# CHECK-NEXT:        Flags:           [  ]

diff  --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 62df038aaf4a2..af30e13cbadf0 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -77,6 +77,7 @@ class Writer {
   void calculateCustomSections();
   void calculateTypes();
   void createOutputSegments();
+  OutputSegment *createOutputSegment(StringRef name);
   void combineOutputSegments();
   void layoutMemory();
   void createHeader();
@@ -830,26 +831,37 @@ static StringRef getOutputDataSegmentName(StringRef name) {
   return name;
 }
 
+OutputSegment *Writer::createOutputSegment(StringRef name) {
+  LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
+  OutputSegment *s = make<OutputSegment>(name);
+  if (config->sharedMemory)
+    s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
+  // Exported memories are guaranteed to be zero-initialized, so no need
+  // to emit data segments for bss sections.
+  // TODO: consider initializing bss sections with memory.fill
+  // instructions when memory is imported and bulk-memory is available.
+  if (!config->importMemory && !config->relocatable && name.startswith(".bss"))
+    s->isBss = true;
+  segments.push_back(s);
+  return s;
+}
+
 void Writer::createOutputSegments() {
   for (ObjFile *file : symtab->objectFiles) {
     for (InputSegment *segment : file->segments) {
       if (!segment->live)
         continue;
       StringRef name = getOutputDataSegmentName(segment->getName());
-      OutputSegment *&s = segmentMap[name];
-      if (s == nullptr) {
-        LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
-        s = make<OutputSegment>(name);
-        if (config->sharedMemory)
-          s->initFlags = WASM_DATA_SEGMENT_IS_PASSIVE;
-        // Exported memories are guaranteed to be zero-initialized, so no need
-        // to emit data segments for bss sections.
-        // TODO: consider initializing bss sections with memory.fill
-        // instructions when memory is imported and bulk-memory is available.
-        if (!config->importMemory && !config->relocatable &&
-            name.startswith(".bss"))
-          s->isBss = true;
-        segments.push_back(s);
+      OutputSegment *s = nullptr;
+      // When running in relocatable mode we can't merge segments that are part
+      // of comdat groups since the ultimate linker needs to be able exclude or
+      // include them individually.
+      if (config->relocatable && !segment->getComdatName().empty()) {
+        s = createOutputSegment(name);
+      } else {
+        if (segmentMap.count(name) == 0)
+          segmentMap[name] = createOutputSegment(name);
+        s = segmentMap[name];
       }
       s->addInputSegment(segment);
       LLVM_DEBUG(dbgs() << "added data: " << name << ": " << s->size << "\n");

diff  --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index b7bf7705e4930..946721a3bbb86 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -39,8 +39,8 @@ using namespace object;
 
 void WasmSymbol::print(raw_ostream &Out) const {
   Out << "Name=" << Info.Name
-      << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
-      << ", Flags=" << Info.Flags;
+      << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
+      << Twine::utohexstr(Info.Flags);
   if (!isTypeData()) {
     Out << ", ElemIndex=" << Info.ElementIndex;
   } else if (isDefined()) {


        


More information about the llvm-commits mailing list