brendandahl updated this revision to Diff 535126.
brendandahl added a comment.

Use the annotate attribute to generate custom sections.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150803

Files:
  lld/test/wasm/func-attr-tombstone.s
  lld/test/wasm/func-attr.s
  lld/test/wasm/merge-func-attr-section.s
  lld/wasm/InputChunks.cpp
  lld/wasm/InputFiles.cpp
  llvm/docs/ReleaseNotes.rst
  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/func-attr-annotate.ll
  llvm/test/MC/WebAssembly/func-attr.s

Index: llvm/test/MC/WebAssembly/func-attr.s
===================================================================
--- /dev/null
+++ llvm/test/MC/WebAssembly/func-attr.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.func_attr.custom0,"",@
+    .int32  foo@FUNCINDEX
+
+# CHECK:       .section .custom_section.func_attr.custom0,"",@
+# 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:            func_attr.custom0
Index: llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll
@@ -0,0 +1,36 @@
+; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+@.str = private unnamed_addr constant [8 x i8] c"custom0\00", section "llvm.metadata"
+@.str.1 = private unnamed_addr constant [7 x i8] c"main.c\00", section "llvm.metadata"
+@.str.2 = private unnamed_addr constant [8 x i8] c"custom1\00", section "llvm.metadata"
+@.str.3 = private unnamed_addr constant [8 x i8] c"custom2\00", section "llvm.metadata"
+@.str.4 = private unnamed_addr constant [12 x i8] c"custom2arg0\00", align 1
+@.str.5 = private unnamed_addr constant [12 x i8] c"custom2arg1\00", align 1
+@.args = private unnamed_addr constant { ptr, ptr } { ptr @.str.4, ptr @.str.5 }, section "llvm.metadata"
+@llvm.global.annotations = appending global [4 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @test0, ptr @.str, ptr @.str.1, i32 4, ptr null }, { ptr, ptr, ptr, i32, ptr } { ptr @test1, ptr @.str, ptr @.str.1, i32 5, ptr null }, { ptr, ptr, ptr, i32, ptr } { ptr @test2, ptr @.str.2, ptr @.str.1, i32 6, ptr null }, { ptr, ptr, ptr, i32, ptr } { ptr @test3, ptr @.str.3, ptr @.str.1, i32 7, ptr @.args }], section "llvm.metadata"
+
+define void @test0() {
+  ret void
+}
+
+define void @test1() {
+  ret void
+}
+
+define void @test2() {
+  ret void
+}
+
+define void @test3() {
+  ret void
+}
+
+; CHECK:      .section        .custom_section.func_attr.annotate.custom2.custom2arg0.custom2arg1,"",@
+; CHECK-NEXT: .int32  test3@FUNCINDEX
+; CHECK:      .section        .custom_section.func_attr.annotate.custom0,"",@
+; CHECK-NEXT: .int32  test0@FUNCINDEX
+; CHECK-NEXT: .int32  test1@FUNCINDEX
+; CHECK:      .section        .custom_section.func_attr.annotate.custom1,"",@
+; CHECK-NEXT: .int32  test2@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 EmitFunctionAttributes(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
@@ -27,6 +27,8 @@
 #include "WebAssemblyTargetMachine.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Analysis/ValueTracking.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/CodeGen/AsmPrinter.h"
@@ -438,6 +440,7 @@
 
   EmitProducerInfo(M);
   EmitTargetFeatures(M);
+  EmitFunctionAttributes(M);
 }
 
 void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
@@ -556,6 +559,61 @@
   OutStreamer->popSection();
 }
 
+void WebAssemblyAsmPrinter::EmitFunctionAttributes(Module &M) {
+  auto V = M.getNamedGlobal("llvm.global.annotations");
+  if (!V)
+    return;
+
+  // Group all the custom attributes by name.
+  StringMap<SmallVector<MCSymbol *, 4>> CustomSections;
+  const ConstantArray *CA = cast<ConstantArray>(V->getOperand(0));
+  for (Value *Op : CA->operands()) {
+    auto *CS = cast<ConstantStruct>(Op);
+    // The first field is a pointer to the annotated variable.
+    Value *AnnotatedVar = CS->getOperand(0)->stripPointerCasts();
+    // Only annotated functions are supported for now.
+    if (!isa<Function>(AnnotatedVar))
+      continue;
+    auto *F = cast<Function>(AnnotatedVar);
+
+    // The second field is a pointer to a global annotation string.
+    auto *GV = cast<GlobalVariable>(CS->getOperand(1)->stripPointerCasts());
+    StringRef AnnotationString;
+    getConstantStringInfo(GV, AnnotationString);
+    std::string Name = "annotate." + AnnotationString.str();
+
+    // The fifth field is an optional pointer to the arguments. Append each
+    // argument to the name separated by a '.'.
+    auto *ArgsVar = dyn_cast<GlobalVariable>(CS->getOperand(4)->stripPointerCasts());
+    if (ArgsVar) {
+      auto *ArgsStruct = cast<ConstantStruct>(ArgsVar->getInitializer());
+      for (Value *ArgOp : ArgsStruct->operands()) {
+        StringRef Arg;
+        getConstantStringInfo(ArgOp, Arg);
+        Name += "." + Arg.str();
+      }
+    }
+    auto *Sym = cast<MCSymbolWasm>(getSymbol(F));
+    CustomSections[Name].push_back(Sym);
+  }
+
+  // Emit a custom section for each unique attribute.
+  for (const auto &[Name, Symbols] : CustomSections) {
+    MCSectionWasm *CustomSection = OutContext.getWasmSection(
+        ".custom_section.func_attr." + Name, SectionKind::getMetadata());
+    OutStreamer->pushSection();
+    OutStreamer->switchSection(CustomSection);
+
+    for (auto &Sym : Symbols) {
+      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,7 @@
   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";
@@ -503,6 +504,7 @@
     .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)
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: llvm/docs/ReleaseNotes.rst
===================================================================
--- llvm/docs/ReleaseNotes.rst
+++ llvm/docs/ReleaseNotes.rst
@@ -187,7 +187,10 @@
 Changes to the WebAssembly Backend
 ----------------------------------
 
-* ...
+* Function annotations (``__attribute__((annotate(<name>,<arg0>,<arg1>,..)))``)
+  now generate custom sections in the Wasm output file. A custom section
+  for each unique name and arguments is created that contains each function
+  index the annotation applies to.
 
 Changes to the Windows Target
 -----------------------------
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:
@@ -519,13 +520,17 @@
   // function to -1 to avoid overlapping with a valid range. However for the
   // debug_ranges and debug_loc sections that would conflict with the existing
   // meaning of -1 so we use -2.
-  // Returning 0 means there is no tombstone value for this section, and relocation
-  // will just use the addend.
-  if (!name.startswith(".debug_"))
-    return 0;
   if (name.equals(".debug_ranges") || name.equals(".debug_loc"))
     return UINT64_C(-2);
-  return UINT64_C(-1);
+  if (name.startswith(".debug_"))
+    return UINT64_C(-1);
+  // If the function occurs in an function attribute section change it to -1 since
+  // 0 is a valid function index.
+  if (name.startswith("func_attr."))
+    return UINT64_C(-1);
+  // Returning 0 means there is no tombstone value for this section, and relocation
+  // will just use the addend.
+  return 0;
 }
 
 } // namespace wasm
Index: lld/test/wasm/merge-func-attr-section.s
===================================================================
--- /dev/null
+++ lld/test/wasm/merge-func-attr-section.s
@@ -0,0 +1,56 @@
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/a.s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %t/b.s -o %t2.o
+# RUN: wasm-ld -o %t.wasm %t1.o %t2.o
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Ensure two custom funct_attr sections are concatenated together.
+
+# CHECK:       - Type:            CUSTOM
+# CHECK-NEXT:    Name:            func_attr.custom0
+# CHECK-NEXT:    Payload:         '000000000100000003000000'
+
+#--- a.s
+
+# Function index 3 (after linking)
+        .functype       baz () -> ()
+# Function index 1
+        .functype       foo () -> ()
+# Function index 2
+        .functype       bar () -> ()
+        .functype       _start () -> ()
+        .globl  foo
+        .type   foo,@function
+foo:
+        .functype       foo () -> ()
+        end_function
+
+        .globl  bar
+        .type   bar,@function
+bar:
+        .functype       bar () -> ()
+        end_function
+
+        .globl  _start
+        .type   _start,@function
+_start:
+        .functype       _start () -> ()
+        call    foo
+        call    bar
+        call    baz
+        end_function
+
+        .section        .custom_section.func_attr.custom0,"",@
+        .int32  foo@FUNCINDEX
+        .int32  bar@FUNCINDEX
+
+#--- b.s
+        .functype       baz () -> ()
+        .globl  baz
+        .type   baz,@function
+baz:
+        .functype       baz () -> ()
+        end_function
+
+        .section        .custom_section.func_attr.custom0,"",@
+        .int32  baz@FUNCINDEX
Index: lld/test/wasm/func-attr.s
===================================================================
--- /dev/null
+++ lld/test/wasm/func-attr.s
@@ -0,0 +1,35 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+        .functype       foo () -> ()
+        .functype       bar () -> ()
+        .functype       _start () -> ()
+        .globl  foo
+        .type   foo,@function
+foo:
+        .functype       foo () -> ()
+        end_function
+
+        .section        .text.bar,"",@
+        .globl  bar
+        .type   bar,@function
+bar:
+        .functype       bar () -> ()
+        end_function
+
+        .globl  _start
+        .type   _start,@function
+_start:
+        .functype       _start () -> ()
+        call    foo
+        call    bar
+        end_function
+
+        .section        .custom_section.func_attr.custom0,"",@
+        .int32  foo@FUNCINDEX
+        .int32  bar@FUNCINDEX
+
+# CHECK:       - Type:            CUSTOM
+# CHECK-NEXT:    Name:            func_attr.custom0
+# CHECK-NEXT:    Payload:         '0000000001000000'
Index: lld/test/wasm/func-attr-tombstone.s
===================================================================
--- /dev/null
+++ lld/test/wasm/func-attr-tombstone.s
@@ -0,0 +1,34 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+        .functype       foo () -> ()
+        .functype       bar () -> ()
+        .functype       _start () -> ()
+        .globl  foo
+        .type   foo,@function
+foo:
+        .functype       foo () -> ()
+        end_function
+
+        .section        .text.bar,"",@
+        .globl  bar
+        .type   bar,@function
+bar:
+        .functype       bar () -> ()
+        end_function
+
+        .globl  _start
+        .type   _start,@function
+_start:
+        .functype       _start () -> ()
+        call    foo
+        end_function
+
+        .section        .custom_section.func_attr.custom0,"",@
+        .int32  foo@FUNCINDEX
+        .int32  bar@FUNCINDEX
+
+# CHECK:       - Type:            CUSTOM
+# CHECK-NEXT:    Name:            func_attr.custom0
+# CHECK-NEXT:    Payload:         00000000FFFFFFFF
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to