summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2019-05-10 01:52:08 +0000
committerSam Clegg <sbc@chromium.org>2019-05-10 01:52:08 +0000
commitea38ac5ba3148e72dc1a260910ef65d2f623e0b5 (patch)
treeb5472fd8e2136c519abf59c8871b257706977234
parent2147365484f1b16d945a45890e9b2d75d14e55e1 (diff)
downloadbcm5719-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.ll2
-rw-r--r--lld/test/wasm/shared.ll21
-rw-r--r--lld/wasm/InputFiles.cpp2
-rw-r--r--lld/wasm/Writer.cpp10
-rw-r--r--llvm/lib/Target/TargetMachine.cpp6
-rw-r--r--llvm/test/CodeGen/WebAssembly/call-pic.ll2
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() {
OpenPOWER on IntegriCloud