From 67abf5396124384be2ad484abd8660bb10dcd94d Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 24 Jan 2018 21:45:25 +0000 Subject: [PATCH] [WebAssembly] Don't duplicate functions in table output Previously, we were ensuring that the "output index" for InputFunctions was unique across all symbols that referenced a function body, but allowing the same function body to have multiple table indexes. Now, we use the same mechanism for table indexes as we already do for output indexes, ensuring that each InputFunction is only placed in the table once. This makes the LLD output table denser and smaller, but should not change the behaviour. Note that we still need the `Symbol::TableIndex` member, to store the table index for function Symbols that don't have an InputFunction, i.e. for address-taken imports. Patch by Nicholas Wilson! Differential Revision: https://reviews.llvm.org/D42476 llvm-svn: 323379 --- lld/test/wasm/weak-alias.ll | 16 ++++++++-------- lld/wasm/InputChunks.cpp | 6 ++++++ lld/wasm/InputChunks.h | 4 ++++ lld/wasm/Symbols.cpp | 19 +++++++++++++++++++ lld/wasm/Symbols.h | 4 ++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll index b9ee6a4b7aae..9e0a1fbf212b 100644 --- a/lld/test/wasm/weak-alias.ll +++ b/lld/test/wasm/weak-alias.ll @@ -35,8 +35,8 @@ entry: ; CHECK-NEXT: - ElemType: ANYFUNC ; CHECK-NEXT: Limits: ; CHECK-NEXT: Flags: [ HAS_MAX ] -; CHECK-NEXT: Initial: 0x00000003 -; CHECK-NEXT: Maximum: 0x00000003 +; CHECK-NEXT: Initial: 0x00000002 +; CHECK-NEXT: Maximum: 0x00000002 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x00000002 @@ -88,7 +88,7 @@ entry: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 -; CHECK-NEXT: Functions: [ 1, 1 ] +; CHECK-NEXT: Functions: [ 1 ] ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Functions: ; CHECK-NEXT: - Index: 0 @@ -112,7 +112,7 @@ entry: ; CHECK-NEXT: Locals: ; CHECK-NEXT: - Type: I32 ; CHECK-NEXT: Count: 2 -; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081081808080002101200041106A24808080800020010B +; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B ; CHECK-NEXT: - Index: 6 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 0B @@ -164,8 +164,8 @@ entry: ; RELOC-NEXT: - ElemType: ANYFUNC ; RELOC-NEXT: Limits: ; RELOC-NEXT: Flags: [ HAS_MAX ] -; RELOC-NEXT: Initial: 0x00000003 -; RELOC-NEXT: Maximum: 0x00000003 +; RELOC-NEXT: Initial: 0x00000002 +; RELOC-NEXT: Maximum: 0x00000002 ; RELOC-NEXT: - Type: MEMORY ; RELOC-NEXT: Memories: ; RELOC-NEXT: - Initial: 0x00000000 @@ -197,7 +197,7 @@ entry: ; RELOC-NEXT: - Offset: ; RELOC-NEXT: Opcode: I32_CONST ; RELOC-NEXT: Value: 1 -; RELOC-NEXT: Functions: [ 1, 1 ] +; RELOC-NEXT: Functions: [ 1 ] ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB @@ -261,7 +261,7 @@ entry: ; RELOC-NEXT: Locals: ; RELOC-NEXT: - Type: I32 ; RELOC-NEXT: Count: 2 -; RELOC-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081081808080002101200041106A24808080800020010B +; RELOC-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: linking ; RELOC-NEXT: DataSize: 0 diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index 1aabe3beed04..054a50039fe8 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -117,3 +117,9 @@ void InputFunction::setOutputIndex(uint32_t Index) { assert(!hasOutputIndex()); OutputIndex = Index; } + +void InputFunction::setTableIndex(uint32_t Index) { + DEBUG(dbgs() << "InputFunction::setTableIndex " << Index << "\n"); + assert(!hasTableIndex()); + TableIndex = Index; +} diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h index 3823168a37de..5e00d27caa1b 100644 --- a/lld/wasm/InputChunks.h +++ b/lld/wasm/InputChunks.h @@ -120,6 +120,9 @@ public: uint32_t getOutputIndex() const { return OutputIndex.getValue(); } bool hasOutputIndex() const { return OutputIndex.hasValue(); } void setOutputIndex(uint32_t Index); + uint32_t getTableIndex() const { return TableIndex.getValue(); } + bool hasTableIndex() const { return TableIndex.hasValue(); } + void setTableIndex(uint32_t Index); const WasmSignature &Signature; @@ -134,6 +137,7 @@ protected: const WasmFunction *Function; llvm::Optional OutputIndex; + llvm::Optional TableIndex; }; class SyntheticFunction : public InputFunction { diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index e4c70340517d..5bb646e040a7 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -67,7 +67,26 @@ void Symbol::setOutputIndex(uint32_t Index) { OutputIndex = Index; } +uint32_t Symbol::getTableIndex() const { + if (Function) + return Function->getTableIndex(); + return TableIndex.getValue(); +} + +bool Symbol::hasTableIndex() const { + if (Function) + return Function->hasTableIndex(); + return TableIndex.hasValue(); +} + void Symbol::setTableIndex(uint32_t Index) { + // For imports, we set the table index here on the Symbol; for defined + // functions we set the index on the InputFunction so that we don't export + // the same thing twice (keeps the table size down). + if (Function) { + Function->setTableIndex(Index); + return; + } DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n"); assert(!TableIndex.hasValue()); TableIndex = Index; diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 3e80944ae97a..b7e8c27b3fd3 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -77,10 +77,10 @@ public: // space of the output object. void setOutputIndex(uint32_t Index); - uint32_t getTableIndex() const { return TableIndex.getValue(); } + uint32_t getTableIndex() const; // Returns true if a table index has been set for this symbol - bool hasTableIndex() const { return TableIndex.hasValue(); } + bool hasTableIndex() const; // Set the table index of the symbol void setTableIndex(uint32_t Index);