pmatos updated this revision to Diff 432876. pmatos added a comment. Rebased the work on D126535 <https://reviews.llvm.org/D126535>. Added support for funcrefs as return values. Still having problems with funcrefs as function arguments though. So, further work is required. Not ready for review.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D122215/new/ https://reviews.llvm.org/D122215 Files: clang/include/clang/AST/ASTContext.h clang/include/clang/AST/Type.h clang/include/clang/AST/TypeProperties.td clang/include/clang/Basic/AddressSpaces.h clang/include/clang/Basic/Attr.td clang/include/clang/Basic/Builtins.def clang/include/clang/Basic/BuiltinsWebAssembly.def clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/WebAssemblyReferenceTypes.def clang/include/clang/Sema/Sema.h clang/include/clang/Serialization/ASTBitCodes.h clang/include/clang/module.modulemap clang/lib/AST/ASTContext.cpp clang/lib/AST/ASTImporter.cpp clang/lib/AST/ExprConstant.cpp clang/lib/AST/ItaniumMangle.cpp clang/lib/AST/MicrosoftMangle.cpp clang/lib/AST/NSAPI.cpp clang/lib/AST/PrintfFormatString.cpp clang/lib/AST/Type.cpp clang/lib/AST/TypeLoc.cpp clang/lib/AST/TypePrinter.cpp clang/lib/Basic/Targets/DirectX.h clang/lib/Basic/Targets/NVPTX.h clang/lib/Basic/Targets/SPIR.h clang/lib/Basic/Targets/TCE.h clang/lib/Basic/Targets/X86.h clang/lib/CodeGen/CGBuiltin.cpp clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/CGExprScalar.cpp clang/lib/CodeGen/CodeGenModule.cpp clang/lib/CodeGen/CodeGenTypes.cpp clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/CodeGen/TargetInfo.cpp clang/lib/CodeGen/TargetInfo.h clang/lib/Index/USRGeneration.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaType.cpp clang/lib/Serialization/ASTCommon.cpp clang/lib/Serialization/ASTReader.cpp clang/test/CodeGen/WebAssembly/wasm-externref.c clang/test/CodeGen/WebAssembly/wasm-funcref.c clang/test/CodeGen/builtins-wasm.c clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp clang/tools/libclang/CIndex.cpp llvm/include/llvm/IR/Type.h llvm/lib/CodeGen/ValueTypes.cpp llvm/lib/IR/Type.cpp llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -404,11 +404,17 @@ } //===----------------------------------------------------------------------===// -// The following functions are called from lib/CodeGen/Passes.cpp to modify -// the CodeGen pass sequence. +// The following functions are called from lib/CodeGen/TargetPassConfig.cpp +// to modify the CodeGen pass sequence. //===----------------------------------------------------------------------===// void WebAssemblyPassConfig::addIRPasses() { + // Run mem2reg to remove alloca references - needed for reference types + // FIXME: this should only be added when the subtarget has reference types + // enabled but the subtarget is dependent on the function being compiled to + // which we don't have access atm. + addPass(createPromoteMemoryToRegisterPass()); + // Add signatures to prototype-less function declarations addPass(createWebAssemblyAddMissingPrototypes()); Index: llvm/lib/IR/Type.cpp =================================================================== --- llvm/lib/IR/Type.cpp +++ llvm/lib/IR/Type.cpp @@ -304,6 +304,18 @@ return getInt64Ty(C)->getPointerTo(AS); } +Type *Type::getWasm_ExternrefTy(LLVMContext &C) { + // pointer to opaque struct in addrspace(10) + static PointerType *Ty = PointerType::get(StructType::get(C), 10); + return Ty; +} + +Type *Type::getWasm_FuncrefTy(LLVMContext &C) { + // pointer to i8 addrspace(20) + static PointerType *Ty = PointerType::get(Type::getInt8Ty(C), 20); + return Ty; +} + //===----------------------------------------------------------------------===// // IntegerType Implementation //===----------------------------------------------------------------------===// Index: llvm/lib/CodeGen/ValueTypes.cpp =================================================================== --- llvm/lib/CodeGen/ValueTypes.cpp +++ llvm/lib/CodeGen/ValueTypes.cpp @@ -201,12 +201,8 @@ case MVT::x86mmx: return Type::getX86_MMXTy(Context); case MVT::x86amx: return Type::getX86_AMXTy(Context); case MVT::i64x8: return IntegerType::get(Context, 512); - case MVT::externref: - // pointer to opaque struct in addrspace(10) - return PointerType::get(StructType::create(Context), 10); - case MVT::funcref: - // pointer to i8 addrspace(20) - return PointerType::get(Type::getInt8Ty(Context), 20); + case MVT::externref: return Type::getWasm_ExternrefTy(Context); + case MVT::funcref: return Type::getWasm_FuncrefTy(Context); case MVT::v1i1: return FixedVectorType::get(Type::getInt1Ty(Context), 1); case MVT::v2i1: Index: llvm/include/llvm/IR/Type.h =================================================================== --- llvm/include/llvm/IR/Type.h +++ llvm/include/llvm/IR/Type.h @@ -468,6 +468,8 @@ static PointerType *getInt16PtrTy(LLVMContext &C, unsigned AS = 0); static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0); static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0); + static Type *getWasm_ExternrefTy(LLVMContext &C); + static Type *getWasm_FuncrefTy(LLVMContext &C); /// Return a pointer to the current type. This is equivalent to /// PointerType::get(Foo, AddrSpace). Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -1627,6 +1627,8 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define BUILTIN_TYPE(Id, SingletonId) #define SIGNED_TYPE(Id, SingletonId) case BuiltinType::Id: #define UNSIGNED_TYPE(Id, SingletonId) case BuiltinType::Id: Index: clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp @@ -0,0 +1,10 @@ +// REQUIRES: webassembly-registered-target +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -target-feature +reference-types -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -target-feature +reference-types -emit-llvm -o - -std=c++11 | FileCheck %s + +namespace std { class type_info; }; + +auto &externref = typeid(__externref_t); + +// CHECK-DAG: @_ZTS11externref_t = {{.*}} c"11externref_t\00" +// CHECK-DAG: @_ZTI11externref_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTS11externref_t Index: clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp @@ -0,0 +1,7 @@ +// REQUIRES: webassembly-registered-target +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -target-feature +reference-types -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -target-feature +reference-types -emit-llvm -o - -std=c++11 | FileCheck %s + +// CHECK: _Z2f111externref_t +void f1(__externref_t) {} + Index: clang/test/CodeGen/builtins-wasm.c =================================================================== --- clang/test/CodeGen/builtins-wasm.c +++ clang/test/CodeGen/builtins-wasm.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -no-opaque-pointers -triple wasm32-unknown-unknown -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32 -// RUN: %clang_cc1 -no-opaque-pointers -triple wasm64-unknown-unknown -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64 -// RUN: not %clang_cc1 -no-opaque-pointers -triple wasm64-unknown-unknown -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD +// RUN: %clang_cc1 -no-opaque-pointers -triple wasm32-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY32 +// RUN: %clang_cc1 -no-opaque-pointers -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +simd128 -target-feature +relaxed-simd -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s | FileCheck %s -check-prefixes WEBASSEMBLY,WEBASSEMBLY64 +// RUN: not %clang_cc1 -no-opaque-pointers -triple wasm64-unknown-unknown -target-feature +reference-types -target-feature +nontrapping-fptoint -target-feature +exception-handling -target-feature +bulk-memory -target-feature +atomics -flax-vector-conversions=none -O3 -emit-llvm -o - %s 2>&1 | FileCheck %s -check-prefixes MISSING-SIMD // SIMD convenience types typedef signed char i8x16 __attribute((vector_size(16))); @@ -777,3 +777,9 @@ // WEBASSEMBLY: call <4 x i32> @llvm.wasm.relaxed.trunc.unsigned.zero(<2 x double> %x) // WEBASSEMBLY-NEXT: ret } + +__externref_t externref_null() { + return __builtin_wasm_ref_null_extern(); + // WEBASSEMBLY: tail call {} addrspace(10)* @llvm.wasm.ref.null.extern() + // WEBASSEMBLY-NEXT: ret +} Index: clang/test/CodeGen/WebAssembly/wasm-funcref.c =================================================================== --- /dev/null +++ clang/test/CodeGen/WebAssembly/wasm-funcref.c @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -triple wasm32 -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s + +typedef void (*funcref_t)() __attribute__((__funcref)); + +funcref_t get_null() { +// CHECK: define i8 addrspace(20)* @get_null() #0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: %0 = call i8 addrspace(20)* @llvm.wasm.ref.null.func() +// CHECK-NEXT: ret i8 addrspace(20)* %0 +// CHECK-NEXT: } + return __builtin_wasm_ref_null_func(); +} + +void helper(funcref_t); + +void handle(funcref_t fn) { +// CHECK: define void @handle(i8 addrspace(20)* %fn) #0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: %fn.addr = alloca i8 addrspace(20)*, align 1 +// CHECK-NEXT: store i8 addrspace(20)* %fn, i8 addrspace(20)** %fn.addr, align 1 +// CHECK-NEXT: %0 = load i8 addrspace(20)*, i8 addrspace(20)** %fn.addr, align 1 +// CHECK-NEXT: call void @helper(i8 addrspace(20)* %0) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + helper(fn); +} + +typedef int (*fn_t)(int); +typedef fn_t __attribute__((__funcref)) fn_funcref_t; + +// What happens when we move a function pointer into a funcref and then call it? +fn_funcref_t get_ref(fn_t fnptr) { + return fnptr; +} + +int call_fn(fn_funcref_t ref, int x) { + return ref(x); +} Index: clang/test/CodeGen/WebAssembly/wasm-externref.c =================================================================== --- /dev/null +++ clang/test/CodeGen/WebAssembly/wasm-externref.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s + +typedef __externref_t externref_t; + +externref_t get_null() { +// CHECK: define {} addrspace(10)* @get_null() #0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: %0 = call {} addrspace(10)* @llvm.wasm.ref.null.extern() +// CHECK-NEXT: ret {} addrspace(10)* %0 +// CHECK-NEXT: } + return __builtin_wasm_ref_null_extern(); +} + +void helper(externref_t); + +void handle(externref_t obj) { +// CHECK: define void @handle({} addrspace(10)* %obj) #0 { +// CHECK-NEXT: entry: +// CHECK-NEXT: %obj.addr = alloca {} addrspace(10)*, align 1 +// CHECK-NEXT: store {} addrspace(10)* %obj, {} addrspace(10)** %obj.addr, align 1 +// CHECK-NEXT: %0 = load {} addrspace(10)*, {} addrspace(10)** %obj.addr, align 1 +// CHECK-NEXT: call void @helper({} addrspace(10)* %0) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + helper(obj); +} Index: clang/lib/Serialization/ASTReader.cpp =================================================================== --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -7103,6 +7103,11 @@ T = Context.SingletonId; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case PREDEF_TYPE_##Id##_ID: \ + T = Context.SingletonId; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } assert(!T.isNull() && "Unknown predefined type"); Index: clang/lib/Serialization/ASTCommon.cpp =================================================================== --- clang/lib/Serialization/ASTCommon.cpp +++ clang/lib/Serialization/ASTCommon.cpp @@ -250,6 +250,11 @@ ID = PREDEF_TYPE_##Id##_ID; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + ID = PREDEF_TYPE_##Id##_ID; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: ID = PREDEF_TYPE_BUILTIN_FN; break; Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -8059,6 +8059,27 @@ CurType, CurType); } +static void HandleWebAssemblyFuncrefAttr(TypeProcessingState &State, + QualType &CurType, + ParsedAttr &Attr) { + if (!CurType->isFunctionPointerType()) { + State.getSema().Diag(Attr.getLoc(), + diag::err_attribute_webassembly_funcref); + Attr.setInvalid(); + return; + } + + // Add attribute + CurType = + State.getAttributedType(createSimpleAttr<WebAssemblyFuncrefAttr>( + State.getSema().Context, Attr), + CurType, CurType); + + // Change address space to the funcref addrspace + Qualifiers Q = CurType.getQualifiers(); + Q.setAddressSpace(LangAS::wasm_funcref); +} + /// Handle OpenCL Access Qualifier Attribute. static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr, Sema &S) { @@ -8305,6 +8326,12 @@ attr.setUsedAsTypeAttr(); break; + case ParsedAttr::AT_WebAssemblyFuncref: { + HandleWebAssemblyFuncrefAttr(state, type, attr); + attr.setUsedAsTypeAttr(); + break; + } + MS_TYPE_ATTRS_CASELIST: if (!handleMSPointerTypeQualifierAttr(state, attr, type)) attr.setUsedAsTypeAttr(); Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -6326,6 +6326,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define PLACEHOLDER_TYPE(ID, SINGLETON_ID) #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: #include "clang/AST/BuiltinTypes.def" @@ -20591,6 +20594,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define BUILTIN_TYPE(Id, SingletonId) case BuiltinType::Id: #define PLACEHOLDER_TYPE(Id, SingletonId) #include "clang/AST/BuiltinTypes.def" Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -14278,7 +14278,10 @@ // OpenCL allows function arguments declared to be an array of a type // to be qualified with an address space. !(getLangOpts().OpenCL && - (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private))) { + (T->isArrayType() || T.getAddressSpace() == LangAS::opencl_private)) && + // WebAssembly allows reference types as parameters. Funcref in particular + // lives in a different address space + !T->isWebAssemblyFuncrefType()) { Diag(NameLoc, diag::err_arg_with_address_space); New->setInvalidDecl(); } Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -2643,7 +2643,14 @@ diag::err_hip_invalid_args_builtin_mangled_name); return ExprError(); } + break; } + + case WebAssembly::BI__builtin_wasm_ref_null_func: + if (SemaBuiltinWasmRefNullFunc(TheCall)) + return ExprError(); + break; + } // Since the target specific builtins for each arch overlap, only check those @@ -6502,6 +6509,20 @@ return false; } +bool +Sema::SemaBuiltinWasmRefNullFunc(CallExpr *TheCall) { + if (TheCall->getNumArgs() != 0) + return true; + + // Set return type to a function pointer with the funcref attribute attached + QualType FnType = Context.getFunctionType(Context.VoidTy, {}, {}); + QualType FnPtrType = Context.getPointerType(FnType); + + TheCall->setType(FnPtrType); + + return false; +} + /// We have a call to a function like __sync_fetch_and_add, which is an /// overloaded function based on the pointer type of its first argument. /// The main BuildCallExpr routines have already promoted the types of Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -455,6 +455,13 @@ #include "clang/Basic/RISCVVTypes.def" } + if (Context.getTargetInfo().getTriple().isWasm() && + Context.getTargetInfo().hasFeature("reference-types")) { +#define WASM_TYPE(Name, Id, SingletonId) \ + addImplicitTypedef(Name, Context.SingletonId); +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + if (Context.getTargetInfo().hasBuiltinMSVaList()) { DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list"); if (IdResolver.begin(MSVaList) == IdResolver.end()) Index: clang/lib/Index/USRGeneration.cpp =================================================================== --- clang/lib/Index/USRGeneration.cpp +++ clang/lib/Index/USRGeneration.cpp @@ -736,6 +736,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::ShortAccum: case BuiltinType::Accum: case BuiltinType::LongAccum: Index: clang/lib/CodeGen/TargetInfo.h =================================================================== --- clang/lib/CodeGen/TargetInfo.h +++ clang/lib/CodeGen/TargetInfo.h @@ -349,6 +349,15 @@ return nullptr; } + /// Return the WebAssembly externref reference type. + virtual llvm::Type *getWasmExternrefReferenceType() const { + return nullptr; + } + /// Return the WebAssembly funcref reference type. + virtual llvm::Type *getWasmFuncrefReferenceType() const { + return nullptr; + } + /// Emit the device-side copy of the builtin surface type. virtual bool emitCUDADeviceBuiltinSurfaceDeviceCopy(CodeGenFunction &CGF, LValue Dst, Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -884,6 +884,15 @@ Fn->addFnAttr("no-prototype"); } } + + /// Return the WebAssembly externref reference type. + virtual llvm::Type *getWasmExternrefReferenceType() const override { + return llvm::Type::getWasm_ExternrefTy(getABIInfo().getVMContext()); + } + /// Return the WebAssembly funcref reference type. + virtual llvm::Type *getWasmFuncrefReferenceType() const override { + return llvm::Type::getWasm_FuncrefTy(getABIInfo().getVMContext()); + } }; /// Classify argument of given type \p Ty. Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3257,6 +3257,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::ShortAccum: case BuiltinType::Accum: case BuiltinType::LongAccum: Index: clang/lib/CodeGen/CodeGenTypes.cpp =================================================================== --- clang/lib/CodeGen/CodeGenTypes.cpp +++ clang/lib/CodeGen/CodeGenTypes.cpp @@ -399,6 +399,7 @@ /// ConvertType - Convert the specified type to its LLVM form. llvm::Type *CodeGenTypes::ConvertType(QualType T) { + const bool isWebAssemblyFuncref = T.getTypePtr()->isWebAssemblyFuncrefType(); T = Context.getCanonicalType(T); const Type *Ty = T.getTypePtr(); @@ -417,6 +418,19 @@ } } + if (isWebAssemblyFuncref) { + // Copies what we do later for PointerType but takes Funcref attribute into + // consideration. We cannot this reach caching which doesn't take the + // funcref attribute into consideration. + const PointerType *PTy = cast<PointerType>(Ty); + QualType ETy = PTy->getPointeeType(); + llvm::Type *PointeeType = ConvertTypeForMem(ETy); + if (PointeeType->isVoidTy()) + PointeeType = llvm::Type::getInt8Ty(getLLVMContext()); + llvm::Type *FuncTy = llvm::PointerType::get(PointeeType, 20 /*FixMe hardcoded AS*/); + return FuncTy; + } + // RecordTypes are cached and processed specially. if (const RecordType *RT = dyn_cast<RecordType>(Ty)) return ConvertRecordDeclType(RT->getDecl()); @@ -633,6 +647,17 @@ Info.EC.getKnownMinValue() * Info.NumVectors); } +#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ + case BuiltinType::Id: \ + { \ + if (BuiltinType::Id == BuiltinType::WasmExternRef) \ + ResultType = CGM.getTargetCodeGenInfo() \ + .getWasmExternrefReferenceType(); \ + else \ + llvm_unreachable("Unexpected wasm reference builtin type!"); \ + } \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::Dependent: #define BUILTIN_TYPE(Id, SingletonId) #define PLACEHOLDER_TYPE(Id, SingletonId) \ Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -5113,6 +5113,15 @@ const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); llvm::FunctionType *Ty = getTypes().GetFunctionType(FI); + // If FI FunctionType is a WebAssembly funcref, + // then transform Ty so that it points to the funcref AS + if (D->getReturnType()->isWebAssemblyFuncrefType()) { + llvm::PointerType *PtrTy = dyn_cast<llvm::PointerType>(Ty->getReturnType()); + assert(PtrTy); + Ty = llvm::FunctionType::get(llvm::PointerType::getWithSamePointeeType(PtrTy, 20), + Ty->params(), Ty->isVarArg()); + } + // Get or create the prototype for the function. if (!GV || (GV->getValueType() != Ty)) GV = cast<llvm::GlobalValue>(GetAddrOfFunction(GD, Ty, /*ForVTable=*/false, Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -2036,6 +2036,17 @@ Value *Src = Visit(const_cast<Expr*>(E)); llvm::Type *SrcTy = Src->getType(); llvm::Type *DstTy = ConvertType(DestTy); + + // If the destination type is a WebAssembly Funcref then, we allow the + // types to have different address spaces and the one not in the + // funcref address space is converted at this point. + if (DestTy->isWebAssemblyFuncrefType()) { + llvm::PointerType *PtrTy = cast<llvm::PointerType>(DstTy); + // FIXME: hardcoded addrspace, should be + // llvm::WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF + DstTy = llvm::PointerType::getWithSamePointeeType(PtrTy, 20); + } + if (SrcTy->isPtrOrPtrVectorTy() && DstTy->isPtrOrPtrVectorTy() && SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace()) { llvm_unreachable("wrong cast for pointers in different address spaces" Index: clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- clang/lib/CodeGen/CGDebugInfo.h +++ clang/lib/CodeGen/CGDebugInfo.h @@ -80,6 +80,9 @@ #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ llvm::DIType *Id##Ty = nullptr; #include "clang/Basic/OpenCLExtensionTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + llvm::DIType *SingletonId = nullptr; +#include "clang/Basic/WebAssemblyReferenceTypes.def" /// Cache of previously constructed Types. llvm::DenseMap<const void *, llvm::TrackingMDRef> TypeCache; Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -798,6 +798,17 @@ return DBuilder.createVectorType(/*Size=*/0, Align, ElemTy, SubscriptArray); } + +#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ + case BuiltinType::Id: { \ + if (!SingletonId) \ + SingletonId = DBuilder.createForwardDecl( \ + llvm::dwarf::DW_TAG_structure_type, MangledName, TheCU, \ + TheCU->getFile(), 0); \ + return SingletonId; \ + } +#include "clang/Basic/WebAssemblyReferenceTypes.def" + case BuiltinType::UChar: case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -18343,6 +18343,14 @@ Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType())); return Builder.CreateCall(Callee, Value); } + case WebAssembly::BI__builtin_wasm_ref_null_extern: { + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_extern); + return Builder.CreateCall(Callee); + } + case WebAssembly::BI__builtin_wasm_ref_null_func: { + Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_ref_null_func); + return Builder.CreateCall(Callee); + } case WebAssembly::BI__builtin_wasm_swizzle_i8x16: { Value *Src = EmitScalarExpr(E->getArg(0)); Value *Indices = EmitScalarExpr(E->getArg(1)); @@ -18464,7 +18472,7 @@ IntNo = Intrinsic::wasm_extadd_pairwise_unsigned; break; default: - llvm_unreachable("unexptected builtin ID"); + llvm_unreachable("unexpected builtin ID"); } Function *Callee = CGM.getIntrinsic(IntNo, ConvertType(E->getType())); Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -42,7 +42,10 @@ 0, // sycl_private 270, // ptr32_sptr 271, // ptr32_uptr - 272 // ptr64 + 272, // ptr64 + 1, // wasm_var + 10, // wasm_externref, + 20, // wasm_funcref }; // X86 target abstract base class; x86-32 and x86-64 are very close, so Index: clang/lib/Basic/Targets/TCE.h =================================================================== --- clang/lib/Basic/Targets/TCE.h +++ clang/lib/Basic/Targets/TCE.h @@ -38,18 +38,21 @@ 1, // opencl_global_device 1, // opencl_global_host // FIXME: generic has to be added to the target - 0, // opencl_generic - 0, // cuda_device - 0, // cuda_constant - 0, // cuda_shared - 0, // sycl_global - 0, // sycl_global_device - 0, // sycl_global_host - 0, // sycl_local - 0, // sycl_private - 0, // ptr32_sptr - 0, // ptr32_uptr - 0, // ptr64 + 0, // opencl_generic + 0, // cuda_device + 0, // cuda_constant + 0, // cuda_shared + 0, // sycl_global + 0, // sycl_global_device + 0, // sycl_global_host + 0, // sycl_local + 0, // sycl_private + 0, // ptr32_sptr + 0, // ptr32_uptr + 0, // ptr64 + 1, // wasm_var + 10, // wasm_externref, + 20, // wasm_funcref }; class LLVM_LIBRARY_VISIBILITY TCETargetInfo : public TargetInfo { Index: clang/lib/Basic/Targets/SPIR.h =================================================================== --- clang/lib/Basic/Targets/SPIR.h +++ clang/lib/Basic/Targets/SPIR.h @@ -42,7 +42,10 @@ 0, // sycl_private 0, // ptr32_sptr 0, // ptr32_uptr - 0 // ptr64 + 0, // ptr64 + 1, // wasm_var + 10,// wasm_externref + 20,// wasm_funcref }; // Used by both the SPIR and SPIR-V targets. @@ -71,7 +74,10 @@ 0, // sycl_private 0, // ptr32_sptr 0, // ptr32_uptr - 0 // ptr64 + 0, // ptr64 + 1, // wasm_var + 10,// wasm_externref + 20,// wasm_funcref }; // Base class for SPIR and SPIR-V target info. Index: clang/lib/Basic/Targets/NVPTX.h =================================================================== --- clang/lib/Basic/Targets/NVPTX.h +++ clang/lib/Basic/Targets/NVPTX.h @@ -29,20 +29,23 @@ 4, // opencl_constant 0, // opencl_private // FIXME: generic has to be added to the target - 0, // opencl_generic - 1, // opencl_global_device - 1, // opencl_global_host - 1, // cuda_device - 4, // cuda_constant - 3, // cuda_shared - 1, // sycl_global - 1, // sycl_global_device - 1, // sycl_global_host - 3, // sycl_local - 0, // sycl_private - 0, // ptr32_sptr - 0, // ptr32_uptr - 0 // ptr64 + 0, // opencl_generic + 1, // opencl_global_device + 1, // opencl_global_host + 1, // cuda_device + 4, // cuda_constant + 3, // cuda_shared + 1, // sycl_global + 1, // sycl_global_device + 1, // sycl_global_host + 3, // sycl_local + 0, // sycl_private + 0, // ptr32_sptr + 0, // ptr32_uptr + 0, // ptr64 + 1, // wasm_var + 10, // wasm_externref, + 20, // wasm_funcref }; /// The DWARF address class. Taken from Index: clang/lib/Basic/Targets/DirectX.h =================================================================== --- clang/lib/Basic/Targets/DirectX.h +++ clang/lib/Basic/Targets/DirectX.h @@ -33,14 +33,17 @@ 0, // cuda_constant 0, // cuda_shared // SYCL address space values for this map are dummy - 0, // sycl_global - 0, // sycl_global_device - 0, // sycl_global_host - 0, // sycl_local - 0, // sycl_private - 0, // ptr32_sptr - 0, // ptr32_uptr - 0 // ptr64 + 0, // sycl_global + 0, // sycl_global_device + 0, // sycl_global_host + 0, // sycl_local + 0, // sycl_private + 0, // ptr32_sptr + 0, // ptr32_uptr + 0, // ptr64 + 1, // wasm_var + 10, // wasm_externref + 20, // wasm_funcref }; class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo { Index: clang/lib/AST/TypePrinter.cpp =================================================================== --- clang/lib/AST/TypePrinter.cpp +++ clang/lib/AST/TypePrinter.cpp @@ -1710,6 +1710,8 @@ // AttributedType nodes for them. break; + case attr::WebAssemblyFuncref: OS << "__funcref"; break; + case attr::LifetimeBound: case attr::TypeNonNull: case attr::TypeNullable: Index: clang/lib/AST/TypeLoc.cpp =================================================================== --- clang/lib/AST/TypeLoc.cpp +++ clang/lib/AST/TypeLoc.cpp @@ -418,6 +418,8 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: case BuiltinType::IncompleteMatrixIdx: case BuiltinType::OMPArraySection: Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -2311,6 +2311,10 @@ #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" return true; + // WebAssembly reference types +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" + return true; default: return false; } @@ -2318,6 +2322,18 @@ return false; } +bool Type::isWebAssemblyReferenceType() const { + return isWebAssemblyFuncrefType() || + isWebAssemblyExternrefType(); +} + +bool Type::isWebAssemblyExternrefType() const { + const BuiltinType *BT = getAs<BuiltinType>(); + if (BT && BT->getKind() == BuiltinType::WasmExternRef) + return true; + return false; +} + bool Type::isSizelessType() const { return isSizelessBuiltinType(); } bool Type::isVLSTBuiltinType() const { @@ -3143,6 +3159,10 @@ case Id: \ return Name; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case Id: \ + return Name; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } llvm_unreachable("Invalid builtin type."); @@ -4184,6 +4204,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: case BuiltinType::IncompleteMatrixIdx: Index: clang/lib/AST/PrintfFormatString.cpp =================================================================== --- clang/lib/AST/PrintfFormatString.cpp +++ clang/lib/AST/PrintfFormatString.cpp @@ -797,6 +797,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SIGNED_TYPE(Id, SingletonId) #define UNSIGNED_TYPE(Id, SingletonId) #define FLOATING_TYPE(Id, SingletonId) Index: clang/lib/AST/NSAPI.cpp =================================================================== --- clang/lib/AST/NSAPI.cpp +++ clang/lib/AST/NSAPI.cpp @@ -480,6 +480,8 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::BoundMember: case BuiltinType::Dependent: case BuiltinType::Overload: Index: clang/lib/AST/MicrosoftMangle.cpp =================================================================== --- clang/lib/AST/MicrosoftMangle.cpp +++ clang/lib/AST/MicrosoftMangle.cpp @@ -2472,6 +2472,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" case BuiltinType::ShortAccum: case BuiltinType::Accum: case BuiltinType::LongAccum: Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -3141,6 +3141,13 @@ Out << 'u' << type_name.size() << type_name; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_REF_TYPE(InternalName, MangledName, Id, SingletonId, AS) \ + case BuiltinType::Id: \ + type_name = MangledName; \ + Out << (type_name == InternalName ? "u" : "") << type_name.size() \ + << type_name; \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } } Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -11288,6 +11288,9 @@ #include "clang/Basic/PPCTypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" return GCCTypeClass::None; case BuiltinType::Dependent: Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -1099,6 +1099,10 @@ case BuiltinType::Id: \ return Importer.getToContext().SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + return Importer.getToContext().SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" #define SHARED_SINGLETON_TYPE(Expansion) #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: return Importer.getToContext().SingletonId; Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -948,7 +948,10 @@ 0, // sycl_private 10, // ptr32_sptr 11, // ptr32_uptr - 12 // ptr64 + 12, // ptr64 + 1, // wasm_var + 10, // wasm_externref, + 20, // wasm_funcref }; return &FakeAddrSpaceMap; } else { @@ -1460,6 +1463,13 @@ #include "clang/Basic/RISCVVTypes.def" } + if (Target.getTriple().isWasm() && + Target.hasFeature("reference-types")) { +#define WASM_TYPE(Name, Id, SingletonId) \ + InitBuiltinType(SingletonId, BuiltinType::Id); +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + // Builtin type for __objc_yes and __objc_no ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ? SignedCharTy : BoolTy); @@ -2235,6 +2245,12 @@ Align = 8; \ break; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + case BuiltinType::Id: \ + Width = 0; \ + Align = 8; /* ? */ \ + break; +#include "clang/Basic/WebAssemblyReferenceTypes.def" } break; case Type::ObjCObjectPointer: @@ -3939,6 +3955,26 @@ } } +/// getExternrefType - Return a WebAssembly externref type, which represents an +/// opaque reference to a host value. +QualType ASTContext::getExternrefType() const { + if (Target->hasFeature("reference-types")) { +#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ + if (BuiltinType::Id == BuiltinType::WasmExternRef) \ + return SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" + } + return QualType(); +} + +/// getFuncrefType - Return a WebAssembly funcref type, which represents an +/// opaque reference to a function. +QualType ASTContext::getFuncrefType() const { + // FIXME: this cannot be written because there's no single funcref type + // anymore + return QualType(); +} + /// getScalableVectorType - Return the unique reference to a scalable vector /// type of the specified element type and size. VectorType must be a built-in /// type. @@ -7840,6 +7876,8 @@ #include "clang/Basic/AArch64SVEACLETypes.def" #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/WebAssemblyReferenceTypes.def" { DiagnosticsEngine &Diags = C->getDiagnostics(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, @@ -11065,6 +11103,10 @@ Type = Context.getScalableVectorType(ElementType, NumElements); break; } + case 'e': { + Type = Context.getExternrefType(); + break; + } case 'V': { char *End; unsigned NumElements = strtoul(Str, &End, 10); Index: clang/include/clang/module.modulemap =================================================================== --- clang/include/clang/module.modulemap +++ clang/include/clang/module.modulemap @@ -72,6 +72,7 @@ textual header "Basic/Sanitizers.def" textual header "Basic/TargetCXXABI.def" textual header "Basic/TokenKinds.def" + textual header "Basic/WebAssemblyReferenceTypes.def" module * { export * } } Index: clang/include/clang/Serialization/ASTBitCodes.h =================================================================== --- clang/include/clang/Serialization/ASTBitCodes.h +++ clang/include/clang/Serialization/ASTBitCodes.h @@ -1093,6 +1093,9 @@ // \brief RISC-V V types with auto numeration #define RVV_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, #include "clang/Basic/RISCVVTypes.def" +// \brief WebAssembly reference types with auto numeration +#define WASM_TYPE(Name, Id, SingletonId) PREDEF_TYPE_##Id##_ID, +#include "clang/Basic/WebAssemblyReferenceTypes.def" }; /// The number of predefined type IDs that are reserved for Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -13001,6 +13001,9 @@ ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall, ExprResult CallResult); + // WebAssembly builtin handling + bool SemaBuiltinWasmRefNullFunc(CallExpr *TheCall); + public: enum FormatStringType { FST_Scanf, Index: clang/include/clang/Basic/WebAssemblyReferenceTypes.def =================================================================== --- /dev/null +++ clang/include/clang/Basic/WebAssemblyReferenceTypes.def @@ -0,0 +1,38 @@ +//===-- WebAssemblyReferenceTypes.def - Wasm reference types ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines externref_t, funcref_t, and the like. The macros are: +// +// WASM_TYPE(Name, Id, SingletonId) +// WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) +// +// where: +// +// - Name is the name of the builtin type. MangledName is the mangled name. +// +// - BuiltinType::Id is the enumerator defining the type. +// +// - Context.SingletonId is the global singleton of this type. +// +// - AS indicates the address space for values of this type. +// +// To include this file, define either WASM_REF_TYPE or WASM_TYPE, depending on +// how much information you want. The macros will be undefined after inclusion. +// +//===----------------------------------------------------------------------===// + + +#ifndef WASM_REF_TYPE +#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \ + WASM_TYPE(Name, Id, SingletonId) +#endif + +WASM_REF_TYPE("__externref_t", "externref_t", WasmExternRef, WasmExternRefTy, 10) + +#undef WASM_TYPE +#undef WASM_REF_TYPE Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7306,6 +7306,8 @@ "'__clang_arm_builtin_alias' attribute can only be applied to an ARM builtin">; def err_attribute_arm_mve_polymorphism : Error< "'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type">; +def err_attribute_webassembly_funcref : Error< + "'__clang_webassembly_funcref' attribute can only be applied to function pointer types">; def warn_setter_getter_impl_required : Warning< "property %0 requires method %1 to be defined - " Index: clang/include/clang/Basic/BuiltinsWebAssembly.def =================================================================== --- clang/include/clang/Basic/BuiltinsWebAssembly.def +++ clang/include/clang/Basic/BuiltinsWebAssembly.def @@ -184,5 +184,13 @@ TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_s_zero_i32x4_f64x2, "V4iV2d", "nc", "relaxed-simd") TARGET_BUILTIN(__builtin_wasm_relaxed_trunc_u_zero_i32x4_f64x2, "V4UiV2d", "nc", "relaxed-simd") +// Reference Types builtins +// Some builtins are polymorphic - see 't' as part of the third argument, +// in which case the argument spec (second argument) is unused. +TARGET_BUILTIN(__builtin_wasm_ref_null_extern, "e", "nc", "reference-types") +// A funcref represented as a function pointer with the funcref attribute +// attached to the type, therefore SemaChecking will check for the right +// return type. +TARGET_BUILTIN(__builtin_wasm_ref_null_func, "i", "nct", "reference-types") #undef BUILTIN #undef TARGET_BUILTIN Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -47,6 +47,7 @@ // SJ -> sigjmp_buf // K -> ucontext_t // p -> pid_t +// e -> wasm externref // . -> "...". This may only occur at the end of the function list. // // Types may be prefixed with the following modifiers: Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -4011,3 +4011,9 @@ let LangOpts = [COnly]; } def : MutualExclusions<[RandomizeLayout, NoRandomizeLayout]>; + +def WebAssemblyFuncref : TypeAttr, TargetSpecificAttr<TargetWebAssembly> { + let Spellings = [Clang<"__funcref">]; + let Args = []; + let Documentation = [Undocumented]; +} Index: clang/include/clang/Basic/AddressSpaces.h =================================================================== --- clang/include/clang/Basic/AddressSpaces.h +++ clang/include/clang/Basic/AddressSpaces.h @@ -56,6 +56,10 @@ ptr32_uptr, ptr64, + wasm_var, + wasm_externref, + wasm_funcref, + // This denotes the count of language-specific address spaces and also // the offset added to the target-specific address spaces, which are usually // specified by address space attributes __attribute__(address_space(n))). Index: clang/include/clang/AST/TypeProperties.td =================================================================== --- clang/include/clang/AST/TypeProperties.td +++ clang/include/clang/AST/TypeProperties.td @@ -799,6 +799,10 @@ case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(NAME, ID, SINGLETON_ID) \ + case BuiltinType::ID: return ctx.SINGLETON_ID; +#include "clang/Basic/WebAssemblyReferenceTypes.def" + #define BUILTIN_TYPE(ID, SINGLETON_ID) \ case BuiltinType::ID: return ctx.SINGLETON_ID; #include "clang/AST/BuiltinTypes.def" Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -1426,8 +1426,12 @@ return Quals.getObjCLifetime(); } - bool hasAddressSpace() const { return Quals.hasAddressSpace(); } - LangAS getAddressSpace() const { return Quals.getAddressSpace(); } + bool hasAddressSpace() const { + return Quals.hasAddressSpace(); + } + LangAS getAddressSpace() const { + return Quals.getAddressSpace(); + } const Type *getBaseType() const { return BaseType; } @@ -1909,6 +1913,11 @@ bool isSizelessType() const; bool isSizelessBuiltinType() const; + /// Check if this is a WebAssembly Reference Type. + bool isWebAssemblyReferenceType() const; + bool isWebAssemblyExternrefType() const; + bool isWebAssemblyFuncrefType() const; + /// Determines if this is a sizeless type supported by the /// 'arm_sve_vector_bits' type attribute, which can be applied to a single /// SVE vector or predicate, excluding tuple types such as svint32x4_t. @@ -2519,6 +2528,9 @@ // RVV Types #define RVV_TYPE(Name, Id, SingletonId) Id, #include "clang/Basic/RISCVVTypes.def" +// WebAssembly reference types +#define WASM_TYPE(Name, Id, SingletonId) Id, +#include "clang/Basic/WebAssemblyReferenceTypes.def" // All other builtin types #define BUILTIN_TYPE(Id, SingletonId) Id, #define LAST_BUILTIN_TYPE(Id) LastKind = Id @@ -6619,6 +6631,9 @@ /// Return the address space of this type. inline LangAS QualType::getAddressSpace() const { + if (getTypePtr()->isWebAssemblyFuncrefType()) { + return LangAS::wasm_funcref; + } return getQualifiers().getAddressSpace(); } @@ -6786,6 +6801,11 @@ return false; } +inline bool Type::isWebAssemblyFuncrefType() const { + return isFunctionPointerType() && + hasAttr(attr::WebAssemblyFuncref); +} + inline bool Type::isFunctionReferenceType() const { if (const auto *T = getAs<ReferenceType>()) return T->getPointeeType()->isFunctionType(); Index: clang/include/clang/AST/ASTContext.h =================================================================== --- clang/include/clang/AST/ASTContext.h +++ clang/include/clang/AST/ASTContext.h @@ -1145,6 +1145,9 @@ #define RVV_TYPE(Name, Id, SingletonId) \ CanQualType SingletonId; #include "clang/Basic/RISCVVTypes.def" +#define WASM_TYPE(Name, Id, SingletonId) \ + CanQualType SingletonId; +#include "clang/Basic/WebAssemblyReferenceTypes.def" // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. mutable QualType AutoDeductTy; // Deduction against 'auto'. @@ -1490,6 +1493,12 @@ /// \pre \p EltTy must be a built-in type. QualType getScalableVectorType(QualType EltTy, unsigned NumElts) const; + /// Return a WebAssembly externref type + QualType getExternrefType() const; + + /// Return a WebAssembly funcref type + QualType getFuncrefType() const; + /// Return the unique reference to a vector type of the specified /// element type and size. ///
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits