[WebAssembly] Add support for local symbol bindings
authorSam Clegg <sbc@chromium.org>
Wed, 20 Sep 2017 21:17:04 +0000 (21:17 +0000)
committerSam Clegg <sbc@chromium.org>
Wed, 20 Sep 2017 21:17:04 +0000 (21:17 +0000)
Differential Revision: https://reviews.llvm.org/D38096

llvm-svn: 313817

llvm/include/llvm/BinaryFormat/Wasm.h
llvm/include/llvm/Object/Wasm.h
llvm/lib/MC/WasmObjectWriter.cpp
llvm/lib/Object/WasmObjectFile.cpp
llvm/test/MC/WebAssembly/unnamed-data.ll
llvm/test/tools/llvm-nm/wasm/local-symbols.ll [new file with mode: 0644]
llvm/test/tools/llvm-objdump/WebAssembly/symbol-table.test
llvm/tools/llvm-cfi-verify/CMakeLists.txt
llvm/tools/obj2yaml/wasm2yaml.cpp

index 53a812b..ffb4535 100644 (file)
@@ -188,8 +188,12 @@ enum : unsigned {
   WASM_SEGMENT_NAMES  = 0x5,
 };
 
+const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
+
 enum : unsigned {
-  WASM_SYMBOL_FLAG_WEAK = 0x1,
+  WASM_SYMBOL_BINDING_GLOBAL = 0x0,
+  WASM_SYMBOL_BINDING_WEAK   = 0x1,
+  WASM_SYMBOL_BINDING_LOCAL  = 0x2,
 };
 
 #define WASM_RELOC(name, value) name = value,
index 2084ff0..172b150 100644 (file)
@@ -56,7 +56,19 @@ public:
   uint32_t ElementIndex;
 
   bool isWeak() const {
-    return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
+    return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
+  }
+
+  bool isGlobal() const {
+    return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
+  }
+
+  bool isLocal() const {
+    return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
+  }
+
+  unsigned getBinding() const {
+    return Flags & wasm::WASM_SYMBOL_BINDING_MASK;
   }
 
   void print(raw_ostream &Out) const {
@@ -132,6 +144,7 @@ public:
   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
 
   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+  uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const;
   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
index 6ec9324..f17801a 100644 (file)
@@ -280,11 +280,11 @@ private:
                         uint32_t NumFuncImports);
   void writeCodeRelocSection();
   void writeDataRelocSection();
-  void writeLinkingMetaDataSection(ArrayRef<WasmDataSegment> Segments,
-                                   uint32_t DataSize, uint32_t DataAlignment,
-                                   ArrayRef<StringRef> WeakSymbols,
-                                   bool HasStackPointer,
-                                   uint32_t StackPointerGlobal);
+  void writeLinkingMetaDataSection(
+      ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
+      uint32_t DataAlignment,
+      SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags,
+      bool HasStackPointer, uint32_t StackPointerGlobal);
 
   uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@@ -914,7 +914,8 @@ void WasmObjectWriter::writeDataRelocSection() {
 
 void WasmObjectWriter::writeLinkingMetaDataSection(
     ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
-    uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
+    uint32_t DataAlignment,
+    SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags,
     bool HasStackPointer, uint32_t StackPointerGlobal) {
   SectionBookkeeping Section;
   startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
@@ -926,12 +927,12 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
     endSection(SubSection);
   }
 
-  if (WeakSymbols.size() != 0) {
+  if (SymbolFlags.size() != 0) {
     startSection(SubSection, wasm::WASM_SYMBOL_INFO);
-    encodeULEB128(WeakSymbols.size(), getStream());
-    for (const StringRef Export: WeakSymbols) {
-      writeString(Export);
-      encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
+    encodeULEB128(SymbolFlags.size(), getStream());
+    for (auto Pair: SymbolFlags) {
+      writeString(Pair.first);
+      encodeULEB128(Pair.second, getStream());
     }
     endSection(SubSection);
   }
@@ -993,7 +994,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   SmallVector<uint32_t, 4> TableElems;
   SmallVector<WasmImport, 4> Imports;
   SmallVector<WasmExport, 4> Exports;
-  SmallVector<StringRef, 4> WeakSymbols;
+  SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
   SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
   unsigned NumFuncImports = 0;
   SmallVector<WasmDataSegment, 4> DataSegments;
@@ -1164,7 +1165,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
                  << " isVariable=" << WS.isVariable() << "\n");
 
     if (WS.isWeak())
-      WeakSymbols.push_back(WS.getName());
+      SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_WEAK);
 
     if (WS.isVariable())
       continue;
@@ -1235,7 +1236,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     }
 
     // If the symbol is visible outside this translation unit, export it.
-    if ((WS.isExternal() && WS.isDefined(/*SetUsed=*/false))) {
+    if (WS.isDefined(/*SetUsed=*/false)) {
       WasmExport Export;
       Export.FieldName = WS.getName();
       Export.Index = Index;
@@ -1245,6 +1246,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
         Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
       DEBUG(dbgs() << "  -> export " << Exports.size() << "\n");
       Exports.push_back(Export);
+      if (!WS.isExternal())
+        SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
     }
   }
 
@@ -1254,6 +1257,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   for (const MCSymbol &S : Asm.symbols()) {
     if (!S.isVariable())
       continue;
+
     assert(S.isDefined(/*SetUsed=*/false));
 
     // Find the target symbol of this weak alias and export that index
@@ -1273,6 +1277,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
       Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
     DEBUG(dbgs() << "  -> export " << Exports.size() << "\n");
     Exports.push_back(Export);
+
+    if (!WS.isExternal())
+      SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
   }
 
   // Add types for indirect function calls.
@@ -1301,7 +1308,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   writeCodeRelocSection();
   writeDataRelocSection();
   writeLinkingMetaDataSection(DataSegments, DataSize, DataAlignment,
-                              WeakSymbols, HasStackPointer, StackPointerGlobal);
+                              SymbolFlags, HasStackPointer, StackPointerGlobal);
 
   // TODO: Translate the .comment section to the output.
   // TODO: Translate debug sections to the output.
index d2d3aba..3b62ccf 100644 (file)
@@ -767,15 +767,17 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
   const WasmSymbol &Sym = getWasmSymbol(Symb);
 
   DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
-  if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
+  if (Sym.isWeak())
     Result |= SymbolRef::SF_Weak;
+  else if (Sym.isGlobal())
+    Result |= SymbolRef::SF_Global;
 
   switch (Sym.Type) {
   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
     break;
   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
-    Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
+    Result |= SymbolRef::SF_Executable;
     break;
   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
     Result |= SymbolRef::SF_Executable;
@@ -785,7 +787,6 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
     Result |= SymbolRef::SF_Undefined;
     break;
   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
-    Result |= SymbolRef::SF_Global;
     break;
   }
 
@@ -820,8 +821,7 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
   return getSymbolValue(Symb);
 }
 
-uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
-  const WasmSymbol& Sym = getWasmSymbol(Symb);
+uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
   switch (Sym.Type) {
   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
@@ -842,6 +842,10 @@ uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
   llvm_unreachable("invalid symbol type");
 }
 
+uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
+  return getWasmSymbolValue(getWasmSymbol(Symb));
+}
+
 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
   llvm_unreachable("not yet implemented");
   return 0;
index a484913..32526c2 100644 (file)
 ; CHECK-NEXT:           Value:           16
 ; CHECK-NEXT:       - Type:            I32
 ; CHECK-NEXT:         Mutable:         false
-; CHECK-NEXT:         InitExpr:        
+; CHECK-NEXT:         InitExpr:
 ; CHECK-NEXT:           Opcode:          I32_CONST
 ; CHECK-NEXT:           Value:           24
 ; CHECK-NEXT:   - Type:            EXPORT
-; CHECK-NEXT:     Exports:         
+; CHECK-NEXT:     Exports:
+; CHECK-NEXT:       - Name:            .L.str1
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:       - Name:            .L.str2
+; CHECK-NEXT:         Kind:            GLOBAL
+; CHECK-NEXT:         Index:           1
 ; CHECK-NEXT:       - Name:            a
 ; CHECK-NEXT:         Kind:            GLOBAL
 ; CHECK-NEXT:         Index:           2
 ; CHECK-NEXT:     Name:            linking
 ; CHECK-NEXT:     DataSize:        28
 ; CHECK-NEXT:     DataAlignment:   8
+; CHECK-NEXT:     SymbolInfo:      
+; CHECK-NEXT:       - Name:            .L.str1
+; CHECK-NEXT:         Flags:           2
+; CHECK-NEXT:       - Name:            .L.str2
+; CHECK-NEXT:         Flags:           2
 ; CHECK-NEXT:     SegmentNames:    
 ; CHECK-NEXT:       - Index:       0
 ; CHECK-NEXT:         Name:        .rodata..L.str1
@@ -83,4 +94,4 @@
 ; CHECK-NEXT:         Name:        .data.a
 ; CHECK-NEXT:       - Index:       3
 ; CHECK-NEXT:         Name:        .data.b
-; CHECK-NEXT: ...
+; CHECK_NEXT:   ...
diff --git a/llvm/test/tools/llvm-nm/wasm/local-symbols.ll b/llvm/test/tools/llvm-nm/wasm/local-symbols.ll
new file mode 100644 (file)
index 0000000..6360b76
--- /dev/null
@@ -0,0 +1,8 @@
+; RUN: llc -filetype=obj -mtriple=wasm32-unknown-unknown-wasm -o %t.o %s
+; RUN: llvm-nm %t.o | FileCheck %s
+
+@foo = internal global i32 1, align 4
+@bar = global i32 1, align 4
+
+; CHECK: 00000004 D bar
+; CHECK: 00000000 d foo
index bb67259..4e46d0d 100644 (file)
@@ -1,11 +1,11 @@
 RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s
 
 CHECK:      SYMBOL TABLE:
-CHECK-NEXT: 00000000 l     F name      puts
-CHECK-NEXT: 00000001 l     F name      SomeOtherFunction
-CHECK-NEXT: 00000002 l     F name      main
-CHECK-NEXT: 00000000 l     F IMPORT    puts
-CHECK-NEXT: 00000000 l     F IMPORT    SomeOtherFunction
+CHECK-NEXT: 00000000 g     F name      puts
+CHECK-NEXT: 00000001 g     F name      SomeOtherFunction
+CHECK-NEXT: 00000002 g     F name      main
+CHECK-NEXT: 00000000 g     F IMPORT    puts
+CHECK-NEXT: 00000000 g     F IMPORT    SomeOtherFunction
 CHECK-NEXT: 00000002 g     F EXPORT    main
 CHECK-NEXT: 00000010 g       EXPORT    var
 
index b34390a..d6dce72 100644 (file)
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
   AllTargetsDisassemblers
   AllTargetsInfos
   MC
+  Object
   MCParser
   Object
   Support
index 8b2a0ad..d37599b 100644 (file)
@@ -54,16 +54,11 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
   if (WasmSec.Name == "name") {
     std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
     for (const object::SymbolRef& Sym: Obj.symbols()) {
-      uint32_t Flags = Sym.getFlags();
-      // Skip over symbols that come from imports or exports
-      if (Flags &
-          (object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
-        continue;
-      Expected<StringRef> NameOrError = Sym.getName();
-      if (!NameOrError)
+      const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
+      if (Symbol.Type != object::WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME)
         continue;
       WasmYAML::NameEntry NameEntry;
-      NameEntry.Name = *NameOrError;
+      NameEntry.Name = Symbol.Name;
       NameEntry.Index = Sym.getValue();
       NameSec->FunctionNames.push_back(NameEntry);
     }