[clang] [compiler-rt] [lld] [llvm] [Coverage][WebAssembly] Add initial support for WebAssembly/WASI (PR #111332)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 6 19:59:53 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-webassembly
Author: Yuta Saito (kateinoigakukun)
<details>
<summary>Changes</summary>
Currently, WebAssembly/WASI target does not provide direct support for code coverage.
This patch set fixes several issues to unlock the feature. The main changes are:
1. Port `compiler-rt/lib/profile` to WebAssembly/WASI.
2. Adjust profile metadata sections for Wasm object file format.
- [CodeGen] Emit `__llvm_covmap` and `__llvm_covfun` as custom sections instead of data segments.
- [lld] Align the interval space of custom sections at link time.
- [llvm-cov] Copy misaligned custom section data if the start address is not aligned.
- [llvm-cov] Read `__llvm_prf_names` from data segments
3. [clang] Link with profile runtime libraries if requested
See each commit message for more details and rationale.
---
Patch is 22.72 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/111332.diff
21 Files Affected:
- (modified) clang/lib/Driver/ToolChains/WebAssembly.cpp (+2)
- (modified) compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake (+1-1)
- (modified) compiler-rt/cmake/config-ix.cmake (+1-1)
- (modified) compiler-rt/lib/profile/CMakeLists.txt (+24)
- (modified) compiler-rt/lib/profile/GCDAProfiling.c (+1-1)
- (modified) compiler-rt/lib/profile/InstrProfilingPlatformLinux.c (+2-2)
- (modified) compiler-rt/lib/profile/InstrProfilingPlatformOther.c (+1-1)
- (modified) compiler-rt/lib/profile/InstrProfilingPort.h (+1-1)
- (modified) compiler-rt/lib/profile/InstrProfilingUtil.c (+8-4)
- (added) lld/test/wasm/custom-section-align.s (+31)
- (modified) lld/wasm/InputChunks.h (+6-4)
- (modified) lld/wasm/InputFiles.cpp (+16-2)
- (modified) lld/wasm/OutputSections.cpp (+1)
- (modified) llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp (+5-1)
- (modified) llvm/lib/MC/MCContext.cpp (+5)
- (modified) llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp (+64-9)
- (modified) llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp (+2-2)
- (added) llvm/test/CodeGen/WebAssembly/profile.ll (+47)
- (added) llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.wasm32 ()
- (added) llvm/test/tools/llvm-cov/Inputs/binary-formats.wasm.proftext (+4)
- (modified) llvm/test/tools/llvm-cov/binary-formats.c (+6)
``````````diff
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 9aec11e69fde1d..44a6894d30fb29 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -163,6 +163,8 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}
+ ToolChain.addProfileRTLibs(Args, CmdArgs);
+
CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());
diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index 809e9277156912..d00d39518104bf 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -77,7 +77,7 @@ set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64})
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
- ${RISCV32} ${RISCV64} ${LOONGARCH64})
+ ${RISCV32} ${RISCV64} ${LOONGARCH64} ${WASM32})
set(ALL_CTX_PROFILE_SUPPORTED_ARCH ${X86_64})
if (OS_NAME MATCHES "FreeBSD")
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64})
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index a93a88a9205001..a494e0532a50bc 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -822,7 +822,7 @@ else()
endif()
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
- OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX")
+ OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI")
set(COMPILER_RT_HAS_PROFILE TRUE)
else()
set(COMPILER_RT_HAS_PROFILE FALSE)
diff --git a/compiler-rt/lib/profile/CMakeLists.txt b/compiler-rt/lib/profile/CMakeLists.txt
index ef23492514898b..a6402f80b890a2 100644
--- a/compiler-rt/lib/profile/CMakeLists.txt
+++ b/compiler-rt/lib/profile/CMakeLists.txt
@@ -38,6 +38,17 @@ int main() {
" COMPILER_RT_TARGET_HAS_FCNTL_LCK)
+CHECK_CXX_SOURCE_COMPILES("
+#include <sys/file.h>
+
+int fd;
+int main() {
+ flock(fd, LOCK_EX);
+ return 0;
+}
+
+" COMPILER_RT_TARGET_HAS_FLOCK)
+
CHECK_CXX_SOURCE_COMPILES("
#include <sys/utsname.h>
int main() {
@@ -93,6 +104,13 @@ if(FUCHSIA OR UNIX)
-Wno-pedantic)
endif()
+if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
+ set(EXTRA_FLAGS
+ ${EXTRA_FLAGS}
+ -D_WASI_EMULATED_MMAN
+ -D_WASI_EMULATED_GETPID)
+endif()
+
if(COMPILER_RT_TARGET_HAS_ATOMICS)
set(EXTRA_FLAGS
${EXTRA_FLAGS}
@@ -105,6 +123,12 @@ if(COMPILER_RT_TARGET_HAS_FCNTL_LCK)
-DCOMPILER_RT_HAS_FCNTL_LCK=1)
endif()
+if(COMPILER_RT_TARGET_HAS_FLOCK)
+ set(EXTRA_FLAGS
+ ${EXTRA_FLAGS}
+ -DCOMPILER_RT_HAS_FLOCK=1)
+endif()
+
if(COMPILER_RT_TARGET_HAS_UNAME)
set(EXTRA_FLAGS
${EXTRA_FLAGS}
diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c
index d6e2175169e4a5..a207ddf97c8831 100644
--- a/compiler-rt/lib/profile/GCDAProfiling.c
+++ b/compiler-rt/lib/profile/GCDAProfiling.c
@@ -584,7 +584,7 @@ void llvm_reset_counters(void) {
}
}
-#if !defined(_WIN32)
+#if !defined(_WIN32) && !defined(__wasi__)
COMPILER_RT_VISIBILITY
pid_t __gcov_fork() {
pid_t parent_pid = getpid();
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
index b766436497b741..a9791eebabc9df 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
@@ -8,9 +8,9 @@
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
- defined(_AIX)
+ defined(_AIX) || defined(__wasm__)
-#if !defined(_AIX)
+#if !defined(_AIX) && !defined(__wasm__)
#include <elf.h>
#include <link.h>
#endif
diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
index aa79a5641ceca6..e873e9ffbfc6d7 100644
--- a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
+++ b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c
@@ -8,7 +8,7 @@
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
!defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
- !defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX)
+ !defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && !defined(__wasm__)
#include <stdlib.h>
#include <stdio.h>
diff --git a/compiler-rt/lib/profile/InstrProfilingPort.h b/compiler-rt/lib/profile/InstrProfilingPort.h
index ed0905cc5f2022..8715a3b0d2a6f0 100644
--- a/compiler-rt/lib/profile/InstrProfilingPort.h
+++ b/compiler-rt/lib/profile/InstrProfilingPort.h
@@ -54,7 +54,7 @@
#endif
#define COMPILER_RT_MAX_HOSTLEN 128
-#ifdef __ORBIS__
+#if defined(__ORBIS__) || defined(__wasi__)
#define COMPILER_RT_GETHOSTNAME(Name, Len) ((void)(Name), (void)(Len), (-1))
#else
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
diff --git a/compiler-rt/lib/profile/InstrProfilingUtil.c b/compiler-rt/lib/profile/InstrProfilingUtil.c
index 642393d432d7ea..95ec4080ba2504 100644
--- a/compiler-rt/lib/profile/InstrProfilingUtil.c
+++ b/compiler-rt/lib/profile/InstrProfilingUtil.c
@@ -152,9 +152,11 @@ COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
}
}
return 0;
-#else
+#elif defined(COMPILER_RT_HAS_FLOCK)
flock(fd, LOCK_EX);
return 0;
+#else
+ return 0;
#endif
}
@@ -177,9 +179,11 @@ COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
}
}
return 0;
-#else
+#elif defined(COMPILER_RT_HAS_FLOCK)
flock(fd, LOCK_UN);
return 0;
+#else
+ return 0;
#endif
}
@@ -353,8 +357,8 @@ COMPILER_RT_VISIBILITY void lprofRestoreSigKill(void) {
COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
uintptr_t End) {
-#if defined(__ve__)
- // VE doesn't support madvise.
+#if defined(__ve__) || defined(__wasi__)
+ // VE and WASI doesn't support madvise.
return 0;
#else
size_t PageSize = getpagesize();
diff --git a/lld/test/wasm/custom-section-align.s b/lld/test/wasm/custom-section-align.s
new file mode 100644
index 00000000000000..0e46177f4cdb79
--- /dev/null
+++ b/lld/test/wasm/custom-section-align.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
+# RUN: wasm-ld --no-entry %t.o -o %t.wasm
+# RUN: obj2yaml %t.wasm | FileCheck %s
+
+# Check that "__llvm_covfun" custom section is aligned to 8 bytes.
+
+ .section .custom_section.__llvm_covfun,"GR",@,__covrec_A
+ .int32 1
+ .int8 2
+# pad .int8 0
+# .int8 0
+# .int8 0
+
+ .section .custom_section.__llvm_covfun,"GR",@,__covrec_B
+ .int32 3
+
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: __llvm_covfun
+# CHECK-NEXT: Payload: '010000000200000003000000'
+
+# Check that regular custom sections are not aligned.
+ .section .custom_section.foo,"GR",@,foo_A
+ .int32 1
+ .int8 2
+
+ .section .custom_section.foo,"GR",@,foo_B
+ .int32 3
+
+# CHECK: - Type: CUSTOM
+# CHECK-NEXT: Name: foo
+# CHECK-NEXT: Payload: '010000000203000000'
diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h
index 14eb008c212fb5..d6769bcf5c8232 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -177,8 +177,9 @@ class MergeInputChunk : public InputChunk {
inputSectionOffset = seg.SectionOffset;
}
- MergeInputChunk(const WasmSection &s, ObjFile *f)
- : InputChunk(f, Merge, s.Name, 0, llvm::wasm::WASM_SEG_FLAG_STRINGS) {
+ MergeInputChunk(const WasmSection &s, ObjFile *f, uint32_t alignment)
+ : InputChunk(f, Merge, s.Name, alignment,
+ llvm::wasm::WASM_SEG_FLAG_STRINGS) {
assert(s.Type == llvm::wasm::WASM_SEC_CUSTOM);
comdat = s.Comdat;
rawData = s.Content;
@@ -234,6 +235,7 @@ class SyntheticMergedChunk : public InputChunk {
void addMergeChunk(MergeInputChunk *ms) {
comdat = ms->getComdat();
+ alignment = std::max(alignment, ms->alignment);
ms->parent = this;
chunks.push_back(ms);
}
@@ -337,8 +339,8 @@ class SyntheticFunction : public InputFunction {
// Represents a single Wasm Section within an input file.
class InputSection : public InputChunk {
public:
- InputSection(const WasmSection &s, ObjFile *f)
- : InputChunk(f, InputChunk::Section, s.Name),
+ InputSection(const WasmSection &s, ObjFile *f, uint32_t alignment)
+ : InputChunk(f, InputChunk::Section, s.Name, alignment),
tombstoneValue(getTombstoneForSection(s.Name)), section(s) {
assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM);
comdat = section.Comdat;
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index de8e707ab2b497..a60deba9113cd4 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -18,6 +18,7 @@
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/Wasm.h"
+#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TarWriter.h"
#include "llvm/Support/raw_ostream.h"
@@ -451,6 +452,18 @@ void SharedFile::parse() {
}
}
+/// Returns the alignment for a custom section. This is used to concatenate
+/// custom sections with the same name into a single custom section.
+static uint32_t getCustomSectionAlignment(const WasmSection &sec) {
+ // TODO: Add a section attribute for alignment in the linking spec.
+ if (sec.Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm) ||
+ sec.Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm)) {
+ // llvm-cov assumes that coverage metadata sections are 8-byte aligned.
+ return 8;
+ }
+ return 1;
+}
+
WasmFileBase::WasmFileBase(Kind k, MemoryBufferRef m) : InputFile(k, m) {
// Parse a memory buffer as a wasm file.
LLVM_DEBUG(dbgs() << "Reading object: " << toString(this) << "\n");
@@ -520,10 +533,11 @@ void ObjFile::parse(bool ignoreComdats) {
dataSection = §ion;
} else if (section.Type == WASM_SEC_CUSTOM) {
InputChunk *customSec;
+ uint32_t alignment = getCustomSectionAlignment(section);
if (shouldMerge(section))
- customSec = make<MergeInputChunk>(section, this);
+ customSec = make<MergeInputChunk>(section, this, alignment);
else
- customSec = make<InputSection>(section, this);
+ customSec = make<InputSection>(section, this, alignment);
customSec->discarded = isExcludedByComdat(customSec);
customSections.emplace_back(customSec);
customSections.back()->setRelocations(section.Relocations);
diff --git a/lld/wasm/OutputSections.cpp b/lld/wasm/OutputSections.cpp
index b0b2446cb56bfc..e4f75829ec4c3e 100644
--- a/lld/wasm/OutputSections.cpp
+++ b/lld/wasm/OutputSections.cpp
@@ -244,6 +244,7 @@ void CustomSection::finalizeContents() {
for (InputChunk *section : inputSections) {
assert(!section->discarded);
+ payloadSize = alignTo(payloadSize, section->alignment);
section->outSecOff = payloadSize;
payloadSize += section->getSize();
}
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 0d3e4ba5662e01..ce50a3c19ffe04 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2171,7 +2171,11 @@ MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
// This could be avoided if all data segements (the wasm sense) were
// represented as their own sections (in the llvm sense).
// TODO(sbc): https://github.com/WebAssembly/tool-conventions/issues/138
- if (Name == ".llvmcmd" || Name == ".llvmbc")
+ if (Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm,
+ /*AddSegmentInfo=*/false) ||
+ Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm,
+ /*AddSegmentInfo=*/false) ||
+ Name == ".llvmbc" || Name == ".llvmcmd")
Kind = SectionKind::getMetadata();
StringRef Group = "";
diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp
index ac3946b6ef46f3..b97f9d9f5fed0f 100644
--- a/llvm/lib/MC/MCContext.cpp
+++ b/llvm/lib/MC/MCContext.cpp
@@ -757,6 +757,11 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
if (!Group.isTriviallyEmpty() && !Group.str().empty()) {
GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
GroupSym->setComdat(true);
+ if (K.isMetadata() && !GroupSym->getType().has_value()) {
+ // Comdat group symbol associated with a custom section is a section
+ // symbol (not a data symbol).
+ GroupSym->setType(wasm::WASM_SYMBOL_TYPE_SECTION);
+ }
}
return getWasmSection(Section, K, Flags, GroupSym, UniqueID);
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index bc4e780fb67a60..347578ad5fbfbe 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -18,12 +18,14 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/Wasm.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
@@ -1075,6 +1077,53 @@ lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) {
return Sections;
}
+/// Find a section that matches \p Name and is allocatable at runtime.
+///
+/// Returns the contents of the section and its start offset in the object file.
+static Expected<std::pair<StringRef, uint64_t>>
+lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK) {
+ // On Wasm, allocatable sections can live only in data segments.
+ if (auto *WOF = dyn_cast<WasmObjectFile>(&OF)) {
+ std::vector<const WasmSegment *> Segments;
+ auto ObjFormat = OF.getTripleObjectFormat();
+ auto Name =
+ getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false);
+ for (const auto &DebugName : WOF->debugNames()) {
+ if (DebugName.Type != wasm::NameType::DATA_SEGMENT ||
+ DebugName.Name != Name)
+ continue;
+ if (DebugName.Index >= WOF->dataSegments().size())
+ return make_error<CoverageMapError>(coveragemap_error::malformed);
+ auto &Segment = WOF->dataSegments()[DebugName.Index];
+ Segments.push_back(&Segment);
+ }
+ if (Segments.empty())
+ return make_error<CoverageMapError>(coveragemap_error::no_data_found);
+ if (Segments.size() != 1)
+ return make_error<CoverageMapError>(coveragemap_error::malformed);
+
+ const auto &Segment = *Segments.front();
+ auto &Data = Segment.Data;
+ StringRef Content(reinterpret_cast<const char *>(Data.Content.data()),
+ Data.Content.size());
+ return std::make_pair(Content, Segment.SectionOffset);
+ }
+
+ // On other object file types, delegate to lookupSections to find the section.
+ auto Sections = lookupSections(OF, IPSK);
+ if (!Sections)
+ return Sections.takeError();
+ if (Sections->size() != 1)
+ return make_error<CoverageMapError>(
+ coveragemap_error::malformed,
+ "the size of coverage mapping section is not one");
+ auto &Section = Sections->front();
+ auto ContentsOrErr = Section.getContents();
+ if (!ContentsOrErr)
+ return ContentsOrErr.takeError();
+ return std::make_pair(*ContentsOrErr, Section.getAddress());
+}
+
static Expected<std::unique_ptr<BinaryCoverageReader>>
loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
StringRef CompilationDir = "",
@@ -1105,23 +1154,20 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
// Look for the sections that we are interested in.
auto ProfileNames = std::make_unique<InstrProfSymtab>();
- std::vector<SectionRef> NamesSectionRefs;
// If IPSK_name is not found, fallback to search for IPK_covname, which is
// used when binary correlation is enabled.
- auto NamesSection = lookupSections(*OF, IPSK_name);
+ auto NamesSection = lookupAllocatableSection(*OF, IPSK_name);
if (auto E = NamesSection.takeError()) {
consumeError(std::move(E));
- NamesSection = lookupSections(*OF, IPSK_covname);
+ NamesSection = lookupAllocatableSection(*OF, IPSK_covname);
if (auto E = NamesSection.takeError())
return std::move(E);
}
- NamesSectionRefs = *NamesSection;
- if (NamesSectionRefs.size() != 1)
- return make_error<CoverageMapError>(
- coveragemap_error::malformed,
- "the size of coverage mapping section is not one");
- if (Error E = ProfileNames->create(NamesSectionRefs.back()))
+ uint64_t NamesAddress;
+ StringRef NamesContent;
+ std::tie(NamesContent, NamesAddress) = *NamesSection;
+ if (Error E = ProfileNames->create(NamesContent, NamesAddress))
return std::move(E);
auto CoverageSection = lookupSections(*OF, IPSK_covmap);
@@ -1136,6 +1182,15 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
return CoverageMappingOrErr.takeError();
StringRef CoverageMapping = CoverageMappingOrErr.get();
+ // If the coverage mapping section is not aligned to 8 bytes, copy it to a
+ // new buffer that is. Wasm format typically has unaligned section contents
+ // because it doesn't have a good way to insert padding bytes.
+ std::unique_ptr<MemoryBuffer> CoverageMappingBufferOwner;
+ if (!isAddrAligned(Align(8), CoverageMapping.data())) {
+ CoverageMappingBufferOwner = MemoryBuffer::getMemBufferCopy(CoverageMapping);
+ CoverageMapping = CoverageMappingBufferOwner->getBuffer();
+ }
+
// Look for the coverage records section (Version4 only).
auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun);
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index 1c95a4606ecc56..b875f851a57e9f 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -1406,9 +1406,9 @@ static inline Constant *getFuncAddrForProfData(Function *Fn) {
static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
// compiler-rt uses linker support to get data/counters/name start/end for
- // ELF, COFF, Mach-O and XCOFF.
+ // ELF, COFF, Mach-O, XCOFF, and Wasm.
if (TT.isOSBinFormatELF() || TT.isOSBinFormatCOFF() ||
- TT.isOSBinFormatMachO() || TT.isOSBinFormatXCOFF())
+ TT.isOSBinFormatMachO() || TT.isOSBinFormatXCOFF() || TT.isOSBinFormatWasm())
return false;
return true;
diff --git a/llvm/test/CodeGen/WebAssembly/profile.ll b/llvm/test/CodeGen/WebAssembly/profile.ll
new file mode 100644
index 00000000000000..27802cc3bf3567
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/profile.ll
@@ -0,0 +1,47 @@
+; RUN: llc < %s --filetype=obj | obj2yaml | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+$__covrec_A = comdat any
+$__covrec_B = comdat any
+
+ at __covrec_A = linkonce_odr hidden constant <{ i64, i32, i64, i64, [4 x i8] }> <{
+ i64 -1978722966671112904,
+ i32 4,
+ i64 0,
+ i64 -8102528905418564625,
+ [4 x i8] c"\01\01\04\11"
+}>, section "__llvm_covfun", comdat, align 8
+ at __covrec_B = linkonce_odr hidden constant <{ i64, i32, i64, i64, [4 x i8] }> <{
+ i64 8006510647218728891,
+ i32 9,
+ i64 0,
+ i64 -8102528905418564625,
+ [4 x i8] c"\01\01\00\01"
+}>, section "__llvm_covfun", comdat, align 8
+ at __llvm_coverage_mapping = private constant { { i32, i32, i32, i32 }, [4 x i8] } {
+ { i32, i32, i32, i32 } { i32 0, i32 87, i32 0, i32 5 },
+ [4 x i8] c"\01\01\00\02"
+}, section "__llvm_covmap", align 8
+
+; CHECK: - T...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/111332
More information about the cfe-commits
mailing list