diff options
| author | Sam Clegg <sbc@chromium.org> | 2019-05-10 01:52:08 +0000 | 
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2019-05-10 01:52:08 +0000 | 
| commit | ea38ac5ba3148e72dc1a260910ef65d2f623e0b5 (patch) | |
| tree | b5472fd8e2136c519abf59c8871b257706977234 | |
| parent | 2147365484f1b16d945a45890e9b2d75d14e55e1 (diff) | |
| download | bcm5719-llvm-ea38ac5ba3148e72dc1a260910ef65d2f623e0b5.tar.gz bcm5719-llvm-ea38ac5ba3148e72dc1a260910ef65d2f623e0b5.zip  | |
[WebAssembly] Don't assume that strongly defined symbols are DSO-local
The current PIC model for WebAssembly is more like ELF in that it
allows symbol interposition.
This means that more functions end up being addressed via the GOT
and fewer directly added to the wasm table.
One effect is a reduction in the number of wasm table entries similar
to the previous attempt in https://reviews.llvm.org/D61539 which was
reverted.
Differential Revision: https://reviews.llvm.org/D61772
llvm-svn: 360402
| -rw-r--r-- | lld/test/wasm/pie.ll | 2 | ||||
| -rw-r--r-- | lld/test/wasm/shared.ll | 21 | ||||
| -rw-r--r-- | lld/wasm/InputFiles.cpp | 2 | ||||
| -rw-r--r-- | lld/wasm/Writer.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/Target/TargetMachine.cpp | 6 | ||||
| -rw-r--r-- | llvm/test/CodeGen/WebAssembly/call-pic.ll | 2 | 
6 files changed, 27 insertions, 16 deletions
diff --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll index 06f95bc3950..90952faab5e 100644 --- a/lld/test/wasm/pie.ll +++ b/lld/test/wasm/pie.ll @@ -11,7 +11,7 @@ target triple = "wasm32-unknown-unknown"  @data_addr = local_unnamed_addr global i32* @data, align 4  @data_addr_external = local_unnamed_addr global i32* @data_external, align 4 -define i32 @foo() { +define hidden i32 @foo() {  entry:    ; To ensure we use __stack_pointer    %ptr = alloca i32 diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll index 50a4c8b4a2e..9fbbfc099e5 100644 --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -28,12 +28,12 @@ entry:    ret i32 %0  } -define default i32* @get_data_address() { +define hidden i32* @get_data_address() {  entry:    ret i32* @data_external  } -define default i8* @get_func_address() { +define hidden i8* @get_func_address() {  entry:    ret i8* bitcast (void ()* @func_external to i8*)  } @@ -54,7 +54,7 @@ declare void @func_external()  ; CHECK-NEXT:     Name:            dylink  ; CHECK-NEXT:     MemorySize:      24  ; CHECK-NEXT:     MemoryAlignment: 2 -; CHECK-NEXT:     TableSize:       3 +; CHECK-NEXT:     TableSize:       2  ; CHECK-NEXT:     TableAlignment:  0  ; CHECK-NEXT:     Needed:          []  ; CHECK-NEXT:   - Type:            TYPE @@ -74,7 +74,7 @@ declare void @func_external()  ; CHECK-NEXT:         Table:  ; CHECK-NEXT:           ElemType:        FUNCREF  ; CHECK-NEXT:           Limits: -; CHECK-NEXT:             Initial:         0x00000003 +; CHECK-NEXT:             Initial:         0x00000002  ; CHECK-NEXT:       - Module:          env  ; CHECK-NEXT:         Field:           __stack_pointer  ; CHECK-NEXT:         Kind:            GLOBAL @@ -95,7 +95,7 @@ declare void @func_external()  ; CHECK-NEXT:         Kind:            FUNCTION  ; CHECK-NEXT:         SigIndex:        1  ; CHECK-NEXT:       - Module:          GOT.mem -; CHECK-NEXT:         Field:           data_external +; CHECK-NEXT:         Field:           indirect_func  ; CHECK-NEXT:         Kind:            GLOBAL  ; CHECK-NEXT:         GlobalType:      I32  ; CHECK-NEXT:         GlobalMutable:   true @@ -105,6 +105,11 @@ declare void @func_external()  ; CHECK-NEXT:         GlobalType:      I32  ; CHECK-NEXT:         GlobalMutable:   true  ; CHECK-NEXT:       - Module:          GOT.mem +; CHECK-NEXT:         Field:           data_external +; CHECK-NEXT:         Kind:            GLOBAL +; CHECK-NEXT:         GlobalType:      I32 +; CHECK-NEXT:         GlobalMutable:   true +; CHECK-NEXT:       - Module:          GOT.mem  ; CHECK-NEXT:         Field:           extern_struct  ; CHECK-NEXT:         Kind:            GLOBAL  ; CHECK-NEXT:         GlobalType:      I32 @@ -124,7 +129,7 @@ declare void @func_external()  ; CHECK-NEXT:       - Offset:  ; CHECK-NEXT:           Opcode:          GLOBAL_GET  ; CHECK-NEXT:           Index:           2 -; CHECK-NEXT:         Functions:       [ 5, 3, 0 ] +; CHECK-NEXT:         Functions:       [ 4, 3 ]  ; check the generated code in __wasm_call_ctors and __wasm_apply_relocs functions  ; TODO(sbc): Disassemble and verify instructions. @@ -136,7 +141,7 @@ declare void @func_external()  ; CHECK-NEXT:         Body:            10020B  ; CHECK-NEXT:       - Index:           2  ; CHECK-NEXT:         Locals:          [] -; CHECK-NEXT:         Body:            230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2303360200230141146A230541046A3602000B +; CHECK-NEXT:         Body:            230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B  ; check the data segment initialized with __memory_base global as offset @@ -147,4 +152,4 @@ declare void @func_external()  ; CHECK-NEXT:         Offset:  ; CHECK-NEXT:           Opcode:          GLOBAL_GET  ; CHECK-NEXT:           Index:           1 -; CHECK-NEXT:         Content:         '020000000100000002000000000000000000000000000000' +; CHECK-NEXT:         Content:         '020000000100000000000000000000000000000000000000' diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index b62b1feb74d..f6c72f434fd 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -171,6 +171,8 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {    case R_WASM_TABLE_INDEX_I32:    case R_WASM_TABLE_INDEX_SLEB:    case R_WASM_TABLE_INDEX_REL_SLEB: +    if (Config->Pic && !getFunctionSymbol(Reloc.Index)->hasTableIndex()) +      return 0;      return getFunctionSymbol(Reloc.Index)->getTableIndex();    case R_WASM_MEMORY_ADDR_SLEB:    case R_WASM_MEMORY_ADDR_I32: diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 47e76748f79..8ed4d6b94cd 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1142,6 +1142,10 @@ void Writer::calculateTypes() {      registerType(E->Signature);  } +static bool requiresGOTAccess(const Symbol* Sym) { +  return Config->Pic && !Sym->isHidden() && !Sym->isLocal(); +} +  void Writer::processRelocations(InputChunk *Chunk) {    if (!Chunk->Live)      return; @@ -1153,8 +1157,8 @@ void Writer::processRelocations(InputChunk *Chunk) {      case R_WASM_TABLE_INDEX_SLEB:      case R_WASM_TABLE_INDEX_REL_SLEB: {        FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); -      if (Sym->hasTableIndex() || !Sym->hasFunctionIndex()) -        continue; +      if (Sym->hasTableIndex() || !Sym->hasFunctionIndex() || requiresGOTAccess(Sym)) +        break;        Sym->setTableIndex(TableBase + IndirectFunctions.size());        IndirectFunctions.emplace_back(Sym);        break; @@ -1206,7 +1210,7 @@ void Writer::processRelocations(InputChunk *Chunk) {          // will be converted into code by `generateRelocationCode`.  This code          // requires the symbols to have GOT entires.          auto* Sym = File->getSymbols()[Reloc.Index]; -        if (!Sym->isHidden() && !Sym->isLocal() && !Sym->isInGOT()) { +        if (requiresGOTAccess(Sym) && !Sym->isInGOT()) {            Sym->setGOTIndex(NumImportedGlobals++);            GOTSymbols.push_back(Sym);          } diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 5b2bdc37af8..fd70b836421 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -167,13 +167,13 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M,    if (GV && !GV->hasDefaultVisibility())      return true; -  if (TT.isOSBinFormatMachO() || TT.isOSBinFormatWasm()) { +  if (TT.isOSBinFormatMachO()) {      if (RM == Reloc::Static)        return true;      return GV && GV->isStrongDefinitionForLinker();    } -  assert(TT.isOSBinFormatELF()); +  assert(TT.isOSBinFormatELF() || TT.isOSBinFormatWasm());    assert(RM != Reloc::DynamicNoPIC);    bool IsExecutable = @@ -201,7 +201,7 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M,        return true;    } -  // ELF supports preemption of other symbols. +  // ELF & wasm support preemption of other symbols.    return false;  } diff --git a/llvm/test/CodeGen/WebAssembly/call-pic.ll b/llvm/test/CodeGen/WebAssembly/call-pic.ll index b319ea4924f..53a397ac769 100644 --- a/llvm/test/CodeGen/WebAssembly/call-pic.ll +++ b/llvm/test/CodeGen/WebAssembly/call-pic.ll @@ -7,7 +7,7 @@ declare i32 @foo()  declare i32 @bar()  declare hidden i32 @hidden_function() -@indirect_func = global i32 ()* @foo +@indirect_func = hidden global i32 ()* @foo  @alias_func = hidden alias i32 (), i32 ()* @local_function  define i32 @local_function() {  | 

