Skip to content

Commit ea38ac5

Browse files
committed
[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
1 parent 2147365 commit ea38ac5

File tree

6 files changed

+27
-16
lines changed

6 files changed

+27
-16
lines changed

lld/test/wasm/pie.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ target triple = "wasm32-unknown-unknown"
1111
@data_addr = local_unnamed_addr global i32* @data, align 4
1212
@data_addr_external = local_unnamed_addr global i32* @data_external, align 4
1313

14-
define i32 @foo() {
14+
define hidden i32 @foo() {
1515
entry:
1616
; To ensure we use __stack_pointer
1717
%ptr = alloca i32

lld/test/wasm/shared.ll

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ entry:
2828
ret i32 %0
2929
}
3030

31-
define default i32* @get_data_address() {
31+
define hidden i32* @get_data_address() {
3232
entry:
3333
ret i32* @data_external
3434
}
3535

36-
define default i8* @get_func_address() {
36+
define hidden i8* @get_func_address() {
3737
entry:
3838
ret i8* bitcast (void ()* @func_external to i8*)
3939
}
@@ -54,7 +54,7 @@ declare void @func_external()
5454
; CHECK-NEXT: Name: dylink
5555
; CHECK-NEXT: MemorySize: 24
5656
; CHECK-NEXT: MemoryAlignment: 2
57-
; CHECK-NEXT: TableSize: 3
57+
; CHECK-NEXT: TableSize: 2
5858
; CHECK-NEXT: TableAlignment: 0
5959
; CHECK-NEXT: Needed: []
6060
; CHECK-NEXT: - Type: TYPE
@@ -74,7 +74,7 @@ declare void @func_external()
7474
; CHECK-NEXT: Table:
7575
; CHECK-NEXT: ElemType: FUNCREF
7676
; CHECK-NEXT: Limits:
77-
; CHECK-NEXT: Initial: 0x00000003
77+
; CHECK-NEXT: Initial: 0x00000002
7878
; CHECK-NEXT: - Module: env
7979
; CHECK-NEXT: Field: __stack_pointer
8080
; CHECK-NEXT: Kind: GLOBAL
@@ -95,7 +95,7 @@ declare void @func_external()
9595
; CHECK-NEXT: Kind: FUNCTION
9696
; CHECK-NEXT: SigIndex: 1
9797
; CHECK-NEXT: - Module: GOT.mem
98-
; CHECK-NEXT: Field: data_external
98+
; CHECK-NEXT: Field: indirect_func
9999
; CHECK-NEXT: Kind: GLOBAL
100100
; CHECK-NEXT: GlobalType: I32
101101
; CHECK-NEXT: GlobalMutable: true
@@ -105,6 +105,11 @@ declare void @func_external()
105105
; CHECK-NEXT: GlobalType: I32
106106
; CHECK-NEXT: GlobalMutable: true
107107
; CHECK-NEXT: - Module: GOT.mem
108+
; CHECK-NEXT: Field: data_external
109+
; CHECK-NEXT: Kind: GLOBAL
110+
; CHECK-NEXT: GlobalType: I32
111+
; CHECK-NEXT: GlobalMutable: true
112+
; CHECK-NEXT: - Module: GOT.mem
108113
; CHECK-NEXT: Field: extern_struct
109114
; CHECK-NEXT: Kind: GLOBAL
110115
; CHECK-NEXT: GlobalType: I32
@@ -124,7 +129,7 @@ declare void @func_external()
124129
; CHECK-NEXT: - Offset:
125130
; CHECK-NEXT: Opcode: GLOBAL_GET
126131
; CHECK-NEXT: Index: 2
127-
; CHECK-NEXT: Functions: [ 5, 3, 0 ]
132+
; CHECK-NEXT: Functions: [ 4, 3 ]
128133

129134
; check the generated code in __wasm_call_ctors and __wasm_apply_relocs functions
130135
; TODO(sbc): Disassemble and verify instructions.
@@ -136,7 +141,7 @@ declare void @func_external()
136141
; CHECK-NEXT: Body: 10020B
137142
; CHECK-NEXT: - Index: 2
138143
; CHECK-NEXT: Locals: []
139-
; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2303360200230141146A230541046A3602000B
144+
; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B
140145

141146
; check the data segment initialized with __memory_base global as offset
142147

@@ -147,4 +152,4 @@ declare void @func_external()
147152
; CHECK-NEXT: Offset:
148153
; CHECK-NEXT: Opcode: GLOBAL_GET
149154
; CHECK-NEXT: Index: 1
150-
; CHECK-NEXT: Content: '020000000100000002000000000000000000000000000000'
155+
; CHECK-NEXT: Content: '020000000100000000000000000000000000000000000000'

lld/wasm/InputFiles.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
171171
case R_WASM_TABLE_INDEX_I32:
172172
case R_WASM_TABLE_INDEX_SLEB:
173173
case R_WASM_TABLE_INDEX_REL_SLEB:
174+
if (Config->Pic && !getFunctionSymbol(Reloc.Index)->hasTableIndex())
175+
return 0;
174176
return getFunctionSymbol(Reloc.Index)->getTableIndex();
175177
case R_WASM_MEMORY_ADDR_SLEB:
176178
case R_WASM_MEMORY_ADDR_I32:

lld/wasm/Writer.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,10 @@ void Writer::calculateTypes() {
11421142
registerType(E->Signature);
11431143
}
11441144

1145+
static bool requiresGOTAccess(const Symbol* Sym) {
1146+
return Config->Pic && !Sym->isHidden() && !Sym->isLocal();
1147+
}
1148+
11451149
void Writer::processRelocations(InputChunk *Chunk) {
11461150
if (!Chunk->Live)
11471151
return;
@@ -1153,8 +1157,8 @@ void Writer::processRelocations(InputChunk *Chunk) {
11531157
case R_WASM_TABLE_INDEX_SLEB:
11541158
case R_WASM_TABLE_INDEX_REL_SLEB: {
11551159
FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index);
1156-
if (Sym->hasTableIndex() || !Sym->hasFunctionIndex())
1157-
continue;
1160+
if (Sym->hasTableIndex() || !Sym->hasFunctionIndex() || requiresGOTAccess(Sym))
1161+
break;
11581162
Sym->setTableIndex(TableBase + IndirectFunctions.size());
11591163
IndirectFunctions.emplace_back(Sym);
11601164
break;
@@ -1206,7 +1210,7 @@ void Writer::processRelocations(InputChunk *Chunk) {
12061210
// will be converted into code by `generateRelocationCode`. This code
12071211
// requires the symbols to have GOT entires.
12081212
auto* Sym = File->getSymbols()[Reloc.Index];
1209-
if (!Sym->isHidden() && !Sym->isLocal() && !Sym->isInGOT()) {
1213+
if (requiresGOTAccess(Sym) && !Sym->isInGOT()) {
12101214
Sym->setGOTIndex(NumImportedGlobals++);
12111215
GOTSymbols.push_back(Sym);
12121216
}

llvm/lib/Target/TargetMachine.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,13 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M,
167167
if (GV && !GV->hasDefaultVisibility())
168168
return true;
169169

170-
if (TT.isOSBinFormatMachO() || TT.isOSBinFormatWasm()) {
170+
if (TT.isOSBinFormatMachO()) {
171171
if (RM == Reloc::Static)
172172
return true;
173173
return GV && GV->isStrongDefinitionForLinker();
174174
}
175175

176-
assert(TT.isOSBinFormatELF());
176+
assert(TT.isOSBinFormatELF() || TT.isOSBinFormatWasm());
177177
assert(RM != Reloc::DynamicNoPIC);
178178

179179
bool IsExecutable =
@@ -201,7 +201,7 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M,
201201
return true;
202202
}
203203

204-
// ELF supports preemption of other symbols.
204+
// ELF & wasm support preemption of other symbols.
205205
return false;
206206
}
207207

llvm/test/CodeGen/WebAssembly/call-pic.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ declare i32 @foo()
77
declare i32 @bar()
88
declare hidden i32 @hidden_function()
99

10-
@indirect_func = global i32 ()* @foo
10+
@indirect_func = hidden global i32 ()* @foo
1111
@alias_func = hidden alias i32 (), i32 ()* @local_function
1212

1313
define i32 @local_function() {

0 commit comments

Comments
 (0)