mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 08:02:08 +00:00
[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
This commit is contained in:
parent
2147365484
commit
ea38ac5ba3
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user