From e4888be74e342840cc1d9e42c9f42938169ae96b Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 18 Aug 2021 22:20:55 -0400 Subject: [PATCH] [WebAssembly] Avoid unused function imports in PIC mode In PIC mode we import function address via `GOT.mem` imports but for direct function calls we still import the first class function. However, if the function is never directly called we can avoid the first class import completely. Differential Revision: https://reviews.llvm.org/D108345 --- lld/test/wasm/shared.s | 14 +++++--------- lld/test/wasm/shared64.s | 14 +++++--------- lld/wasm/SymbolTable.cpp | 5 ++++- lld/wasm/Writer.cpp | 8 ++++++++ 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lld/test/wasm/shared.s b/lld/test/wasm/shared.s index 3299d84..29cf8f6 100644 --- a/lld/test/wasm/shared.s +++ b/lld/test/wasm/shared.s @@ -167,10 +167,6 @@ get_local_func_address: # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I32 # CHECK-NEXT: GlobalMutable: false -# CHECK-NEXT: - Module: env -# CHECK-NEXT: Field: func_external -# CHECK-NEXT: Kind: FUNCTION -# CHECK-NEXT: SigIndex: 1 # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: indirect_func # CHECK-NEXT: Kind: GLOBAL @@ -197,7 +193,7 @@ get_local_func_address: # CHECK-NEXT: Exports: # CHECK-NEXT: - Name: __wasm_call_ctors # CHECK-NEXT: Kind: FUNCTION -# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Index: 0 # check for elem segment initialized with __table_base global as offset @@ -206,17 +202,17 @@ get_local_func_address: # CHECK-NEXT: - Offset: # CHECK-NEXT: Opcode: GLOBAL_GET # CHECK-NEXT: Index: 2 -# CHECK-NEXT: Functions: [ 4, 3 ] +# CHECK-NEXT: Functions: [ 3, 2 ] # check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions # TODO(sbc): Disassemble and verify instructions. # CHECK: - Type: CODE # CHECK-NEXT: Functions: -# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: - Index: 0 # CHECK-NEXT: Locals: [] -# CHECK-NEXT: Body: 10020B -# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Body: 10010B +# CHECK-NEXT: - Index: 1 # CHECK-NEXT: Locals: [] # CHECK-NEXT: Body: 230141046A2304360200230141086A230241016A3602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B diff --git a/lld/test/wasm/shared64.s b/lld/test/wasm/shared64.s index 36528e1..d441dd3 100644 --- a/lld/test/wasm/shared64.s +++ b/lld/test/wasm/shared64.s @@ -174,10 +174,6 @@ get_local_func_address: # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I32 # CHECK-NEXT: GlobalMutable: false -# CHECK-NEXT: - Module: env -# CHECK-NEXT: Field: func_external -# CHECK-NEXT: Kind: FUNCTION -# CHECK-NEXT: SigIndex: 1 # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: indirect_func # CHECK-NEXT: Kind: GLOBAL @@ -204,7 +200,7 @@ get_local_func_address: # CHECK-NEXT: Exports: # CHECK-NEXT: - Name: __wasm_call_ctors # CHECK-NEXT: Kind: FUNCTION -# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Index: 0 # check for elem segment initialized with __table_base global as offset @@ -213,17 +209,17 @@ get_local_func_address: # CHECK-NEXT: - Offset: # CHECK-NEXT: Opcode: GLOBAL_GET # CHECK-NEXT: Index: 3 -# CHECK-NEXT: Functions: [ 4, 3 ] +# CHECK-NEXT: Functions: [ 3, 2 ] # check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions # TODO(sbc): Disassemble and verify instructions. # CHECK: - Type: CODE # CHECK-NEXT: Functions: -# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: - Index: 0 # CHECK-NEXT: Locals: [] -# CHECK-NEXT: Body: 10020B -# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Body: 10010B +# CHECK-NEXT: - Index: 1 # CHECK-NEXT: Locals: [] # CHECK-NEXT: Body: 230142047C23053702002301420C7C230242017C370200230142147C230141006A360200230142187C2306370200230142207C230741046A3602000B diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 1a52133..89fb481 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -548,9 +548,12 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name, else if (getFunctionVariant(s, sig, file, &s)) replaceSym(); } - if (existingUndefined) + if (existingUndefined) { setImportAttributes(existingUndefined, importName, importModule, flags, file); + if (isCalledDirectly) + existingUndefined->isCalledDirectly = true; + } } return s; diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index cf9356b..efe64e6 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -562,6 +562,14 @@ static bool shouldImport(Symbol *sym) { if (isa(sym)) return false; + // In PIC mode we only need to import functions when they are called directly. + // Indirect usage all goes via GOT imports. + if (config->isPic) { + if (auto *f = dyn_cast(sym)) + if (!f->isCalledDirectly) + return false; + } + if (config->isPic || config->relocatable || config->importUndefined) return true; if (config->allowUndefinedSymbols.count(sym->getName()) != 0) -- 2.7.4