diff --git a/llvm/include/llvm/CodeGen/ValueTypes.h b/llvm/include/llvm/CodeGen/ValueTypes.h --- a/llvm/include/llvm/CodeGen/ValueTypes.h +++ b/llvm/include/llvm/CodeGen/ValueTypes.h @@ -209,7 +209,8 @@ /// Return true if this is an overloaded type for TableGen. bool isOverloaded() const { - return (V==MVT::iAny || V==MVT::fAny || V==MVT::vAny || V==MVT::iPTRAny); + return (V == MVT::rAny || V == MVT::iAny || V == MVT::fAny || + V == MVT::vAny || V == MVT::iPTRAny); } /// Return true if the bit size is a multiple of 8. diff --git a/llvm/include/llvm/CodeGen/ValueTypes.td b/llvm/include/llvm/CodeGen/ValueTypes.td --- a/llvm/include/llvm/CodeGen/ValueTypes.td +++ b/llvm/include/llvm/CodeGen/ValueTypes.td @@ -218,22 +218,24 @@ def x86amx : ValueType<8192, 177>; // X86 AMX value def i64x8 : ValueType<512, 178>; // 8 Consecutive GPRs (AArch64) - -def token : ValueType<0, 248>; // TokenTy -def MetadataVT : ValueType<0, 249>; // Metadata +def token : ValueType<0, 247>; // TokenTy +def MetadataVT : ValueType<0, 248>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. // Should only be used in TableGen. -def iPTRAny : ValueType<0, 250>; +def iPTRAny : ValueType<0, 249>; // Pseudo valuetype to represent "vector of any size" -def vAny : ValueType<0, 251>; +def vAny : ValueType<0, 250>; // Pseudo valuetype to represent "float of any format" -def fAny : ValueType<0, 252>; +def fAny : ValueType<0, 251>; // Pseudo valuetype to represent "integer of any bit width" -def iAny : ValueType<0, 253>; +def iAny : ValueType<0, 252>; + +// Pseudo valuetype to represent "any reference type" +def rAny : ValueType<0, 253>; // Pseudo valuetype mapped to the current pointer size. def iPTR : ValueType<0, 254>; diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -92,9 +92,9 @@ /// it. /// /// The Tys parameter is for intrinsics with overloaded types (e.g., those - /// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded - /// intrinsic, Tys must provide exactly one type for each overloaded type in - /// the intrinsic. + /// using rAny, iAny, fAny, vAny, or iPTRAny). For a declaration of an + /// overloaded intrinsic, Tys must provide exactly one type for each + /// overloaded type in the intrinsic. Function *getDeclaration(Module *M, ID id, ArrayRef Tys = None); /// Looks up Name in NameTable via binary search. NameTable must be sorted @@ -159,6 +159,7 @@ AK_AnyFloat, AK_AnyVector, AK_AnyPointer, + AK_AnyRef, AK_MatchType = 7 }; diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -235,6 +235,7 @@ def llvm_anyint_ty : LLVMType; def llvm_anyfloat_ty : LLVMType; def llvm_anyvector_ty : LLVMType; + def llvm_anyref_ty : LLVMType; } def llvm_i1_ty : LLVMType; def llvm_i8_ty : LLVMType; @@ -331,6 +332,9 @@ def llvm_vararg_ty : LLVMType; // this means vararg here +def llvm_externref_ty : LLVMType; +def llvm_funcref_ty : LLVMType; + //===----------------------------------------------------------------------===// // Intrinsic Definitions. //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/Type.h b/llvm/include/llvm/IR/Type.h --- a/llvm/include/llvm/IR/Type.h +++ b/llvm/include/llvm/IR/Type.h @@ -77,6 +77,21 @@ ScalableVectorTyID ///< Scalable SIMD vector type }; + enum WasmAddressSpace : unsigned { + // Default address space, for pointers to linear memory (stack, heap, data). + WASM_ADDRESS_SPACE_DEFAULT = 0, + // A non-integral address space for pointers to named objects outside of + // linear memory: WebAssembly globals or 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_VAR = 1, + // A non-integral address space for externref values + WASM_ADDRESS_SPACE_EXTERNREF = 10, + // A non-integral address space for funcref values + WASM_ADDRESS_SPACE_FUNCREF = 20, + }; + private: /// This refers to the LLVMContext in which this type was uniqued. LLVMContext &Context; @@ -311,6 +326,22 @@ return const_cast(this); } + bool isWasmFuncrefType() const { + return isa(this) && + getPointerAddressSpace() == + WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF; + } + + bool isWasmExternrefType() const { + return isa(this) && + getPointerAddressSpace() == + WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF; + } + + bool isWasmRefType() const { + return isWasmFuncrefType() || isWasmExternrefType(); + } + //===--------------------------------------------------------------------===// // Type Iteration support. // diff --git a/llvm/include/llvm/Support/MachineValueType.h b/llvm/include/llvm/Support/MachineValueType.h --- a/llvm/include/llvm/Support/MachineValueType.h +++ b/llvm/include/llvm/Support/MachineValueType.h @@ -269,6 +269,10 @@ funcref = 175, // WebAssembly's funcref type externref = 176, // WebAssembly's externref type + + FIRST_REFTYPE_VALUETYPE = funcref, + LAST_REFTYPE_VALUETYPE = externref, + x86amx = 177, // This is an X86 AMX value i64x8 = 178, // 8 Consecutive GPRs (AArch64) @@ -280,32 +284,35 @@ // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors // This value must be a multiple of 32. MAX_ALLOWED_VALUETYPE = 192, - + // A value of type llvm::TokenTy - token = 248, + token = 247, // This is MDNode or MDString. - Metadata = 249, + Metadata = 248, // An int value the size of the pointer of the current // target to any address space. This must only be used internal to // tblgen. Other than for overloading, we treat iPTRAny the same as iPTR. - iPTRAny = 250, + iPTRAny = 249, // A vector with any length and element size. This is used // for intrinsics that have overloadings based on vector types. // This is only for tblgen's consumption! - vAny = 251, + vAny = 250, // Any floating-point or vector floating-point value. This is used // for intrinsics that have overloadings based on floating-point types. // This is only for tblgen's consumption! - fAny = 252, + fAny = 251, // An integer or vector integer value of any bit width. This is // used for intrinsics that have overloadings based on integer bit widths. // This is only for tblgen's consumption! - iAny = 253, + iAny = 252, + + // Any Wasm reference type + rAny = 253, // An int value the size of the pointer of the current // target. This should only be used internal to tblgen! @@ -451,7 +458,7 @@ bool isOverloaded() const { return (SimpleTy == MVT::Any || SimpleTy == MVT::iAny || SimpleTy == MVT::fAny || SimpleTy == MVT::vAny || - SimpleTy == MVT::iPTRAny); + SimpleTy == MVT::iPTRAny || SimpleTy == MVT::rAny); } /// Return a vector with the same number of elements as this vector, but @@ -870,6 +877,7 @@ case fAny: case vAny: case Any: + case rAny: llvm_unreachable("Value type is overloaded."); case token: llvm_unreachable("Token type is a sentinel that cannot be used " @@ -1409,6 +1417,12 @@ force_iteration_on_noniterable_enum); } + static auto ref_valuetypes() { + return enum_seq_inclusive(MVT::FIRST_REFTYPE_VALUETYPE, + MVT::LAST_REFTYPE_VALUETYPE, + force_iteration_on_noniterable_enum); + } + static auto integer_valuetypes() { return enum_seq_inclusive(MVT::FIRST_INTEGER_VALUETYPE, MVT::LAST_INTEGER_VALUETYPE, diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1491,6 +1491,8 @@ case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy(); case IITDescriptor::AK_AnyVector: return !isa(Ty); case IITDescriptor::AK_AnyPointer: return !isa(Ty); + case IITDescriptor::AK_AnyRef: + return !Ty->isWasmRefType(); default: break; } llvm_unreachable("all argument kinds not covered"); diff --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h --- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h +++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyUtilities.h @@ -16,6 +16,7 @@ #define LLVM_LIB_TARGET_WEBASSEMBLY_UTILS_WEBASSEMBLYUTILITIES_H #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" namespace llvm { @@ -30,42 +31,15 @@ namespace WebAssembly { -enum WasmAddressSpace : unsigned { - // Default address space, for pointers to linear memory (stack, heap, data). - WASM_ADDRESS_SPACE_DEFAULT = 0, - // A non-integral address space for pointers to named objects outside of - // linear memory: WebAssembly globals or 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_VAR = 1, - // A non-integral address space for externref values - WASM_ADDRESS_SPACE_EXTERNREF = 10, - // A non-integral address space for funcref values - WASM_ADDRESS_SPACE_FUNCREF = 20, -}; - inline bool isDefaultAddressSpace(unsigned AS) { - return AS == WASM_ADDRESS_SPACE_DEFAULT; + return AS == Type::WASM_ADDRESS_SPACE_DEFAULT; } inline bool isWasmVarAddressSpace(unsigned AS) { - return AS == WASM_ADDRESS_SPACE_VAR; + return AS == Type::WASM_ADDRESS_SPACE_VAR; } inline bool isValidAddressSpace(unsigned AS) { return isDefaultAddressSpace(AS) || isWasmVarAddressSpace(AS); } -inline bool isFuncrefType(const Type *Ty) { - return isa(Ty) && - Ty->getPointerAddressSpace() == - WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF; -} -inline bool isExternrefType(const Type *Ty) { - return isa(Ty) && - Ty->getPointerAddressSpace() == - WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF; -} -inline bool isRefType(const Type *Ty) { - return isFuncrefType(Ty) || isExternrefType(Ty); -} bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI); bool mayThrow(const MachineInstr &MI); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsWebAssembly.h" +#include "llvm/IR/Type.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" @@ -347,18 +348,18 @@ MVT WebAssemblyTargetLowering::getPointerTy(const DataLayout &DL, uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) + if (AS == Type::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) return MVT::externref; - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) + if (AS == Type::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) return MVT::funcref; return TargetLowering::getPointerTy(DL, AS); } MVT WebAssemblyTargetLowering::getPointerMemTy(const DataLayout &DL, uint32_t AS) const { - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) + if (AS == Type::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF) return MVT::externref; - if (AS == WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) + if (AS == Type::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF) return MVT::funcref; return TargetLowering::getPointerMemTy(DL, AS); } @@ -1173,8 +1174,7 @@ // Lastly, if this is a call to a funcref we need to add an instruction // table.set to the chain and transform the call. - if (CLI.CB && - WebAssembly::isFuncrefType(CLI.CB->getCalledOperand()->getType())) { + if (CLI.CB && CLI.CB->getCalledOperand()->getType()->isWasmFuncrefType()) { // In the absence of function references proposal where a funcref call is // lowered to call_ref, using reference types we generate a table.set to set // the funcref to a special table used solely for this purpose, followed by @@ -1192,8 +1192,7 @@ WebAssemblyISD::TABLE_SET, DL, DAG.getVTList(MVT::Other), TableSetOps, MVT::funcref, // Machine Mem Operand args - MachinePointerInfo( - WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF), + MachinePointerInfo(Type::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF), CLI.CB->getCalledOperand()->getPointerAlignment(DAG.getDataLayout()), MachineMemOperand::MOStore); @@ -1441,7 +1440,7 @@ const GlobalValue *Value = GA->getGlobal(); const Type *Ty = Value->getValueType(); - if (Ty->isArrayTy() && WebAssembly::isRefType(Ty->getArrayElementType())) + if (Ty->isArrayTy() && Ty->getArrayElementType()->isWasmRefType()) return true; } return false; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerRefTypesIntPtrConv.cpp @@ -62,8 +62,8 @@ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { PtrToIntInst *PTI = dyn_cast(&*I); IntToPtrInst *ITP = dyn_cast(&*I); - if (!(PTI && WebAssembly::isRefType(PTI->getPointerOperand()->getType())) && - !(ITP && WebAssembly::isRefType(ITP->getDestTy()))) + if (!(PTI && PTI->getPointerOperand()->getType()->isWasmRefType()) && + !(ITP && ITP->getDestTy()->isWasmRefType())) continue; UndefValue *U = UndefValue::get(I->getType()); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -22,6 +22,7 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Type.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" @@ -67,13 +68,13 @@ // that is a reference type. wasm::ValType Type; if (GlobalVT->isArrayTy() && - WebAssembly::isRefType(GlobalVT->getArrayElementType())) { + GlobalVT->getArrayElementType()->isWasmRefType()) { MVT VT; switch (GlobalVT->getArrayElementType()->getPointerAddressSpace()) { - case WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF: + case Type::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF: VT = MVT::funcref; break; - case WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF: + case Type::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF: VT = MVT::externref; break; default: diff --git a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp --- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -834,6 +834,11 @@ if (Legal.count(T)) Out.insert(T); return; + case MVT::rAny: + for (MVT T : MVT::ref_valuetypes()) + if (Legal.count(T)) + Out.insert(T); + return; case MVT::Any: for (MVT T : MVT::all_valuetypes()) if (Legal.count(T)) diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -68,6 +68,8 @@ case MVT::iAny: return "MVT::iAny"; case MVT::fAny: return "MVT::fAny"; case MVT::vAny: return "MVT::vAny"; + case MVT::rAny: + return "MVT::rAny"; case MVT::f16: return "MVT::f16"; case MVT::bf16: return "MVT::bf16"; case MVT::f32: return "MVT::f32"; diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -338,9 +338,16 @@ MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); + // Note: The order in which these cases show up need + // to match the inverse order of the respective ArgKind in + // Intrinsics.h. The value of Tmp when it reaches MVT::Any needs + // to be the value of the respective ArgKind enum. unsigned Tmp = 0; switch (VT) { default: break; + case MVT::rAny: + ++Tmp; + LLVM_FALLTHROUGH; case MVT::iPTRAny: ++Tmp; LLVM_FALLTHROUGH; case MVT::vAny: ++Tmp; LLVM_FALLTHROUGH; case MVT::fAny: ++Tmp; LLVM_FALLTHROUGH; @@ -412,12 +419,19 @@ return; } + // Note: The order in which these cases show up need + // to match the inverse order of the respective ArgKind in + // Intrinsics.h. The value of Tmp when it reaches MVT::Any needs + // to be the value of the respective ArgKind enum. unsigned Tmp = 0; switch (getValueType(R->getValueAsDef("VT"))) { default: break; case MVT::iPTR: UpdateArgCodes(R->getValueAsDef("ElTy"), ArgCodes, NumInserted, Mapping); break; + case MVT::rAny: + ++Tmp; + LLVM_FALLTHROUGH; case MVT::iPTRAny: ++Tmp; LLVM_FALLTHROUGH;