pmatos updated this revision to Diff 461159.
pmatos added a comment.
Addressed some of the concerns from the comments but not ready for review yet.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D128440/new/
https://reviews.llvm.org/D128440
Files:
clang/include/clang/AST/Type.h
clang/include/clang/Basic/AddressSpaces.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/BuiltinsWebAssembly.def
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Type.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/WebAssembly.h
clang/lib/Basic/Targets/X86.h
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/lib/CodeGen/TargetInfo.h
clang/lib/Format/FormatToken.h
clang/lib/Parse/ParseDecl.cpp
clang/lib/Parse/ParseTentative.cpp
clang/lib/Sema/SemaChecking.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaType.cpp
clang/test/CodeGen/WebAssembly/wasm-funcref.c
clang/test/SemaTemplate/address_space-dependent.cpp
Index: clang/test/SemaTemplate/address_space-dependent.cpp
===================================================================
--- clang/test/SemaTemplate/address_space-dependent.cpp
+++ clang/test/SemaTemplate/address_space-dependent.cpp
@@ -43,7 +43,7 @@
template <long int I>
void tooBig() {
- __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388586)}}
+ __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388585)}}
}
template <long int I>
@@ -101,7 +101,7 @@
car<1, 2, 3>(); // expected-note {{in instantiation of function template specialization 'car<1, 2, 3>' requested here}}
HasASTemplateFields<1> HASTF;
neg<-1>(); // expected-note {{in instantiation of function template specialization 'neg<-1>' requested here}}
- correct<0x7FFFEA>();
+ correct<0x7FFFE9>();
tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650L>' requested here}}
__attribute__((address_space(1))) char *x;
Index: clang/test/CodeGen/WebAssembly/wasm-funcref.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/WebAssembly/wasm-funcref.c
@@ -0,0 +1,84 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple wasm32 -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s
+
+typedef void (*__funcref funcref_t)();
+typedef int (*__funcref fn_funcref_t)(int);
+typedef int (*fn_t)(int);
+
+// Null funcref builtin call
+// CHECK-LABEL: @get_null(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call ptr addrspace(20) @llvm.wasm.ref.null.func()
+// CHECK-NEXT: ret ptr addrspace(20) [[TMP0]]
+//
+funcref_t get_null() {
+ return __builtin_wasm_ref_null_func();
+}
+
+// Call to null funcref builtin but requires cast since
+// default return value for builtin is a funcref with function type () -> ().
+// CHECK-LABEL: @get_null_ii(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = call ptr addrspace(20) @llvm.wasm.ref.null.func()
+// CHECK-NEXT: ret ptr addrspace(20) [[TMP0]]
+//
+fn_funcref_t get_null_ii() {
+ return (fn_funcref_t) __builtin_wasm_ref_null_func();
+}
+
+// Identity function for funcref.
+// CHECK-LABEL: @identity(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4
+// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr [[FN_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[FN_ADDR]], align 4
+// CHECK-NEXT: ret ptr addrspace(20) [[TMP0]]
+//
+funcref_t identity(funcref_t fn) {
+ return fn;
+}
+
+void helper(funcref_t);
+
+// Pass funcref ref as an argument to a helper function.
+// CHECK-LABEL: @handle(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[FN_ADDR:%.*]] = alloca ptr addrspace(20), align 4
+// CHECK-NEXT: store ptr addrspace(20) [[FN:%.*]], ptr [[FN_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[FN_ADDR]], align 4
+// CHECK-NEXT: call void @helper(ptr addrspace(20) noundef [[TMP0]])
+// CHECK-NEXT: ret i32 0
+//
+int handle(funcref_t fn) {
+ helper(fn);
+ return 0;
+}
+
+// Return funcref from function pointer.
+// CHECK-LABEL: @get_ref(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[FNPTR_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT: store ptr [[FNPTR:%.*]], ptr [[FNPTR_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[FNPTR_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = addrspacecast ptr [[TMP0]] to ptr addrspace(20)
+// CHECK-NEXT: ret ptr addrspace(20) [[TMP1]]
+//
+fn_funcref_t get_ref(fn_t fnptr) {
+ return (fn_funcref_t) fnptr;
+}
+
+// Call funcref
+// CHECK-LABEL: @call_fn(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[REF_ADDR:%.*]] = alloca ptr addrspace(20), align 4
+// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store ptr addrspace(20) [[REF:%.*]], ptr [[REF_ADDR]], align 4
+// CHECK-NEXT: store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[TMP0:%.*]] = load ptr addrspace(20), ptr [[REF_ADDR]], align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT: [[CALL:%.*]] = call addrspace(20) i32 [[TMP0]](i32 noundef [[TMP1]])
+// CHECK-NEXT: ret i32 [[CALL]]
+//
+int call_fn(fn_funcref_t ref, int x) {
+ return ref(x);
+}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -7261,6 +7261,55 @@
return false;
}
+static bool HandleWebAssemblyFuncrefAttr(TypeProcessingState &State,
+ QualType &Type, ParsedAttr &PAttr) {
+ assert(PAttr.getKind() == ParsedAttr::AT_WebAssemblyFuncref);
+
+ Sema &S = State.getSema();
+ Attr *A = createSimpleAttr<WebAssemblyFuncrefAttr>(S.Context, PAttr);
+
+ std::bitset<attr::LastAttr> Attrs;
+ attr::Kind NewAttrKind = A->getKind();
+ QualType Desugared = Type;
+ const auto *AT = dyn_cast<AttributedType>(Type);
+ while (AT) {
+ Attrs[AT->getAttrKind()] = true;
+ Desugared = AT->getModifiedType();
+ AT = dyn_cast<AttributedType>(Desugared);
+ }
+
+ // You cannot specify duplicate type attributes, so if the attribute has
+ // already been applied, flag it.
+ if (Attrs[NewAttrKind]) {
+ S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
+ return true;
+ }
+ Attrs[NewAttrKind] = true;
+
+ // Pointer type qualifiers can only operate on pointer types, but not
+ // pointer-to-member types.
+ //
+ // FIXME: Should we really be disallowing this attribute if there is any
+ // type sugar between it and the pointer (other than attributes)? Eg, this
+ // disallows the attribute on a parenthesized pointer.
+ // And if so, should we really allow *any* type attribute?
+ if (!isa<PointerType>(Desugared)) {
+ if (Type->isMemberPointerType())
+ S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
+ else
+ S.Diag(PAttr.getLoc(), diag::err_attribute_pointers_only) << PAttr << 0;
+ return true;
+ }
+
+ // Add address space to type based on its attributes.
+ LangAS ASIdx = LangAS::wasm_funcref;
+ QualType Pointee = Type->getPointeeType();
+ Pointee = S.Context.getAddrSpaceQualType(
+ S.Context.removeAddrSpaceQualType(Pointee), ASIdx);
+ Type = State.getAttributedType(A, Type, S.Context.getPointerType(Pointee));
+ return false;
+}
+
/// Map a nullability attribute kind to a nullability kind.
static NullabilityKind mapNullabilityAttrKind(ParsedAttr::Kind kind) {
switch (kind) {
@@ -8417,6 +8466,12 @@
attr.setUsedAsTypeAttr();
break;
+ case ParsedAttr::AT_WebAssemblyFuncref: {
+ if (!HandleWebAssemblyFuncrefAttr(state, type, attr))
+ attr.setUsedAsTypeAttr();
+ break;
+ }
+
MS_TYPE_ATTRS_CASELIST:
if (!handleMSPointerTypeQualifierAttr(state, attr, type))
attr.setUsedAsTypeAttr();
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14518,7 +14518,11 @@
// 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->isFunctionPointerType() &&
+ T.getAddressSpace() == LangAS::wasm_funcref)) {
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
@@ -4530,6 +4530,8 @@
switch(BuiltinID) {
case WebAssembly::BI__builtin_wasm_ref_null_extern:
return SemaBuiltinWasmRefNullExtern(TheCall);
+ case WebAssembly::BI__builtin_wasm_ref_null_func:
+ return BuiltinWasmRefNullFunc(TheCall);
}
return false;
@@ -6561,6 +6563,32 @@
return false;
}
+bool Sema::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
+ if (TheCall->getNumArgs() != 0)
+ return true;
+
+ // The call we get looks like
+ // CallExpr
+ // `- ImplicitCastExpr
+ // `- DeclRefExpr
+ //
+ // Therefore we need to change the types of the DeclRefExpr (stored in FDecl)
+ // and regenerate a straight up CallExpr on the modified FDecl.
+ // returning
+ // CallExpr
+ // `- FunctionDecl
+
+ // Prepare FDecl type
+ QualType Pointee = Context.getFunctionType(Context.VoidTy, {}, {});
+ QualType Type = Context.getPointerType(Pointee);
+ Pointee = Context.getAddrSpaceQualType(Pointee, LangAS::wasm_funcref);
+ Type = Context.getAttributedType(attr::WebAssemblyFuncref, Type,
+ Context.getPointerType(Pointee));
+ TheCall->setType(Type);
+
+ 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/Parse/ParseTentative.cpp
===================================================================
--- clang/lib/Parse/ParseTentative.cpp
+++ clang/lib/Parse/ParseTentative.cpp
@@ -1445,6 +1445,10 @@
case tok::kw___kindof:
return TPResult::True;
+ // WebAssemblyFuncref
+ case tok::kw___funcref:
+ return TPResult::True;
+
// Borland
case tok::kw___pascal:
return TPResult::True;
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -842,6 +842,15 @@
}
}
+void Parser::ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &attrs) {
+ if (Tok.is(tok::kw___funcref)) {
+ IdentifierInfo *AttrName = Tok.getIdentifierInfo();
+ SourceLocation AttrNameLoc = ConsumeToken();
+ attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
+ ParsedAttr::AS_Keyword);
+ }
+}
+
void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() {
SourceLocation StartLoc = Tok.getLocation();
SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes();
@@ -3735,6 +3744,10 @@
ParseMicrosoftTypeAttributes(DS.getAttributes());
continue;
+ case tok::kw___funcref:
+ ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());
+ continue;
+
// Borland single token adornments.
case tok::kw___pascal:
ParseBorlandTypeAttributes(DS.getAttributes());
@@ -5281,6 +5294,8 @@
case tok::kw___read_only:
case tok::kw___read_write:
case tok::kw___write_only:
+
+ case tok::kw___funcref:
return true;
case tok::kw_private:
@@ -5516,6 +5531,7 @@
#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
#include "clang/Basic/OpenCLImageTypes.def"
+ case tok::kw___funcref:
return true;
case tok::kw_private:
@@ -5767,6 +5783,14 @@
continue;
}
goto DoneWithTypeQuals;
+
+ case tok::kw___funcref:
+ if (AttrReqs & AR_DeclspecAttributesParsed) {
+ ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());
+ continue;
+ }
+ goto DoneWithTypeQuals;
+
case tok::kw___pascal:
if (AttrReqs & AR_VendorAttributesParsed) {
ParseBorlandTypeAttributes(DS.getAttributes());
Index: clang/lib/Format/FormatToken.h
===================================================================
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -596,7 +596,7 @@
return isOneOf(tok::kw_const, tok::kw_restrict, tok::kw_volatile,
tok::kw___attribute, tok::kw__Nonnull, tok::kw__Nullable,
tok::kw__Null_unspecified, tok::kw___ptr32, tok::kw___ptr64,
- TT_AttributeMacro);
+ tok::kw___funcref, TT_AttributeMacro);
}
/// Determine whether the token is a simple-type-specifier.
Index: clang/lib/CodeGen/TargetInfo.h
===================================================================
--- clang/lib/CodeGen/TargetInfo.h
+++ clang/lib/CodeGen/TargetInfo.h
@@ -364,7 +364,9 @@
/// 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
@@ -896,6 +896,10 @@
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/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -18533,6 +18533,10 @@
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));
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -46,6 +46,7 @@
272, // ptr64
// Wasm address space values for this map are dummy
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/WebAssembly.h
===================================================================
--- clang/lib/Basic/Targets/WebAssembly.h
+++ clang/lib/Basic/Targets/WebAssembly.h
@@ -21,6 +21,30 @@
namespace clang {
namespace targets {
+static const unsigned WebAssemblyAddrSpaceMap[] = {
+ 0, // Default
+ 0, // opencl_global
+ 0, // opencl_local
+ 0, // opencl_constant
+ 0, // opencl_private
+ 0, // opencl_generic
+ 0, // opencl_global_device
+ 0, // opencl_global_host
+ 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
+ 10, // wasm_externref,
+ 20, // wasm_funcref
+};
+
class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
static const Builtin::Info BuiltinInfo[];
@@ -46,6 +70,7 @@
public:
explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)
: TargetInfo(T) {
+ AddrSpaceMap = &WebAssemblyAddrSpaceMap;
NoAsmVariants = true;
SuitableAlign = 128;
LargeArrayMinWidth = 128;
Index: clang/lib/Basic/Targets/TCE.h
===================================================================
--- clang/lib/Basic/Targets/TCE.h
+++ clang/lib/Basic/Targets/TCE.h
@@ -52,6 +52,7 @@
0, // ptr64
// Wasm address space values for this map are dummy
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
@@ -45,6 +45,7 @@
0, // ptr64
// Wasm address space values for this map are dummy
10,// wasm_externref
+ 20,// wasm_funcref
};
// Used by both the SPIR and SPIR-V targets.
@@ -76,6 +77,7 @@
0, // ptr64
// Wasm address space values for this map are dummy
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
@@ -45,6 +45,7 @@
0, // ptr64
// Wasm address space values for this map are dummy
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
@@ -43,6 +43,7 @@
0, // ptr64
// Wasm address space values for this map are dummy
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
@@ -1640,6 +1640,11 @@
spaceBeforePlaceHolder(OS);
}
+ if (T->isWebAssemblyFuncrefSpec()) {
+ assert(T->getAttrKind() == attr::WebAssemblyFuncref);
+ OS << "__funcref";
+ }
+
// Print nullability type specifiers.
if (T->getImmediateNullability()) {
if (T->getAttrKind() == attr::TypeNonNull)
@@ -1673,8 +1678,8 @@
// Some attributes are printed as qualifiers before the type, so we have
// nothing left to do.
- if (T->getAttrKind() == attr::ObjCKindOf ||
- T->isMSTypeSpec() || T->getImmediateNullability())
+ if (T->getAttrKind() == attr::ObjCKindOf || T->isMSTypeSpec() ||
+ T->getImmediateNullability() || T->isWebAssemblyFuncrefSpec())
return;
// Don't print the inert __unsafe_unretained attribute at all.
@@ -1745,6 +1750,7 @@
case attr::AddressSpace:
case attr::CmseNSCall:
case attr::AnnotateType:
+ case attr::WebAssemblyFuncref:
llvm_unreachable("This attribute should have been handled already");
case attr::NSReturnsRetained:
@@ -2220,6 +2226,8 @@
return "__uptr __ptr32";
case LangAS::ptr64:
return "__ptr64";
+ case LangAS::wasm_funcref:
+ return "__funcref";
default:
return std::to_string(toTargetAddressSpace(AS));
}
Index: clang/lib/AST/Type.cpp
===================================================================
--- clang/lib/AST/Type.cpp
+++ clang/lib/AST/Type.cpp
@@ -3632,6 +3632,10 @@
llvm_unreachable("invalid attr kind");
}
+bool AttributedType::isWebAssemblyFuncrefSpec() const {
+ return getAttrKind() == attr::WebAssemblyFuncref;
+}
+
bool AttributedType::isCallingConv() const {
// FIXME: Generate this with TableGen.
switch (getAttrKind()) {
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -954,6 +954,7 @@
12, // ptr64
// Wasm address space values for this map are dummy
10, // wasm_externref,
+ 20, // wasm_funcref
};
return &FakeAddrSpaceMap;
} else {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -13199,8 +13199,9 @@
ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
ExprResult CallResult);
- // WebAssembly builtin handling
+ // WebAssembly builtin handling.
bool SemaBuiltinWasmRefNullExtern(CallExpr *TheCall);
+ bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
public:
enum FormatStringType {
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2841,6 +2841,7 @@
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs);
void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs);
+ void ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &Attrs);
void DiagnoseAndSkipExtendedMicrosoftTypeAttributes();
SourceLocation SkipExtendedMicrosoftTypeAttributes();
void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs);
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -664,6 +664,9 @@
KEYWORD(_Nullable_result , KEYALL)
KEYWORD(_Null_unspecified , KEYALL)
+// WebAssembly Type Extension
+KEYWORD(__funcref , KEYALL)
+
// Microsoft extensions which should be disabled in strict conformance mode
KEYWORD(__ptr64 , KEYMS)
KEYWORD(__ptr32 , KEYMS)
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7338,6 +7338,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<
+ "'__funcref' attribute can only be applied to a function pointer type">;
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
@@ -191,8 +191,15 @@
TARGET_BUILTIN(__builtin_wasm_relaxed_dot_bf16x8_add_f32_f32x4, "V4fV8UsV8UsV4f", "nc", "relaxed-simd")
// Reference Types builtins
+// Some builtins are custom type-checked - 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, "i", "nct", "reference-types")
+TARGET_BUILTIN(__builtin_wasm_ref_null_extern, "e", "nct", "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/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -6688,3 +6688,12 @@
As such, this function attribute is currently only supported on X86 targets.
}];
}
+
+def WebAssemblyFuncrefDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+Clang supports the ``__funcref`` attribute for the WebAssembly target.
+This attribute may be attached to a function pointer declaration, where it modifies
+its underlying representation to be a WebAssembly ``funcref``.
+ }];
+}
\ No newline at end of file
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -4093,3 +4093,9 @@
let Subjects = SubjectList<[Function]>;
let Documentation = [FunctionReturnThunksDocs];
}
+
+def WebAssemblyFuncref : TypeAttr, TargetSpecificAttr<TargetWebAssembly> {
+ let Spellings = [Keyword<"__funcref">];
+ let Documentation = [WebAssemblyExportNameDocs];
+ let Subjects = SubjectList<[TypedefName], ErrorDiag>;
+}
Index: clang/include/clang/Basic/AddressSpaces.h
===================================================================
--- clang/include/clang/Basic/AddressSpaces.h
+++ clang/include/clang/Basic/AddressSpaces.h
@@ -57,6 +57,8 @@
ptr64,
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/Type.h
===================================================================
--- clang/include/clang/AST/Type.h
+++ clang/include/clang/AST/Type.h
@@ -4815,6 +4815,8 @@
bool isMSTypeSpec() const;
+ bool isWebAssemblyFuncrefSpec() const;
+
bool isCallingConv() const;
llvm::Optional<NullabilityKind> getImmediateNullability() const;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits