wingo updated this revision to Diff 343360. wingo added a comment. yarr, shiver me timbers, fix me typos
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101608/new/ https://reviews.llvm.org/D101608 Files: clang/lib/Basic/Targets/WebAssembly.h clang/test/CodeGen/target-data.c llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp llvm/lib/Target/WebAssembly/WebAssemblyISD.def llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp llvm/test/CodeGen/WebAssembly/global-get.ll llvm/test/CodeGen/WebAssembly/global-set.ll
Index: llvm/test/CodeGen/WebAssembly/global-set.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/WebAssembly/global-set.ll @@ -0,0 +1,57 @@ +; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false < %s | FileCheck %s + +@i32_global = local_unnamed_addr addrspace(1) global i32 undef +@i64_global = local_unnamed_addr addrspace(1) global i64 undef +@f32_global = local_unnamed_addr addrspace(1) global float undef +@f64_global = local_unnamed_addr addrspace(1) global double undef + +define void @set_i32_global(i32 %v) { +; CHECK-LABEL: set_i32_global: +; CHECK-NEXT: functype set_i32_global (i32) -> () +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: global.set i32_global +; CHECK-NEXT: end_function + store i32 %v, i32 addrspace(1)* @i32_global + ret void +} + +define void @set_i64_global(i64 %v) { +; CHECK-LABEL: set_i64_global: +; CHECK-NEXT: functype set_i64_global (i64) -> () +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: global.set i64_global +; CHECK-NEXT: end_function + store i64 %v, i64 addrspace(1)* @i64_global + ret void +} + +define void @set_f32_global(float %v) { +; CHECK-LABEL: set_f32_global: +; CHECK-NEXT: functype set_f32_global (f32) -> () +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: global.set f32_global +; CHECK-NEXT: end_function + store float %v, float addrspace(1)* @f32_global + ret void +} + +define void @set_f64_global(double %v) { +; CHECK-LABEL: set_f64_global: +; CHECK-NEXT: functype set_f64_global (f64) -> () +; CHECK-NEXT: local.get 0 +; CHECK-NEXT: global.set f64_global +; CHECK-NEXT: end_function + store double %v, double addrspace(1)* @f64_global + ret void +} + +;; LLVM doesn't yet declare proper WebAssembly globals for these values, +;; instead placing them in linear memory. To fix in a followup. +; FIXME-CHECK: .globl i32_global +; FIXME-CHECK: .globaltype i32_global, i32 +; FIXME-CHECK: .globl i64_global +; FIXME-CHECK: .globaltype i64_global, i64 +; FIXME-CHECK: .globl f32_global +; FIXME-CHECK: .globaltype f32_global, f32 +; FIXME-CHECK: .globl f64_global +; FIXME-CHECK: .globaltype f64_global, f64 Index: llvm/test/CodeGen/WebAssembly/global-get.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/WebAssembly/global-get.ll @@ -0,0 +1,54 @@ +; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false | FileCheck %s + +@i32_global = local_unnamed_addr addrspace(1) global i32 undef +@i64_global = local_unnamed_addr addrspace(1) global i64 undef +@f32_global = local_unnamed_addr addrspace(1) global float undef +@f64_global = local_unnamed_addr addrspace(1) global double undef + +define i32 @return_i32_global() { +; CHECK-LABEL: return_i32_global: +; CHECK-NEXT: functype return_i32_global () -> (i32) +; CHECK-NEXT: global.get i32_global +; CHECK-NEXT: end_function + %v = load i32, i32 addrspace(1)* @i32_global + ret i32 %v +} + +define i64 @return_i64_global() { +; CHECK-LABEL: return_i64_global: +; CHECK-NEXT: functype return_i64_global () -> (i64) +; CHECK-NEXT: global.get i64_global +; CHECK-NEXT: end_function + %v = load i64, i64 addrspace(1)* @i64_global + ret i64 %v +} + +define float @return_f32_global() { +; CHECK-LABEL: return_f32_global: +; CHECK-NEXT: functype return_f32_global () -> (f32) +; CHECK-NEXT: global.get f32_global +; CHECK-NEXT: end_function + %v = load float, float addrspace(1)* @f32_global + ret float %v +} + +define double @return_f64_global() { +; CHECK-LABEL: return_f64_global: +; CHECK-NEXT: functype return_f64_global () -> (f64) +; CHECK-NEXT: global.get f64_global +; CHECK-NEXT: end_function + %v = load double, double addrspace(1)* @f64_global + ret double %v +} + + +;; LLVM doesn't yet declare proper WebAssembly globals for these values, +;; instead placing them in linear memory. To fix in a followup. +; FIXME-CHECK: .globl i32_global +; FIXME-CHECK: .globaltype i32_global, i32 +; FIXME-CHECK: .globl i64_global +; FIXME-CHECK: .globaltype i64_global, i64 +; FIXME-CHECK: .globl f32_global +; FIXME-CHECK: .globaltype f32_global, f32 +; FIXME-CHECK: .globl f64_global +; FIXME-CHECK: .globaltype f64_global, f64 Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -119,8 +119,9 @@ const TargetOptions &Options, Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT) : LLVMTargetMachine(T, - TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128" - : "e-m:e-p:32:32-i64:64-n32:64-S128", + TT.isArch64Bit() + ? "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1" + : "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1", TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT), getEffectiveCodeModel(CM, CodeModel::Large), OL), TLOF(new WebAssemblyTargetObjectFile()) { Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrRef.td @@ -11,29 +11,29 @@ /// //===----------------------------------------------------------------------===// -multiclass REF_I<WebAssemblyRegClass reg, ValueType vt> { - defm REF_NULL_#reg : I<(outs reg:$res), (ins HeapType:$heaptype), - (outs), (ins HeapType:$heaptype), - [], - "ref.null\t$res, $heaptype", - "ref.null\t$heaptype", - 0xd0>, - Requires<[HasReferenceTypes]>; - defm SELECT_#reg: I<(outs reg:$dst), (ins reg:$lhs, reg:$rhs, I32:$cond), - (outs), (ins), - [(set reg:$dst, - (select I32:$cond, reg:$lhs, reg:$rhs))], - vt#".select\t$dst, $lhs, $rhs, $cond", - vt#".select", 0x1b>, - Requires<[HasReferenceTypes]>; +multiclass REF_I<WebAssemblyRegClass rc, ValueType vt> { + defm REF_NULL_#rc : I<(outs rc:$res), (ins HeapType:$heaptype), + (outs), (ins HeapType:$heaptype), + [], + "ref.null\t$res, $heaptype", + "ref.null\t$heaptype", + 0xd0>, + Requires<[HasReferenceTypes]>; + defm SELECT_#rc: I<(outs rc:$dst), (ins rc:$lhs, rc:$rhs, I32:$cond), + (outs), (ins), + [(set rc:$dst, + (select I32:$cond, rc:$lhs, rc:$rhs))], + vt#".select\t$dst, $lhs, $rhs, $cond", + vt#".select", 0x1b>, + Requires<[HasReferenceTypes]>; } defm "" : REF_I<FUNCREF, funcref>; defm "" : REF_I<EXTERNREF, externref>; -foreach reg = [FUNCREF, EXTERNREF] in { -def : Pat<(select (i32 (setne I32:$cond, 0)), reg:$lhs, reg:$rhs), - (!cast<Instruction>("SELECT_"#reg) reg:$lhs, reg:$rhs, I32:$cond)>; -def : Pat<(select (i32 (seteq I32:$cond, 0)), reg:$lhs, reg:$rhs), - (!cast<Instruction>("SELECT_"#reg) reg:$rhs, reg:$lhs, I32:$cond)>; +foreach rc = [FUNCREF, EXTERNREF] in { +def : Pat<(select (i32 (setne I32:$cond, 0)), rc:$lhs, rc:$rhs), + (!cast<Instruction>("SELECT_"#rc) rc:$lhs, rc:$rhs, I32:$cond)>; +def : Pat<(select (i32 (seteq I32:$cond, 0)), rc:$lhs, rc:$rhs), + (!cast<Instruction>("SELECT_"#rc) rc:$rhs, rc:$lhs, I32:$cond)>; } Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -79,6 +79,8 @@ SDTCisPtrTy<0>]>; def SDT_WebAssemblyThrow : SDTypeProfile<0, -1, []>; def SDT_WebAssemblyCatch : SDTypeProfile<1, 1, [SDTCisPtrTy<0>]>; +def SDT_WebAssemblyGlobalGet : SDTypeProfile<1, 1, [SDTCisPtrTy<1>]>; +def SDT_WebAssemblyGlobalSet : SDTypeProfile<0, 2, [SDTCisPtrTy<1>]>; //===----------------------------------------------------------------------===// // WebAssembly-specific DAG Nodes. @@ -106,6 +108,12 @@ [SDNPHasChain, SDNPVariadic]>; def WebAssemblycatch : SDNode<"WebAssemblyISD::CATCH", SDT_WebAssemblyCatch, [SDNPHasChain, SDNPSideEffect]>; +def WebAssemblyglobal_get : + SDNode<"WebAssemblyISD::GLOBAL_GET", SDT_WebAssemblyGlobalGet, + [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; +def WebAssemblyglobal_set : + SDNode<"WebAssemblyISD::GLOBAL_SET", SDT_WebAssemblyGlobalSet, + [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>; //===----------------------------------------------------------------------===// // WebAssembly-specific Operands. @@ -241,12 +249,12 @@ // Additional instructions. //===----------------------------------------------------------------------===// -multiclass ARGUMENT<WebAssemblyRegClass reg, ValueType vt> { +multiclass ARGUMENT<WebAssemblyRegClass rc, ValueType vt> { let hasSideEffects = 1, isCodeGenOnly = 1, Defs = []<Register>, Uses = [ARGUMENTS] in defm ARGUMENT_#vt : - I<(outs reg:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno), - [(set (vt reg:$res), (WebAssemblyargument timm:$argno))]>; + I<(outs rc:$res), (ins i32imm:$argno), (outs), (ins i32imm:$argno), + [(set (vt rc:$res), (WebAssemblyargument timm:$argno))]>; } defm "": ARGUMENT<I32, i32>; defm "": ARGUMENT<I64, i64>; @@ -257,7 +265,7 @@ // local.get and local.set are not generated by instruction selection; they // are implied by virtual register uses and defs. -multiclass LOCAL<WebAssemblyRegClass vt, Operand global_op> { +multiclass LOCAL<WebAssemblyRegClass rc, Operand global_op> { let hasSideEffects = 0 in { // COPY is not an actual instruction in wasm, but since we allow local.get and // local.set to be implicit during most of codegen, we can have a COPY which @@ -265,21 +273,21 @@ // and local.set. COPYs are eliminated (and replaced with // local.get/local.set) in the ExplicitLocals pass. let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in - defm COPY_#vt : I<(outs vt:$res), (ins vt:$src), (outs), (ins), [], + defm COPY_#rc : I<(outs rc:$res), (ins rc:$src), (outs), (ins), [], "local.copy\t$res, $src", "local.copy">; // TEE is similar to COPY, but writes two copies of its result. Typically // this would be used to stackify one result and write the other result to a // local. let isAsCheapAsAMove = 1, isCodeGenOnly = 1 in - defm TEE_#vt : I<(outs vt:$res, vt:$also), (ins vt:$src), (outs), (ins), [], + defm TEE_#rc : I<(outs rc:$res, rc:$also), (ins rc:$src), (outs), (ins), [], "local.tee\t$res, $also, $src", "local.tee">; // This is the actual local.get instruction in wasm. These are made explicit // by the ExplicitLocals pass. It has mayLoad because it reads from a wasm // local, which is a side effect not otherwise modeled in LLVM. let mayLoad = 1, isAsCheapAsAMove = 1 in - defm LOCAL_GET_#vt : I<(outs vt:$res), (ins local_op:$local), + defm LOCAL_GET_#rc : I<(outs rc:$res), (ins local_op:$local), (outs), (ins local_op:$local), [], "local.get\t$res, $local", "local.get\t$local", 0x20>; @@ -287,7 +295,7 @@ // by the ExplicitLocals pass. It has mayStore because it writes to a wasm // local, which is a side effect not otherwise modeled in LLVM. let mayStore = 1, isAsCheapAsAMove = 1 in - defm LOCAL_SET_#vt : I<(outs), (ins local_op:$local, vt:$src), + defm LOCAL_SET_#rc : I<(outs), (ins local_op:$local, rc:$src), (outs), (ins local_op:$local), [], "local.set\t$local, $src", "local.set\t$local", 0x21>; @@ -295,28 +303,36 @@ // LOCAL_TEEs by the ExplicitLocals pass. It has mayStore for the same reason // as LOCAL_SET. let mayStore = 1, isAsCheapAsAMove = 1 in - defm LOCAL_TEE_#vt : I<(outs vt:$res), (ins local_op:$local, vt:$src), + defm LOCAL_TEE_#rc : I<(outs rc:$res), (ins local_op:$local, rc:$src), (outs), (ins local_op:$local), [], "local.tee\t$res, $local, $src", "local.tee\t$local", 0x22>; // Unused values must be dropped in some contexts. - defm DROP_#vt : I<(outs), (ins vt:$src), (outs), (ins), [], + defm DROP_#rc : I<(outs), (ins rc:$src), (outs), (ins), [], "drop\t$src", "drop", 0x1a>; let mayLoad = 1 in - defm GLOBAL_GET_#vt : I<(outs vt:$res), (ins global_op:$local), - (outs), (ins global_op:$local), [], - "global.get\t$res, $local", "global.get\t$local", + defm GLOBAL_GET_#rc : I<(outs rc:$res), (ins global_op:$addr), + (outs), (ins global_op:$addr), [], + "global.get\t$res, $addr", "global.get\t$addr", 0x23>; let mayStore = 1 in - defm GLOBAL_SET_#vt : I<(outs), (ins global_op:$local, vt:$src), - (outs), (ins global_op:$local), [], - "global.set\t$local, $src", "global.set\t$local", + defm GLOBAL_SET_#rc : I<(outs), (ins global_op:$addr, rc:$src), + (outs), (ins global_op:$addr), [], + "global.set\t$addr, $src", "global.set\t$addr", 0x24>; -} // hasSideEffects = 0 + } // hasSideEffects = 0 + foreach vt = rc.RegTypes in { + def : Pat<(vt (WebAssemblyglobal_get + (WebAssemblywrapper tglobaladdr:$addr))), + (!cast<NI>("GLOBAL_GET_" # rc) tglobaladdr:$addr)>; + def : Pat<(WebAssemblyglobal_set + vt:$src, (WebAssemblywrapper tglobaladdr:$addr)), + (!cast<NI>("GLOBAL_SET_" # rc) tglobaladdr:$addr, vt:$src)>; + } } defm "" : LOCAL<I32, global_op32>; defm "" : LOCAL<I64, global_op64>; // 64-bit only needed for pointers. Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -120,6 +120,8 @@ SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerLoad(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerStore(SDValue Op, SelectionDAG &DAG) const; // Custom DAG combine hooks SDValue Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -17,13 +17,13 @@ #include "WebAssemblyMachineFunctionInfo.h" #include "WebAssemblySubtarget.h" #include "WebAssemblyTargetMachine.h" -#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/WasmEHFuncInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" @@ -69,6 +69,20 @@ // Compute derived properties from the register classes. computeRegisterProperties(Subtarget->getRegisterInfo()); + // Transform loads and stores to pointers in address space 1 to loads and + // stores to WebAssembly global variables, outside linear memory. + for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64}) { + setOperationAction(ISD::LOAD, T, Custom); + setOperationAction(ISD::STORE, T, Custom); + } + if (Subtarget->hasSIMD128()) { + for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64, + MVT::v2f64}) { + setOperationAction(ISD::LOAD, T, Custom); + setOperationAction(ISD::STORE, T, Custom); + } + } + setOperationAction(ISD::GlobalAddress, MVTPtr, Custom); setOperationAction(ISD::GlobalTLSAddress, MVTPtr, Custom); setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom); @@ -1253,9 +1267,63 @@ case ISD::FP_TO_SINT_SAT: case ISD::FP_TO_UINT_SAT: return LowerFP_TO_INT_SAT(Op, DAG); + case ISD::LOAD: + return LowerLoad(Op, DAG); + case ISD::STORE: + return LowerStore(Op, DAG); } } +static bool IsWebAssemblyGlobal(SDValue Op) { + if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) + return WebAssembly::isManagedAddressSpace(GA->getAddressSpace()); + + return false; +} + +SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + StoreSDNode *SN = cast<StoreSDNode>(Op.getNode()); + const SDValue &Value = SN->getValue(); + const SDValue &Base = SN->getBasePtr(); + const SDValue &Offset = SN->getOffset(); + + if (IsWebAssemblyGlobal(Base)) { + if (!Offset->isUndef()) + report_fatal_error("unexpected offset when storing to webassembly global", + false); + + SDVTList Tys = DAG.getVTList(MVT::Other); + SDValue Ops[] = {SN->getChain(), Value, Base}; + return DAG.getMemIntrinsicNode(WebAssemblyISD::GLOBAL_SET, DL, Tys, Ops, + SN->getMemoryVT(), SN->getMemOperand()); + } + + return Op; +} + +SDValue WebAssemblyTargetLowering::LowerLoad(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + LoadSDNode *LN = cast<LoadSDNode>(Op.getNode()); + const SDValue &Base = LN->getBasePtr(); + const SDValue &Offset = LN->getOffset(); + + if (IsWebAssemblyGlobal(Base)) { + if (!Offset->isUndef()) + report_fatal_error( + "unexpected offset when loading from webassembly global", false); + + SDVTList Tys = DAG.getVTList(LN->getValueType(0), MVT::Other); + SDValue Ops[] = {LN->getChain(), Base}; + return DAG.getMemIntrinsicNode(WebAssemblyISD::GLOBAL_GET, DL, Tys, Ops, + LN->getMemoryVT(), LN->getMemOperand()); + } + + return Op; +} + SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op, SelectionDAG &DAG) const { SDValue Src = Op.getOperand(2); @@ -1374,8 +1442,8 @@ EVT VT = Op.getValueType(); assert(GA->getTargetFlags() == 0 && "Unexpected target flags on generic GlobalAddressSDNode"); - if (GA->getAddressSpace() != 0) - fail(DL, DAG, "WebAssembly only expects the 0 address space"); + if (!WebAssembly::isValidAddressSpace(GA->getAddressSpace())) + fail(DL, DAG, "Invalid address space for WebAssembly target"); unsigned OperandFlags = 0; if (isPositionIndependent()) { Index: llvm/lib/Target/WebAssembly/WebAssemblyISD.def =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyISD.def +++ llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -19,7 +19,7 @@ HANDLE_NODETYPE(ARGUMENT) // A wrapper node for TargetExternalSymbol, TargetGlobalAddress, and MCSymbol HANDLE_NODETYPE(Wrapper) -// A special wapper used in PIC code for __memory_base/__table_base relcative +// A special wapper used in PIC code for __memory_base/__table_base relative // access. HANDLE_NODETYPE(WrapperPIC) HANDLE_NODETYPE(BR_IF) @@ -44,3 +44,5 @@ // Memory intrinsics HANDLE_MEM_NODETYPE(LOAD_SPLAT) +HANDLE_MEM_NODETYPE(GLOBAL_GET) +HANDLE_MEM_NODETYPE(GLOBAL_SET) Index: llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -1182,6 +1182,8 @@ const auto *Load = cast<LoadInst>(I); if (Load->isAtomic()) return false; + if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace())) + return false; if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy()) return false; @@ -1240,6 +1242,8 @@ const auto *Store = cast<StoreInst>(I); if (Store->isAtomic()) return false; + if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace())) + return false; if (!Subtarget->hasSIMD128() && Store->getValueOperand()->getType()->isVectorTy()) return false; Index: llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h =================================================================== --- llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h +++ llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h @@ -28,6 +28,28 @@ namespace WebAssembly { +enum WasmAddressSpace : unsigned { + // Default address space, for pointers to unmanaged data in linear memory + // (stack, heap, data). + WASM_ADDRESS_SPACE_DEFAULT = 0, + // A non-integral address space for pointers to named objects outside of + // linear memory: static-storage-duration WebAssembly globals, or + // automatic-storage-duration WebAssembly locals. Loads and stores to these + // pointers are lowered to global.get / global.set or local.get / local.set, + // as appropriate. + WASM_ADDRESS_SPACE_MANAGED = 1 +}; + +inline bool isDefaultAddressSpace(unsigned AS) { + return AS == WASM_ADDRESS_SPACE_DEFAULT; +} +inline bool isManagedAddressSpace(unsigned AS) { + return AS == WASM_ADDRESS_SPACE_MANAGED; +} +inline bool isValidAddressSpace(unsigned AS) { + return isDefaultAddressSpace(AS) || isManagedAddressSpace(AS); +} + bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI); bool mayThrow(const MachineInstr &MI); Index: clang/test/CodeGen/target-data.c =================================================================== --- clang/test/CodeGen/target-data.c +++ clang/test/CodeGen/target-data.c @@ -108,11 +108,11 @@ // RUN: %clang_cc1 -triple wasm32-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=WEBASSEMBLY32 -// WEBASSEMBLY32: target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +// WEBASSEMBLY32: target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1" // RUN: %clang_cc1 -triple wasm64-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=WEBASSEMBLY64 -// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128" +// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1" // RUN: %clang_cc1 -triple lanai-unknown-unknown -o - -emit-llvm %s | \ // RUN: FileCheck %s -check-prefix=LANAI Index: clang/lib/Basic/Targets/WebAssembly.h =================================================================== --- clang/lib/Basic/Targets/WebAssembly.h +++ clang/lib/Basic/Targets/WebAssembly.h @@ -147,7 +147,7 @@ explicit WebAssembly32TargetInfo(const llvm::Triple &T, const TargetOptions &Opts) : WebAssemblyTargetInfo(T, Opts) { - resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128"); + resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128-ni:1"); } protected: @@ -166,7 +166,7 @@ SizeType = UnsignedLong; PtrDiffType = SignedLong; IntPtrType = SignedLong; - resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128"); + resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128-ni:1"); } protected:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits