-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[WebAssembly] Implement addrspacecast to funcref #166820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -409,6 +409,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering( | |
| setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); | ||
| setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom); | ||
|
|
||
| // Allow converting function ptrs in address space 0 to WASM funcref (address | ||
| // space 20) | ||
| setOperationAction(ISD::ADDRSPACECAST, MVT::funcref, Custom); | ||
|
|
||
| setMaxAtomicSizeInBitsSupported(64); | ||
|
|
||
| // Always convert switches to br_tables unless there is only one case, which | ||
|
|
@@ -1733,6 +1737,8 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op, | |
| return LowerMUL_LOHI(Op, DAG); | ||
| case ISD::UADDO: | ||
| return LowerUADDO(Op, DAG); | ||
| case ISD::ADDRSPACECAST: | ||
| return LowerADDRSPACECAST(Op, DAG); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -1876,6 +1882,58 @@ SDValue WebAssemblyTargetLowering::LowerUADDO(SDValue Op, | |
| return DAG.getMergeValues(Ops, DL); | ||
| } | ||
|
|
||
| SDValue WebAssemblyTargetLowering::LowerADDRSPACECAST(SDValue Op, | ||
| SelectionDAG &DAG) const { | ||
| SDLoc DL(Op); | ||
|
|
||
| AddrSpaceCastSDNode *ACN = cast<AddrSpaceCastSDNode>(Op.getNode()); | ||
|
|
||
| if (ACN->getSrcAddressSpace() != | ||
| WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_DEFAULT || | ||
| ACN->getDestAddressSpace() != | ||
| WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) | ||
| return Op; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't want to lower this operation, I think we want return an empty |
||
|
|
||
| if (ACN->getValueType(0) != MVT::funcref) { | ||
| reportFatalInternalError("Cannot addrspacecast to funcref addrspace with " | ||
| "results other than MVT::funcref"); | ||
| } | ||
|
|
||
| SDValue Src = ACN->getOperand(0); | ||
|
|
||
| // Lower addrspacecasts of direct/constant function ptrs to ref.func | ||
| if (auto *GA = dyn_cast<GlobalAddressSDNode>( | ||
| Src->getOpcode() == WebAssemblyISD::Wrapper ? Src->getOperand(0) | ||
| : Src)) { | ||
| auto *GV = GA->getGlobal(); | ||
|
|
||
| if (const Function *F = dyn_cast<Function>(GV)) { | ||
| SDValue FnAddress = DAG.getTargetGlobalAddress(F, DL, MVT::i32); | ||
|
|
||
| SDValue RefFuncNode = | ||
| DAG.getNode(WebAssemblyISD::REF_FUNC, DL, MVT::funcref, FnAddress); | ||
| return RefFuncNode; | ||
| } | ||
| } | ||
|
|
||
| // Lower everything else to a table.get from the indirect function table | ||
| const MachineFunction &MF = DAG.getMachineFunction(); | ||
|
|
||
| MVT PtrVT = getPointerTy(MF.getDataLayout()); | ||
|
|
||
| MCSymbolWasm *Table = | ||
| WebAssembly::getOrCreateFunctionTableSymbol(MF.getContext(), Subtarget); | ||
| SDValue TableSym = DAG.getMCSymbol(Table, PtrVT); | ||
|
|
||
| SDValue TableSlot = Op.getOperand(0); | ||
|
|
||
| SDValue Result(DAG.getMachineNode(WebAssembly::TABLE_GET_FUNCREF, DL, | ||
| MVT::funcref, TableSym, TableSlot), | ||
| 0); | ||
|
|
||
| return Result; | ||
| } | ||
|
|
||
| SDValue WebAssemblyTargetLowering::Replace128Op(SDNode *N, | ||
| SelectionDAG &DAG) const { | ||
| assert(Subtarget->hasWideArithmetic()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 | ||
| ; RUN: llc -mtriple=wasm32-unknown-unknown -mattr=+reference-types < %s | FileCheck -check-prefixes=CHECK,WASM32 %s | ||
| ; RUN: llc -mtriple=wasm64-unknown-unknown -mattr=+reference-types < %s | FileCheck -check-prefixes=CHECK,WASM64 %s | ||
|
|
||
| %funcref = type ptr addrspace(20) ;; addrspace 20 is nonintegral | ||
|
|
||
| declare void @foo(); | ||
|
|
||
| @global_var = local_unnamed_addr global i32 0 | ||
|
|
||
| define %funcref @cast_const_funcptr() { | ||
| ; CHECK-LABEL: cast_const_funcptr: | ||
| ; CHECK: .functype cast_const_funcptr () -> (funcref) | ||
| ; CHECK-NEXT: # %bb.0: | ||
| ; CHECK-NEXT: ref.func foo | ||
| ; CHECK-NEXT: # fallthrough-return | ||
| %result = addrspacecast ptr @foo to ptr addrspace(20) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any reason the target type has to be spelled out and can't be just |
||
| ret %funcref %result | ||
| } | ||
|
|
||
| define %funcref @cast_const_not_funcptr() { | ||
| ; WASM32-LABEL: cast_const_not_funcptr: | ||
| ; WASM32: .functype cast_const_not_funcptr () -> (funcref) | ||
| ; WASM32-NEXT: # %bb.0: | ||
| ; WASM32-NEXT: i32.const global_var | ||
| ; WASM32-NEXT: table.get __indirect_function_table | ||
| ; WASM32-NEXT: # fallthrough-return | ||
| ; | ||
| ; WASM64-LABEL: cast_const_not_funcptr: | ||
| ; WASM64: .functype cast_const_not_funcptr () -> (funcref) | ||
| ; WASM64-NEXT: # %bb.0: | ||
| ; WASM64-NEXT: i64.const global_var | ||
| ; WASM64-NEXT: table.get __indirect_function_table | ||
| ; WASM64-NEXT: # fallthrough-return | ||
| %result = addrspacecast ptr @global_var to ptr addrspace(20) | ||
| ret %funcref %result | ||
| } | ||
|
|
||
| define %funcref @cast_param_funcptr(ptr %funcptr) { | ||
| ; WASM32-LABEL: cast_param_funcptr: | ||
| ; WASM32: .functype cast_param_funcptr (i32) -> (funcref) | ||
| ; WASM32-NEXT: # %bb.0: | ||
| ; WASM32-NEXT: local.get 0 | ||
| ; WASM32-NEXT: table.get __indirect_function_table | ||
| ; WASM32-NEXT: # fallthrough-return | ||
| ; | ||
| ; WASM64-LABEL: cast_param_funcptr: | ||
| ; WASM64: .functype cast_param_funcptr (i64) -> (funcref) | ||
| ; WASM64-NEXT: # %bb.0: | ||
| ; WASM64-NEXT: local.get 0 | ||
| ; WASM64-NEXT: table.get __indirect_function_table | ||
| ; WASM64-NEXT: # fallthrough-return | ||
| %result = addrspacecast ptr %funcptr to ptr addrspace(20) | ||
| ret %funcref %result | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.