From 2ff10d99fa298e2638ccccedf01ed743ea652344 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 13 May 2024 14:42:34 -0700 Subject: [PATCH] [WebAssembly] Use 64-bit table when targeting wasm64 See https://github.com/WebAssembly/memory64/issues/51 --- lld/test/wasm/shared64.s | 14 +++++--------- lld/wasm/Driver.cpp | 10 ---------- lld/wasm/Symbols.cpp | 2 -- lld/wasm/Symbols.h | 5 ----- lld/wasm/SyntheticSections.cpp | 8 +++----- lld/wasm/Writer.cpp | 10 ++++------ .../lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 12 ------------ .../Target/WebAssembly/WebAssemblyISelLowering.cpp | 14 -------------- .../WebAssembly/fast-isel-call-indirect64.ll | 14 -------------- .../test/CodeGen/WebAssembly/function-pointer64.ll | 5 ++--- 10 files changed, 14 insertions(+), 80 deletions(-) delete mode 100644 llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll diff --git a/lld/test/wasm/shared64.s b/lld/test/wasm/shared64.s index 3401faed8610c..73f77436cabf9 100644 --- a/lld/test/wasm/shared64.s +++ b/lld/test/wasm/shared64.s @@ -154,6 +154,7 @@ get_local_func_address: # CHECK-NEXT: Index: 0 # CHECK-NEXT: ElemType: FUNCREF # CHECK-NEXT: Limits: +# CHECK-NEXT: Flags: [ IS_64 ] # CHECK-NEXT: Minimum: 0x2 # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: __stack_pointer @@ -170,11 +171,6 @@ get_local_func_address: # CHECK-NEXT: Kind: GLOBAL # CHECK-NEXT: GlobalType: I64 # CHECK-NEXT: GlobalMutable: false -# CHECK-NEXT: - Module: env -# CHECK-NEXT: Field: __table_base32 -# CHECK-NEXT: Kind: GLOBAL -# CHECK-NEXT: GlobalType: I32 -# CHECK-NEXT: GlobalMutable: false # CHECK-NEXT: - Module: GOT.mem # CHECK-NEXT: Field: indirect_func # CHECK-NEXT: Kind: GLOBAL @@ -209,7 +205,7 @@ get_local_func_address: # CHECK-NEXT: Segments: # CHECK-NEXT: - Offset: # CHECK-NEXT: Opcode: GLOBAL_GET -# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Index: 2 # CHECK-NEXT: Functions: [ 3, 2 ] # check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions @@ -223,7 +219,7 @@ get_local_func_address: # DIS-NEXT: i64.const 4 # DIS-NEXT: global.get 1 # DIS-NEXT: i64.add -# DIS-NEXT: global.get 5 +# DIS-NEXT: global.get 4 # DIS-NEXT: i64.store 0:p2align=2 # DIS-NEXT: i64.const 12 # DIS-NEXT: global.get 1 @@ -242,12 +238,12 @@ get_local_func_address: # DIS-NEXT: i64.const 24 # DIS-NEXT: global.get 1 # DIS-NEXT: i64.add -# DIS-NEXT: global.get 6 +# DIS-NEXT: global.get 5 # DIS-NEXT: i64.store 0:p2align=2 # DIS-NEXT: i64.const 32 # DIS-NEXT: global.get 1 # DIS-NEXT: i64.add -# DIS-NEXT: global.get 7 +# DIS-NEXT: global.get 6 # DIS-NEXT: i32.const 4 # DIS-NEXT: i32.add # DIS-NEXT: i32.store 0 diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index d5d763b0a4ae1..cc79f80d005dc 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -870,13 +870,6 @@ static void createSyntheticSymbols() { WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType); WasmSym::memoryBase->markLive(); WasmSym::tableBase->markLive(); - if (is64) { - WasmSym::tableBase32 = - createUndefinedGlobal("__table_base32", &globalTypeI32); - WasmSym::tableBase32->markLive(); - } else { - WasmSym::tableBase32 = nullptr; - } } else { // For non-PIC code WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true); @@ -923,9 +916,6 @@ static void createOptionalSymbols() { WasmSym::heapEnd = symtab->addOptionalDataSymbol("__heap_end"); WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); - if (config->is64.value_or(false)) - WasmSym::definedTableBase32 = - symtab->addOptionalDataSymbol("__table_base32"); } // For non-shared memory programs we still need to define __tls_base since we diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index ace6bade02d43..687728d00c856 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -96,8 +96,6 @@ GlobalSymbol *WasmSym::tlsSize; GlobalSymbol *WasmSym::tlsAlign; UndefinedGlobal *WasmSym::tableBase; DefinedData *WasmSym::definedTableBase; -UndefinedGlobal *WasmSym::tableBase32; -DefinedData *WasmSym::definedTableBase32; UndefinedGlobal *WasmSym::memoryBase; DefinedData *WasmSym::definedMemoryBase; TableSymbol *WasmSym::indirectFunctionTable; diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 38586bbd13236..65a062b8321b9 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -603,11 +603,6 @@ struct WasmSym { // Used in PIC code for offset of indirect function table static UndefinedGlobal *tableBase; static DefinedData *definedTableBase; - // 32-bit copy in wasm64 to work around init expr limitations. - // These can potentially be removed again once we have - // https://github.com/WebAssembly/extended-const - static UndefinedGlobal *tableBase32; - static DefinedData *definedTableBase32; // __memory_base // Used in PIC code for offset of global data diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index 72e255951608e..b359e0fdc856c 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -584,12 +584,10 @@ void ElemSection::writeBody() { initExpr.Extended = false; if (ctx.isPic) { initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET; - initExpr.Inst.Value.Global = - (config->is64.value_or(false) ? WasmSym::tableBase32 - : WasmSym::tableBase) - ->getGlobalIndex(); + initExpr.Inst.Value.Global = WasmSym::tableBase->getGlobalIndex(); } else { - initExpr.Inst.Opcode = WASM_OPCODE_I32_CONST; + bool is64 = config->is64.value_or(false); + initExpr.Inst.Opcode = is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST; initExpr.Inst.Value.Int32 = config->tableBase; } writeInitExpr(os, initExpr); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 55eff995fb8a1..7a015764b77ca 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -939,6 +939,8 @@ static void finalizeIndirectFunctionTable() { limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX; limits.Maximum = limits.Minimum; } + if (config->is64.value_or(false)) + limits.Flags |= WASM_LIMITS_FLAG_IS_64; WasmSym::indirectFunctionTable->setLimits(limits); } @@ -1691,12 +1693,8 @@ void Writer::createSyntheticSectionsPostLayout() { void Writer::run() { // For PIC code the table base is assigned dynamically by the loader. // For non-PIC, we start at 1 so that accessing table index 0 always traps. - if (!ctx.isPic) { - if (WasmSym::definedTableBase) - WasmSym::definedTableBase->setVA(config->tableBase); - if (WasmSym::definedTableBase32) - WasmSym::definedTableBase32->setVA(config->tableBase); - } + if (!ctx.isPic && WasmSym::definedTableBase) + WasmSym::definedTableBase->setVA(config->tableBase); log("-- createOutputSegments"); createOutputSegments(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp index 1c62290704fe4..26e13948bc9a6 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -885,18 +885,6 @@ bool WebAssemblyFastISel::selectCall(const Instruction *I) { Table->setNoStrip(); MIB.addImm(0); } - // See if we must truncate the function pointer. - // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers - // as 64-bit for uniformity with other pointer types. - // See also: WebAssemblyISelLowering.cpp: LowerCallResults - if (Subtarget->hasAddr64()) { - auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), MIMD, - TII.get(WebAssembly::I32_WRAP_I64)); - Register Reg32 = createResultReg(&WebAssembly::I32RegClass); - Wrap.addReg(Reg32, RegState::Define); - Wrap.addReg(CalleeReg); - CalleeReg = Reg32; - } } for (unsigned ArgReg : Args) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 527bb4c9fbea6..d524539944170 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -576,20 +576,6 @@ LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB, const MCInstrDesc &MCID = TII.get(CallOp); MachineInstrBuilder MIB(MF, MF.CreateMachineInstr(MCID, DL)); - // See if we must truncate the function pointer. - // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers - // as 64-bit for uniformity with other pointer types. - // See also: WebAssemblyFastISel::selectCall - if (IsIndirect && MF.getSubtarget().hasAddr64()) { - Register Reg32 = - MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass); - auto &FnPtr = CallParams.getOperand(0); - BuildMI(*BB, CallResults.getIterator(), DL, - TII.get(WebAssembly::I32_WRAP_I64), Reg32) - .addReg(FnPtr.getReg()); - FnPtr.setReg(Reg32); - } - // Move the function pointer to the end of the arguments for indirect calls if (IsIndirect) { auto FnPtr = CallParams.getOperand(0); diff --git a/llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll b/llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll deleted file mode 100644 index 8224c3bc4e374..0000000000000 --- a/llvm/test/CodeGen/WebAssembly/fast-isel-call-indirect64.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: llc < %s -fast-isel --mtriple=wasm64 -asm-verbose=false -wasm-keep-registers | FileCheck %s - -target triple = "wasm64" - -; Ensure fast isel also lowers function pointers to 32-bit. - -; CHECK: local.get $push[[L0:[0-9]+]]=, 0 -; CHECK-NEXT: i32.wrap_i64 $push[[L1:[0-9]+]]=, $pop[[L0]] -; CHECK-NEXT: call_indirect $pop[[L1]] - -define hidden void @f(ptr %g) { - call void %g() - ret void -} diff --git a/llvm/test/CodeGen/WebAssembly/function-pointer64.ll b/llvm/test/CodeGen/WebAssembly/function-pointer64.ll index c7c90f6b7ac21..7f98d3e648bd4 100644 --- a/llvm/test/CodeGen/WebAssembly/function-pointer64.ll +++ b/llvm/test/CodeGen/WebAssembly/function-pointer64.ll @@ -34,7 +34,6 @@ entry: ; CHECK: .functype foo (i64) -> () ; CHECK-NEXT: i32.const 1 ; CHECK-NEXT: local.get 0 -; CHECK-NEXT: i32.wrap_i64 ; CHECK-NEXT: call_indirect (i32) -> () ; REF: call_indirect __indirect_function_table, (i32) -> () @@ -53,10 +52,10 @@ entry: ; YAML: - Type: CODE ; YAML: - Type: R_WASM_TABLE_INDEX_SLEB64 ; YAML-NEXT: Index: 0 -; YAML-NEXT: Offset: 0x16 +; YAML-NEXT: Offset: 0x15 ; YAML: - Type: R_WASM_TABLE_INDEX_SLEB64 ; YAML-NEXT: Index: 0 -; YAML-NEXT: Offset: 0x29 +; YAML-NEXT: Offset: 0x28 ; YAML: - Type: DATA ; YAML: - Type: R_WASM_TABLE_INDEX_I64