pmatos updated this revision to Diff 379917.
pmatos added a comment.
Herald added subscribers: cfe-commits, ormris, jdoerfert, steven_wu.
Herald added a project: clang.

Simplified a lot of code that required some further fixes and de-duplication.

Most importantly, I added many more testcases to ensure different addressing 
modes are supported.
The way to tell LLVM that externref and funcref pointers should not have 
complex addressing DAGS with shift/add/muls, 
was to add that information to the DataLayout string (p10:8:8-p20:8:8). This 
forced changes in many testfiles.

This looks now ready for another round of reviewing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D111154

Files:
  clang/lib/Basic/Targets/WebAssembly.h
  clang/test/CodeGen/target-data.c
  lld/test/wasm/lto/Inputs/archive.ll
  lld/test/wasm/lto/Inputs/cache.ll
  lld/test/wasm/lto/Inputs/libcall-archive.ll
  lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll
  lld/test/wasm/lto/Inputs/save-temps.ll
  lld/test/wasm/lto/Inputs/thinlto.ll
  lld/test/wasm/lto/Inputs/used.ll
  lld/test/wasm/lto/archive.ll
  lld/test/wasm/lto/atomics.ll
  lld/test/wasm/lto/cache.ll
  lld/test/wasm/lto/comdat.ll
  lld/test/wasm/lto/diagnostics.ll
  lld/test/wasm/lto/export.ll
  lld/test/wasm/lto/import-attributes.ll
  lld/test/wasm/lto/internalize-basic.ll
  lld/test/wasm/lto/libcall-archive.ll
  lld/test/wasm/lto/libcall-truncsfhf2.ll
  lld/test/wasm/lto/lto-start.ll
  lld/test/wasm/lto/new-pass-manager.ll
  lld/test/wasm/lto/opt-level.ll
  lld/test/wasm/lto/parallel.ll
  lld/test/wasm/lto/relocatable-undefined.ll
  lld/test/wasm/lto/relocatable.ll
  lld/test/wasm/lto/save-temps.ll
  lld/test/wasm/lto/thinlto.ll
  lld/test/wasm/lto/tls.ll
  lld/test/wasm/lto/undef.ll
  lld/test/wasm/lto/used.ll
  lld/test/wasm/lto/verify-invalid.ll
  lld/test/wasm/lto/weak-undefined.ll
  lld/test/wasm/lto/weak.ll
  llvm/lib/Target/WebAssembly/WebAssemblyISD.def
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
  llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
  llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
  llvm/test/CodeGen/WebAssembly/externref-tableget.ll
  llvm/test/CodeGen/WebAssembly/externref-tableset.ll
  llvm/test/CodeGen/WebAssembly/funcref-table_call.ll
  llvm/test/CodeGen/WebAssembly/funcref-tableget.ll
  llvm/test/CodeGen/WebAssembly/funcref-tableset.ll

Index: llvm/test/CodeGen/WebAssembly/funcref-tableset.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/funcref-tableset.ll
@@ -0,0 +1,82 @@
+; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s
+
+%func = type void ()
+%funcref = type %func addrspace(20)* ;; addrspace 20 is nonintegral
+
+@funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef
+
+define void @set_funcref_table(%funcref %g, i32 %i) {
+; CHECK-LABEL: set_funcref_table:
+; CHECK-NEXT: .functype       set_funcref_table (funcref, i32) -> ()
+; CHECK-NEXT: local.get      1
+; CHECK-NEXT: local.get      0
+; CHECK-NEXT: table.set     funcref_table
+; CHECK-NEXT: end_function
+
+;; this generates a table.set of @funcref_table
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %i
+  store %funcref %g, %funcref addrspace(1)* %p
+  ret void
+}
+
+define void @set_funcref_table_const(%funcref %g) {
+; CHECK-LABEL: set_funcref_table_const:
+; CHECK-NEXT:  .functype      set_funcref_table_const (funcref) -> ()
+; CHECK-NEXT:  i32.const      0
+; CHECK-NEXT:  local.get      0
+; CHECK-NEXT:  table.set      funcref_table
+; CHECK-NEXT:  end_function
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 0
+  store %funcref %g, %funcref addrspace(1)* %p
+  ret void
+}
+
+define void @set_funcref_table_with_offset(%funcref %g, i32 %i) {
+; CHECK-LABEL: set_funcref_table_with_offset:
+; CHECK-NEXT:  .functype       set_funcref_table_with_offset (funcref, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  i32.const       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       funcref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, 2
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  store %funcref %g, %funcref addrspace(1)* %p
+  ret void
+}
+
+define void @set_funcref_table_with_var_offset(%funcref %g, i32 %i, i32 %j) {
+; CHECK-LABEL: set_funcref_table_with_var_offset:
+; CHECK-NEXT:  .functype       set_funcref_table_with_var_offset (funcref, i32, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  local.get       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       funcref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  store %funcref %g, %funcref addrspace(1)* %p
+  ret void
+}
+
+declare i32 @set_offset()
+
+define void @set_funcref_table_with_var_offset2(%funcref %g, i32 %i) {
+; CHECK-LABEL: set_funcref_table_with_var_offset2:
+; CHECK-NEXT:  .functype       set_funcref_table_with_var_offset2 (funcref, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  call    set_offset
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       funcref_table
+; CHECK-NEXT:  end_function
+  %j = call i32 @set_offset()
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  store %funcref %g, %funcref addrspace(1)* %p
+  ret void
+}
+
+; CHECK: .globl funcref_table
Index: llvm/test/CodeGen/WebAssembly/funcref-tableget.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/funcref-tableget.ll
@@ -0,0 +1,76 @@
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s
+
+%func = type void ()
+%funcref = type %func addrspace(20)* ;; addrspace 20 is nonintegral
+
+@funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef
+
+define %funcref @get_funcref_from_table(i32 %i) {
+; CHECK-LABEL: get_funcref_from_table:
+; CHECK-NEXT: .functype       get_funcref_from_table (i32) -> (funcref)
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: table.get funcref_table
+; CHECK-NEXT: end_function
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %i
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  ret %funcref %ref
+}
+
+define %funcref @get_funcref_from_table_const() {
+; CHECK-LABEL: get_funcref_from_table_const:
+; CHECK-NEXT:  .functype      get_funcref_from_table_const () -> (funcref)
+; CHECK-NEXT:  i32.const      0
+; CHECK-NEXT:  table.get      funcref_table
+; CHECK-NEXT:  end_function
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 0
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  ret %funcref %ref
+}
+
+define %funcref @get_funcref_from_table_with_offset(i32 %i) {
+; CHECK-LABEL: get_funcref_from_table_with_offset:
+; CHECK-NEXT:  .functype       get_funcref_from_table_with_offset (i32) -> (funcref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  i32.const       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       funcref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, 2
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  ret %funcref %ref
+}
+
+
+define %funcref @get_funcref_from_table_with_var_offset(i32 %i, i32 %j) {
+; CHECK-LABEL: get_funcref_from_table_with_var_offset:
+; CHECK-NEXT:  .functype       get_funcref_from_table_with_var_offset (i32, i32) -> (funcref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       funcref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  ret %funcref %ref
+}
+
+declare i32 @get_offset()
+
+define %funcref @get_funcref_from_table_with_var_offset2(i32 %i) {
+; CHECK-LABEL: get_funcref_from_table_with_var_offset2:
+; CHECK-NEXT:  .functype       get_funcref_from_table_with_var_offset2 (i32) -> (funcref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  call    get_offset
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       funcref_table
+; CHECK-NEXT:  end_function
+  %j = call i32 @get_offset()
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %off
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  ret %funcref %ref
+}
+
+; CHECK: .globl funcref_table
Index: llvm/test/CodeGen/WebAssembly/funcref-table_call.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/funcref-table_call.ll
@@ -0,0 +1,32 @@
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s
+
+%func = type void ()
+%funcref = type %func addrspace(20)* ;; addrspace 20 is nonintegral
+
+@funcref_table = local_unnamed_addr addrspace(1) global [0 x %funcref] undef
+
+define void @call_funcref_from_table(i32 %i) {
+  %p = getelementptr [0 x %funcref], [0 x %funcref] addrspace (1)* @funcref_table, i32 0, i32 %i
+  %ref = load %funcref, %funcref addrspace(1)* %p
+  call addrspace(20) void %ref()
+  ret void
+}
+
+; CHECK: .tabletype __funcref_call_table, funcref, 1
+
+; CHECK-LABEL: call_funcref_from_table:
+; CHECK-NEXT: .functype       call_funcref_from_table (i32) -> ()
+; CHECK-NEXT: i32.const       0
+; CHECK-NEXT: local.get       0
+; CHECK-NEXT: table.get       funcref_table
+; CHECK-NEXT: table.set       __funcref_call_table
+; CHECK-NEXT: i32.const       0
+; CHECK-NEXT: call_indirect    __funcref_call_table, () -> ()
+; CHECK-NEXT: i32.const       0
+; CHECK-NEXT: ref.null        func
+; CHECK-NEXT: table.set       __funcref_call_table
+; CHECK-NEXT: end_function
+
+
+; CHECK:     .globl funcref_table
+; CHECK-NEXT .globaltype     funcref_table, funcref
Index: llvm/test/CodeGen/WebAssembly/externref-tableset.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/externref-tableset.ll
@@ -0,0 +1,82 @@
+; RUN: llc --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types < %s | FileCheck %s
+
+%extern = type opaque
+%externref = type %extern addrspace(10)* ;; addrspace 10 is nonintegral
+
+@externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef
+
+define void @set_externref_table(%externref %g, i32 %i) {
+; CHECK-LABEL: set_externref_table:
+; CHECK-NEXT: .functype       set_externref_table (externref, i32) -> ()
+; CHECK-NEXT: local.get      1
+; CHECK-NEXT: local.get      0
+; CHECK-NEXT: table.set     externref_table
+; CHECK-NEXT: end_function
+
+;; this generates a table.set of @externref_table
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %i
+  store %externref %g, %externref addrspace(1)* %p
+  ret void
+}
+
+define void @set_externref_table_const(%externref %g) {
+; CHECK-LABEL: set_externref_table_const:
+; CHECK-NEXT:  .functype      set_externref_table_const (externref) -> ()
+; CHECK-NEXT:  i32.const      0
+; CHECK-NEXT:  local.get      0
+; CHECK-NEXT:  table.set      externref_table
+; CHECK-NEXT:  end_function
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 0
+  store %externref %g, %externref addrspace(1)* %p
+  ret void
+}
+
+define void @set_externref_table_with_offset(%externref %g, i32 %i) {
+; CHECK-LABEL: set_externref_table_with_offset:
+; CHECK-NEXT:  .functype       set_externref_table_with_offset (externref, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  i32.const       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       externref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, 2
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  store %externref %g, %externref addrspace(1)* %p
+  ret void
+}
+
+define void @set_externref_table_with_var_offset(%externref %g, i32 %i, i32 %j) {
+; CHECK-LABEL: set_externref_table_with_var_offset:
+; CHECK-NEXT:  .functype       set_externref_table_with_var_offset (externref, i32, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  local.get       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       externref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  store %externref %g, %externref addrspace(1)* %p
+  ret void
+}
+
+declare i32 @set_offset()
+
+define void @set_externref_table_with_var_offset2(%externref %g, i32 %i) {
+; CHECK-LABEL: set_externref_table_with_var_offset2:
+; CHECK-NEXT:  .functype       set_externref_table_with_var_offset2 (externref, i32) -> ()
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  call    set_offset
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  table.set       externref_table
+; CHECK-NEXT:  end_function
+  %j = call i32 @set_offset()
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  store %externref %g, %externref addrspace(1)* %p
+  ret void
+}
+
+; CHECK: .globl externref_table
Index: llvm/test/CodeGen/WebAssembly/externref-tableget.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/externref-tableget.ll
@@ -0,0 +1,76 @@
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -mattr=+reference-types | FileCheck %s
+
+%extern = type opaque
+%externref = type %extern addrspace(10)* ;; addrspace 10 is nonintegral
+
+@externref_table = local_unnamed_addr addrspace(1) global [0 x %externref] undef
+
+define %externref @get_externref_from_table(i32 %i) {
+; CHECK-LABEL: get_externref_from_table:
+; CHECK-NEXT: .functype       get_externref_from_table (i32) -> (externref)
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: table.get externref_table
+; CHECK-NEXT: end_function
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %i
+  %ref = load %externref, %externref addrspace(1)* %p
+  ret %externref %ref
+}
+
+define %externref @get_externref_from_table_const() {
+; CHECK-LABEL: get_externref_from_table_const:
+; CHECK-NEXT:  .functype      get_externref_from_table_const () -> (externref)
+; CHECK-NEXT:  i32.const      0
+; CHECK-NEXT:  table.get      externref_table
+; CHECK-NEXT:  end_function
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 0
+  %ref = load %externref, %externref addrspace(1)* %p
+  ret %externref %ref
+}
+
+define %externref @get_externref_from_table_with_offset(i32 %i) {
+; CHECK-LABEL: get_externref_from_table_with_offset:
+; CHECK-NEXT:  .functype       get_externref_from_table_with_offset (i32) -> (externref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  i32.const       2
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       externref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, 2
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  %ref = load %externref, %externref addrspace(1)* %p
+  ret %externref %ref
+}
+
+
+define %externref @get_externref_from_table_with_var_offset(i32 %i, i32 %j) {
+; CHECK-LABEL: get_externref_from_table_with_var_offset:
+; CHECK-NEXT:  .functype       get_externref_from_table_with_var_offset (i32, i32) -> (externref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  local.get       1
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       externref_table
+; CHECK-NEXT:  end_function
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  %ref = load %externref, %externref addrspace(1)* %p
+  ret %externref %ref
+}
+
+declare i32 @get_offset()
+
+define %externref @get_externref_from_table_with_var_offset2(i32 %i) {
+; CHECK-LABEL: get_externref_from_table_with_var_offset2:
+; CHECK-NEXT:  .functype       get_externref_from_table_with_var_offset2 (i32) -> (externref)
+; CHECK-NEXT:  local.get       0
+; CHECK-NEXT:  call    get_offset
+; CHECK-NEXT:  i32.add
+; CHECK-NEXT:  table.get       externref_table
+; CHECK-NEXT:  end_function
+  %j = call i32 @get_offset()
+  %off = add nsw i32 %i, %j
+  %p = getelementptr [0 x %externref], [0 x %externref] addrspace (1)* @externref_table, i32 0, i32 %off
+  %ref = load %externref, %externref addrspace(1)* %p
+  ret %externref %ref
+}
+
+; CHECK: .globl externref_table
Index: llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -133,12 +133,14 @@
     : LLVMTargetMachine(
           T,
           TT.isArch64Bit()
-              ? (TT.isOSEmscripten()
-                     ? "e-m:e-p:64:64-i64:64-f128:64-n32:64-S128-ni:1:10:20"
-                     : "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20")
-              : (TT.isOSEmscripten()
-                     ? "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20"
-                     : "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"),
+              ? (TT.isOSEmscripten() ? "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
+                                       "f128:64-n32:64-S128-ni:1:10:20"
+                                     : "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
+                                       "n32:64-S128-ni:1:10:20")
+              : (TT.isOSEmscripten() ? "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
+                                       "f128:64-n32:64-S128-ni:1:10:20"
+                                     : "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
+                                       "n32:64-S128-ni:1:10:20"),
           TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT),
           getEffectiveCodeModel(CM, CodeModel::Large), OL),
       TLOF(new WebAssemblyTargetObjectFile()) {
Index: llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -497,6 +497,10 @@
     return WebAssembly::TEE_F64;
   if (RC == &WebAssembly::V128RegClass)
     return WebAssembly::TEE_V128;
+  if (RC == &WebAssembly::EXTERNREFRegClass)
+    return WebAssembly::TEE_EXTERNREF;
+  if (RC == &WebAssembly::FUNCREFRegClass)
+    return WebAssembly::TEE_FUNCREF;
   llvm_unreachable("Unexpected register class");
 }
 
Index: llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -17,6 +17,7 @@
 #include "Utils/WebAssemblyTypeUtilities.h"
 #include "Utils/WebAssemblyUtilities.h"
 #include "WebAssemblyAsmPrinter.h"
+#include "WebAssemblyISelLowering.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -28,6 +29,7 @@
 #include "llvm/MC/MCSymbolWasm.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+
 using namespace llvm;
 
 // This disables the removal of registers when lowering into MC, as required
@@ -56,15 +58,30 @@
       const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
       const TargetMachine &TM = MF.getTarget();
       const Function &CurrentFunc = MF.getFunction();
+      Type *GlobalVT = Global->getValueType();
       SmallVector<MVT, 1> VTs;
-      computeLegalValueVTs(CurrentFunc, TM, Global->getValueType(), VTs);
-      if (VTs.size() != 1)
+      computeLegalValueVTs(CurrentFunc, TM, GlobalVT, VTs);
+
+      // Tables are represented as Arrays in LLVM IR therefore
+      // they reach this point as aggregate Array types with an element type
+      // that is a reference type.
+      wasm::ValType Type;
+      if (GlobalVT->isArrayTy() &&
+          WebAssembly::isRefType(GlobalVT->getArrayElementType())) {
+        MVT VT =
+            GlobalVT->getArrayElementType()->getPointerAddressSpace() ==
+                    WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF
+                ? MVT::funcref
+                : MVT::externref;
+        Type = WebAssembly::toValType(VT);
+      } else if (VTs.size() == 1) {
+        Type = WebAssembly::toValType(VTs[0]);
+      } else
         report_fatal_error("Aggregate globals not yet implemented");
 
-      bool Mutable = true;
-      wasm::ValType Type = WebAssembly::toValType(VTs[0]);
       WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
-      WasmSym->setGlobalType(wasm::WasmGlobalType{uint8_t(Type), Mutable});
+      WasmSym->setGlobalType(
+          wasm::WasmGlobalType{uint8_t(Type), /*Mutable=*/true});
     }
     return WasmSym;
   }
Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
+++ llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
@@ -11,9 +11,18 @@
 /// Instructions that handle tables
 //===----------------------------------------------------------------------===//
 
-multiclass TABLE<WebAssemblyRegClass rt> {
+def WebAssemblyTableSet_t : SDTypeProfile<0, 3, [SDTCisPtrTy<1>]>;
+def WebAssemblyTableSet : SDNode<"WebAssemblyISD::TABLE_SET", WebAssemblyTableSet_t,
+                                 [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
+
+def WebAssemblyTableGet_t : SDTypeProfile<1, 2, [SDTCisPtrTy<1>]>;
+def WebAssemblyTableGet : SDNode<"WebAssemblyISD::TABLE_GET", WebAssemblyTableGet_t,
+                                 [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
+
+
+multiclass TABLE<WebAssemblyRegClass rc> {
   let mayLoad = 1 in
-  defm TABLE_GET_#rt : I<(outs rt:$res), (ins table32_op:$table, I32:$i),
+  defm TABLE_GET_#rc : I<(outs rc:$res), (ins table32_op:$table, I32:$i),
                          (outs), (ins table32_op:$table),
                          [],
                          "table.get\t$res, $table, $i",
@@ -21,41 +30,43 @@
                          0x25>;
 
   let mayStore = 1 in
-  defm TABLE_SET_#rt : I<(outs), (ins table32_op:$table, I32:$i, rt:$val),
+  defm TABLE_SET_#rc : I<(outs), (ins table32_op:$table, I32:$i, rc:$val),
                          (outs), (ins table32_op:$table),
                          [],
                          "table.set\t$table, $i, $val",
                          "table.set\t$table",
                          0x26>;
 
-  defm TABLE_GROW_#rt : I<(outs I32:$sz), (ins table32_op:$table, rt:$val, I32:$n),
+  defm TABLE_GROW_#rc : I<(outs I32:$sz), (ins table32_op:$table, rc:$val, I32:$n),
                           (outs), (ins table32_op:$table),
                           [],
                           "table.grow\t$sz, $table, $val, $n",
                           "table.grow\t$table",
                           0xfc0f>;
 
-  defm TABLE_FILL_#rt : I<(outs), (ins table32_op:$table, I32:$i, rt:$val, I32:$n),
+  defm TABLE_FILL_#rc : I<(outs), (ins table32_op:$table, I32:$i, rc:$val, I32:$n),
                           (outs), (ins table32_op:$table),
                           [],
                           "table.fill\t$table, $i, $val, $n",
                           "table.fill\t$table",
                           0xfc11>;
 
+  foreach vt = rc.RegTypes in {
+    def : Pat<(vt (WebAssemblyTableGet (WebAssemblyWrapper tglobaladdr:$table), i32:$idx)),
+              (!cast<NI>("TABLE_GET_" # rc) tglobaladdr:$table, i32:$idx)>;
+    def : Pat<(WebAssemblyTableSet
+               (WebAssemblyWrapper tglobaladdr:$table),
+               i32:$idx,
+               vt:$src),
+              (!cast<NI>("TABLE_SET_" # rc) tglobaladdr:$table, i32:$idx, vt:$src)>;
+  }
 }
 
 defm "" : TABLE<FUNCREF>, Requires<[HasReferenceTypes]>;
 defm "" : TABLE<EXTERNREF>, Requires<[HasReferenceTypes]>;
 
-def wasm_table_set_t : SDTypeProfile<0, 3, []>;
-def wasm_table_set : SDNode<"WebAssemblyISD::TABLE_SET", wasm_table_set_t,
-                            [SDNPHasChain, SDNPMayStore, SDNPMemOperand]>;
-
-def : Pat<(wasm_table_set i32:$table, i32:$idx, funcref:$r),
-          (TABLE_SET_FUNCREF i32:$table, i32:$idx, funcref:$r)>,
-          Requires<[HasReferenceTypes]>;
-def : Pat<(wasm_table_set i32:$table, i32:$idx, externref:$r),
-          (TABLE_SET_EXTERNREF i32:$table, i32:$idx, externref:$r)>,
+def : Pat<(WebAssemblyTableSet mcsym:$table, i32:$idx, funcref:$r),
+          (TABLE_SET_FUNCREF mcsym:$table, i32:$idx, funcref:$r)>,
           Requires<[HasReferenceTypes]>;
 
 defm TABLE_SIZE : I<(outs I32:$sz), (ins table32_op:$table),
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -136,6 +136,11 @@
   SDValue LowerLoad(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerStore(SDValue Op, SelectionDAG &DAG) const;
 
+  // Helper for LoadLoad and LowerStore
+  bool MatchTableForLowering(SelectionDAG &DAG, const SDLoc &DL,
+                             const SDValue &Base, GlobalAddressSDNode **GA,
+                             SDValue &Idx) const;
+
   // Custom DAG combine hooks
   SDValue
   PerformDAGCombine(SDNode *N,
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -88,7 +88,9 @@
     }
   }
   if (Subtarget->hasReferenceTypes()) {
-    for (auto T : {MVT::externref, MVT::funcref}) {
+    // We need custom load and store lowering for both externref, funcref and
+    // Other. The MVT::Other here represents tables of reference types.
+    for (auto T : {MVT::externref, MVT::funcref, MVT::Other}) {
       setOperationAction(ISD::LOAD, T, Custom);
       setOperationAction(ISD::STORE, T, Custom);
     }
@@ -1422,6 +1424,81 @@
   return WebAssemblyFrameLowering::getLocalForStackObject(MF, FI->getIndex());
 }
 
+static bool IsWebAssemblyTable(SDValue Op) {
+  const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
+  if (GA && WebAssembly::isWasmVarAddressSpace(GA->getAddressSpace())) {
+    const GlobalValue *Value = GA->getGlobal();
+    const Type *Ty = Value->getValueType();
+
+    if (Ty->isArrayTy() && WebAssembly::isRefType(Ty->getArrayElementType()))
+      return true;
+  }
+  return false;
+}
+
+// This function will accept as Op any access to a table, so Op can
+// be the actual table or an offset into the table.
+static bool IsWebAssemblyTableWithOffset(SDValue Op) {
+  if (Op->getOpcode() == ISD::ADD && Op->getNumOperands() == 2)
+    return (Op->getOperand(1).getSimpleValueType() == MVT::i32 &&
+            IsWebAssemblyTableWithOffset(Op->getOperand(0))) ||
+           (Op->getOperand(0).getSimpleValueType() == MVT::i32 &&
+            IsWebAssemblyTableWithOffset(Op->getOperand(1)));
+
+  return IsWebAssemblyTable(Op);
+}
+
+// Helper for table pattern matching used in LowerStore and LowerLoad
+bool WebAssemblyTargetLowering::MatchTableForLowering(SelectionDAG &DAG,
+                                                      const SDLoc &DL,
+                                                      const SDValue &Base,
+                                                      GlobalAddressSDNode **GA,
+                                                      SDValue &Idx) const {
+  // We expect the following graph for a load of the form:
+  // table[<var> + <constant offset>]
+  //
+  // Case 1:
+  // externref = load t1
+  // t1: i32 = add t2, i32:<constant offset>
+  // t2: i32 = add tX, table
+  //
+  // This is in some cases simplified to just:
+  // Case 2:
+  // externref = load t1
+  // t1: i32 = add t2, i32:tX
+  //
+  // So, unfortunately we need to check for both cases and if we are in the
+  // first case extract the table GlobalAddressNode and build a new node tY
+  // that's tY: i32 = add i32:<constant offset>, i32:tX
+  //
+  if (IsWebAssemblyTable(Base)) {
+    *GA = cast<GlobalAddressSDNode>(Base);
+    Idx = DAG.getConstant(0, DL, MVT::i32);
+  } else {
+    *GA = dyn_cast<GlobalAddressSDNode>(Base->getOperand(0));
+    if (!*GA) {
+      // This might be Case 1 above (or an error)
+      SDValue V = Base->getOperand(0);
+      *GA = dyn_cast<GlobalAddressSDNode>(V->getOperand(1));
+
+      if (V->getOpcode() != ISD::ADD || V->getNumOperands() != 2 || !*GA)
+        return false;
+
+      SDValue IdxV = DAG.getNode(ISD::ADD, DL, MVT::i32, Base->getOperand(1),
+                                 V->getOperand(0));
+      Idx = IdxV;
+    } else {
+      // We are in Case 2 above.
+
+      Idx = Base->getOperand(1);
+      if (!Idx || (*GA)->getNumValues() != 1 || Idx->getNumValues() != 1)
+        return false;
+    }
+  }
+
+  return true;
+}
+
 SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
                                               SelectionDAG &DAG) const {
   SDLoc DL(Op);
@@ -1430,6 +1507,26 @@
   const SDValue &Base = SN->getBasePtr();
   const SDValue &Offset = SN->getOffset();
 
+  if (IsWebAssemblyTableWithOffset(Base)) {
+    if (!Offset->isUndef())
+      report_fatal_error(
+          "unexpected offset when loading from webassembly table", false);
+
+    SDValue Idx;
+    GlobalAddressSDNode *GA;
+
+    if (!MatchTableForLowering(DAG, DL, Base, &GA, Idx))
+      report_fatal_error("failed pattern matching for lowering table store",
+                         false);
+
+    SDVTList Tys = DAG.getVTList(MVT::Other);
+    SDValue TableSetOps[] = {SN->getChain(), SDValue(GA, 0), Idx, Value};
+    SDValue TableSet =
+        DAG.getMemIntrinsicNode(WebAssemblyISD::TABLE_SET, DL, Tys, TableSetOps,
+                                SN->getMemoryVT(), SN->getMemOperand());
+    return TableSet;
+  }
+
   if (IsWebAssemblyGlobal(Base)) {
     if (!Offset->isUndef())
       report_fatal_error("unexpected offset when storing to webassembly global",
@@ -1462,6 +1559,26 @@
   const SDValue &Base = LN->getBasePtr();
   const SDValue &Offset = LN->getOffset();
 
+  if (IsWebAssemblyTableWithOffset(Base)) {
+    if (!Offset->isUndef())
+      report_fatal_error(
+          "unexpected offset when loading from webassembly table", false);
+
+    GlobalAddressSDNode *GA;
+    SDValue Idx;
+
+    if (!MatchTableForLowering(DAG, DL, Base, &GA, Idx))
+      report_fatal_error("failed pattern matching for lowering table load",
+                         false);
+
+    SDVTList Tys = DAG.getVTList(LN->getValueType(0), MVT::Other);
+    SDValue TableGetOps[] = {LN->getChain(), SDValue(GA, 0), Idx};
+    SDValue TableGet =
+        DAG.getMemIntrinsicNode(WebAssemblyISD::TABLE_GET, DL, Tys, TableGetOps,
+                                LN->getMemoryVT(), LN->getMemOperand());
+    return TableGet;
+  }
+
   if (IsWebAssemblyGlobal(Base)) {
     if (!Offset->isUndef())
       report_fatal_error(
Index: llvm/lib/Target/WebAssembly/WebAssemblyISD.def
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISD.def
+++ llvm/lib/Target/WebAssembly/WebAssemblyISD.def
@@ -48,4 +48,5 @@
 HANDLE_MEM_NODETYPE(LOAD_SPLAT)
 HANDLE_MEM_NODETYPE(GLOBAL_GET)
 HANDLE_MEM_NODETYPE(GLOBAL_SET)
+HANDLE_MEM_NODETYPE(TABLE_GET)
 HANDLE_MEM_NODETYPE(TABLE_SET)
Index: lld/test/wasm/lto/weak.ll
===================================================================
--- lld/test/wasm/lto/weak.ll
+++ lld/test/wasm/lto/weak.ll
@@ -2,7 +2,7 @@
 ; RUN: wasm-ld %t.o %t.o -o %t.wasm -r
 ; RUN: llvm-readobj --symbols %t.wasm | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 define weak void @f() {
Index: lld/test/wasm/lto/weak-undefined.ll
===================================================================
--- lld/test/wasm/lto/weak-undefined.ll
+++ lld/test/wasm/lto/weak-undefined.ll
@@ -6,7 +6,7 @@
 ; We had a bug where stub function generation was failing because functions
 ; that are in bitcode (pre-LTO) don't have signatures assigned.
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 declare extern_weak i32 @foo()
Index: lld/test/wasm/lto/verify-invalid.ll
===================================================================
--- lld/test/wasm/lto/verify-invalid.ll
+++ lld/test/wasm/lto/verify-invalid.ll
@@ -8,7 +8,7 @@
 ; RUN: wasm-ld %t.o -o %t2 --no-lto-legacy-pass-manager --lto-debug-pass-manager \
 ; RUN:   -disable-verify 2>&1 | FileCheck -check-prefix=DISABLE-NPM %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @_start() {
Index: lld/test/wasm/lto/used.ll
===================================================================
--- lld/test/wasm/lto/used.ll
+++ lld/test/wasm/lto/used.ll
@@ -5,7 +5,7 @@
 
 ; Verify that symbols references from regular objects are preserved by LTO
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 declare void @bar()
Index: lld/test/wasm/lto/undef.ll
===================================================================
--- lld/test/wasm/lto/undef.ll
+++ lld/test/wasm/lto/undef.ll
@@ -2,7 +2,7 @@
 ; RUN: wasm-ld %t.o -o %t.wasm --allow-undefined
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 declare i32 @bar()
Index: lld/test/wasm/lto/tls.ll
===================================================================
--- lld/test/wasm/lto/tls.ll
+++ lld/test/wasm/lto/tls.ll
@@ -7,7 +7,7 @@
 ; RUN: wasm-ld --export=tls_int --export=get_tls %t1.o -o %t
 ; RUN: obj2yaml %t | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20"
 target triple = "wasm32-unknown-emscripten"
 
 @tls_int = dso_local thread_local global i32 99
Index: lld/test/wasm/lto/thinlto.ll
===================================================================
--- lld/test/wasm/lto/thinlto.ll
+++ lld/test/wasm/lto/thinlto.ll
@@ -52,7 +52,7 @@
 ; NM1: T f
 ; NM2: T g
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 declare void @g(...)
Index: lld/test/wasm/lto/save-temps.ll
===================================================================
--- lld/test/wasm/lto/save-temps.ll
+++ lld/test/wasm/lto/save-temps.ll
@@ -8,7 +8,7 @@
 ; RUN: llvm-nm a.out.lto.o | FileCheck %s
 ; RUN: llvm-dis a.out.0.0.preopt.bc
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @foo() {
Index: lld/test/wasm/lto/relocatable.ll
===================================================================
--- lld/test/wasm/lto/relocatable.ll
+++ lld/test/wasm/lto/relocatable.ll
@@ -12,7 +12,7 @@
 ; CHECK-NEXT:   }
 ; CHECK-NEXT: ]
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @foo() {
Index: lld/test/wasm/lto/relocatable-undefined.ll
===================================================================
--- lld/test/wasm/lto/relocatable-undefined.ll
+++ lld/test/wasm/lto/relocatable-undefined.ll
@@ -2,7 +2,7 @@
 ; RUN: wasm-ld -r -o %t.wasm %t.o
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 @missing_data = external global i32
Index: lld/test/wasm/lto/parallel.ll
===================================================================
--- lld/test/wasm/lto/parallel.ll
+++ lld/test/wasm/lto/parallel.ll
@@ -4,7 +4,7 @@
 ; RUN: llvm-nm %t.lto.o | FileCheck --check-prefix=CHECK0 %s
 ; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 ; CHECK0-NOT: bar
Index: lld/test/wasm/lto/opt-level.ll
===================================================================
--- lld/test/wasm/lto/opt-level.ll
+++ lld/test/wasm/lto/opt-level.ll
@@ -15,7 +15,7 @@
 ; RUN:   FileCheck --check-prefix=INVALIDNEGATIVE %s
 ; INVALIDNEGATIVE: invalid optimization level for LTO: 4294967295
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 ; CHECK-O0: Name: foo
Index: lld/test/wasm/lto/new-pass-manager.ll
===================================================================
--- lld/test/wasm/lto/new-pass-manager.ll
+++ lld/test/wasm/lto/new-pass-manager.ll
@@ -5,7 +5,7 @@
 ; CHECK: Running pass: GlobalOptPass
 ; LPM-NOT: Running pass: GlobalOptPass
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @_start() local_unnamed_addr {
Index: lld/test/wasm/lto/lto-start.ll
===================================================================
--- lld/test/wasm/lto/lto-start.ll
+++ lld/test/wasm/lto/lto-start.ll
@@ -8,7 +8,7 @@
 ; CHECK-NEXT:       - Index:           0
 ; CHECK-NEXT:         Name:            _start
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 define void @_start() {
Index: lld/test/wasm/lto/libcall-truncsfhf2.ll
===================================================================
--- lld/test/wasm/lto/libcall-truncsfhf2.ll
+++ lld/test/wasm/lto/libcall-truncsfhf2.ll
@@ -4,7 +4,7 @@
 ; RUN: llvm-ar rcs %t.a %t.truncsfhf2.o
 ; RUN: not wasm-ld --export-all %t.o %t.a -o %t.wasm 2>&1 | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 @g_float = global float 0.0
Index: lld/test/wasm/lto/libcall-archive.ll
===================================================================
--- lld/test/wasm/lto/libcall-archive.ll
+++ lld/test/wasm/lto/libcall-archive.ll
@@ -5,7 +5,7 @@
 ; RUN: wasm-ld -o %t %t.o %t.a
 ; RUN: obj2yaml %t | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @_start(i8* %a, i8* %b) {
Index: lld/test/wasm/lto/internalize-basic.ll
===================================================================
--- lld/test/wasm/lto/internalize-basic.ll
+++ lld/test/wasm/lto/internalize-basic.ll
@@ -2,7 +2,7 @@
 ; RUN: wasm-ld %t.o -o %t2 -save-temps
 ; RUN: llvm-dis < %t2.0.2.internalize.bc | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 define void @_start() {
Index: lld/test/wasm/lto/import-attributes.ll
===================================================================
--- lld/test/wasm/lto/import-attributes.ll
+++ lld/test/wasm/lto/import-attributes.ll
@@ -3,7 +3,7 @@
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
 target triple = "wasm32-unknown-unknown-wasm"
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 
 define void @_start() {
   call void @foo();
Index: lld/test/wasm/lto/export.ll
===================================================================
--- lld/test/wasm/lto/export.ll
+++ lld/test/wasm/lto/export.ll
@@ -3,7 +3,7 @@
 ; RUN: wasm-ld --export=hidden_function -o %t.wasm %t.bc
 ; RUN: obj2yaml %t.wasm | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define hidden i32 @hidden_function() local_unnamed_addr {
Index: lld/test/wasm/lto/diagnostics.ll
===================================================================
--- lld/test/wasm/lto/diagnostics.ll
+++ lld/test/wasm/lto/diagnostics.ll
@@ -4,7 +4,7 @@
 ; RUN: llvm-as %s -o %t.o
 ; RUN: not wasm-ld --lto-O0 %t.o -o %t2 2>&1 | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @_start() {
Index: lld/test/wasm/lto/comdat.ll
===================================================================
--- lld/test/wasm/lto/comdat.ll
+++ lld/test/wasm/lto/comdat.ll
@@ -6,7 +6,7 @@
 ; RUN: wasm-ld %t.bc %t.o -o %t.wasm
 ; RUN: wasm-ld %t.o %t.bc -o %t.wasm
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 $foo = comdat any
Index: lld/test/wasm/lto/cache.ll
===================================================================
--- lld/test/wasm/lto/cache.ll
+++ lld/test/wasm/lto/cache.ll
@@ -36,7 +36,7 @@
 ; RUN: wasm-ld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=0s:cache_size=0%:cache_size_files=1:prune_interval=0s -o %t.wasm %t2.o %t.o
 ; RUN: ls %t.cache | count 3
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 define void @globalfunc() #0 {
Index: lld/test/wasm/lto/atomics.ll
===================================================================
--- lld/test/wasm/lto/atomics.ll
+++ lld/test/wasm/lto/atomics.ll
@@ -4,7 +4,7 @@
 ; Atomic operations will not fail to compile if atomics are not
 ; enabled because LLVM atomics will be lowered to regular ops.
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown-wasm"
 
 @foo = hidden global i32 1
Index: lld/test/wasm/lto/archive.ll
===================================================================
--- lld/test/wasm/lto/archive.ll
+++ lld/test/wasm/lto/archive.ll
@@ -5,7 +5,7 @@
 ; RUN: wasm-ld --export-dynamic %t2.o %t.a -o %t3
 ; RUN: obj2yaml %t3 | FileCheck %s
 
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @_start() {
Index: lld/test/wasm/lto/Inputs/used.ll
===================================================================
--- lld/test/wasm/lto/Inputs/used.ll
+++ lld/test/wasm/lto/Inputs/used.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 @foo = hidden global i32 1
Index: lld/test/wasm/lto/Inputs/thinlto.ll
===================================================================
--- lld/test/wasm/lto/Inputs/thinlto.ll
+++ lld/test/wasm/lto/Inputs/thinlto.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @g() {
Index: lld/test/wasm/lto/Inputs/save-temps.ll
===================================================================
--- lld/test/wasm/lto/Inputs/save-temps.ll
+++ lld/test/wasm/lto/Inputs/save-temps.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @bar() {
Index: lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll
===================================================================
--- lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll
+++ lld/test/wasm/lto/Inputs/libcall-truncsfhf2.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define half @__truncsfhf2(float) {
Index: lld/test/wasm/lto/Inputs/libcall-archive.ll
===================================================================
--- lld/test/wasm/lto/Inputs/libcall-archive.ll
+++ lld/test/wasm/lto/Inputs/libcall-archive.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @memcpy() {
Index: lld/test/wasm/lto/Inputs/cache.ll
===================================================================
--- lld/test/wasm/lto/Inputs/cache.ll
+++ lld/test/wasm/lto/Inputs/cache.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define i32 @_start() {
Index: lld/test/wasm/lto/Inputs/archive.ll
===================================================================
--- lld/test/wasm/lto/Inputs/archive.ll
+++ lld/test/wasm/lto/Inputs/archive.ll
@@ -1,4 +1,4 @@
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
 define void @f() {
Index: clang/test/CodeGen/target-data.c
===================================================================
--- clang/test/CodeGen/target-data.c
+++ clang/test/CodeGen/target-data.c
@@ -108,11 +108,11 @@
 
 // RUN: %clang_cc1 -triple wasm32-unknown-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=WEBASSEMBLY32
-// WEBASSEMBLY32: target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"
+// WEBASSEMBLY32: target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
 
 // RUN: %clang_cc1 -triple wasm64-unknown-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=WEBASSEMBLY64
-// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20"
+// WEBASSEMBLY64: target datalayout = "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
 
 // RUN: %clang_cc1 -triple lanai-unknown-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=LANAI
Index: clang/lib/Basic/Targets/WebAssembly.h
===================================================================
--- clang/lib/Basic/Targets/WebAssembly.h
+++ clang/lib/Basic/Targets/WebAssembly.h
@@ -151,9 +151,11 @@
                                    const TargetOptions &Opts)
       : WebAssemblyTargetInfo(T, Opts) {
     if (T.isOSEmscripten())
-      resetDataLayout("e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20");
+      resetDataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-"
+                      "S128-ni:1:10:20");
     else
-      resetDataLayout("e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20");
+      resetDataLayout(
+          "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20");
   }
 
 protected:
@@ -173,9 +175,11 @@
     PtrDiffType = SignedLong;
     IntPtrType = SignedLong;
     if (T.isOSEmscripten())
-      resetDataLayout("e-m:e-p:64:64-i64:64-f128:64-n32:64-S128-ni:1:10:20");
+      resetDataLayout("e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-"
+                      "S128-ni:1:10:20");
     else
-      resetDataLayout("e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20");
+      resetDataLayout(
+          "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20");
   }
 
 protected:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to