brendandahl created this revision.
brendandahl added a reviewer: sbc100.
Herald added subscribers: pmatos, asb, jdoerfert, ecnelises, sunfish, 
hiraditya, jgravelle-google, dschuff.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
brendandahl requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, aheejin.
Herald added projects: clang, LLVM.

The attribute may be attached to a function definition, which indicates
the function will be used with JavaScript promise integration (JSPI). The
attribute will cause the creation of a custom section named "async" that
contains each wasm_async function's index value.

A new patchable relocation type for function indexes had to be created so
the custom section could be updated during linking.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150803

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGen/WebAssembly/wasm-async.c
  clang/test/Misc/pragma-attribute-supported-attributes-list.test
  lld/test/wasm/async.ll
  lld/test/wasm/merge-async-section.ll
  lld/wasm/InputChunks.cpp
  lld/wasm/InputFiles.cpp
  llvm/include/llvm/BinaryFormat/WasmRelocs.def
  llvm/include/llvm/MC/MCExpr.h
  llvm/lib/MC/MCExpr.cpp
  llvm/lib/MC/WasmObjectWriter.cpp
  llvm/lib/Object/WasmObjectFile.cpp
  llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
  llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
  llvm/test/CodeGen/WebAssembly/async.ll
  llvm/test/MC/WebAssembly/async.s

Index: llvm/test/MC/WebAssembly/async.s
===================================================================
--- /dev/null
+++ llvm/test/MC/WebAssembly/async.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s
+# Check that it also comiled to object for format.
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o - < %s | obj2yaml | FileCheck -check-prefix=CHECK-OBJ %s
+
+foo:
+    .globl foo
+    .functype foo () -> ()
+    end_function
+
+.section        .custom_section.async,"",@
+    .int32  foo@FUNCINDEX
+
+# CHECK:       .section .custom_section.async,"",@
+# CHECK-NEXT: .int32  foo@FUNCINDEX
+
+# CHECK-OBJ:        - Type:            CUSTOM
+# CHECK-OBJ-NEXT:     Relocations:
+# CHECK-OBJ-NEXT:        - Type:            R_WASM_FUNCTION_INDEX_I32
+# CHECK-OBJ-NEXT:        Index:           0
+# CHECK-OBJ-NEXT:        Offset:          0x0
+# CHECK-OBJ-NEXT:     Name:            async
Index: llvm/test/CodeGen/WebAssembly/async.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/async.ll
@@ -0,0 +1,18 @@
+; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define void @test0() #0 {
+  ret void
+}
+
+define void @test1() #1 {
+  ret void
+}
+
+attributes #0 = { "wasm-async" }
+attributes #1 = { "wasm-async" }
+
+; CHECK:      .section        .custom_section.async,"",@
+; CHECK-NEXT: .int32  test0@FUNCINDEX
+; CHECK-NEXT: .int32  test1@FUNCINDEX
Index: llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -66,6 +66,7 @@
   void emitEndOfAsmFile(Module &M) override;
   void EmitProducerInfo(Module &M);
   void EmitTargetFeatures(Module &M);
+  void EmitAsync(Module &M);
   void emitSymbolType(const MCSymbolWasm *Sym);
   void emitGlobalVariable(const GlobalVariable *GV) override;
   void emitJumpTableInfo() override;
Index: llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -438,6 +438,7 @@
 
   EmitProducerInfo(M);
   EmitTargetFeatures(M);
+  EmitAsync(M);
 }
 
 void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
@@ -556,6 +557,33 @@
   OutStreamer->popSection();
 }
 
+void WebAssemblyAsmPrinter::EmitAsync(Module &M) {
+  SmallVector<MCSymbol *, 4> EmittedAsyncs;
+
+  for (const auto &F : M) {
+    auto *Sym = cast<MCSymbolWasm>(getSymbol(&F));
+    if (F.hasFnAttribute("wasm-async")) {
+      EmittedAsyncs.push_back(Sym);
+    }
+  }
+  if (EmittedAsyncs.size() == 0)
+    return;
+
+  MCSectionWasm *AsyncSection = OutContext.getWasmSection(
+      ".custom_section.async", SectionKind::getMetadata());
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(AsyncSection);
+
+  for (auto &Sym : EmittedAsyncs) {
+    OutStreamer->emitValue(
+        MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_WASM_FUNCINDEX,
+                                OutContext),
+        4);
+  }
+
+  OutStreamer->popSection();
+}
+
 void WebAssemblyAsmPrinter::emitConstantPool() {
   emitDecls(*MMI->getModule());
   assert(MF->getConstantPool()->getConstants().empty() &&
Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -91,6 +91,8 @@
       return wasm::R_WASM_TYPE_INDEX_LEB;
     case MCSymbolRefExpr::VK_None:
       break;
+    case MCSymbolRefExpr::VK_WASM_FUNCINDEX:
+      return wasm::R_WASM_FUNCTION_INDEX_I32;
     default:
       report_fatal_error("unknown VariantKind");
       break;
Index: llvm/lib/Object/WasmObjectFile.cpp
===================================================================
--- llvm/lib/Object/WasmObjectFile.cpp
+++ llvm/lib/Object/WasmObjectFile.cpp
@@ -948,6 +948,7 @@
     Reloc.Index = readVaruint32(Ctx);
     switch (type) {
     case wasm::R_WASM_FUNCTION_INDEX_LEB:
+    case wasm::R_WASM_FUNCTION_INDEX_I32:
     case wasm::R_WASM_TABLE_INDEX_SLEB:
     case wasm::R_WASM_TABLE_INDEX_SLEB64:
     case wasm::R_WASM_TABLE_INDEX_I32:
@@ -1045,6 +1046,7 @@
         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
+        Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
       Size = 4;
     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
Index: llvm/lib/MC/WasmObjectWriter.cpp
===================================================================
--- llvm/lib/MC/WasmObjectWriter.cpp
+++ llvm/lib/MC/WasmObjectWriter.cpp
@@ -671,6 +671,7 @@
     // Provisional value is same as the index
     return getRelocationIndexValue(RelEntry);
   case wasm::R_WASM_FUNCTION_INDEX_LEB:
+  case wasm::R_WASM_FUNCTION_INDEX_I32:
   case wasm::R_WASM_GLOBAL_INDEX_LEB:
   case wasm::R_WASM_GLOBAL_INDEX_I32:
   case wasm::R_WASM_TAG_INDEX_LEB:
@@ -791,6 +792,7 @@
     case wasm::R_WASM_TABLE_INDEX_I32:
     case wasm::R_WASM_MEMORY_ADDR_I32:
     case wasm::R_WASM_FUNCTION_OFFSET_I32:
+    case wasm::R_WASM_FUNCTION_INDEX_I32:
     case wasm::R_WASM_SECTION_OFFSET_I32:
     case wasm::R_WASM_GLOBAL_INDEX_I32:
     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
Index: llvm/lib/MC/MCExpr.cpp
===================================================================
--- llvm/lib/MC/MCExpr.cpp
+++ llvm/lib/MC/MCExpr.cpp
@@ -360,6 +360,8 @@
   case VK_WASM_TLSREL: return "TLSREL";
   case VK_WASM_TBREL: return "TBREL";
   case VK_WASM_GOT_TLS: return "GOT@TLS";
+  case VK_WASM_FUNCINDEX:
+    return "FUNCINDEX";
   case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
   case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
   case VK_AMDGPU_REL32_LO: return "rel32@lo";
@@ -388,143 +390,144 @@
 MCSymbolRefExpr::VariantKind
 MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
   return StringSwitch<VariantKind>(Name.lower())
-    .Case("dtprel", VK_DTPREL)
-    .Case("dtpoff", VK_DTPOFF)
-    .Case("got", VK_GOT)
-    .Case("gotoff", VK_GOTOFF)
-    .Case("gotrel", VK_GOTREL)
-    .Case("pcrel", VK_PCREL)
-    .Case("gotpcrel", VK_GOTPCREL)
-    .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX)
-    .Case("gottpoff", VK_GOTTPOFF)
-    .Case("indntpoff", VK_INDNTPOFF)
-    .Case("ntpoff", VK_NTPOFF)
-    .Case("gotntpoff", VK_GOTNTPOFF)
-    .Case("plt", VK_PLT)
-    .Case("tlscall", VK_TLSCALL)
-    .Case("tlsdesc", VK_TLSDESC)
-    .Case("tlsgd", VK_TLSGD)
-    .Case("tlsld", VK_TLSLD)
-    .Case("tlsldm", VK_TLSLDM)
-    .Case("tpoff", VK_TPOFF)
-    .Case("tprel", VK_TPREL)
-    .Case("tlvp", VK_TLVP)
-    .Case("tlvppage", VK_TLVPPAGE)
-    .Case("tlvppageoff", VK_TLVPPAGEOFF)
-    .Case("page", VK_PAGE)
-    .Case("pageoff", VK_PAGEOFF)
-    .Case("gotpage", VK_GOTPAGE)
-    .Case("gotpageoff", VK_GOTPAGEOFF)
-    .Case("imgrel", VK_COFF_IMGREL32)
-    .Case("secrel32", VK_SECREL)
-    .Case("size", VK_SIZE)
-    .Case("abs8", VK_X86_ABS8)
-    .Case("pltoff", VK_X86_PLTOFF)
-    .Case("l", VK_PPC_LO)
-    .Case("h", VK_PPC_HI)
-    .Case("ha", VK_PPC_HA)
-    .Case("high", VK_PPC_HIGH)
-    .Case("higha", VK_PPC_HIGHA)
-    .Case("higher", VK_PPC_HIGHER)
-    .Case("highera", VK_PPC_HIGHERA)
-    .Case("highest", VK_PPC_HIGHEST)
-    .Case("highesta", VK_PPC_HIGHESTA)
-    .Case("got@l", VK_PPC_GOT_LO)
-    .Case("got@h", VK_PPC_GOT_HI)
-    .Case("got@ha", VK_PPC_GOT_HA)
-    .Case("local", VK_PPC_LOCAL)
-    .Case("tocbase", VK_PPC_TOCBASE)
-    .Case("toc", VK_PPC_TOC)
-    .Case("toc@l", VK_PPC_TOC_LO)
-    .Case("toc@h", VK_PPC_TOC_HI)
-    .Case("toc@ha", VK_PPC_TOC_HA)
-    .Case("u", VK_PPC_U)
-    .Case("l", VK_PPC_L)
-    .Case("tls", VK_PPC_TLS)
-    .Case("dtpmod", VK_PPC_DTPMOD)
-    .Case("tprel@l", VK_PPC_TPREL_LO)
-    .Case("tprel@h", VK_PPC_TPREL_HI)
-    .Case("tprel@ha", VK_PPC_TPREL_HA)
-    .Case("tprel@high", VK_PPC_TPREL_HIGH)
-    .Case("tprel@higha", VK_PPC_TPREL_HIGHA)
-    .Case("tprel@higher", VK_PPC_TPREL_HIGHER)
-    .Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
-    .Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
-    .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)
-    .Case("dtprel@l", VK_PPC_DTPREL_LO)
-    .Case("dtprel@h", VK_PPC_DTPREL_HI)
-    .Case("dtprel@ha", VK_PPC_DTPREL_HA)
-    .Case("dtprel@high", VK_PPC_DTPREL_HIGH)
-    .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA)
-    .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
-    .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
-    .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
-    .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)
-    .Case("got@tprel", VK_PPC_GOT_TPREL)
-    .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)
-    .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)
-    .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)
-    .Case("got@dtprel", VK_PPC_GOT_DTPREL)
-    .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)
-    .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)
-    .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)
-    .Case("got@tlsgd", VK_PPC_GOT_TLSGD)
-    .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)
-    .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)
-    .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)
-    .Case("got@tlsld", VK_PPC_GOT_TLSLD)
-    .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
-    .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
-    .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
-    .Case("got@pcrel", VK_PPC_GOT_PCREL)
-    .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL)
-    .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL)
-    .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL)
-    .Case("tls@pcrel", VK_PPC_TLS_PCREL)
-    .Case("notoc", VK_PPC_NOTOC)
-    .Case("gdgot", VK_Hexagon_GD_GOT)
-    .Case("gdplt", VK_Hexagon_GD_PLT)
-    .Case("iegot", VK_Hexagon_IE_GOT)
-    .Case("ie", VK_Hexagon_IE)
-    .Case("ldgot", VK_Hexagon_LD_GOT)
-    .Case("ldplt", VK_Hexagon_LD_PLT)
-    .Case("none", VK_ARM_NONE)
-    .Case("got_prel", VK_ARM_GOT_PREL)
-    .Case("target1", VK_ARM_TARGET1)
-    .Case("target2", VK_ARM_TARGET2)
-    .Case("prel31", VK_ARM_PREL31)
-    .Case("sbrel", VK_ARM_SBREL)
-    .Case("tlsldo", VK_ARM_TLSLDO)
-    .Case("lo8", VK_AVR_LO8)
-    .Case("hi8", VK_AVR_HI8)
-    .Case("hlo8", VK_AVR_HLO8)
-    .Case("typeindex", VK_WASM_TYPEINDEX)
-    .Case("tbrel", VK_WASM_TBREL)
-    .Case("mbrel", VK_WASM_MBREL)
-    .Case("tlsrel", VK_WASM_TLSREL)
-    .Case("got@tls", VK_WASM_GOT_TLS)
-    .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
-    .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
-    .Case("rel32@lo", VK_AMDGPU_REL32_LO)
-    .Case("rel32@hi", VK_AMDGPU_REL32_HI)
-    .Case("rel64", VK_AMDGPU_REL64)
-    .Case("abs32@lo", VK_AMDGPU_ABS32_LO)
-    .Case("abs32@hi", VK_AMDGPU_ABS32_HI)
-    .Case("hi", VK_VE_HI32)
-    .Case("lo", VK_VE_LO32)
-    .Case("pc_hi", VK_VE_PC_HI32)
-    .Case("pc_lo", VK_VE_PC_LO32)
-    .Case("got_hi", VK_VE_GOT_HI32)
-    .Case("got_lo", VK_VE_GOT_LO32)
-    .Case("gotoff_hi", VK_VE_GOTOFF_HI32)
-    .Case("gotoff_lo", VK_VE_GOTOFF_LO32)
-    .Case("plt_hi", VK_VE_PLT_HI32)
-    .Case("plt_lo", VK_VE_PLT_LO32)
-    .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
-    .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
-    .Case("tpoff_hi", VK_VE_TPOFF_HI32)
-    .Case("tpoff_lo", VK_VE_TPOFF_LO32)
-    .Default(VK_Invalid);
+      .Case("dtprel", VK_DTPREL)
+      .Case("dtpoff", VK_DTPOFF)
+      .Case("got", VK_GOT)
+      .Case("gotoff", VK_GOTOFF)
+      .Case("gotrel", VK_GOTREL)
+      .Case("pcrel", VK_PCREL)
+      .Case("gotpcrel", VK_GOTPCREL)
+      .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX)
+      .Case("gottpoff", VK_GOTTPOFF)
+      .Case("indntpoff", VK_INDNTPOFF)
+      .Case("ntpoff", VK_NTPOFF)
+      .Case("gotntpoff", VK_GOTNTPOFF)
+      .Case("plt", VK_PLT)
+      .Case("tlscall", VK_TLSCALL)
+      .Case("tlsdesc", VK_TLSDESC)
+      .Case("tlsgd", VK_TLSGD)
+      .Case("tlsld", VK_TLSLD)
+      .Case("tlsldm", VK_TLSLDM)
+      .Case("tpoff", VK_TPOFF)
+      .Case("tprel", VK_TPREL)
+      .Case("tlvp", VK_TLVP)
+      .Case("tlvppage", VK_TLVPPAGE)
+      .Case("tlvppageoff", VK_TLVPPAGEOFF)
+      .Case("page", VK_PAGE)
+      .Case("pageoff", VK_PAGEOFF)
+      .Case("gotpage", VK_GOTPAGE)
+      .Case("gotpageoff", VK_GOTPAGEOFF)
+      .Case("imgrel", VK_COFF_IMGREL32)
+      .Case("secrel32", VK_SECREL)
+      .Case("size", VK_SIZE)
+      .Case("abs8", VK_X86_ABS8)
+      .Case("pltoff", VK_X86_PLTOFF)
+      .Case("l", VK_PPC_LO)
+      .Case("h", VK_PPC_HI)
+      .Case("ha", VK_PPC_HA)
+      .Case("high", VK_PPC_HIGH)
+      .Case("higha", VK_PPC_HIGHA)
+      .Case("higher", VK_PPC_HIGHER)
+      .Case("highera", VK_PPC_HIGHERA)
+      .Case("highest", VK_PPC_HIGHEST)
+      .Case("highesta", VK_PPC_HIGHESTA)
+      .Case("got@l", VK_PPC_GOT_LO)
+      .Case("got@h", VK_PPC_GOT_HI)
+      .Case("got@ha", VK_PPC_GOT_HA)
+      .Case("local", VK_PPC_LOCAL)
+      .Case("tocbase", VK_PPC_TOCBASE)
+      .Case("toc", VK_PPC_TOC)
+      .Case("toc@l", VK_PPC_TOC_LO)
+      .Case("toc@h", VK_PPC_TOC_HI)
+      .Case("toc@ha", VK_PPC_TOC_HA)
+      .Case("u", VK_PPC_U)
+      .Case("l", VK_PPC_L)
+      .Case("tls", VK_PPC_TLS)
+      .Case("dtpmod", VK_PPC_DTPMOD)
+      .Case("tprel@l", VK_PPC_TPREL_LO)
+      .Case("tprel@h", VK_PPC_TPREL_HI)
+      .Case("tprel@ha", VK_PPC_TPREL_HA)
+      .Case("tprel@high", VK_PPC_TPREL_HIGH)
+      .Case("tprel@higha", VK_PPC_TPREL_HIGHA)
+      .Case("tprel@higher", VK_PPC_TPREL_HIGHER)
+      .Case("tprel@highera", VK_PPC_TPREL_HIGHERA)
+      .Case("tprel@highest", VK_PPC_TPREL_HIGHEST)
+      .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA)
+      .Case("dtprel@l", VK_PPC_DTPREL_LO)
+      .Case("dtprel@h", VK_PPC_DTPREL_HI)
+      .Case("dtprel@ha", VK_PPC_DTPREL_HA)
+      .Case("dtprel@high", VK_PPC_DTPREL_HIGH)
+      .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA)
+      .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER)
+      .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA)
+      .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST)
+      .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA)
+      .Case("got@tprel", VK_PPC_GOT_TPREL)
+      .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO)
+      .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI)
+      .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA)
+      .Case("got@dtprel", VK_PPC_GOT_DTPREL)
+      .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO)
+      .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI)
+      .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA)
+      .Case("got@tlsgd", VK_PPC_GOT_TLSGD)
+      .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO)
+      .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI)
+      .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA)
+      .Case("got@tlsld", VK_PPC_GOT_TLSLD)
+      .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO)
+      .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI)
+      .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA)
+      .Case("got@pcrel", VK_PPC_GOT_PCREL)
+      .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL)
+      .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL)
+      .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL)
+      .Case("tls@pcrel", VK_PPC_TLS_PCREL)
+      .Case("notoc", VK_PPC_NOTOC)
+      .Case("gdgot", VK_Hexagon_GD_GOT)
+      .Case("gdplt", VK_Hexagon_GD_PLT)
+      .Case("iegot", VK_Hexagon_IE_GOT)
+      .Case("ie", VK_Hexagon_IE)
+      .Case("ldgot", VK_Hexagon_LD_GOT)
+      .Case("ldplt", VK_Hexagon_LD_PLT)
+      .Case("none", VK_ARM_NONE)
+      .Case("got_prel", VK_ARM_GOT_PREL)
+      .Case("target1", VK_ARM_TARGET1)
+      .Case("target2", VK_ARM_TARGET2)
+      .Case("prel31", VK_ARM_PREL31)
+      .Case("sbrel", VK_ARM_SBREL)
+      .Case("tlsldo", VK_ARM_TLSLDO)
+      .Case("lo8", VK_AVR_LO8)
+      .Case("hi8", VK_AVR_HI8)
+      .Case("hlo8", VK_AVR_HLO8)
+      .Case("typeindex", VK_WASM_TYPEINDEX)
+      .Case("tbrel", VK_WASM_TBREL)
+      .Case("mbrel", VK_WASM_MBREL)
+      .Case("tlsrel", VK_WASM_TLSREL)
+      .Case("got@tls", VK_WASM_GOT_TLS)
+      .Case("funcindex", VK_WASM_FUNCINDEX)
+      .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
+      .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
+      .Case("rel32@lo", VK_AMDGPU_REL32_LO)
+      .Case("rel32@hi", VK_AMDGPU_REL32_HI)
+      .Case("rel64", VK_AMDGPU_REL64)
+      .Case("abs32@lo", VK_AMDGPU_ABS32_LO)
+      .Case("abs32@hi", VK_AMDGPU_ABS32_HI)
+      .Case("hi", VK_VE_HI32)
+      .Case("lo", VK_VE_LO32)
+      .Case("pc_hi", VK_VE_PC_HI32)
+      .Case("pc_lo", VK_VE_PC_LO32)
+      .Case("got_hi", VK_VE_GOT_HI32)
+      .Case("got_lo", VK_VE_GOT_LO32)
+      .Case("gotoff_hi", VK_VE_GOTOFF_HI32)
+      .Case("gotoff_lo", VK_VE_GOTOFF_LO32)
+      .Case("plt_hi", VK_VE_PLT_HI32)
+      .Case("plt_lo", VK_VE_PLT_LO32)
+      .Case("tls_gd_hi", VK_VE_TLS_GD_HI32)
+      .Case("tls_gd_lo", VK_VE_TLS_GD_LO32)
+      .Case("tpoff_hi", VK_VE_TPOFF_HI32)
+      .Case("tpoff_lo", VK_VE_TPOFF_LO32)
+      .Default(VK_Invalid);
 }
 
 /* *** */
Index: llvm/include/llvm/MC/MCExpr.h
===================================================================
--- llvm/include/llvm/MC/MCExpr.h
+++ llvm/include/llvm/MC/MCExpr.h
@@ -330,6 +330,7 @@
     VK_WASM_MBREL,     // Memory address relative to __memory_base
     VK_WASM_TBREL,     // Table index relative to __table_base
     VK_WASM_GOT_TLS,   // Wasm global index of TLS symbol.
+    VK_WASM_FUNCINDEX, // Wasm function index.
 
     VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo
     VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
Index: llvm/include/llvm/BinaryFormat/WasmRelocs.def
===================================================================
--- llvm/include/llvm/BinaryFormat/WasmRelocs.def
+++ llvm/include/llvm/BinaryFormat/WasmRelocs.def
@@ -28,3 +28,4 @@
 WASM_RELOC(R_WASM_MEMORY_ADDR_LOCREL_I32, 23)
 WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB64, 24)
 WASM_RELOC(R_WASM_MEMORY_ADDR_TLS_SLEB64, 25)
+WASM_RELOC(R_WASM_FUNCTION_INDEX_I32,     26)
Index: lld/wasm/InputFiles.cpp
===================================================================
--- lld/wasm/InputFiles.cpp
+++ lld/wasm/InputFiles.cpp
@@ -193,6 +193,7 @@
   case R_WASM_TYPE_INDEX_LEB:
     return typeMap[reloc.Index];
   case R_WASM_FUNCTION_INDEX_LEB:
+  case R_WASM_FUNCTION_INDEX_I32:
     return getFunctionSymbol(reloc.Index)->getFunctionIndex();
   case R_WASM_GLOBAL_INDEX_LEB:
   case R_WASM_GLOBAL_INDEX_I32:
Index: lld/wasm/InputChunks.cpp
===================================================================
--- lld/wasm/InputChunks.cpp
+++ lld/wasm/InputChunks.cpp
@@ -150,6 +150,7 @@
     case R_WASM_TABLE_INDEX_I32:
     case R_WASM_MEMORY_ADDR_I32:
     case R_WASM_FUNCTION_OFFSET_I32:
+    case R_WASM_FUNCTION_INDEX_I32:
     case R_WASM_SECTION_OFFSET_I32:
     case R_WASM_GLOBAL_INDEX_I32:
     case R_WASM_MEMORY_ADDR_LOCREL_I32:
Index: lld/test/wasm/merge-async-section.ll
===================================================================
--- /dev/null
+++ lld/test/wasm/merge-async-section.ll
@@ -0,0 +1,49 @@
+; RUN: split-file %s %t
+; RUN: llc -filetype=obj %t/a.ll -o %t1.o
+; RUN: llc -filetype=obj %t/b.ll -o %t2.o
+; RUN: wasm-ld -o %t.wasm %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+; Ensure two async sections are concatenated together.
+
+; CHECK:       - Type:            CUSTOM
+; CHECK-NEXT:    Name:            async
+; CHECK-NEXT:    Payload:         '000000000100000003000000'
+
+;--- a.ll
+
+target triple = "wasm32-unknown-unknown"
+
+; Function index 3 (after linking)
+declare void @baz()
+
+; Function index 0
+define void @foo() #0 {
+    ret void
+}
+
+; Function index 1
+define void @bar() #1 {
+    ret void
+}
+
+; Function index 2
+define void @_start() {
+    call void @foo()
+    call void @bar()
+    call void @baz()
+    ret void
+}
+
+attributes #0 = { "wasm-async" }
+attributes #1 = { "wasm-async" }
+
+;--- b.ll
+
+target triple = "wasm32-unknown-unknown"
+
+define void @baz() #0 {
+    ret void
+}
+
+attributes #0 = { "wasm-async" }
Index: lld/test/wasm/async.ll
===================================================================
--- /dev/null
+++ lld/test/wasm/async.ll
@@ -0,0 +1,26 @@
+; RUN: llc -filetype=obj %s -o %t.o
+; RUN: wasm-ld -o %t.wasm %t.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define void @foo() #0 {
+    ret void
+}
+
+define void @bar() #1 {
+    ret void
+}
+
+define void @_start() {
+    call void @foo()
+    call void @bar()
+    ret void
+}
+
+attributes #0 = { "wasm-async" }
+attributes #1 = { "wasm-async" }
+
+; CHECK:       - Type:            CUSTOM
+; CHECK-NEXT:    Name:            async
+; CHECK-NEXT:    Payload:         '0000000001000000'
Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test
===================================================================
--- clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -196,6 +196,7 @@
 // CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType, SubjectMatchRule_type_alias)
 // CHECK-NEXT: Weak (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)
 // CHECK-NEXT: WeakRef (SubjectMatchRule_variable, SubjectMatchRule_function)
+// CHECK-NEXT: WebAssemblyAsync (SubjectMatchRule_function)
 // CHECK-NEXT: WebAssemblyExportName (SubjectMatchRule_function)
 // CHECK-NEXT: WebAssemblyImportModule (SubjectMatchRule_function)
 // CHECK-NEXT: WebAssemblyImportName (SubjectMatchRule_function)
Index: clang/test/CodeGen/WebAssembly/wasm-async.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/WebAssembly/wasm-async.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown-wasm -emit-llvm -o - %s | FileCheck %s
+
+__attribute__((wasm_async)) int foo(void) {
+  return 43;
+}
+
+// CHECK: define i32 @foo() [[A:#[0-9]+]]
+
+// CHECK: attributes [[A]] = {{{.*}} "wasm-async" {{.*}}}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -7633,6 +7633,23 @@
   FD->addAttr(::new (S.Context) WebAssemblyImportNameAttr(S.Context, AL, Str));
 }
 
+static void handleWebAssemblyAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  if (!isFunctionOrMethod(D)) {
+    S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
+        << "'wasm_async'" << ExpectedFunction;
+    return;
+  }
+
+  auto *FD = cast<FunctionDecl>(D);
+  if (FD->isThisDeclarationADefinition()) {
+    S.Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WebAssemblyAsyncAttr(S.Context, AL));
+  D->addAttr(UsedAttr::CreateImplicit(S.Context));
+}
+
 static void handleRISCVInterruptAttr(Sema &S, Decl *D,
                                      const ParsedAttr &AL) {
   // Warn about repeated attributes.
@@ -8739,6 +8756,9 @@
   case ParsedAttr::AT_WebAssemblyImportName:
     handleWebAssemblyImportNameAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_WebAssemblyAsync:
+    handleWebAssemblyAsyncAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_IBOutlet:
     handleIBOutlet(S, D, AL);
     break;
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -894,6 +894,12 @@
         B.addAttribute("wasm-export-name", Attr->getExportName());
         Fn->addFnAttrs(B);
       }
+      if (FD->getAttr<WebAssemblyAsyncAttr>()) {
+        llvm::Function *Fn = cast<llvm::Function>(GV);
+        llvm::AttrBuilder B(GV->getContext());
+        B.addAttribute("wasm-async");
+        Fn->addFnAttrs(B);
+      }
     }
 
     if (auto *FD = dyn_cast_or_null<FunctionDecl>(D)) {
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -5602,6 +5602,17 @@
   }];
 }
 
+def WebAssemblyAsyncDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+Clang supports the ``__attribute__((wasm_async))``
+attribute for the WebAssembly target. This attribute may be attached to a
+function definition, which indicates the function will be used with JavaScript
+promise integration (JSPI). The attribute will cause the creation of a custom
+section named "async" that contains each wasm_async function's index value.
+  }];
+}
+
 def ArtificialDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -1979,6 +1979,13 @@
   let Subjects = SubjectList<[Function], ErrorDiag>;
 }
 
+def WebAssemblyAsync : InheritableAttr,
+                       TargetSpecificAttr<TargetWebAssembly> {
+  let Spellings = [Clang<"wasm_async">];
+  let Documentation = [WebAssemblyAsyncDocs];
+  let Subjects = SubjectList<[Function], ErrorDiag>;
+}
+
 def NoSplitStack : InheritableAttr {
   let Spellings = [GCC<"no_split_stack">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to