pmatos updated this revision to Diff 445490.
pmatos added a comment.

Updated patch over current main. Fixed all failint tests. 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/Builtins.def
  clang/include/clang/Basic/BuiltinsWebAssembly.def
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/WebAssemblyReferenceTypes.def
  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/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/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/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/builtins-wasm.c
  clang/test/CodeGenCXX/wasm-reftypes-mangle.cpp
  clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp
  clang/test/Sema/wasm-refs-and-tables.c
  clang/test/SemaCXX/wasm-refs-and-tables.cpp
  clang/test/SemaTemplate/address_space-dependent.cpp
  clang/tools/libclang/CIndex.cpp
  llvm/include/llvm/IR/Type.h
  llvm/lib/CodeGen/ValueTypes.cpp
  llvm/lib/IR/Type.cpp

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) {
+  // opaque pointer in addrspace(10)
+  static PointerType *Ty = PointerType::get(C, 10);
+  return Ty;
+}
+
+Type *Type::getWasm_FuncrefTy(LLVMContext &C) {
+  // opaque pointer in addrspace(20)
+  static PointerType *Ty = PointerType::get(C, 20);
+  return Ty;
+}
+
 //===----------------------------------------------------------------------===//
 //                       IntegerType Implementation
 //===----------------------------------------------------------------------===//
Index: llvm/lib/CodeGen/ValueTypes.cpp
===================================================================
--- llvm/lib/CodeGen/ValueTypes.cpp
+++ llvm/lib/CodeGen/ValueTypes.cpp
@@ -204,12 +204,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/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 (8388588)}}
+  __attribute__((address_space(I))) int *bounds; // expected-error {{address space is larger than the maximum supported (8388586)}}
 }
 
 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<0x7FFFEB>();
+  correct<0x7FFFEA>();
   tooBig<8388650>(); // expected-note {{in instantiation of function template specialization 'tooBig<8388650L>' requested here}}
 
   __attribute__((address_space(1))) char *x;
Index: clang/test/SemaCXX/wasm-refs-and-tables.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/wasm-refs-and-tables.cpp
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -std=gnu++11 -triple wasm32 -Wno-unused-value -target-feature +reference-types %s
+
+// This file tests C++ specific constructs with WebAssembly references and
+// tables. See wasm-refs-and-tables.c for C constructs.
+
+__externref_t ref;
+__externref_t &ref_ref1 = ref; // expected-error {{references to WebAssembly reference types are illegal}}
+__externref_t &ref_ref2(ref);  // expected-error {{references to WebAssembly reference types are illegal}}
+
+static __externref_t table[0];                    // expected-error {{array has sizeless element type '__externref_t'}}
+static __externref_t (&ref_to_table1)[0] = table; // expected-error {{array has sizeless element type '__externref_t'}}
+static __externref_t (&ref_to_table2)[0](table);  // expected-error {{array has sizeless element type '__externref_t'}}
+
+void illegal_argument_1(__externref_t &r); // expected-error {{references to WebAssembly reference types are illegal}}
+void illegal_argument_2(__externref_t (&t)[0]); // expected-error {{array has sizeless element type '__externref_t'}}
+
+__externref_t &illegal_return_1(); // expected-error {{references to WebAssembly reference types are illegal}}
+__externref_t (&illegal_return_2())[0]; // expected-error {{array has sizeless element type '__externref_t'}}
+
+void illegal_throw1() throw(__externref_t);   // expected-error {{sizeless type '__externref_t' is not allowed in exception specification}}
+void illegal_throw2() throw(__externref_t *); // expected-error {{pointers to WebAssembly reference types are illegal}}
+void illegal_throw3() throw(__externref_t &); // expected-error {{references to WebAssembly reference types are illegal}}
+void illegal_throw4() throw(__externref_t[0]); // expected-error {{array has sizeless element type '__externref_t'}}
+
+class RefClass {
+  __externref_t f1;       // expected-error {{field has sizeless type '__externref_t'}}
+  __externref_t f2[0];    // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f3[];     // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t *f5;      // expected-error {{pointers to WebAssembly reference types are illegal}}
+  __externref_t ****f6;   // expected-error {{pointers to WebAssembly reference types are illegal}}
+  __externref_t (*f7)[0]; // expected-error {{array has sizeless element type '__externref_t'}}
+};
+
+struct AStruct {};
+
+template <typename T>
+struct TemplatedStruct {
+  T f; // expected-error {{field has sizeless type '__externref_t'}}
+  void foo(T);
+  T bar(void);
+  T arr[0]; // expected-error {{array has sizeless element type '__externref_t'}}
+  T *ptr;   // expected-error {{pointers to WebAssembly reference types are illegal}}
+};
+
+void func() {
+  int foo = 40;
+  static_cast<__externref_t>(foo);      // expected-error {{static_cast from 'int' to '__externref_t' is not allowed}}
+  static_cast<__externref_t *>(&foo);   // expected-error {{pointers to WebAssembly reference types are illegal}}
+  static_cast<int>(ref);                // expected-error {{static_cast from '__externref_t' to 'int' is not allowed}}
+  __externref_t(10);                    // expected-error {{functional-style cast from 'int' to '__externref_t' is not allowed}}
+  int i(ref);                           // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type '__externref_t'}}
+  const_cast<__externref_t[0]>(table);  // expected-error {{array has sizeless element type '__externref_t'}}
+  const_cast<__externref_t *>(table);   // expected-error {{pointers to WebAssembly reference types are illegal}}
+  reinterpret_cast<__externref_t>(foo); // expected-error {{reinterpret_cast from 'int' to '__externref_t' is not allowed}}
+  reinterpret_cast<int>(ref);           // expected-error {{reinterpret_cast from '__externref_t' to 'int' is not allowed}}
+  int iarr[0];
+  reinterpret_cast<__externref_t[0]>(iarr); // expected-error {{array has sizeless element type '__externref_t'}}
+  reinterpret_cast<__externref_t *>(iarr);  // expected-error {{pointers to WebAssembly reference types are illegal}}
+  dynamic_cast<__externref_t>(foo);         // expected-error {{invalid target type '__externref_t' for dynamic_cast; target type must be a reference or pointer type to a defined class}}
+  dynamic_cast<__externref_t *>(&foo);      // expected-error {{pointers to WebAssembly reference types are illegal}}
+
+  TemplatedStruct<__externref_t> ts1;    // expected-note {{in instantiation}}
+  TemplatedStruct<__externref_t *> ts2;  // expected-error {{pointers to WebAssembly reference types are illegal}}
+  TemplatedStruct<__externref_t &> ts3;  // expected-error {{references to WebAssembly reference types are illegal}}
+  TemplatedStruct<__externref_t[0]> ts4; // expected-error {{array has sizeless element type '__externref_t'}}
+
+  auto auto_ref = ref;
+
+  auto fn1 = [](__externref_t x) { return x; };
+  auto fn2 = [](__externref_t *x) { return x; };   // expected-error {{pointers to WebAssembly reference types are illegal}}
+  auto fn3 = [](__externref_t &x) { return x; };   // expected-error {{references to WebAssembly reference types are illegal}}
+  auto fn4 = [](__externref_t x[0]) { return x; }; // expected-error {{array has sizeless element type '__externref_t'}}
+  auto fn5 = [&auto_ref](void) { return true; };   // expected-error {{cannot capture WebAssembly reference}}
+  auto fn6 = [auto_ref](void) { return true; };    // expected-error {{cannot capture WebAssembly reference}}
+  auto fn7 = [&](void) { auto_ref; return true; };                        // expected-error {{cannot capture WebAssembly reference}}
+  auto fn8 = [=](void) { auto_ref; return true; };                        // expected-error {{cannot capture WebAssembly reference}}
+
+  alignof(__externref_t);    // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}}
+  alignof(ref);              // expected-warning {{'alignof' applied to an expression is a GNU extension}} expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}}
+  alignof(__externref_t[0]); // expected-error {{array has sizeless element type '__externref_t'}}
+
+  throw ref;  // expected-error {{cannot throw object of sizeless type '__externref_t'}}
+  throw &ref; // expected-error {{cannot take address of WebAssembly reference}}
+
+  try {
+  } catch (__externref_t) { // expected-error {{cannot catch sizeless type '__externref_t'}}
+  }
+  try {
+  } catch (__externref_t *) { // expected-error {{pointers to WebAssembly reference types are illegal}}
+  }
+  try {
+  } catch (__externref_t &) { // expected-error {{references to WebAssembly reference types are illegal}}
+  }
+  try {
+  } catch (__externref_t[0]) { // expected-error {{array has sizeless element type '__externref_t'}}
+  }
+
+  new __externref_t;    // expected-error {{allocation of sizeless type '__externref_t'}}
+  new __externref_t[0]; // expected-error {{allocation of sizeless type '__externref_t'}}
+
+  delete ref;     // expected-error {{cannot delete expression of type '__externref_t'}}
+}
Index: clang/test/Sema/wasm-refs-and-tables.c
===================================================================
--- /dev/null
+++ clang/test/Sema/wasm-refs-and-tables.c
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple wasm32 -target-feature +reference-types %s
+
+// Note: As WebAssembly references are sizeless types, we don't exhaustively
+// test for cases covered by sizeless-1.c and similar tests.
+
+// Unlike standard sizeless types, reftype globals are supported.
+__externref_t r1;
+extern __externref_t r2;
+static __externref_t r3;
+
+__externref_t *t1;               // expected-error {{pointers to WebAssembly reference types are illegal}}
+__externref_t **t2;              // expected-error {{pointers to WebAssembly reference types are illegal}}
+__externref_t ******t3;          // expected-error {{pointers to WebAssembly reference types are illegal}}
+static __externref_t t4[3];      // expected-error {{array has sizeless element type '__externref_t'}}
+static __externref_t t5[];       // expected-error {{array has sizeless element type '__externref_t'}}
+static __externref_t t6[] = {0}; // expected-error {{array has sizeless element type '__externref_t'}}
+__externref_t t7[0];             // expected-error {{array has sizeless element type '__externref_t'}}
+static __externref_t t8[0][0];   // expected-error {{array has sizeless element type '__externref_t'}}
+
+static __externref_t table[0]; // expected-error {{array has sizeless element type '__externref_t'}}
+
+struct s {
+  __externref_t f1;       // expected-error {{field has sizeless type '__externref_t'}}
+  __externref_t f2[0];    // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f3[];     // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t *f5;      // expected-error {{pointers to WebAssembly reference types are illegal}}
+  __externref_t ****f6;   // expected-error {{pointers to WebAssembly reference types are illegal}}
+};
+
+union u {
+  __externref_t f1;       // expected-error {{field has sizeless type '__externref_t'}}
+  __externref_t f2[0];    // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f3[];     // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}}
+  __externref_t *f5;      // expected-error {{pointers to WebAssembly reference types are illegal}}
+  __externref_t ****f6;   // expected-error {{pointers to WebAssembly reference types are illegal}}
+};
+
+void illegal_argument_1(__externref_t table[]);     // expected-error {{array has sizeless element type '__externref_t'}}
+void illegal_argument_2(__externref_t table[0][0]); // expected-error {{array has sizeless element type '__externref_t'}}
+void illegal_argument_3(__externref_t *table);      // expected-error {{pointers to WebAssembly reference types are illegal}}
+void illegal_argument_4(__externref_t ***table);    // expected-error {{pointers to WebAssembly reference types are illegal}}
+
+__externref_t *illegal_return_1();   // expected-error {{pointers to WebAssembly reference types are illegal}}
+__externref_t ***illegal_return_2(); // expected-error {{pointers to WebAssembly reference types are illegal}}
+
+void varargs(int, ...);
+
+__externref_t func(__externref_t ref) {
+  &ref; // expected-error {{cannot take address of WebAssembly reference}}
+  int foo = 40;
+  (__externref_t *)(&foo);     // expected-error {{pointers to WebAssembly reference types are illegal}}
+  (__externref_t ****)(&foo);  // expected-error {{pointers to WebAssembly reference types are illegal}}
+  sizeof(ref);                 // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}}
+  sizeof(__externref_t);       // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}}
+  sizeof(__externref_t[0]);    // expected-error {{array has sizeless element type '__externref_t'}}
+  sizeof(__externref_t[0][0]); // expected-error {{array has sizeless element type '__externref_t'}}
+  sizeof(__externref_t *);     // expected-error {{pointers to WebAssembly reference types are illegal}}
+  sizeof(__externref_t ***);   // expected-error {{pointers to WebAssembly reference types are illegal}};
+  // expected-warning@+1 {{'_Alignof' applied to an expression is a GNU extension}}
+  _Alignof(ref);                 // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}}
+  _Alignof(__externref_t);       // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}}
+  _Alignof(__externref_t[]);     // expected-error {{array has sizeless element type '__externref_t'}}
+  _Alignof(__externref_t[0][0]); // expected-error {{array has sizeless element type '__externref_t'}}
+  _Alignof(__externref_t *);     // expected-error {{pointers to WebAssembly reference types are illegal}}
+  _Alignof(__externref_t ***);   // expected-error {{pointers to WebAssembly reference types are illegal}};
+  varargs(1, ref);               // expected-error {{cannot pass expression of type '__externref_t' to variadic function}}
+
+  return ref;
+}
Index: clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/wasm-reftypes-typeinfo.cpp
@@ -0,0 +1,12 @@
+// 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,6 @@
+// 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 -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 -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 -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 -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 -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 -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)));
@@ -794,3 +794,9 @@
   // WEBASSEMBLY-SAME: <16 x i8> %a, <16 x i8> %b, <4 x i32> %c)
   // WEBASSEMBLY-NEXT: ret
 }
+
+__externref_t externref_null() {
+  return __builtin_wasm_ref_null_extern();
+  // WEBASSEMBLY: tail call ptr addrspace(10) @llvm.wasm.ref.null.extern()
+  // WEBASSEMBLY-NEXT: ret
+}
Index: clang/test/CodeGen/WebAssembly/wasm-externref.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/WebAssembly/wasm-externref.c
@@ -0,0 +1,27 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s
+
+typedef __externref_t externref_t;
+
+// CHECK-LABEL: @get_null(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call ptr addrspace(10) @llvm.wasm.ref.null.extern()
+// CHECK-NEXT:    ret ptr addrspace(10) [[TMP0]]
+//
+externref_t get_null() {
+  return __builtin_wasm_ref_null_extern();
+}
+
+void helper(externref_t);
+
+// CHECK-LABEL: @handle(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[OBJ_ADDR:%.*]] = alloca ptr addrspace(10), align 1
+// CHECK-NEXT:    store ptr addrspace(10) [[OBJ:%.*]], ptr [[OBJ_ADDR]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr addrspace(10), ptr [[OBJ_ADDR]], align 1
+// CHECK-NEXT:    call void @helper(ptr addrspace(10) [[TMP0]])
+// CHECK-NEXT:    ret void
+//
+void handle(externref_t obj) {
+  helper(obj);
+}
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -7105,6 +7105,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
@@ -2175,6 +2175,14 @@
   if (getLangOpts().OpenCL)
     T = deduceOpenCLPointeeAddrSpace(*this, T);
 
+  // In WebAssembly, pointers to reference types are illegal.
+  if (getASTContext().getTargetInfo().getTriple().isWasm()) {
+    if (T->isWebAssemblyReferenceType()) {
+      Diag(Loc, diag::err_wasm_reference_pointer);
+      return QualType();
+    }
+  }
+
   // Build the pointer type.
   return Context.getPointerType(T);
 }
@@ -2250,6 +2258,14 @@
   if (getLangOpts().OpenCL)
     T = deduceOpenCLPointeeAddrSpace(*this, T);
 
+  // In WebAssembly, references to reference types are illegal.
+  if (getASTContext().getTargetInfo().getTriple().isWasm()) {
+    if (T->isWebAssemblyReferenceType()) {
+      Diag(Loc, diag::err_wasm_reference_reference);
+      return QualType();
+    }
+  }
+
   // Handle restrict on references.
   if (LValueRef)
     return Context.getLValueReferenceType(T, SpelledAsLValue);
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -936,6 +936,11 @@
   if (Ty.isDestructedType() == QualType::DK_nontrivial_c_struct)
     return VAK_Invalid;
 
+  if (Context.getTargetInfo().getTriple().isWasm() &&
+      Ty->isWebAssemblyReferenceType()) {
+    return VAK_Invalid;
+  }
+
   if (Ty.isCXX98PODType(Context))
     return VAK_Valid;
 
@@ -6327,6 +6332,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 PLACEHOLDER_TYPE(ID, SINGLETON_ID)
 #define BUILTIN_TYPE(ID, SINGLETON_ID) case BuiltinType::ID:
 #include "clang/AST/BuiltinTypes.def"
@@ -14453,6 +14460,13 @@
   if (op->getType()->isObjCObjectType())
     return Context.getObjCObjectPointerType(op->getType());
 
+  if (Context.getTargetInfo().getTriple().isWasm() &&
+      op->getType()->isWebAssemblyReferenceType()) {
+    Diag(OpLoc, diag::err_wasm_addrof_reference)
+        << OrigOp.get()->getSourceRange();
+    return QualType();
+  }
+
   CheckAddressOfPackedMember(op);
 
   return Context.getPointerType(op->getType());
@@ -18508,6 +18522,12 @@
     ByRef = (LSI->ImpCaptureStyle == LambdaScopeInfo::ImpCap_LambdaByref);
   }
 
+  if (BuildAndDiagnose && S.Context.getTargetInfo().getTriple().isWasm() &&
+      CaptureType.getNonReferenceType()->isWebAssemblyReferenceType()) {
+    S.Diag(Loc, diag::err_wasm_capture_reference);
+    Invalid = true;
+  }
+
   // Compute the type of the field that will capture this variable.
   if (ByRef) {
     // C++11 [expr.prim.lambda]p15:
@@ -20705,6 +20725,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) 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
@@ -8466,7 +8466,8 @@
     return;
   }
 
-  if (!NewVD->hasLocalStorage() && T->isSizelessType()) {
+  if (!NewVD->hasLocalStorage() && T->isSizelessType() &&
+      !T->isWebAssemblyReferenceType()) {
     Diag(NewVD->getLocation(), diag::err_sizeless_nonlocal) << T;
     NewVD->setInvalidDecl();
     return;
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -442,6 +442,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,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::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,8 @@
     return nullptr;
   }
 
+  /// Return the WebAssembly externref reference type.
+  virtual llvm::Type *getWasmExternrefReferenceType() 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
@@ -889,6 +889,11 @@
         Fn->addFnAttr("no-prototype");
     }
   }
+
+  /// Return the WebAssembly externref reference type.
+  virtual llvm::Type *getWasmExternrefReferenceType() const override {
+    return llvm::Type::getWasm_ExternrefTy(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
@@ -3259,6 +3259,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::ShortAccum:
     case BuiltinType::Accum:
     case BuiltinType::LongAccum:
Index: clang/lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.cpp
+++ clang/lib/CodeGen/CodeGenTypes.cpp
@@ -633,7 +633,15 @@
                                            Info.EC.getKnownMinValue() *
                                            Info.NumVectors);
     }
-   case BuiltinType::Dependent:
+#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) \
     case BuiltinType::Id:
Index: clang/lib/CodeGen/CGDebugInfo.h
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.h
+++ clang/lib/CodeGen/CGDebugInfo.h
@@ -80,6 +80,8 @@
 #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
@@ -18473,6 +18473,10 @@
     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_swizzle_i8x16: {
     Value *Src = EmitScalarExpr(E->getArg(0));
     Value *Indices = EmitScalarExpr(E->getArg(1));
@@ -18594,7 +18598,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
@@ -43,7 +43,9 @@
     0,   // sycl_private
     270, // ptr32_sptr
     271, // ptr32_uptr
-    272  // ptr64
+    272, // ptr64
+    1,   // wasm_var
+    10,  // wasm_externref,
 };
 
 // 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,20 @@
     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
 };
 
 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
@@ -35,14 +35,16 @@
     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
 };
 
 // Used by both the SPIR and SPIR-V targets.
@@ -62,16 +64,18 @@
     // cuda_constant pointer can be casted to default/"flat" pointer, but in
     // SPIR-V casts between constant and generic pointers are not allowed. For
     // this reason cuda_constant is mapped to SPIR-V CrossWorkgroup.
-    1, // cuda_constant
-    3, // cuda_shared
-    1, // sycl_global
-    5, // sycl_global_device
-    6, // sycl_global_host
-    3, // sycl_local
-    0, // sycl_private
-    0, // ptr32_sptr
-    0, // ptr32_uptr
-    0  // ptr64
+    1,  // cuda_constant
+    3,  // cuda_shared
+    1,  // sycl_global
+    5,  // sycl_global_device
+    6,  // sycl_global_host
+    3,  // sycl_local
+    0,  // sycl_private
+    0,  // ptr32_sptr
+    0,  // ptr32_uptr
+    0,  // ptr64
+    1,  // wasm_var
+    10, // wasm_externref
 };
 
 // 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,22 @@
     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
 };
 
 /// 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,16 @@
     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
 };
 
 class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo {
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,17 @@
   return false;
 }
 
+bool Type::isWebAssemblyReferenceType() const {
+  return 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 +3158,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.");
@@ -4190,6 +4209,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::NullPtr:
     case BuiltinType::IncompleteMatrixIdx:
Index: clang/lib/AST/PrintfFormatString.cpp
===================================================================
--- clang/lib/AST/PrintfFormatString.cpp
+++ clang/lib/AST/PrintfFormatString.cpp
@@ -797,6 +797,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 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
@@ -2477,6 +2477,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::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
@@ -11283,6 +11283,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"
       return GCCTypeClass::None;
 
     case BuiltinType::Dependent:
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1098,6 +1098,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,9 @@
         0,  // sycl_private
         10, // ptr32_sptr
         11, // ptr32_uptr
-        12  // ptr64
+        12, // ptr64
+        1,  // wasm_var
+        10, // wasm_externref,
     };
     return &FakeAddrSpaceMap;
   } else {
@@ -1460,6 +1462,12 @@
 #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);
@@ -2244,6 +2252,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:
@@ -3964,6 +3978,18 @@
   }
 }
 
+/// 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();
+}
+
 /// getScalableVectorType - Return the unique reference to a scalable vector
 /// type of the specified element type and size. VectorType must be a built-in
 /// type.
@@ -7925,6 +7951,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,
@@ -11150,6 +11178,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/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
@@ -11678,4 +11678,14 @@
   "a randomized struct can only be initialized with a designated initializer">;
 def err_cast_from_randomized_struct : Error<
   "casting from randomized structure pointer type %0 to %1">;
+
+// WebAssembly reference type and table diagnostics
+def err_wasm_reference_pointer : Error<
+  "pointers to WebAssembly reference types are illegal">;
+def err_wasm_reference_reference : Error<
+  "references to WebAssembly reference types are illegal">;
+def err_wasm_capture_reference : Error<
+  "cannot capture WebAssembly reference">;
+def err_wasm_addrof_reference : Error<
+  "cannot take address of WebAssembly reference">;
 } // end of sema component.
Index: clang/include/clang/Basic/BuiltinsWebAssembly.def
===================================================================
--- clang/include/clang/Basic/BuiltinsWebAssembly.def
+++ clang/include/clang/Basic/BuiltinsWebAssembly.def
@@ -189,5 +189,9 @@
 TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_s_i16x8, "V8sV16ScV16Sc", "nc", "relaxed-simd")
 TARGET_BUILTIN(__builtin_wasm_dot_i8x16_i7x16_add_s_i32x4, "V4iV16ScV16ScV4i", "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")
 #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/AddressSpaces.h
===================================================================
--- clang/include/clang/Basic/AddressSpaces.h
+++ clang/include/clang/Basic/AddressSpaces.h
@@ -56,6 +56,8 @@
   ptr32_uptr,
   ptr64,
 
+  wasm_var,
+  wasm_externref,
   // 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
@@ -1968,6 +1968,9 @@
   bool isSizelessType() const;
   bool isSizelessBuiltinType() const;
 
+  /// Check if this is a WebAssembly Reference Type.
+  bool isWebAssemblyReferenceType() const;
+  bool isWebAssemblyExternrefType() 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.
@@ -2578,6 +2581,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
Index: clang/include/clang/AST/ASTContext.h
===================================================================
--- clang/include/clang/AST/ASTContext.h
+++ clang/include/clang/AST/ASTContext.h
@@ -1146,6 +1146,8 @@
 #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'.
@@ -1491,6 +1493,9 @@
   /// \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 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

Reply via email to