Paulo Matos via llvm-dev
2021-Jan-27 13:21 UTC
[llvm-dev] [WebAssembly] Lower type in new DAG node
Hi all, Through my work on implementing the reference types WebAssembly proposal in LLVM IR, I have hit a blocker and would be keen to have suggestions on how to proceed or similar cases from which to draw inspiration. The current WIP patch is at https://reviews.llvm.org/D95425 The current design to represent the externref type is to use LLVM type opaque in address space 1. Therefore an externref looks like: %extern = type opaque %externref = type %extern addrspace(1)* ;; addrspace 1 is nonintegral To represent storing and loading of externref from globals, we use store and load from LLVM globals. So, a store of externref would look like: @externref_global = local_unnamed_addr addrspace(1) global %externref undef define void @set_externref_global(%externref %g) { ;; this generates a global.set of @externref.global store %externref %g, %externref addrspace(1)* @externref_global ret void } What's currently happening is that we lower the store into a new DAG node GLOBAL_SET and then pattern match it into a GLOBAL_SET_EXTERNREF that generates the proper global.set Wasm instruction. // Global SET def wasm_global_set_t : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>; def wasm_global_set : SDNode<"WebAssemblyISD::GLOBAL_SET", wasm_global_set_t, [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; def : Pat<(wasm_global_set externref:$v, (WebAssemblywrapper tglobaladdr:$addr)), (GLOBAL_SET_EXTERNREF global_op:$addr, EXTERNREF:$v)>, Requires<[HasReferenceTypes]>; The problem I am finding is that the pattern matcher is not being able to match the new node with (wasm_global_set externref:$v, (WebAssemblywrapper tglobaladdr:$addr)) Further analysis shows that the problem is in matching externref:$v. The issue is that in IR, $v has type opaque addrspace(1)*, but the MVT we re trying to match it to is externref. Initially I assumed, we could somehow lower the type and instruct LLVM to lower all type opaque addrspace(1)* to MVT::externref but I was not able to achieve that. I welcome any suggestions/comments on the approach and ways to proceed. Regards, -- Paulo Matos
David Chisnall via llvm-dev
2021-Jan-27 14:48 UTC
[llvm-dev] [WebAssembly] Lower type in new DAG node
Hi Paulo, In the CHERI port of LLVM, we have added a bunch of fat pointer MVT types (iFATPTR64, iFATPTR128, and so on) and lower CHERI capabilities (which, in the IR, we represent as pointers with address space 200) to them in the relevant back ends (MIPS / RISC-V / AArch64). We also add explicit PTRADD DAG nodes for pointer arithmetic (GEP lowering) We can load and store an iFATPTR{width} via a normal load and store, just as we can any other type. Would this address your use case? David On 27/01/2021 13:21, Paulo Matos via llvm-dev wrote:> > Hi all, > > Through my work on implementing the reference types WebAssembly proposal > in LLVM IR, I have hit a blocker and would be keen to have suggestions > on how to proceed or similar cases from which to draw inspiration. The > current WIP patch is at https://reviews.llvm.org/D95425 > > The current design to represent the externref type is to use LLVM type > opaque in address space 1. Therefore an externref looks like: > > %extern = type opaque > %externref = type %extern addrspace(1)* ;; addrspace 1 is nonintegral > > To represent storing and loading of externref from globals, we use store > and load from LLVM globals. So, a store of externref would look like: > > @externref_global = local_unnamed_addr addrspace(1) global %externref undef > define void @set_externref_global(%externref %g) { > ;; this generates a global.set of @externref.global > store %externref %g, %externref addrspace(1)* @externref_global > ret void > } > > What's currently happening is that we lower the store into a new DAG > node GLOBAL_SET and then pattern match it into a GLOBAL_SET_EXTERNREF > that generates the proper global.set Wasm instruction. > > // Global SET > def wasm_global_set_t : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>; > def wasm_global_set : SDNode<"WebAssemblyISD::GLOBAL_SET", wasm_global_set_t, > [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; > def : Pat<(wasm_global_set externref:$v, (WebAssemblywrapper tglobaladdr:$addr)), > (GLOBAL_SET_EXTERNREF global_op:$addr, EXTERNREF:$v)>, > Requires<[HasReferenceTypes]>; > > The problem I am finding is that the pattern matcher is not being able > to match the new node with (wasm_global_set externref:$v, > (WebAssemblywrapper tglobaladdr:$addr)) > > Further analysis shows that the problem is in matching externref:$v. > > The issue is that in IR, $v has type opaque addrspace(1)*, but the MVT > we re trying to match it to is externref. Initially I assumed, we could > somehow lower the type and instruct LLVM to lower all type opaque > addrspace(1)* to MVT::externref but I was not able to achieve that. I > welcome any suggestions/comments on the approach and ways to proceed. > > Regards, >