[llvm] r313395 - [WebAssembly] MC: Create wasm data segments based on MCSections

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 15 13:54:59 PDT 2017


Author: sbc
Date: Fri Sep 15 13:54:59 2017
New Revision: 313395

URL: http://llvm.org/viewvc/llvm-project?rev=313395&view=rev
Log:
[WebAssembly] MC: Create wasm data segments based on MCSections

This means that we can honor -fdata-sections rather than
always creating a segment for each symbol.

It also allows for a followup change to add .init_array and friends.

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

Added:
    llvm/trunk/test/MC/WebAssembly/explicit-sections.ll
Modified:
    llvm/trunk/include/llvm/MC/MCSectionWasm.h
    llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
    llvm/trunk/lib/MC/MCObjectFileInfo.cpp
    llvm/trunk/lib/MC/MCWasmStreamer.cpp
    llvm/trunk/lib/MC/WasmObjectWriter.cpp

Modified: llvm/trunk/include/llvm/MC/MCSectionWasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCSectionWasm.h?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCSectionWasm.h (original)
+++ llvm/trunk/include/llvm/MC/MCSectionWasm.h Fri Sep 15 13:54:59 2017
@@ -43,11 +43,17 @@ private:
   // itself and does not include the size of the section header.
   uint64_t SectionOffset;
 
+  // For data sections, this is the offset of the corresponding wasm data
+  // segment
+  uint64_t MemoryOffset;
+
   friend class MCContext;
   MCSectionWasm(StringRef Section, unsigned type, SectionKind K,
                 const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin)
       : MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type),
-        UniqueID(UniqueID), Group(group), SectionOffset(0) {}
+        UniqueID(UniqueID), Group(group), SectionOffset(0) {
+    assert(type == wasm::WASM_SEC_CODE || type == wasm::WASM_SEC_DATA);
+  }
 
   void setSectionName(StringRef Name) { SectionName = Name; }
 
@@ -74,6 +80,9 @@ public:
   uint64_t getSectionOffset() const { return SectionOffset; }
   void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; }
 
+  uint32_t getMemoryOffset() const { return MemoryOffset; }
+  void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; }
+
   static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; }
 };
 

Modified: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (original)
+++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp Fri Sep 15 13:54:59 2017
@@ -1248,8 +1248,8 @@ static const Comdat *getWasmComdat(const
 
 MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
     const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
-  llvm_unreachable("getExplicitSectionGlobal not yet implemented");
-  return nullptr;
+  StringRef Name = GO->getSection();
+  return getContext().getWasmSection(Name, wasm::WASM_SEC_DATA);
 }
 
 static MCSectionWasm *selectWasmSectionForGlobal(
@@ -1262,10 +1262,12 @@ static MCSectionWasm *selectWasmSectionF
   bool UniqueSectionNames = TM.getUniqueSectionNames();
   SmallString<128> Name = getSectionPrefixForGlobal(Kind);
 
+  uint32_t Type = wasm::WASM_SEC_DATA;
   if (const auto *F = dyn_cast<Function>(GO)) {
     const auto &OptionalPrefix = F->getSectionPrefix();
     if (OptionalPrefix)
       Name += *OptionalPrefix;
+    Type = wasm::WASM_SEC_CODE;
   }
 
   if (EmitUniqueSection && UniqueSectionNames) {
@@ -1277,7 +1279,7 @@ static MCSectionWasm *selectWasmSectionF
     UniqueID = *NextUniqueID;
     (*NextUniqueID)++;
   }
-  return Ctx.getWasmSection(Name, /*Type=*/0, Group, UniqueID);
+  return Ctx.getWasmSection(Name, Type, Group, UniqueID);
 }
 
 MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal(

Modified: llvm/trunk/lib/MC/MCObjectFileInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCObjectFileInfo.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCObjectFileInfo.cpp (original)
+++ llvm/trunk/lib/MC/MCObjectFileInfo.cpp Fri Sep 15 13:54:59 2017
@@ -820,24 +820,24 @@ void MCObjectFileInfo::initCOFFMCObjectF
 
 void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
   // TODO: Set the section types and flags.
-  TextSection = Ctx->getWasmSection(".text", 0);
-  DataSection = Ctx->getWasmSection(".data", 0);
+  TextSection = Ctx->getWasmSection(".text", wasm::WASM_SEC_CODE);
+  DataSection = Ctx->getWasmSection(".data", wasm::WASM_SEC_DATA);
 
   // TODO: Set the section types and flags.
-  DwarfLineSection = Ctx->getWasmSection(".debug_line", 0);
-  DwarfStrSection = Ctx->getWasmSection(".debug_str", 0);
-  DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0);
-  DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, "section_abbrev");
-  DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0);
-  DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, "debug_range");
-  DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, "debug_macinfo");
-  DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0);
-  DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0);
-  DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0);
-  DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, "section_info");
-  DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0);
-  DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0);
-  DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0);
+  DwarfLineSection = Ctx->getWasmSection(".debug_line", wasm::WASM_SEC_DATA);
+  DwarfStrSection = Ctx->getWasmSection(".debug_str", wasm::WASM_SEC_DATA);
+  DwarfLocSection = Ctx->getWasmSection(".debug_loc", wasm::WASM_SEC_DATA);
+  DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", wasm::WASM_SEC_DATA, "section_abbrev");
+  DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", wasm::WASM_SEC_DATA);
+  DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", wasm::WASM_SEC_DATA, "debug_range");
+  DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", wasm::WASM_SEC_DATA, "debug_macinfo");
+  DwarfAddrSection = Ctx->getWasmSection(".debug_addr", wasm::WASM_SEC_DATA);
+  DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", wasm::WASM_SEC_DATA);
+  DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", wasm::WASM_SEC_DATA);
+  DwarfInfoSection = Ctx->getWasmSection(".debug_info", wasm::WASM_SEC_DATA, "section_info");
+  DwarfFrameSection = Ctx->getWasmSection(".debug_frame", wasm::WASM_SEC_DATA);
+  DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", wasm::WASM_SEC_DATA);
+  DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", wasm::WASM_SEC_DATA);
 
   // TODO: Define more sections.
 }

Modified: llvm/trunk/lib/MC/MCWasmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCWasmStreamer.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCWasmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCWasmStreamer.cpp Fri Sep 15 13:54:59 2017
@@ -156,7 +156,7 @@ void MCWasmStreamer::EmitValueToAlignmen
 
 void MCWasmStreamer::EmitIdent(StringRef IdentString) {
   MCSection *Comment = getAssembler().getContext().getWasmSection(
-      ".comment", 0, 0);
+      ".comment", wasm::WASM_SEC_DATA);
   PushSection();
   SwitchSection(Comment);
   if (!SeenIdent) {

Modified: llvm/trunk/lib/MC/WasmObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WasmObjectWriter.cpp?rev=313395&r1=313394&r2=313395&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WasmObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WasmObjectWriter.cpp Fri Sep 15 13:54:59 2017
@@ -163,7 +163,8 @@ struct WasmRelocationEntry {
 
   void print(raw_ostream &Out) const {
     Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
-        << ", Type=" << Type << ", FixupSection=" << FixupSection;
+        << ", Type=" << Type
+        << ", FixupSection=" << FixupSection->getSectionName();
   }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -495,6 +496,39 @@ WasmObjectWriter::getProvisionalValue(co
   return Value;
 }
 
+static void addData(SmallVectorImpl<char> &DataBytes,
+                    MCSectionWasm &DataSection, uint32_t &DataAlignment) {
+  DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
+  DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
+  DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
+
+  for (const MCFragment &Frag : DataSection) {
+    if (Frag.hasInstructions())
+      report_fatal_error("only data supported in data sections");
+
+    if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
+      if (Align->getValueSize() != 1)
+        report_fatal_error("only byte values supported for alignment");
+      // If nops are requested, use zeros, as this is the data section.
+      uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
+      uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
+                                                 Align->getAlignment()),
+                                         DataBytes.size() +
+                                             Align->getMaxBytesToEmit());
+      DataBytes.resize(Size, Value);
+    } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
+      DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
+    } else {
+      const auto &DataFrag = cast<MCDataFragment>(Frag);
+      const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+
+      DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
+    }
+  }
+
+  DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
+}
+
 uint32_t WasmObjectWriter::getRelocationIndexValue(
     const WasmRelocationEntry &RelEntry) {
   switch (RelEntry.Type) {
@@ -773,9 +807,7 @@ void WasmObjectWriter::writeCodeSection(
       report_fatal_error(".size expression must be evaluatable");
 
     encodeULEB128(Size, getStream());
-
     FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
-
     Asm.writeSectionData(&FuncSection, Layout);
   }
 
@@ -1016,7 +1048,7 @@ void WasmObjectWriter::writeObject(MCAss
   // In the special .global_variables section, we've encoded global
   // variables used by the function. Translate them into the Globals
   // list.
-  MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
+  MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", wasm::WASM_SEC_DATA);
   if (!GlobalVars->getFragmentList().empty()) {
     if (GlobalVars->getFragmentList().size() != 1)
       report_fatal_error("only one .global_variables fragment supported");
@@ -1072,7 +1104,7 @@ void WasmObjectWriter::writeObject(MCAss
 
   // In the special .stack_pointer section, we've encoded the stack pointer
   // index.
-  MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
+  MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", wasm::WASM_SEC_DATA);
   if (!StackPtr->getFragmentList().empty()) {
     if (StackPtr->getFragmentList().size() != 1)
       report_fatal_error("only one .stack_pointer fragment supported");
@@ -1089,6 +1121,21 @@ void WasmObjectWriter::writeObject(MCAss
     StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
   }
 
+  for (MCSection &Sec : Asm) {
+    auto &Section = static_cast<MCSectionWasm &>(Sec);
+    if (Section.getType() != wasm::WASM_SEC_DATA)
+      continue;
+
+    DataSize = alignTo(DataSize, Section.getAlignment());
+    DataSegments.emplace_back();
+    WasmDataSegment &Segment = DataSegments.back();
+    Segment.Offset = DataSize;
+    Segment.Section = &Section;
+    addData(Segment.Data, Section, DataAlignment);
+    DataSize += Segment.Data.size();
+    Section.setMemoryOffset(Segment.Offset);
+  }
+
   // Handle regular defined and undefined symbols.
   for (const MCSymbol &S : Asm.symbols()) {
     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
@@ -1151,9 +1198,6 @@ void WasmObjectWriter::writeObject(MCAss
       if (!WS.isDefined(/*SetUsed=*/false))
         continue;
 
-      if (WS.getOffset() != 0)
-        report_fatal_error("data sections must contain one variable each: " +
-                           WS.getName());
       if (!WS.getSize())
         report_fatal_error("data symbols must have a size set with .size: " +
                            WS.getName());
@@ -1162,58 +1206,20 @@ void WasmObjectWriter::writeObject(MCAss
       if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
         report_fatal_error(".size expression must be evaluatable");
 
-      auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
-
-      if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
-        report_fatal_error("data sections must contain at most one variable");
-
-      DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
-
-      DataSegments.emplace_back();
-      WasmDataSegment &Segment = DataSegments.back();
-
-      DataSize = alignTo(DataSize, DataSection.getAlignment());
-      Segment.Offset = DataSize;
-      Segment.Section = &DataSection;
-
       // For each global, prepare a corresponding wasm global holding its
       // address.  For externals these will also be named exports.
       Index = NumGlobalImports + Globals.size();
+      auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
 
       WasmGlobal Global;
       Global.Type = PtrType;
       Global.IsMutable = false;
       Global.HasImport = false;
-      Global.InitialValue = DataSize;
+      Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
       Global.ImportIndex = 0;
       SymbolIndices[&WS] = Index;
       DEBUG(dbgs() << "  -> global index: " << Index << "\n");
       Globals.push_back(Global);
-
-      for (const MCFragment &Frag : DataSection) {
-        if (Frag.hasInstructions())
-          report_fatal_error("only data supported in data sections");
-
-        if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
-          if (Align->getValueSize() != 1)
-            report_fatal_error("only byte values supported for alignment");
-          // If nops are requested, use zeros, as this is the data section.
-          uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
-          uint64_t Size = std::min<uint64_t>(
-              alignTo(Segment.Data.size(), Align->getAlignment()),
-              Segment.Data.size() + Align->getMaxBytesToEmit());
-          Segment.Data.resize(Size, Value);
-        } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
-          Segment.Data.insert(Segment.Data.end(), Fill->getSize(), Fill->getValue());
-        } else {
-          const auto &DataFrag = cast<MCDataFragment>(Frag);
-          const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-
-          Segment.Data.insert(Segment.Data.end(), Contents.begin(),
-                              Contents.end());
-        }
-      }
-      DataSize += Segment.Data.size();
     }
 
     // If the symbol is visible outside this translation unit, export it.

Added: llvm/trunk/test/MC/WebAssembly/explicit-sections.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/explicit-sections.ll?rev=313395&view=auto
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/explicit-sections.ll (added)
+++ llvm/trunk/test/MC/WebAssembly/explicit-sections.ll Fri Sep 15 13:54:59 2017
@@ -0,0 +1,65 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
+
+%struct.bd = type { i32, i8 }
+
+ at global0 = global i32 8, align 8
+ at global1 = global %struct.bd  { i32 1, i8 3 }, align 8, section ".sec1"
+ at global2 = global i64 7, align 8, section ".sec1"
+ at global3 = global i32 8, align 8, section ".sec2"
+
+; CHECK:        - Type:            GLOBAL
+; CHECK-NEXT:     Globals:         
+; CHECK-NEXT:       - Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           0
+; CHECK-NEXT:       - Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           8
+; CHECK-NEXT:       - Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           16
+; CHECK-NEXT:       - Type:            I32
+; CHECK-NEXT:         Mutable:         false
+; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           24
+; CHECK-NEXT:   - Type:            EXPORT
+; CHECK-NEXT:     Exports:         
+; CHECK-NEXT:       - Name:            global0
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            global1
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           1
+; CHECK-NEXT:       - Name:            global2
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           2
+; CHECK-NEXT:       - Name:            global3
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           3
+; CHECK-NEXT:   - Type:            DATA
+; CHECK-NEXT:     Segments:        
+; CHECK-NEXT:       - SectionOffset:   6
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           0
+; CHECK-NEXT:         Content:         '08000000'
+; CHECK-NEXT:       - SectionOffset:   15
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           8
+; CHECK-NEXT:         Content:         '01000000030000000700000000000000'
+; CHECK-NEXT:       - SectionOffset:   36
+; CHECK-NEXT:         MemoryIndex:     0
+; CHECK-NEXT:         Offset:          
+; CHECK-NEXT:           Opcode:          I32_CONST
+; CHECK-NEXT:           Value:           24
+; CHECK-NEXT:         Content:         '08000000'




More information about the llvm-commits mailing list