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 + +@__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 +@__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 +@__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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits