[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    [PATCH] D66035: [WebAssembly] WIP: Add support for reference types
From:       Valentin Churavy via Phabricator via cfe-commits <cfe-commits () lists ! llvm ! org>
Date:       2019-11-30 23:02:05
Message-ID: 90cb8ac9e4d9268ac4a1e4ccb3024975 () localhost ! localdomain
[Download RAW message or body]

vchuravy updated this revision to Diff 231601.
vchuravy added a comment.

- fix AS in anyref testfile


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66035/new/

https://reviews.llvm.org/D66035

Files:
  clang/lib/Basic/Targets/WebAssembly.h
  lld/wasm/WriterUtils.cpp
  llvm/include/llvm/BinaryFormat/Wasm.h
  llvm/include/llvm/BinaryFormat/WasmRelocs.def
  llvm/include/llvm/CodeGen/TargetLowering.h
  llvm/include/llvm/CodeGen/ValueTypes.td
  llvm/include/llvm/MC/MCExpr.h
  llvm/include/llvm/MC/MCSymbolWasm.h
  llvm/include/llvm/Object/Wasm.h
  llvm/include/llvm/Support/MachineValueType.h
  llvm/lib/BinaryFormat/Wasm.cpp
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
  llvm/lib/CodeGen/ValueTypes.cpp
  llvm/lib/MC/MCExpr.cpp
  llvm/lib/MC/WasmObjectWriter.cpp
  llvm/lib/Object/WasmObjectFile.cpp
  llvm/lib/ObjectYAML/WasmEmitter.cpp
  llvm/lib/ObjectYAML/WasmYAML.cpp
  llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
  llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
  llvm/lib/Target/WebAssembly/WebAssembly.h
  llvm/lib/Target/WebAssembly/WebAssembly.td
  llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
  llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/anyref.ll
  llvm/test/CodeGen/WebAssembly/reg-argument.mir
  llvm/test/CodeGen/WebAssembly/reg-copy.mir
  llvm/utils/TableGen/CodeGenTarget.cpp


["D66035.231601.patch" (text/x-patch)]

Index: llvm/utils/TableGen/CodeGenTarget.cpp
===================================================================
--- llvm/utils/TableGen/CodeGenTarget.cpp
+++ llvm/utils/TableGen/CodeGenTarget.cpp
@@ -196,6 +196,7 @@
   case MVT::iPTRAny:  return "MVT::iPTRAny";
   case MVT::Untyped:  return "MVT::Untyped";
   case MVT::exnref:   return "MVT::exnref";
+  case MVT::anyref:   return "MVT::anyref";
   default: llvm_unreachable("ILLEGAL VALUE TYPE!");
   }
 }
Index: llvm/test/CodeGen/WebAssembly/reg-copy.mir
===================================================================
--- llvm/test/CodeGen/WebAssembly/reg-copy.mir
+++ llvm/test/CodeGen/WebAssembly/reg-copy.mir
@@ -66,3 +66,14 @@
     %0:exnref = COPY %1:exnref
     RETURN implicit-def $arguments
 ...
+---
+name: copy_anyref
+# CHECK-LABEL: copy_anyref
+body: |
+  ; CHECK-LABEL: bb.0
+  ; CHECK-NEXT: %0:anyref = COPY_ANYREF %1:anyref
+  ; CHECK-NEXT: RETURN
+  bb.0:
+    %0:anyref = COPY %1:anyref
+    RETURN implicit-def $arguments
+...
Index: llvm/test/CodeGen/WebAssembly/reg-argument.mir
===================================================================
--- llvm/test/CodeGen/WebAssembly/reg-argument.mir
+++ llvm/test/CodeGen/WebAssembly/reg-argument.mir
@@ -57,3 +57,14 @@
     %1:exnref = ARGUMENT_exnref 0, implicit $arguments
     RETURN implicit-def $arguments
 ...
+---
+name: argument_anyref
+# CHECK-LABEL: argument_anyref
+body: |
+  ; CHECK-LABEL: bb.0:
+  ; CHECK-NEXT: %1:anyref = ARGUMENT_anyref 0
+  bb.0:
+    %0:i32 = CONST_I32 0, implicit-def $arguments
+    %1:anyref = ARGUMENT_anyref 0, implicit $arguments
+    RETURN implicit-def $arguments
+...
Index: llvm/test/CodeGen/WebAssembly/anyref.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/anyref.ll
@@ -0,0 +1,29 @@
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt \
-wasm-disable-explicit-locals -wasm-keep-registers -mattr=+reference-types | \
FileCheck %s +
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:256"
+target triple = "wasm32-unknown-unknown"
+
+declare i8 addrspace(256)* @test(i8 addrspace(256)*) 
+
+
+; CHECK-LABEL: call_test:
+; CHECK: .functype       call_test (anyref) -> (anyref)
+define i8 addrspace(256)* @call_test(i8 addrspace(256)*) {
+; CHECK: anyref.call     $push0=, test, $0
+  %a = call i8 addrspace(256)* @test(i8 addrspace(256)* %0) 
+  ret i8 addrspace(256)* %a
+}
+
+; TODO: nullref?
+; define i8 addrspace(256)* @null_test() {
+;   ret i8 addrspace(256)* null
+; }
+
+; TODO: Loading a anyref from a pointer
+; @glob = external global i8 addrspace(256)*, align 4
+; define i8 addrspace(256)* @global_test() {
+;   %a = load i8 addrspace(256)*, i8 addrspace(256)** @glob
+;   ret i8 addrspace(256)* %a
+; }
+
+; CHECK: .functype       test (anyref) -> (anyref)
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -102,15 +102,45 @@
   return *RM;
 }
 
+static bool HasReferenceTypes(StringRef FS) {
+  bool ReferenceTypes = false;
+  SmallVector<StringRef, 3> Features;
+
+  FS.split(Features, ',', -1, false /* KeepEmpty */);
+  for (auto &Feature : Features) {
+    if (Feature == "reference-types" || Feature == "+reference-types")
+      ReferenceTypes = true;
+    if (Feature == "-reference-types")
+      ReferenceTypes = false;
+  }
+
+  return ReferenceTypes;
+}
+
+static std::string computeDataLayout(const Triple &TT, StringRef FS) {
+  std::string Ret = "e-m:e"; // little endian, mangling elf
+
+  if (TT.isArch64Bit()) {
+    Ret += "-p:64:64";
+  } else {
+    Ret += "-p:32:32";
+  }
+
+  Ret += "-i64:64-n32:64-S128";
+
+  if (HasReferenceTypes(FS)) {
+    Ret += "-ni:256"; // anyref
+  }
+  return Ret;
+}
+
 /// Create an WebAssembly architecture model.
 ///
 WebAssemblyTargetMachine::WebAssemblyTargetMachine(
     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
     const TargetOptions &Options, Optional<Reloc::Model> RM,
     Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
-    : LLVMTargetMachine(T,
-                        TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
-                                         : "e-m:e-p:32:32-i64:64-n32:64-S128",
+    : LLVMTargetMachine(T, computeDataLayout(TT, FS),
                         TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT),
                         getEffectiveCodeModel(CM, CodeModel::Large), OL),
       TLOF(new WebAssemblyTargetObjectFile()) {
Index: llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
+++ llvm/lib/Target/WebAssembly/WebAssemblySubtarget.h
@@ -47,6 +47,7 @@
   bool HasMultivalue = false;
   bool HasMutableGlobals = false;
   bool HasTailCall = false;
+  bool HasReferenceTypes = false;
 
   /// String name of used CPU.
   std::string CPUString;
@@ -104,6 +105,7 @@
   bool hasMultivalue() const { return HasMultivalue; }
   bool hasMutableGlobals() const { return HasMutableGlobals; }
   bool hasTailCall() const { return HasTailCall; }
+  bool hasReferenceTypes() const { return HasReferenceTypes; }
 
   /// Parses features string setting specified subtarget options. Definition of
   /// function is auto generated by tblgen.
Index: llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
+++ llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.td
@@ -44,6 +44,7 @@
 def V128_0: WebAssemblyReg<"%v128">;
 
 def EXNREF_0 : WebAssemblyReg<"%exnref.0">;
+def ANYREF_0 : WebAssemblyReg<"%anyref.0">;
 
 // The value stack "register". This is an opaque entity which serves to order
 // uses and defs that must remain in LIFO order.
@@ -65,3 +66,4 @@
 def V128 : WebAssemblyRegClass<[v4f32, v2f64, v2i64, v4i32, v16i8, v8i16], 128,
                                (add V128_0)>;
 def EXNREF : WebAssemblyRegClass<[exnref], 0, (add EXNREF_0)>;
+def ANYREF : WebAssemblyRegClass<[anyref], 0, (add ANYREF_0)>;
Index: llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyPeephole.cpp
@@ -114,6 +114,9 @@
       case WebAssembly::EXNREFRegClassID:
         CopyLocalOpc = WebAssembly::COPY_EXNREF;
         break;
+      case WebAssembly::ANYREFRegClassID:
+        CopyLocalOpc = WebAssembly::COPY_ANYREF;
+        break;
       default:
         llvm_unreachable("Unexpected register class for return operand");
       }
Index: llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -64,6 +64,11 @@
     WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
   }
 
+  unsigned TargetFlags = MO.getTargetFlags();
+  if (TargetFlags == WebAssemblyII::MO_TABLE_INDEX) {
+    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
+  }
+
   return WasmSym;
 }
 
@@ -90,6 +95,12 @@
     return WasmSym;
   }
 
+  unsigned TargetFlags = MO.getTargetFlags();
+  if (TargetFlags == WebAssemblyII::MO_TABLE_INDEX) {
+    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
+    return WasmSym;
+  }
+
   SmallVector<wasm::ValType, 4> Returns;
   SmallVector<wasm::ValType, 4> Params;
   if (strcmp(Name, "__cpp_exception") == 0) {
@@ -130,6 +141,9 @@
   switch (TargetFlags) {
     case WebAssemblyII::MO_NO_FLAG:
       break;
+    case WebAssemblyII::MO_TABLE_INDEX:
+      Kind = MCSymbolRefExpr::VK_WASM_TABLEINDEX;
+      break;
     case WebAssemblyII::MO_GOT:
       Kind = MCSymbolRefExpr::VK_GOT;
       break;
Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
===================================================================
--- /dev/null
+++ llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
@@ -0,0 +1,12 @@
+multiclass WebAssemblyTableGet<WebAssemblyRegClass rc, string Name, int Opcode> {
+  let mayLoad = 1, UseNamedOperandTable = 1 in
+  defm "": I<(outs rc:$dst),
+             (ins table_op: $table, I32:$offset),
+             (outs), (ins table_op: $table),
+             [], !strconcat(Name, "\t$dst, ${offset}(${table})"),
+             !strconcat(Name, "\t${table}"), Opcode>;
+}
+
+defm TABLE_GET : WebAssemblyTableGet<ANYREF, "table.get", 0x25>;
+
+def : Pat<(anyref (load (WebAssemblywrapper anyref:$addr))), (TABLE_GET \
                anyref:$addr, (CONST_I32 0))>;
Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -62,6 +62,10 @@
     Predicate<"Subtarget->hasBulkMemory()">,
     AssemblerPredicate<"FeatureBulkMemory", "bulk-memory">;
 
+def HasReferenceTypes :
+    Predicate<"Subtarget->hasReferenceTypes()">,
+    AssemblerPredicate<"FeatureReferenceTypes", "reference-types">;
+
 //===----------------------------------------------------------------------===//
 // WebAssembly-specific DAG Node Types.
 //===----------------------------------------------------------------------===//
@@ -141,6 +145,9 @@
 let OperandType = "OPERAND_GLOBAL" in
 def global_op : Operand<i32>;
 
+let OperandType = "OPERAND_TABLE" in
+def table_op : Operand<anyref>;
+
 let OperandType = "OPERAND_I32IMM" in
 def i32imm_op : Operand<i32>;
 
@@ -226,6 +233,7 @@
 defm "": ARGUMENT<F32, f32>;
 defm "": ARGUMENT<F64, f64>;
 defm "": ARGUMENT<EXNREF, exnref>;
+defm "": ARGUMENT<ANYREF, anyref>;
 
 // local.get and local.set are not generated by instruction selection; they
 // are implied by virtual register uses and defs.
@@ -296,6 +304,7 @@
 defm "" : LOCAL<F64>;
 defm "" : LOCAL<V128>, Requires<[HasSIMD128]>;
 defm "" : LOCAL<EXNREF>, Requires<[HasExceptionHandling]>;
+defm "" : LOCAL<ANYREF>, Requires<[HasReferenceTypes]>;
 
 let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in {
 defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm),
@@ -348,3 +357,4 @@
 include "WebAssemblyInstrSIMD.td"
 include "WebAssemblyInstrRef.td"
 include "WebAssemblyInstrBulkMemory.td"
+include "WebAssemblyInstrTable.td"
Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
@@ -77,6 +77,8 @@
     CopyOpcode = WebAssembly::COPY_V128;
   else if (RC == &WebAssembly::EXNREFRegClass)
     CopyOpcode = WebAssembly::COPY_EXNREF;
+  else if (RC == &WebAssembly::ANYREFRegClass)
+    CopyOpcode = WebAssembly::COPY_ANYREF;
   else
     llvm_unreachable("Unexpected register class");
 
Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
+++ llvm/lib/Target/WebAssembly/WebAssemblyInstrCall.td
@@ -60,6 +60,7 @@
 defm "" : CALL<f32, F32, "f32.">;
 defm "" : CALL<f64, F64, "f64.">;
 defm "" : CALL<exnref, EXNREF, "exnref.", [HasExceptionHandling]>;
+defm "" : CALL<anyref, ANYREF, "anyref.", [HasReferenceTypes]>;
 defm "" : CALL<v16i8, V128, "v128.", [HasSIMD128]>;
 defm "" : CALL<v8i16, V128, "v128.", [HasSIMD128]>;
 defm "" : CALL<v4i32, V128, "v128.", [HasSIMD128]>;
@@ -142,6 +143,9 @@
 def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
           (CALL_exnref tglobaladdr:$callee)>,
       Requires<[HasExceptionHandling]>;
+def : Pat<(anyref (WebAssemblycall1 (WebAssemblywrapper tglobaladdr:$callee))),
+          (CALL_anyref tglobaladdr:$callee)>,
+      Requires<[HasReferenceTypes]>;
 def : Pat<(WebAssemblycall0 (WebAssemblywrapper tglobaladdr:$callee)),
           (CALL_VOID tglobaladdr:$callee)>;
 def : Pat<(WebAssemblyretcall (WebAssemblywrapper tglobaladdr:$callee)),
@@ -171,6 +175,9 @@
 def : Pat<(exnref (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
           (CALL_exnref texternalsym:$callee)>,
       Requires<[HasExceptionHandling]>;
+def : Pat<(anyref (WebAssemblycall1 (WebAssemblywrapper texternalsym:$callee))),
+          (CALL_anyref texternalsym:$callee)>,
+      Requires<[HasReferenceTypes]>;
 def : Pat<(WebAssemblycall0 (WebAssemblywrapper texternalsym:$callee)),
           (CALL_VOID texternalsym:$callee)>;
 def : Pat<(WebAssemblyretcall (WebAssemblywrapper texternalsym:$callee)),
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYISELLOWERING_H
 #define LLVM_LIB_TARGET_WEBASSEMBLY_WEBASSEMBLYISELLOWERING_H
 
+#include "WebAssembly.h"
 #include "llvm/CodeGen/TargetLowering.h"
 
 namespace llvm {
@@ -51,6 +52,18 @@
   /// right decision when generating code for different targets.
   const WebAssemblySubtarget *Subtarget;
 
+  MVT getPointerTy(const DataLayout &DL, uint32_t AS = 0) const override {
+    return AS == WebAssemblyAS::ANYREF_ADDRESS
+               ? MVT::anyref
+               : MVT::getIntegerVT(DL.getPointerSizeInBits(AS));
+  }
+
+  MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const override {
+    return AS == WebAssemblyAS::ANYREF_ADDRESS
+               ? MVT::anyref
+               : MVT::getIntegerVT(DL.getPointerSizeInBits(AS));
+  }
+
   AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *) const override;
   FastISel *createFastISel(FunctionLoweringInfo &FuncInfo,
                            const TargetLibraryInfo *LibInfo) const override;
@@ -96,6 +109,7 @@
 
   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
                           SelectionDAG &DAG) const override;
+  bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override;
 
   const char *getClearCacheBuiltinName() const override {
     report_fatal_error("llvm.clear_cache is not supported on wasm");
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -13,6 +13,7 @@
 
 #include "WebAssemblyISelLowering.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "WebAssembly.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblySubtarget.h"
 #include "WebAssemblyTargetMachine.h"
@@ -65,6 +66,10 @@
     addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
     addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
   }
+  if (Subtarget->hasReferenceTypes()) {
+    addRegisterClass(MVT::anyref, &WebAssembly::ANYREFRegClass);
+    setOperationAction(ISD::GlobalAddress, MVT::anyref, Custom);
+  }
   // Compute derived properties from the register classes.
   computeRegisterProperties(Subtarget->getRegisterInfo());
 
@@ -958,6 +963,14 @@
   return Chain;
 }
 
+bool WebAssemblyTargetLowering::isNoopAddrSpaceCast(unsigned SrcAS,
+                                                    unsigned DestAS) const {
+  assert(SrcAS != DestAS && "Expected different address spaces!");
+
+  return SrcAS <= WebAssemblyAS::MAX_CUSTOM_ADDRESS &&
+         DestAS <= WebAssemblyAS::MAX_CUSTOM_ADDRESS;
+}
+
 void WebAssemblyTargetLowering::ReplaceNodeResults(
     SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
   switch (N->getOpcode()) {
@@ -1103,8 +1116,9 @@
   EVT VT = Op.getValueType();
   assert(GA->getTargetFlags() == 0 &&
          "Unexpected target flags on generic GlobalAddressSDNode");
-  if (GA->getAddressSpace() != 0)
-    fail(DL, DAG, "WebAssembly only expects the 0 address space");
+  if (GA->getAddressSpace() != 0 &&
+      GA->getAddressSpace() != WebAssemblyAS::ANYREF_ADDRESS)
+    fail(DL, DAG, "WebAssembly only expects the 0 or 256 (anyref) address space");
 
   unsigned OperandFlags = 0;
   if (isPositionIndependent()) {
@@ -1136,6 +1150,10 @@
     }
   }
 
+  if (GA->getAddressSpace() == WebAssemblyAS::ANYREF_ADDRESS) {
+    OperandFlags = WebAssemblyII::MO_TABLE_INDEX;
+  }
+
   return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
                      DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
                                                 GA->getOffset(), OperandFlags));
Index: llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
@@ -130,6 +130,7 @@
     case MVT::f32:
     case MVT::f64:
     case MVT::exnref:
+    case MVT::anyref:
       return VT;
     case MVT::f16:
       return MVT::f32;
@@ -706,6 +707,10 @@
       Opc = WebAssembly::ARGUMENT_exnref;
       RC = &WebAssembly::EXNREFRegClass;
       break;
+    case MVT::anyref:
+      Opc = WebAssembly::ARGUMENT_anyref;
+      RC = &WebAssembly::ANYREFRegClass;
+      break;
     default:
       return false;
     }
@@ -824,6 +829,11 @@
                      : WebAssembly::PCALL_INDIRECT_exnref;
       ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
       break;
+    case MVT::anyref:
+      Opc = IsDirect ? WebAssembly::CALL_anyref
+                     : WebAssembly::PCALL_INDIRECT_anyref;
+      ResultReg = createResultReg(&WebAssembly::ANYREFRegClass);
+      break;
     default:
       return false;
     }
@@ -1329,6 +1339,7 @@
   case MVT::v4f32:
   case MVT::v2f64:
   case MVT::exnref:
+  case MVT::anyref:
     break;
   default:
     return false;
Index: llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyExplicitLocals.cpp
@@ -92,6 +92,8 @@
     return WebAssembly::DROP_V128;
   if (RC == &WebAssembly::EXNREFRegClass)
     return WebAssembly::DROP_EXNREF;
+  if (RC == &WebAssembly::ANYREFRegClass)
+    return WebAssembly::DROP_ANYREF;
   llvm_unreachable("Unexpected register class");
 }
 
@@ -109,6 +111,8 @@
     return WebAssembly::LOCAL_GET_V128;
   if (RC == &WebAssembly::EXNREFRegClass)
     return WebAssembly::LOCAL_GET_EXNREF;
+  if (RC == &WebAssembly::ANYREFRegClass)
+    return WebAssembly::LOCAL_GET_ANYREF;
   llvm_unreachable("Unexpected register class");
 }
 
@@ -126,6 +130,8 @@
     return WebAssembly::LOCAL_SET_V128;
   if (RC == &WebAssembly::EXNREFRegClass)
     return WebAssembly::LOCAL_SET_EXNREF;
+  if (RC == &WebAssembly::EXNREFRegClass)
+    return WebAssembly::LOCAL_SET_ANYREF;
   llvm_unreachable("Unexpected register class");
 }
 
@@ -143,6 +149,8 @@
     return WebAssembly::LOCAL_TEE_V128;
   if (RC == &WebAssembly::EXNREFRegClass)
     return WebAssembly::LOCAL_TEE_EXNREF;
+  if (RC == &WebAssembly::ANYREFRegClass)
+    return WebAssembly::LOCAL_TEE_ANYREF;
   llvm_unreachable("Unexpected register class");
 }
 
@@ -160,6 +168,8 @@
     return MVT::v16i8;
   if (RC == &WebAssembly::EXNREFRegClass)
     return MVT::exnref;
+  if (RC == &WebAssembly::ANYREFRegClass)
+    return MVT::anyref;
   llvm_unreachable("unrecognized register class");
 }
 
Index: llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -329,6 +329,7 @@
   case WebAssembly::ARGUMENT_v4f32_S:
   case WebAssembly::ARGUMENT_v2f64:
   case WebAssembly::ARGUMENT_v2f64_S:
+  case WebAssembly::ARGUMENT_anyref:
     // These represent values which are live into the function entry, so there's
     // no instruction to emit.
     break;
Index: llvm/lib/Target/WebAssembly/WebAssembly.td
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssembly.td
+++ llvm/lib/Target/WebAssembly/WebAssembly.td
@@ -66,6 +66,10 @@
       SubtargetFeature<"mutable-globals", "HasMutableGlobals", "true",
                        "Enable mutable globals">;
 
+def FeatureReferenceTypes :
+      SubtargetFeature<"reference-types", "HasReferenceTypes", "true",
+                       "Enable referenceTypes">;
+
 //===----------------------------------------------------------------------===//
 // Architectures.
 //===----------------------------------------------------------------------===//
Index: llvm/lib/Target/WebAssembly/WebAssembly.h
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssembly.h
+++ llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -81,4 +81,12 @@
 
 } // end namespace llvm
 
+namespace WebAssemblyAS {
+enum : unsigned {
+  // The maxium value for custom address-spaces.
+  MAX_CUSTOM_ADDRESS = 255,
+  ANYREF_ADDRESS = 256, // Address space for anyref
+};
+}
+
 #endif
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -73,6 +73,8 @@
   switch (Modifier) {
     case MCSymbolRefExpr::VK_GOT:
       return wasm::R_WASM_GLOBAL_INDEX_LEB;
+    case MCSymbolRefExpr::VK_WASM_TABLEINDEX:
+      return wasm::R_WASM_TABLE_INDEX_LEB;
     case MCSymbolRefExpr::VK_WASM_TBREL:
       assert(SymA.isFunction());
       return wasm::R_WASM_TABLE_INDEX_REL_SLEB;
@@ -99,6 +101,8 @@
       return wasm::R_WASM_FUNCTION_INDEX_LEB;
     if (SymA.isEvent())
       return wasm::R_WASM_EVENT_INDEX_LEB;
+    if (SymA.isTable())
+      return wasm::R_WASM_TABLE_INDEX_LEB;
     return wasm::R_WASM_MEMORY_ADDR_LEB;
   case FK_Data_4:
     if (SymA.isFunction())
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h
@@ -48,6 +48,8 @@
   OPERAND_LOCAL,
   /// Global index.
   OPERAND_GLOBAL,
+  /// Table index.
+  OPERAND_TABLE,
   /// 32-bit integer immediates.
   OPERAND_I32IMM,
   /// 64-bit integer immediates.
@@ -102,6 +104,9 @@
   // address relative the __table_base wasm global.
   // Only applicable to function symbols.
   MO_TABLE_BASE_REL,
+
+  // On a symbol operand this indicates that this operand is a table index.
+  MO_TABLE_INDEX,
 };
 
 } // end namespace WebAssemblyII
@@ -132,6 +137,7 @@
   F64 = unsigned(wasm::ValType::F64),
   V128 = unsigned(wasm::ValType::V128),
   Exnref = unsigned(wasm::ValType::EXNREF),
+  Anyref = unsigned(wasm::ValType::ANYREF),
   // Multivalue blocks (and other non-void blocks) are only emitted when the
   // blocks will never be exited and are at the ends of functions (see
   // WebAssemblyCFGStackify::fixEndsAtEndOfFunction). They also are never made
@@ -393,6 +399,8 @@
   case WebAssembly::ARGUMENT_v2f64_S:
   case WebAssembly::ARGUMENT_exnref:
   case WebAssembly::ARGUMENT_exnref_S:
+  case WebAssembly::ARGUMENT_anyref:
+  case WebAssembly::ARGUMENT_anyref_S:
     return true;
   default:
     return false;
@@ -413,6 +421,8 @@
   case WebAssembly::COPY_V128_S:
   case WebAssembly::COPY_EXNREF:
   case WebAssembly::COPY_EXNREF_S:
+  case WebAssembly::COPY_ANYREF:
+  case WebAssembly::COPY_ANYREF_S:
     return true;
   default:
     return false;
@@ -433,6 +443,8 @@
   case WebAssembly::TEE_V128_S:
   case WebAssembly::TEE_EXNREF:
   case WebAssembly::TEE_EXNREF_S:
+  case WebAssembly::TEE_ANYREF:
+  case WebAssembly::TEE_ANYREF_S:
     return true;
   default:
     return false;
@@ -465,6 +477,8 @@
   case WebAssembly::CALL_v2f64_S:
   case WebAssembly::CALL_exnref:
   case WebAssembly::CALL_exnref_S:
+  case WebAssembly::CALL_anyref:
+  case WebAssembly::CALL_anyref_S:
   case WebAssembly::RET_CALL:
   case WebAssembly::RET_CALL_S:
     return true;
@@ -499,6 +513,8 @@
   case WebAssembly::CALL_INDIRECT_v2f64_S:
   case WebAssembly::CALL_INDIRECT_exnref:
   case WebAssembly::CALL_INDIRECT_exnref_S:
+  case WebAssembly::CALL_INDIRECT_anyref:
+  case WebAssembly::CALL_INDIRECT_anyref_S:
   case WebAssembly::RET_CALL_INDIRECT:
   case WebAssembly::RET_CALL_INDIRECT_S:
     return true;
@@ -542,6 +558,8 @@
   case WebAssembly::CALL_v2f64_S:
   case WebAssembly::CALL_exnref:
   case WebAssembly::CALL_exnref_S:
+  case WebAssembly::CALL_anyref:
+  case WebAssembly::CALL_anyref_S:
   case WebAssembly::CALL_INDIRECT_i32:
   case WebAssembly::CALL_INDIRECT_i32_S:
   case WebAssembly::CALL_INDIRECT_i64:
@@ -562,6 +580,8 @@
   case WebAssembly::CALL_INDIRECT_v4f32_S:
   case WebAssembly::CALL_INDIRECT_v2f64:
   case WebAssembly::CALL_INDIRECT_v2f64_S:
+  case WebAssembly::CALL_INDIRECT_anyref:
+  case WebAssembly::CALL_INDIRECT_anyref_S:
   case WebAssembly::CALL_INDIRECT_exnref:
   case WebAssembly::CALL_INDIRECT_exnref_S:
     return 1;
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.cpp
@@ -149,6 +149,8 @@
     return wasm::ValType::V128;
   case MVT::exnref:
     return wasm::ValType::EXNREF;
+  case MVT::anyref:
+    return wasm::ValType::ANYREF;
   default:
     llvm_unreachable("unexpected type");
   }
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -155,6 +155,7 @@
       case WebAssembly::OPERAND_SIGNATURE:
       case WebAssembly::OPERAND_TYPEINDEX:
       case WebAssembly::OPERAND_GLOBAL:
+      case WebAssembly::OPERAND_TABLE:
       case WebAssembly::OPERAND_EVENT:
         FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
         break;
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -305,6 +305,8 @@
     return "v128";
   case wasm::WASM_TYPE_FUNCREF:
     return "funcref";
+  case wasm::WASM_TYPE_ANYREF:
+    return "anyref";
   case wasm::WASM_TYPE_FUNC:
     return "func";
   case wasm::WASM_TYPE_EXNREF:
Index: llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
+++ llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
@@ -197,6 +197,7 @@
     case WebAssembly::OPERAND_BASIC_BLOCK:
     case WebAssembly::OPERAND_LOCAL:
     case WebAssembly::OPERAND_GLOBAL:
+    case WebAssembly::OPERAND_TABLE:
     case WebAssembly::OPERAND_FUNCTION32:
     case WebAssembly::OPERAND_OFFSET32:
     case WebAssembly::OPERAND_P2ALIGN:
Index: llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -310,6 +310,8 @@
       return wasm::ValType::V128;
     if (Type == "exnref")
       return wasm::ValType::EXNREF;
+    if (Type == "anyref")
+      return wasm::ValType::ANYREF;
     return Optional<wasm::ValType>();
   }
 
@@ -322,6 +324,7 @@
         .Case("f64", WebAssembly::BlockType::F64)
         .Case("v128", WebAssembly::BlockType::V128)
         .Case("exnref", WebAssembly::BlockType::Exnref)
+        .Case("anyref", WebAssembly::BlockType::Anyref)
         .Case("void", WebAssembly::BlockType::Void)
         .Default(WebAssembly::BlockType::Invalid);
   }
Index: llvm/lib/ObjectYAML/WasmYAML.cpp
===================================================================
--- llvm/lib/ObjectYAML/WasmYAML.cpp
+++ llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -493,6 +493,8 @@
     IO.mapRequired("Global", Info.ElementIndex);
   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT) {
     IO.mapRequired("Event", Info.ElementIndex);
+  } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE) {
+    IO.mapRequired("Table", Info.ElementIndex);
   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) {
     if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
       IO.mapRequired("Segment", Info.DataRef.Segment);
@@ -547,6 +549,7 @@
   ECase(GLOBAL);
   ECase(SECTION);
   ECase(EVENT);
+  ECase(TABLE);
 #undef ECase
 }
 
@@ -559,6 +562,7 @@
   ECase(F64);
   ECase(V128);
   ECase(FUNCREF);
+  ECase(ANYREF);
   ECase(FUNC);
 #undef ECase
 }
@@ -590,6 +594,7 @@
     IO &IO, WasmYAML::TableType &Type) {
 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
   ECase(FUNCREF);
+  ECase(ANYREF);
 #undef ECase
 }
 
Index: llvm/lib/ObjectYAML/WasmEmitter.cpp
===================================================================
--- llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -188,6 +188,7 @@
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
       case wasm::WASM_SYMBOL_TYPE_EVENT:
+      case wasm::WASM_SYMBOL_TYPE_TABLE:
         encodeULEB128(Info.ElementIndex, SubSection.getStream());
         if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
             (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Index: llvm/lib/Object/WasmObjectFile.cpp
===================================================================
--- llvm/lib/Object/WasmObjectFile.cpp
+++ llvm/lib/Object/WasmObjectFile.cpp
@@ -470,9 +470,11 @@
   std::vector<wasm::WasmImport *> ImportedGlobals;
   std::vector<wasm::WasmImport *> ImportedFunctions;
   std::vector<wasm::WasmImport *> ImportedEvents;
+  std::vector<wasm::WasmImport *> ImportedTables;
   ImportedGlobals.reserve(Imports.size());
   ImportedFunctions.reserve(Imports.size());
   ImportedEvents.reserve(Imports.size());
+  ImportedTables.reserve(Imports.size());
   for (auto &I : Imports) {
     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
       ImportedFunctions.emplace_back(&I);
@@ -480,6 +482,8 @@
       ImportedGlobals.emplace_back(&I);
     else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
       ImportedEvents.emplace_back(&I);
+    else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
+      ImportedTables.emplace_back(&I);
   }
 
   while (Count--) {
@@ -609,6 +613,27 @@
       break;
     }
 
+    case wasm::WASM_SYMBOL_TYPE_TABLE: {
+      Info.ElementIndex = readVaruint32(Ctx);
+      if (!isValidTableIndex(Info.ElementIndex) ||
+          IsDefined != isDefinedTableIndex(Info.ElementIndex))
+        return make_error<GenericBinaryError>("invalid table symbol index",
+                                              object_error::parse_failed);
+      if (IsDefined) {
+        Info.Name = readString(Ctx);
+        unsigned TableIndex = Info.ElementIndex - NumImportedTables;
+      } else {
+        wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
+        if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
+          Info.Name = readString(Ctx);
+        else
+          Info.Name = Import.Field;
+        Info.ImportName = Import.Field;
+        Info.ImportModule = Import.Module;
+      }
+      break;
+    }
+
     default:
       return make_error<GenericBinaryError>("Invalid symbol type",
                                             object_error::parse_failed);
@@ -793,6 +818,11 @@
         return make_error<GenericBinaryError>("Bad relocation event index",
                                               object_error::parse_failed);
       break;
+    case wasm::R_WASM_TABLE_INDEX_LEB:
+      if (!isValidTableSymbol(Reloc.Index))
+        return make_error<GenericBinaryError>("Bad relocation table index",
+                                              object_error::parse_failed);
+      break;
     case wasm::R_WASM_MEMORY_ADDR_LEB:
     case wasm::R_WASM_MEMORY_ADDR_SLEB:
     case wasm::R_WASM_MEMORY_ADDR_I32:
@@ -915,8 +945,10 @@
       Im.Memory = readLimits(Ctx);
       break;
     case wasm::WASM_EXTERNAL_TABLE:
+      NumImportedTables++;
       Im.Table = readTable(Ctx);
-      if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
+      if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF &&
+          Im.Table.ElemType != wasm::WASM_TYPE_ANYREF)
         return make_error<GenericBinaryError>("Invalid table element type",
                                               object_error::parse_failed);
       break;
@@ -959,7 +991,9 @@
   Tables.reserve(Count);
   while (Count--) {
     Tables.push_back(readTable(Ctx));
-    if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
+    if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF &&
+        // TODO: Only allow anyref here when reference-types is enabled?
+        Tables.back().ElemType != wasm::WASM_TYPE_ANYREF) {
       return make_error<GenericBinaryError>("Invalid table element type",
                                             object_error::parse_failed);
     }
@@ -1082,6 +1116,14 @@
   return Index >= NumImportedEvents && isValidEventIndex(Index);
 }
 
+bool WasmObjectFile::isValidTableIndex(uint32_t Index) const {
+  return Index < NumImportedTables + Tables.size();
+}
+
+bool WasmObjectFile::isDefinedTableIndex(uint32_t Index) const {
+  return Index >= NumImportedTables && isValidTableIndex(Index);
+}
+
 bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
 }
@@ -1094,6 +1136,10 @@
   return Index < Symbols.size() && Symbols[Index].isTypeEvent();
 }
 
+bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
+  return Index < Symbols.size() && Symbols[Index].isTypeTable();
+}
+
 bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
   return Index < Symbols.size() && Symbols[Index].isTypeData();
 }
Index: llvm/lib/MC/WasmObjectWriter.cpp
===================================================================
--- llvm/lib/MC/WasmObjectWriter.cpp
+++ llvm/lib/MC/WasmObjectWriter.cpp
@@ -254,6 +254,7 @@
   unsigned NumFunctionImports = 0;
   unsigned NumGlobalImports = 0;
   unsigned NumEventImports = 0;
+  unsigned NumTableImports = 0;
   uint32_t SectionCount = 0;
 
   // TargetObjectWriter wrappers.
@@ -555,6 +556,7 @@
   case wasm::R_WASM_FUNCTION_INDEX_LEB:
   case wasm::R_WASM_GLOBAL_INDEX_LEB:
   case wasm::R_WASM_EVENT_INDEX_LEB:
+  case wasm::R_WASM_TABLE_INDEX_LEB:
     // Provisional value is function/global/event Wasm index
     assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index \
space");  return WasmIndices[RelEntry.Symbol];
@@ -652,6 +654,7 @@
     case wasm::R_WASM_GLOBAL_INDEX_LEB:
     case wasm::R_WASM_MEMORY_ADDR_LEB:
     case wasm::R_WASM_EVENT_INDEX_LEB:
+    case wasm::R_WASM_TABLE_INDEX_LEB:
       writePatchableLEB(Stream, Value, Offset);
       break;
     case wasm::R_WASM_TABLE_INDEX_I32:
@@ -945,6 +948,7 @@
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
       case wasm::WASM_SYMBOL_TYPE_EVENT:
+      case wasm::WASM_SYMBOL_TYPE_TABLE:
         encodeULEB128(Sym.ElementIndex, W.OS);
         if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
             (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
@@ -1137,6 +1141,7 @@
   TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
   TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
   Imports.push_back(TableImport);
+  NumTableImports++;
 
   // Populate SignatureIndices, and Imports and WasmIndices for undefined
   // symbols.  This must be done before populating WasmIndices for defined
@@ -1191,6 +1196,15 @@
         Imports.push_back(Import);
         assert(WasmIndices.count(&WS) == 0);
         WasmIndices[&WS] = NumEventImports++;
+      } else if (WS.isTable()) {
+        wasm::WasmImport Import;
+        Import.Module = WS.getImportModule();
+        Import.Field = WS.getImportName();
+        Import.Kind = wasm::WASM_EXTERNAL_TABLE;
+        Import.Table.ElemType = wasm::WASM_TYPE_ANYREF;
+        Imports.push_back(Import);
+        assert(WasmIndices.count(&WS) == 0);
+        WasmIndices[&WS] = NumTableImports++;
       }
     }
   }
@@ -1389,7 +1403,15 @@
       }
       LLVM_DEBUG(dbgs() << "  -> event index: " << WasmIndices.find(&WS)->second
                         << "\n");
-
+    } else if (WS.isTable()) {
+      if (WS.isDefined()) {
+        report_fatal_error("Defined tables are not supported yet");
+      } else {
+        // An import; the index was assigned above.
+        assert(WasmIndices.count(&WS) > 0);
+      }
+      LLVM_DEBUG(dbgs() << "  -> table index: " << WasmIndices.find(&WS)->second
+                        << "\n");
     } else {
       assert(WS.isSection());
     }
Index: llvm/lib/MC/MCExpr.cpp
===================================================================
--- llvm/lib/MC/MCExpr.cpp
+++ llvm/lib/MC/MCExpr.cpp
@@ -312,6 +312,7 @@
   case VK_Hexagon_IE: return "IE";
   case VK_Hexagon_IE_GOT: return "IEGOT";
   case VK_WASM_TYPEINDEX: return "TYPEINDEX";
+  case VK_WASM_TABLEINDEX: return "TABLEINDEX";
   case VK_WASM_MBREL: return "MBREL";
   case VK_WASM_TBREL: return "TBREL";
   case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
@@ -431,6 +432,7 @@
     .Case("hi8", VK_AVR_HI8)
     .Case("hlo8", VK_AVR_HLO8)
     .Case("typeindex", VK_WASM_TYPEINDEX)
+    .Case("tableindex", VK_WASM_TABLEINDEX)
     .Case("tbrel", VK_WASM_TBREL)
     .Case("mbrel", VK_WASM_MBREL)
     .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
Index: llvm/lib/CodeGen/ValueTypes.cpp
===================================================================
--- llvm/lib/CodeGen/ValueTypes.cpp
+++ llvm/lib/CodeGen/ValueTypes.cpp
@@ -256,6 +256,7 @@
   case MVT::Metadata:return "Metadata";
   case MVT::Untyped: return "Untyped";
   case MVT::exnref : return "exnref";
+  case MVT::anyref : return "anyref";
   }
 }
 
@@ -355,91 +356,94 @@
   case MVT::v2f64:   return VectorType::get(Type::getDoubleTy(Context), 2);
   case MVT::v4f64:   return VectorType::get(Type::getDoubleTy(Context), 4);
   case MVT::v8f64:   return VectorType::get(Type::getDoubleTy(Context), 8);
-  case MVT::nxv1i1:  
+  case MVT::nxv1i1:
     return VectorType::get(Type::getInt1Ty(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2i1:  
+  case MVT::nxv2i1:
     return VectorType::get(Type::getInt1Ty(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4i1:  
+  case MVT::nxv4i1:
     return VectorType::get(Type::getInt1Ty(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8i1:  
+  case MVT::nxv8i1:
     return VectorType::get(Type::getInt1Ty(Context), 8, /*Scalable=*/ true);
-  case MVT::nxv16i1: 
+  case MVT::nxv16i1:
     return VectorType::get(Type::getInt1Ty(Context), 16, /*Scalable=*/ true);
-  case MVT::nxv32i1: 
+  case MVT::nxv32i1:
     return VectorType::get(Type::getInt1Ty(Context), 32, /*Scalable=*/ true);
-  case MVT::nxv1i8:  
+  case MVT::nxv1i8:
     return VectorType::get(Type::getInt8Ty(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2i8:  
+  case MVT::nxv2i8:
     return VectorType::get(Type::getInt8Ty(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4i8:  
+  case MVT::nxv4i8:
     return VectorType::get(Type::getInt8Ty(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8i8:  
+  case MVT::nxv8i8:
     return VectorType::get(Type::getInt8Ty(Context), 8, /*Scalable=*/ true);
-  case MVT::nxv16i8: 
+  case MVT::nxv16i8:
     return VectorType::get(Type::getInt8Ty(Context), 16, /*Scalable=*/ true);
-  case MVT::nxv32i8: 
+  case MVT::nxv32i8:
     return VectorType::get(Type::getInt8Ty(Context), 32, /*Scalable=*/ true);
-  case MVT::nxv1i16: 
+  case MVT::nxv1i16:
     return VectorType::get(Type::getInt16Ty(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2i16: 
+  case MVT::nxv2i16:
     return VectorType::get(Type::getInt16Ty(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4i16: 
+  case MVT::nxv4i16:
     return VectorType::get(Type::getInt16Ty(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8i16: 
+  case MVT::nxv8i16:
     return VectorType::get(Type::getInt16Ty(Context), 8, /*Scalable=*/ true);
   case MVT::nxv16i16:
     return VectorType::get(Type::getInt16Ty(Context), 16, /*Scalable=*/ true);
   case MVT::nxv32i16:
     return VectorType::get(Type::getInt16Ty(Context), 32, /*Scalable=*/ true);
-  case MVT::nxv1i32: 
+  case MVT::nxv1i32:
     return VectorType::get(Type::getInt32Ty(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2i32: 
+  case MVT::nxv2i32:
     return VectorType::get(Type::getInt32Ty(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4i32: 
+  case MVT::nxv4i32:
     return VectorType::get(Type::getInt32Ty(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8i32: 
+  case MVT::nxv8i32:
     return VectorType::get(Type::getInt32Ty(Context), 8, /*Scalable=*/ true);
   case MVT::nxv16i32:
     return VectorType::get(Type::getInt32Ty(Context), 16,/*Scalable=*/ true);
   case MVT::nxv32i32:
     return VectorType::get(Type::getInt32Ty(Context), 32,/*Scalable=*/ true);
-  case MVT::nxv1i64: 
+  case MVT::nxv1i64:
     return VectorType::get(Type::getInt64Ty(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2i64: 
+  case MVT::nxv2i64:
     return VectorType::get(Type::getInt64Ty(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4i64: 
+  case MVT::nxv4i64:
     return VectorType::get(Type::getInt64Ty(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8i64: 
+  case MVT::nxv8i64:
     return VectorType::get(Type::getInt64Ty(Context), 8, /*Scalable=*/ true);
   case MVT::nxv16i64:
     return VectorType::get(Type::getInt64Ty(Context), 16, /*Scalable=*/ true);
   case MVT::nxv32i64:
     return VectorType::get(Type::getInt64Ty(Context), 32, /*Scalable=*/ true);
-  case MVT::nxv2f16: 
+  case MVT::nxv2f16:
     return VectorType::get(Type::getHalfTy(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4f16: 
+  case MVT::nxv4f16:
     return VectorType::get(Type::getHalfTy(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8f16: 
+  case MVT::nxv8f16:
     return VectorType::get(Type::getHalfTy(Context), 8, /*Scalable=*/ true);
-  case MVT::nxv1f32: 
+  case MVT::nxv1f32:
     return VectorType::get(Type::getFloatTy(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2f32: 
+  case MVT::nxv2f32:
     return VectorType::get(Type::getFloatTy(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4f32: 
+  case MVT::nxv4f32:
     return VectorType::get(Type::getFloatTy(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8f32: 
+  case MVT::nxv8f32:
     return VectorType::get(Type::getFloatTy(Context), 8, /*Scalable=*/ true);
   case MVT::nxv16f32:
     return VectorType::get(Type::getFloatTy(Context), 16, /*Scalable=*/ true);
-  case MVT::nxv1f64: 
+  case MVT::nxv1f64:
     return VectorType::get(Type::getDoubleTy(Context), 1, /*Scalable=*/ true);
-  case MVT::nxv2f64: 
+  case MVT::nxv2f64:
     return VectorType::get(Type::getDoubleTy(Context), 2, /*Scalable=*/ true);
-  case MVT::nxv4f64: 
+  case MVT::nxv4f64:
     return VectorType::get(Type::getDoubleTy(Context), 4, /*Scalable=*/ true);
-  case MVT::nxv8f64: 
+  case MVT::nxv8f64:
     return VectorType::get(Type::getDoubleTy(Context), 8, /*Scalable=*/ true);
   case MVT::Metadata: return Type::getMetadataTy(Context);
+  case MVT::anyref:
+    return PointerType::get(Type::getInt8Ty(Context),
+                            256); // TODO: Fix AS for Webassembly
   }
 }
 
Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
===================================================================
--- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4086,10 +4086,12 @@
       Root = Chain;
       ChainI = 0;
     }
-    SDValue A = DAG.getNode(ISD::ADD, dl,
-                            PtrVT, Ptr,
-                            DAG.getConstant(Offsets[i], dl, PtrVT),
-                            Flags);
+    SDValue A = Ptr;
+    if (Offsets[i] != 0)
+      A = DAG.getNode(ISD::ADD, dl,
+                      PtrVT, Ptr,
+                      DAG.getConstant(Offsets[i], dl, PtrVT),
+                      Flags);
     auto MMOFlags = MachineMemOperand::MONone;
     if (isVolatile)
       MMOFlags |= MachineMemOperand::MOVolatile;
Index: llvm/lib/CodeGen/CodeGenPrepare.cpp
===================================================================
--- llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -1952,7 +1952,7 @@
     case Intrinsic::experimental_widenable_condition: {
       // Give up on future widening oppurtunties so that we can fold away dead
       // paths and merge blocks before going into block-local instruction
-      // selection.   
+      // selection.
       if (II->use_empty()) {
         II->eraseFromParent();
         return true;
@@ -5812,6 +5812,9 @@
 
   EVT LoadResultVT = TLI->getValueType(*DL, Load->getType());
   unsigned BitWidth = LoadResultVT.getSizeInBits();
+  if (!BitWidth)
+    return false;
+
   APInt DemandBits(BitWidth, 0);
   APInt WidestAndBits(BitWidth, 0);
 
Index: llvm/lib/BinaryFormat/Wasm.cpp
===================================================================
--- llvm/lib/BinaryFormat/Wasm.cpp
+++ llvm/lib/BinaryFormat/Wasm.cpp
@@ -20,6 +20,8 @@
     return "WASM_SYMBOL_TYPE_SECTION";
   case wasm::WASM_SYMBOL_TYPE_EVENT:
     return "WASM_SYMBOL_TYPE_EVENT";
+  case wasm::WASM_SYMBOL_TYPE_TABLE:
+    return "WASM_SYMBOL_TYPE_TABLE";
   }
   llvm_unreachable("unknown symbol type");
 }
Index: llvm/include/llvm/Support/MachineValueType.h
===================================================================
--- llvm/include/llvm/Support/MachineValueType.h
+++ llvm/include/llvm/Support/MachineValueType.h
@@ -218,9 +218,10 @@
                                // will be determined by the opcode.
 
       exnref         =  134,   // WebAssembly's exnref type
+      anyref         =  135,   // WebAssembly's anyref type
 
       FIRST_VALUETYPE = 1,     // This is always the beginning of the list.
-      LAST_VALUETYPE =  135,   // This always remains at the end of the list.
+      LAST_VALUETYPE =  136,   // This always remains at the end of the list.
 
       // This is the current maximum for LAST_VALUETYPE.
       // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors
@@ -824,6 +825,7 @@
       case v1024f32:  return TypeSize::Fixed(32768);
       case v2048i32:
       case v2048f32:  return TypeSize::Fixed(65536);
+      case anyref:
       case exnref: return TypeSize::Fixed(0); // opaque type
       }
     }
Index: llvm/include/llvm/Object/Wasm.h
===================================================================
--- llvm/include/llvm/Object/Wasm.h
+++ llvm/include/llvm/Object/Wasm.h
@@ -63,6 +63,8 @@
 
   bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; }
 
+  bool isTypeTable() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE; }
+
   bool isDefined() const { return !isUndefined(); }
 
   bool isUndefined() const {
@@ -217,9 +219,12 @@
   bool isDefinedGlobalIndex(uint32_t Index) const;
   bool isValidEventIndex(uint32_t Index) const;
   bool isDefinedEventIndex(uint32_t Index) const;
+  bool isValidTableIndex(uint32_t Index) const;
+  bool isDefinedTableIndex(uint32_t Index) const;
   bool isValidFunctionSymbol(uint32_t Index) const;
   bool isValidGlobalSymbol(uint32_t Index) const;
   bool isValidEventSymbol(uint32_t Index) const;
+  bool isValidTableSymbol(uint32_t Index) const;
   bool isValidDataSymbol(uint32_t Index) const;
   bool isValidSectionSymbol(uint32_t Index) const;
   wasm::WasmFunction &getDefinedFunction(uint32_t Index);
@@ -284,6 +289,7 @@
   uint32_t NumImportedGlobals = 0;
   uint32_t NumImportedFunctions = 0;
   uint32_t NumImportedEvents = 0;
+  uint32_t NumImportedTables = 0;
   uint32_t CodeSection = 0;
   uint32_t DataSection = 0;
   uint32_t GlobalSection = 0;
Index: llvm/include/llvm/MC/MCSymbolWasm.h
===================================================================
--- llvm/include/llvm/MC/MCSymbolWasm.h
+++ llvm/include/llvm/MC/MCSymbolWasm.h
@@ -44,6 +44,7 @@
   bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
   bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; }
   bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; }
+  bool isTable() const { return Type == wasm::WASM_SYMBOL_TYPE_TABLE; }
   wasm::WasmSymbolType getType() const { return Type; }
   void setType(wasm::WasmSymbolType type) { Type = type; }
 
Index: llvm/include/llvm/MC/MCExpr.h
===================================================================
--- llvm/include/llvm/MC/MCExpr.h
+++ llvm/include/llvm/MC/MCExpr.h
@@ -290,9 +290,10 @@
     VK_Hexagon_IE,
     VK_Hexagon_IE_GOT,
 
-    VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature)
-    VK_WASM_MBREL,     // Memory address relative to memory base
-    VK_WASM_TBREL,     // Table index relative to table bare
+    VK_WASM_TYPEINDEX,  // Reference to a symbol's type (signature)
+    VK_WASM_TABLEINDEX, // Reference to a table
+    VK_WASM_MBREL,      // Memory address relative to memory base
+    VK_WASM_TBREL,      // Table index relative to table bare
 
     VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo
     VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
Index: llvm/include/llvm/CodeGen/ValueTypes.td
===================================================================
--- llvm/include/llvm/CodeGen/ValueTypes.td
+++ llvm/include/llvm/CodeGen/ValueTypes.td
@@ -166,6 +166,7 @@
 def isVoid : ValueType<0  , 132>;   // Produces no value
 def untyped: ValueType<8  , 133>;   // Produces an untyped value
 def exnref: ValueType<0, 134>;      // WebAssembly's exnref type
+def anyref: ValueType<0, 135>;      // WebAssembly's anyref type
 def token  : ValueType<0  , 248>;   // TokenTy
 def MetadataVT: ValueType<0, 249>;  // Metadata
 
Index: llvm/include/llvm/CodeGen/TargetLowering.h
===================================================================
--- llvm/include/llvm/CodeGen/TargetLowering.h
+++ llvm/include/llvm/CodeGen/TargetLowering.h
@@ -255,7 +255,7 @@
   /// Return the in-memory pointer type for the given address space, defaults to
   /// the pointer type from the data layout.  FIXME: The default needs to be
   /// removed once all the code is updated.
-  MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const {
+  virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS = 0) const {
     return MVT::getIntegerVT(DL.getPointerSizeInBits(AS));
   }
 
Index: llvm/include/llvm/BinaryFormat/WasmRelocs.def
===================================================================
--- llvm/include/llvm/BinaryFormat/WasmRelocs.def
+++ llvm/include/llvm/BinaryFormat/WasmRelocs.def
@@ -15,3 +15,4 @@
 WASM_RELOC(R_WASM_EVENT_INDEX_LEB,      10)
 WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB, 11)
 WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB, 12)
+WASM_RELOC(R_WASM_TABLE_INDEX_LEB,      13)
Index: llvm/include/llvm/BinaryFormat/Wasm.h
===================================================================
--- llvm/include/llvm/BinaryFormat/Wasm.h
+++ llvm/include/llvm/BinaryFormat/Wasm.h
@@ -225,6 +225,7 @@
   WASM_TYPE_F64 = 0x7C,
   WASM_TYPE_V128 = 0x7B,
   WASM_TYPE_FUNCREF = 0x70,
+  WASM_TYPE_ANYREF = 0x6F,
   WASM_TYPE_EXNREF = 0x68,
   WASM_TYPE_FUNC = 0x60,
   WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
@@ -313,6 +314,7 @@
   WASM_SYMBOL_TYPE_GLOBAL = 0x2,
   WASM_SYMBOL_TYPE_SECTION = 0x3,
   WASM_SYMBOL_TYPE_EVENT = 0x4,
+  WASM_SYMBOL_TYPE_TABLE = 0x5,
 };
 
 // Kinds of event attributes.
@@ -348,6 +350,8 @@
   F32 = WASM_TYPE_F32,
   F64 = WASM_TYPE_F64,
   V128 = WASM_TYPE_V128,
+  FUNCREF = WASM_TYPE_FUNCREF,
+  ANYREF = WASM_TYPE_ANYREF,
   EXNREF = WASM_TYPE_EXNREF,
 };
 
Index: lld/wasm/WriterUtils.cpp
===================================================================
--- lld/wasm/WriterUtils.cpp
+++ lld/wasm/WriterUtils.cpp
@@ -30,6 +30,10 @@
     return "f64";
   case ValType::V128:
     return "v128";
+  case ValType::FUNCREF:
+    return "funcref";
+  case ValType::ANYREF:
+    return "anyref";
   case ValType::EXNREF:
     return "exnref";
   }
Index: clang/lib/Basic/Targets/WebAssembly.h
===================================================================
--- clang/lib/Basic/Targets/WebAssembly.h
+++ clang/lib/Basic/Targets/WebAssembly.h
@@ -38,6 +38,7 @@
   bool HasMutableGlobals = false;
   bool HasMultivalue = false;
   bool HasTailCall = false;
+  bool HasReferenceTypes = false;
 
 public:
   explicit WebAssemblyTargetInfo(const llvm::Triple &T, const TargetOptions &)


[Attachment #4 (text/plain)]

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic