[WebAssembly] Update to match llvm changes to TABLE relocations
authorSam Clegg <sbc@chromium.org>
Tue, 23 Jan 2018 01:25:56 +0000 (01:25 +0000)
committerSam Clegg <sbc@chromium.org>
Tue, 23 Jan 2018 01:25:56 +0000 (01:25 +0000)
TABLE relocations now store the function that is being refered
to indirectly.

See rL323165.

Also extend the call-indirect.ll a little.

Based on a patch by Nicholas Wilson!

llvm-svn: 323168

lld/test/wasm/Inputs/call-indirect.ll
lld/test/wasm/call-indirect.ll
lld/test/wasm/locals-duplicate.test
lld/test/wasm/relocatable.ll
lld/wasm/InputChunks.cpp
lld/wasm/InputChunks.h
lld/wasm/InputFiles.cpp
lld/wasm/InputFiles.h
lld/wasm/Writer.cpp

index 388ea60..11c5a06 100644 (file)
@@ -1,17 +1,18 @@
-@indirect_bar = internal local_unnamed_addr global i32 ()* @bar, align 4
+@indirect_bar = internal local_unnamed_addr global i64 ()* @bar, align 4
 @indirect_foo = internal local_unnamed_addr global i32 ()* @foo, align 4
 
 declare i32 @foo() local_unnamed_addr
 
-define i32 @bar() {
+define i64 @bar() {
 entry:
-  ret i32 1
+  ret i64 1
 }
 
 define void @call_bar_indirect() local_unnamed_addr #1 {
 entry:
-  %0 = load i32 ()*, i32 ()** @indirect_bar, align 4
+  %0 = load i64 ()*, i64 ()** @indirect_bar, align 4
   %1 = load i32 ()*, i32 ()** @indirect_foo, align 4
-  %call = tail call i32 %0() #2
+  %call0 = tail call i64 %0() #2
+  %call1 = tail call i32 %1() #2
   ret void
 }
index 82da34e..11055d7 100644 (file)
@@ -38,21 +38,24 @@ define void @call_ptr(i64 (i64)* %arg) {
 ; CHECK-NEXT:   - Type:            TYPE
 ; CHECK-NEXT:     Signatures:
 ; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ReturnType:      I64
 ; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:       - Index:           1
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:
 ; CHECK-NEXT:       - Index:           2
+; CHECK-NEXT:         ReturnType:      I32
+; CHECK-NEXT:         ParamTypes:
+; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         ReturnType:      NORESULT
 ; CHECK-NEXT:         ParamTypes:      
 ; CHECK-NEXT:           - I32
-; CHECK-NEXT:       - Index:           3
+; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         ReturnType:      I64
 ; CHECK-NEXT:         ParamTypes:      
 ; CHECK-NEXT:           - I64
 ; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 0, 0, 2, 1 ]
+; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 2, 2, 3, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
 ; CHECK-NEXT:       - ElemType:        ANYFUNC
@@ -110,19 +113,21 @@ define void @call_ptr(i64 (i64)* %arg) {
 ; CHECK-NEXT:     Functions:
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            41010B
+; CHECK-NEXT:         Body:            42010B
 ; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            410028028088808000118080808000001A0B
+; CHECK-NEXT:         Locals:          
+; CHECK-NEXT:            - Type:            I32
+; CHECK-NEXT:              Count:           1
+; CHECK-NEXT:          Body:            4100280284888080002100410028028088808000118080808000001A2000118280808000001A0B
 ; CHECK-NEXT:       - Index:           2
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            41020B
 ; CHECK-NEXT:       - Index:           3
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            410028028888808000118080808000001A41000B
+; CHECK-NEXT:         Body:            410028028888808000118280808000001A41000B
 ; CHECK-NEXT:       - Index:           4
 ; CHECK-NEXT:         Locals:
-; CHECK-NEXT:         Body:            42012000118380808000001A0B
+; CHECK-NEXT:         Body:            42012000118480808000001A0B
 ; CHECK-NEXT:       - Index:           5
 ; CHECK-NEXT:         Locals:
 ; CHECK-NEXT:         Body:            0B
index bb62b9f..aeac1f8 100644 (file)
 ; RELOC-NEXT:         Index:           5
 ; RELOC-NEXT:         Offset:          0x0000006A
 ; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
-; RELOC-NEXT:         Index:           3
+; RELOC-NEXT:         Index:           9
 ; RELOC-NEXT:         Offset:          0x00000073
 ; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
-; RELOC-NEXT:         Index:           4
+; RELOC-NEXT:         Index:           10
 ; RELOC-NEXT:         Offset:          0x0000007C
 ; RELOC-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
-; RELOC-NEXT:         Index:           5
+; RELOC-NEXT:         Index:           11
 ; RELOC-NEXT:         Offset:          0x00000085
 ; RELOC-NEXT:     Functions:       
 ; RELOC-NEXT:       - Index:           0
index 8efb240..95de209 100644 (file)
@@ -177,7 +177,7 @@ entry:
 ; CHECK-NEXT:   - Type:            DATA
 ; CHECK-NEXT:     Relocations:
 ; CHECK-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_I32
-; CHECK-NEXT:         Index:           0
+; CHECK-NEXT:         Index:           4
 ; CHECK-NEXT:         Offset:          0x00000012
 ; CHECK-NEXT:       - Type:            R_WEBASSEMBLY_TABLE_INDEX_I32
 ; CHECK-NEXT:         Index:           1
index 3a63d35..1aabe3b 100644 (file)
@@ -48,23 +48,19 @@ static void applyRelocation(uint8_t *Buf, const OutputRelocation &Reloc) {
   switch (Reloc.Reloc.Type) {
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     ExistingValue = decodeULEB128(Buf);
+    // Additional check to verify that the existing value that the location
+    // matches our expectations.
     if (ExistingValue != Reloc.Reloc.Index) {
       DEBUG(dbgs() << "existing value: " << decodeULEB128(Buf) << "\n");
       assert(decodeULEB128(Buf) == Reloc.Reloc.Index);
     }
     LLVM_FALLTHROUGH;
   case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
-  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
     encodeULEB128(Reloc.Value, Buf, 5);
     break;
   case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
-    ExistingValue = decodeSLEB128(Buf);
-    if (ExistingValue != Reloc.Reloc.Index) {
-      DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n");
-      assert(decodeSLEB128(Buf) == Reloc.Reloc.Index);
-    }
-    LLVM_FALLTHROUGH;
   case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
     encodeSLEB128(static_cast<int32_t>(Reloc.Value), Buf, 5);
     break;
@@ -111,17 +107,7 @@ void InputChunk::calcRelocations() {
     if (Config->Relocatable)
       NewReloc.NewIndex = File->calcNewIndex(Reloc);
 
-    switch (Reloc.Type) {
-    case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
-    case R_WEBASSEMBLY_MEMORY_ADDR_I32:
-    case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
-      NewReloc.Value = File->getRelocatedAddress(Reloc.Index) + Reloc.Addend;
-      break;
-    default:
-      NewReloc.Value = File->calcNewIndex(Reloc);
-      break;
-    }
-
+    NewReloc.Value = File->calcNewValue(Reloc);
     OutRelocations.emplace_back(NewReloc);
   }
 }
index d8d0358..3823168 100644 (file)
@@ -46,6 +46,7 @@ public:
   }
 
   uint32_t getOutputOffset() const { return OutputOffset; }
+  ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }
 
   virtual StringRef getComdat() const = 0;
 
index e7f20b8..5e15975 100644 (file)
@@ -47,11 +47,10 @@ void ObjFile::dumpInfo() const {
       "      Total Functions : " + Twine(FunctionSymbols.size()) + "\n" +
       "        Total Globals : " + Twine(GlobalSymbols.size()) + "\n" +
       "     Function Imports : " + Twine(NumFunctionImports) + "\n" +
-      "       Global Imports : " + Twine(NumGlobalImports) + "\n" +
-      "        Table Entries : " + Twine(TableSymbols.size()) + "\n");
+      "       Global Imports : " + Twine(NumGlobalImports) + "\n");
 }
 
-uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const {
+uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const {
   return GlobalSymbols[GlobalIndex]->getVirtualAddress();
 }
 
@@ -68,7 +67,7 @@ uint32_t ObjFile::relocateTypeIndex(uint32_t Original) const {
 }
 
 uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
-  Symbol *Sym = TableSymbols[Original];
+  Symbol *Sym = FunctionSymbols[Original];
   uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
   DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
                << " -> " << Index << "\n");
@@ -92,10 +91,9 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
   case R_WEBASSEMBLY_TYPE_INDEX_LEB:
     return relocateTypeIndex(Reloc.Index);
   case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
-    return relocateFunctionIndex(Reloc.Index);
   case R_WEBASSEMBLY_TABLE_INDEX_I32:
   case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
-    return relocateTableIndex(Reloc.Index);
+    return relocateFunctionIndex(Reloc.Index);
   case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
   case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
@@ -106,6 +104,27 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
   }
 }
 
+// Translate from the relocation's index into the final linked output value.
+uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
+  switch (Reloc.Type) {
+  case R_WEBASSEMBLY_TABLE_INDEX_I32:
+  case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+    return relocateTableIndex(Reloc.Index);
+  case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+  case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+  case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+    return relocateVirtualAddress(Reloc.Index) + Reloc.Addend;
+  case R_WEBASSEMBLY_TYPE_INDEX_LEB:
+    return relocateTypeIndex(Reloc.Index);
+  case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+    return relocateFunctionIndex(Reloc.Index);
+  case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
+    return relocateGlobalIndex(Reloc.Index);
+  default:
+    llvm_unreachable("unknown relocation type");
+  }
+}
+
 void ObjFile::parse() {
   // Parse a memory buffer as a wasm file.
   DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
@@ -271,24 +290,6 @@ void ObjFile::initializeSymbols() {
         for (size_t I = 0; I < GlobalSymbols.size(); ++I)
             assert(GlobalSymbols[I] != nullptr););
 
-  // Populate `TableSymbols` with all symbols that are called indirectly
-  uint32_t SegmentCount = WasmObj->elements().size();
-  if (SegmentCount) {
-    if (SegmentCount > 1)
-      fatal(getName() + ": contains more than one element segment");
-    const WasmElemSegment &Segment = WasmObj->elements()[0];
-    if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST)
-      fatal(getName() + ": unsupported element segment");
-    if (Segment.TableIndex != 0)
-      fatal(getName() + ": unsupported table index in elem segment");
-    uint32_t Offset = Segment.Offset.Value.Int32;
-    TableSymbols.resize(Offset);
-    TableSymbols.reserve(Offset + Segment.Functions.size());
-    for (uint64_t FunctionIndex : Segment.Functions)
-      TableSymbols.push_back(FunctionSymbols[FunctionIndex]);
-  }
-
-  DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
   DEBUG(dbgs() << "Functions   : " << FunctionSymbols.size() << "\n");
   DEBUG(dbgs() << "Globals     : " << GlobalSymbols.size() << "\n");
 }
index fdfaf09..538197c 100644 (file)
@@ -94,8 +94,8 @@ public:
   void dumpInfo() const;
 
   uint32_t relocateFunctionIndex(uint32_t Original) const;
-  uint32_t getRelocatedAddress(uint32_t Index) const;
   uint32_t calcNewIndex(const WasmRelocation &Reloc) const;
+  uint32_t calcNewValue(const WasmRelocation &Reloc) const;
 
   const WasmSection *CodeSection = nullptr;
   const WasmSection *DataSection = nullptr;
@@ -104,10 +104,14 @@ public:
   std::vector<InputSegment *> Segments;
   std::vector<InputFunction *> Functions;
 
-  ArrayRef<Symbol *> getSymbols() { return Symbols; }
-  ArrayRef<Symbol *> getTableSymbols() { return TableSymbols; }
+  ArrayRef<Symbol *> getSymbols() const { return Symbols; }
+
+  Symbol *getFunctionSymbol(uint32_t Index) const {
+    return FunctionSymbols[Index];
+  }
 
 private:
+  uint32_t relocateVirtualAddress(uint32_t Index) const;
   uint32_t relocateTypeIndex(uint32_t Original) const;
   uint32_t relocateGlobalIndex(uint32_t Original) const;
   uint32_t relocateTableIndex(uint32_t Original) const;
@@ -134,9 +138,6 @@ private:
   // List of all global symbols indexed by the global index space
   std::vector<Symbol *> GlobalSymbols;
 
-  // List of all indirect symbols indexed by table index space.
-  std::vector<Symbol *> TableSymbols;
-
   uint32_t NumGlobalImports = 0;
   uint32_t NumFunctionImports = 0;
   std::unique_ptr<WasmObjectFile> WasmObj;
index b9570da..2fd2964 100644 (file)
@@ -744,12 +744,26 @@ void Writer::assignIndexes() {
 
   for (ObjFile *File : Symtab->ObjectFiles) {
     DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n");
-    for (Symbol *Sym : File->getTableSymbols()) {
-      if (!Sym || Sym->hasTableIndex() || !Sym->hasOutputIndex())
-        continue;
-      Sym->setTableIndex(TableIndex++);
-      IndirectFunctions.emplace_back(Sym);
-    }
+    auto HandleTableRelocs = [&](InputChunk *Chunk) {
+      if (Chunk->Discarded)
+        return;
+      for (const WasmRelocation& Reloc : Chunk->getRelocations()) {
+        if (Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_I32 &&
+            Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_SLEB)
+          continue;
+        DEBUG(dbgs() << "getFunctionSymbol: " << Reloc.Index << "\n");
+        Symbol *Sym = File->getFunctionSymbol(Reloc.Index);
+        DEBUG(dbgs() << "gotFunctionSymbol: " << Sym->getName() << "\n");
+        if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
+          continue;
+        Sym->setTableIndex(TableIndex++);
+        IndirectFunctions.emplace_back(Sym);
+      }
+    };
+    for (InputFunction* Function : File->Functions)
+      HandleTableRelocs(Function);
+    for (InputSegment* Segment : File->Segments)
+      HandleTableRelocs(Segment);
   }
 }