[lld] 220fe00 - [WebAssembly] Support `annotate` clang attributes for marking functions.
Derek Schuff via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 11 15:18:08 PDT 2023
Author: Brendan Dahl
Date: 2023-07-11T15:17:26-07:00
New Revision: 220fe00a7c0f73164711f0d6cdefacef264b85dc
URL: https://github.com/llvm/llvm-project/commit/220fe00a7c0f73164711f0d6cdefacef264b85dc
DIFF: https://github.com/llvm/llvm-project/commit/220fe00a7c0f73164711f0d6cdefacef264b85dc.diff
LOG: [WebAssembly] Support `annotate` clang attributes for marking functions.
Annotation attributes may be attached to a function to mark it with
custom data that will be contained in the final Wasm file. The
annotation causes a custom section named
"func_attr.annotate.<name>.<arg0>.<arg1>..." to be created that will
contain each function's index value that was marked with the annotation.
A new patchable relocation type for function indexes had to be created so
the custom section could be updated during linking.
Reviewed By: sbc100
Differential Revision: https://reviews.llvm.org/D150803
Added:
lld/test/wasm/func-attr-tombstone.s
lld/test/wasm/func-attr.s
lld/test/wasm/merge-func-attr-section.s
llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll
llvm/test/MC/WebAssembly/func-attr.s
Modified:
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
Removed:
################################################################################
diff --git a/lld/test/wasm/func-attr-tombstone.s b/lld/test/wasm/func-attr-tombstone.s
new file mode 100644
index 00000000000000..559073783fcf34
--- /dev/null
+++ b/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, at function
+foo:
+ .functype foo () -> ()
+ end_function
+
+ .section .text.bar,"",@
+ .globl bar
+ .type bar, at function
+bar:
+ .functype bar () -> ()
+ end_function
+
+ .globl _start
+ .type _start, at function
+_start:
+ .functype _start () -> ()
+ call foo
+ end_function
+
+ .section .custom_section.llvm.func_attr.custom0,"",@
+ .int32 foo at FUNCINDEX
+ .int32 bar at FUNCINDEX
+
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: llvm.func_attr.custom0
+# CHECK-NEXT: Payload: 00000000FFFFFFFF
diff --git a/lld/test/wasm/func-attr.s b/lld/test/wasm/func-attr.s
new file mode 100644
index 00000000000000..7f6746dd52e02f
--- /dev/null
+++ b/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, at function
+foo:
+ .functype foo () -> ()
+ end_function
+
+ .section .text.bar,"",@
+ .globl bar
+ .type bar, at function
+bar:
+ .functype bar () -> ()
+ end_function
+
+ .globl _start
+ .type _start, at function
+_start:
+ .functype _start () -> ()
+ call foo
+ call bar
+ end_function
+
+ .section .custom_section.llvm.func_attr.custom0,"",@
+ .int32 foo at FUNCINDEX
+ .int32 bar at FUNCINDEX
+
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: llvm.func_attr.custom0
+# CHECK-NEXT: Payload: '0000000001000000'
diff --git a/lld/test/wasm/merge-func-attr-section.s b/lld/test/wasm/merge-func-attr-section.s
new file mode 100644
index 00000000000000..06157782165582
--- /dev/null
+++ b/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: llvm.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, at function
+foo:
+ .functype foo () -> ()
+ end_function
+
+ .globl bar
+ .type bar, at function
+bar:
+ .functype bar () -> ()
+ end_function
+
+ .globl _start
+ .type _start, at function
+_start:
+ .functype _start () -> ()
+ call foo
+ call bar
+ call baz
+ end_function
+
+ .section .custom_section.llvm.func_attr.custom0,"",@
+ .int32 foo at FUNCINDEX
+ .int32 bar at FUNCINDEX
+
+#--- b.s
+ .functype baz () -> ()
+ .globl baz
+ .type baz, at function
+baz:
+ .functype baz () -> ()
+ end_function
+
+ .section .custom_section.llvm.func_attr.custom0,"",@
+ .int32 baz at FUNCINDEX
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 8eda56a61d1e86..a22005fe5f5a7e 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -150,6 +150,7 @@ void InputChunk::relocate(uint8_t *buf) const {
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:
@@ -518,14 +519,18 @@ uint64_t InputSection::getTombstoneForSection(StringRef name) {
// If they occur in DWARF debug symbols, we want to change the pc of the
// 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.starts_with(".debug_"))
- return 0;
+ // meaning of -1 so we use -2.
if (name.equals(".debug_ranges") || name.equals(".debug_loc"))
return UINT64_C(-2);
- return UINT64_C(-1);
+ if (name.starts_with(".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.starts_with("llvm.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
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index bd174c86566924..fa20a35ded9d9e 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -193,6 +193,7 @@ uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc, uint64_t tombstone,
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:
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 606adc92f910d6..62316687b5899d 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -259,7 +259,10 @@ Changes to the RISC-V Backend
Changes to the WebAssembly Backend
----------------------------------
-* ...
+* Function annotations (``__attribute__((annotate(<name>)))``)
+ now generate custom sections in the Wasm output file. A custom section
+ for each unique name will be created that contains each function
+ index the annotation applies to.
Changes to the Windows Target
-----------------------------
diff --git a/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/llvm/include/llvm/BinaryFormat/WasmRelocs.def
index 2913f20dfd26b1..6f5a946b1c63d0 100644
--- a/llvm/include/llvm/BinaryFormat/WasmRelocs.def
+++ b/llvm/include/llvm/BinaryFormat/WasmRelocs.def
@@ -28,3 +28,4 @@ WASM_RELOC(R_WASM_FUNCTION_OFFSET_I64, 22)
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)
diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h
index 49bd6883d4297e..5bc5e04f79ffc3 100644
--- a/llvm/include/llvm/MC/MCExpr.h
+++ b/llvm/include/llvm/MC/MCExpr.h
@@ -331,6 +331,7 @@ class MCSymbolRefExpr : public MCExpr {
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 at gotpcrel32@lo
VK_AMDGPU_GOTPCREL32_HI, // symbol at gotpcrel32@hi
diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp
index a73ae524b8e0ab..f2caadd7fbcf98 100644
--- a/llvm/lib/MC/MCExpr.cpp
+++ b/llvm/lib/MC/MCExpr.cpp
@@ -362,6 +362,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_WASM_TLSREL: return "TLSREL";
case VK_WASM_TBREL: return "TBREL";
case VK_WASM_GOT_TLS: return "GOT at TLS";
+ case VK_WASM_FUNCINDEX: return "FUNCINDEX";
case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32 at lo";
case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32 at hi";
case VK_AMDGPU_REL32_LO: return "rel32 at lo";
@@ -505,6 +506,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("mbrel", VK_WASM_MBREL)
.Case("tlsrel", VK_WASM_TLSREL)
.Case("got at tls", VK_WASM_GOT_TLS)
+ .Case("funcindex", VK_WASM_FUNCINDEX)
.Case("gotpcrel32 at lo", VK_AMDGPU_GOTPCREL32_LO)
.Case("gotpcrel32 at hi", VK_AMDGPU_GOTPCREL32_HI)
.Case("rel32 at lo", VK_AMDGPU_REL32_LO)
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 8c879e3d3b70e3..2b886449f052f2 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -671,6 +671,7 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
// 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 @@ void WasmObjectWriter::applyRelocations(
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:
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 5dbe685a140b3a..a72242bc4ac220 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -948,6 +948,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
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 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
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 ||
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
index 405712906c4006..43c67b4b4749b6 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -91,6 +91,8 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(
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;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 60b1b3f5fc275b..f0002494a95178 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/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 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
EmitProducerInfo(M);
EmitTargetFeatures(M);
+ EmitFunctionAttributes(M);
}
void WebAssemblyAsmPrinter::EmitProducerInfo(Module &M) {
@@ -556,6 +559,49 @@ void WebAssemblyAsmPrinter::EmitTargetFeatures(Module &M) {
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();
+ 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.llvm.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() &&
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index 65d6ee415180b3..c30e0155c81e72 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -66,6 +66,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
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;
diff --git a/llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll b/llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll
new file mode 100644
index 00000000000000..c6640461973b24
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/func-attr-annotate.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+ at .str = private unnamed_addr constant [8 x i8] c"custom0\00", section "llvm.metadata"
+ at .str.1 = private unnamed_addr constant [7 x i8] c"main.c\00", section "llvm.metadata"
+ at .str.2 = private unnamed_addr constant [8 x i8] c"custom1\00", section "llvm.metadata"
+ at .str.3 = private unnamed_addr constant [8 x i8] c"custom2\00", section "llvm.metadata"
+ at llvm.global.annotations = appending global [3 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 }], 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.llvm.func_attr.annotate.custom0,"",@
+; CHECK-NEXT: .int32 test0 at FUNCINDEX
+; CHECK-NEXT: .int32 test1 at FUNCINDEX
+; CHECK: .section .custom_section.llvm.func_attr.annotate.custom1,"",@
+; CHECK-NEXT: .int32 test2 at FUNCINDEX
diff --git a/llvm/test/MC/WebAssembly/func-attr.s b/llvm/test/MC/WebAssembly/func-attr.s
new file mode 100644
index 00000000000000..e99096b30db4d7
--- /dev/null
+++ b/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.llvm.func_attr.custom0,"",@
+ .int32 foo at FUNCINDEX
+
+# CHECK: .section .custom_section.llvm.func_attr.custom0,"",@
+# CHECK-NEXT: .int32 foo at 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: llvm.func_attr.custom0
More information about the llvm-commits
mailing list