[WebAssembly] Elide data segments for .bss sections

Summary:
WebAssembly memories are zero-initialized, so when module does not
import its memory initializing .bss sections is guaranteed to be a
no-op. To reduce binary size and initialization time, .bss sections
are simply not emitted into the final binary unless the memory is
imported.

Reviewers: sbc100

Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits

Tags: #llvm

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

llvm-svn: 374940
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index 469a51a..0403f1d 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -128,8 +128,11 @@
 
 void DataSection::finalizeContents() {
   raw_string_ostream os(dataSectionHeader);
+  unsigned segmentCount =
+      std::count_if(segments.begin(), segments.end(),
+                    [](OutputSegment *segment) { return !segment->isBss; });
 
-  writeUleb128(os, segments.size(), "data segment count");
+  writeUleb128(os, segmentCount, "data segment count");
   os.flush();
   bodySize = dataSectionHeader.size();
 
@@ -137,6 +140,8 @@
          "Currenly only a single data segment is supported in PIC mode");
 
   for (OutputSegment *segment : segments) {
+    if (segment->isBss)
+      continue;
     raw_string_ostream os(segment->header);
     writeUleb128(os, segment->initFlags, "init flags");
     if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
@@ -181,6 +186,8 @@
   memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
 
   for (const OutputSegment *segment : segments) {
+    if (segment->isBss)
+      continue;
     // Write data segment header
     uint8_t *segStart = buf + segment->sectionOffset;
     memcpy(segStart, segment->header.data(), segment->header.size());
@@ -205,6 +212,13 @@
       c->writeRelocations(os);
 }
 
+bool DataSection::isNeeded() const {
+  for (const OutputSegment *seg : segments)
+    if (!seg->isBss)
+      return true;
+  return false;
+}
+
 void CustomSection::finalizeContents() {
   raw_string_ostream os(nameData);
   encodeULEB128(name.size(), os);