https://github.com/kateinoigakukun updated https://github.com/llvm/llvm-project/pull/111332
>From 605e1ad180c9f75fd59d8b783ae2041cbaf34e50 Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sat, 5 Oct 2024 16:54:57 +0000 Subject: [PATCH 1/7] [compiler-rt][profile] Add initial support for WebAssembly/WASI This patch adds initial support for WebAssembly/WASI to the profile runtime library on the top of wasi-libc. This is a part of the ongoing patch series to add coverage support for WebAssembly/WASI. The patch includes the following changes: * Add wasm32-wasi to the list of supported architectures/OSes. * Exclude unsupported features for WASI: flock, madvise, uname. * Enable some user-space emulation provided by wasi-libc: mmap, getpid --- .../cmake/Modules/AllSupportedArchDefs.cmake | 2 +- compiler-rt/cmake/config-ix.cmake | 2 +- compiler-rt/lib/profile/CMakeLists.txt | 24 +++++++++++++++++++ compiler-rt/lib/profile/GCDAProfiling.c | 2 +- compiler-rt/lib/profile/InstrProfilingPort.h | 2 +- compiler-rt/lib/profile/InstrProfilingUtil.c | 12 ++++++---- 6 files changed, 36 insertions(+), 8 deletions(-) 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/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(); >From 5939422c1022d8d85355a800ea7341d56c0378bb Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sat, 5 Oct 2024 17:08:14 +0000 Subject: [PATCH 2/7] [compiler-rt][profile] Use encapsulation symbols for Wasm format Use `InstrProfilingPlatformLinux.c` for Wasm as well as Wasm format has encapsulation symbols (`__start_` and `__stop_`) similar to ELF. This unlocks several additional profile features like value profiling. --- compiler-rt/lib/profile/InstrProfilingPlatformLinux.c | 8 ++++---- compiler-rt/lib/profile/InstrProfilingPlatformOther.c | 3 ++- llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp | 5 +++-- llvm/test/Instrumentation/InstrProfiling/profiling.ll | 7 +------ 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index b766436497b741..02f23379ce98bf 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -6,11 +6,11 @@ |* \*===----------------------------------------------------------------------===*/ -#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ - (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \ - defined(_AIX) +#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ + (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \ + 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..52e82273f8aade 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformOther.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformOther.c @@ -8,7 +8,8 @@ #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/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp index 1c95a4606ecc56..929c787442057a 100644 --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -1406,9 +1406,10 @@ 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/Instrumentation/InstrProfiling/profiling.ll b/llvm/test/Instrumentation/InstrProfiling/profiling.ll index e7678a9dce0891..74dd54cef50fb5 100644 --- a/llvm/test/Instrumentation/InstrProfiling/profiling.ll +++ b/llvm/test/Instrumentation/InstrProfiling/profiling.ll @@ -114,11 +114,6 @@ declare void @llvm.instrprof.increment(ptr, i64, i32, i32) ; PS: %[[REG:.*]] = load i32, ptr @__llvm_profile_runtime ; XCOFF-NOT: define .* __llvm_profile_runtime_user -; WASM: define internal void @__llvm_profile_register_functions() unnamed_addr { -; WASM-NEXT: call void @__llvm_profile_register_function(ptr @__profd_foo) -; WASM-NEXT: call void @__llvm_profile_register_function(ptr @__profd_foo_weak) -; WASM: call void @__llvm_profile_register_names_function(ptr @__llvm_prf_nm -; WASM-NEXT: ret void -; WASM-NEXT: } +; WASM-NOT: internal void @__llvm_profile_register_functions() ; XCOFF-NOT: internal void @__llvm_profile_register_functions() >From 141f533bb4b5bcf73aacfbca53eee5b8e8dee067 Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sat, 5 Oct 2024 17:23:53 +0000 Subject: [PATCH 3/7] [WebAssembly] Emit `__llvm_covmap` and `__llvm_covfun` as custom sections This patch makes `__llvm_covmap` and `__llvm_covfun` as custom sections in the wasm object file because they will not be referenced at runtime but just used by `llvm-cov` post-processing tools. The same approach is used in the ELF object file to emit them without `SHF_ALLOC` flag. Those sections have their associated comdat group symbols, which are section symbols (not data symbols) in the wasm object file. This patch also sets the symbol type explicitly not to hit an assertion in the `WasmObjectWriter::writeOneObject` ("data symbols must live in a data section"). --- .../CodeGen/TargetLoweringObjectFileImpl.cpp | 6 ++- llvm/lib/MC/MCContext.cpp | 5 ++ llvm/test/CodeGen/WebAssembly/profile.ll | 47 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/WebAssembly/profile.ll 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/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: - Type: CUSTOM +; CHECK-NEXT: Name: __llvm_covfun +; CHECK-NEXT: Payload: 3845A90EF2298AE4040000000000000000000000EF1B31BAE3088E8F01010411 +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: __llvm_covfun +; CHECK-NEXT: Payload: BBEFDA6903D71C6F090000000000000000000000EF1B31BAE3088E8F01010001 +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: __llvm_covmap +; CHECK-NEXT: Payload: '0000000057000000000000000500000001010002' +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: Version: 2 +; CHECK-NEXT: Comdats: +; CHECK-NEXT: - Name: __covrec_A +; CHECK-NEXT: Entries: +; CHECK-NEXT: - Kind: SECTION +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: - Name: __covrec_B +; CHECK-NEXT: Entries: +; CHECK-NEXT: - Kind: SECTION +; CHECK-NEXT: Index: 2 >From 29cc14ffa418bf61ed677b5495a4606de660bf8d Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sat, 5 Oct 2024 17:40:17 +0000 Subject: [PATCH 4/7] [wasm-ld][Coverage] Align `__llvm_{covfun,covmap}` sections to 8 bytes This patch aligns the `__llvm_{covfun,covmap}` sections to 8 bytes at the linking stage. This is required because llvm-cov assumes that records in the sections are 8-byte aligned. Unfortunately, custom sections does not have an alignment attribute in the WebAssembly linking spec, so we temporarily do a special case for the metadata sections. In the future, we should generalize this to support alignment for relocatable custom sections. --- lld/test/wasm/custom-section-align.s | 31 ++++++++++++++++++++++++++++ lld/wasm/InputChunks.h | 10 +++++---- lld/wasm/InputFiles.cpp | 18 ++++++++++++++-- lld/wasm/OutputSections.cpp | 1 + 4 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 lld/test/wasm/custom-section-align.s 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(); } >From f2ad45c9e45708d02810d38680e3e5bfd811b425 Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sun, 6 Oct 2024 09:24:58 +0000 Subject: [PATCH 5/7] [llvm-cov][WebAssembly] Align coverage mapping section to 8 bytes Wasm format does not have a good way to insert padding bytes to align the start of a section contents because the size of each section header depends on the size of the section contents (leb128 encoding). This design makes it difficult to align section contents to a specific alignment to load them by post-processing tools like llvm-cov. This patch copies the coverage mapping section to a new buffer that is aligned to 8 bytes if the original section is not aligned. This is not an ideal solution but it works for now. --- .../Coverage/CoverageMappingReader.h | 13 +++++++++-- .../Coverage/CoverageMappingReader.cpp | 23 ++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h index f05b90114d75a6..886b4d3d6894dc 100644 --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -180,6 +180,7 @@ class BinaryCoverageReader : public CoverageMappingReader { }; using FuncRecordsStorage = std::unique_ptr<MemoryBuffer>; + using CoverageMapCopyStorage = std::unique_ptr<MemoryBuffer>; private: std::vector<std::string> Filenames; @@ -195,9 +196,16 @@ class BinaryCoverageReader : public CoverageMappingReader { // D69471, which can split up function records into multiple sections on ELF. FuncRecordsStorage FuncRecords; + // Used to tie the lifetimes of an optional copy of the coverage mapping data + // to the lifetime of this BinaryCoverageReader instance. Needed to support + // Wasm object format, which might require realignment of section contents. + CoverageMapCopyStorage CoverageMapCopy; + BinaryCoverageReader(std::unique_ptr<InstrProfSymtab> Symtab, - FuncRecordsStorage &&FuncRecords) - : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)) {} + FuncRecordsStorage &&FuncRecords, + CoverageMapCopyStorage &&CoverageMapCopy) + : ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)), + CoverageMapCopy(std::move(CoverageMapCopy)) {} public: BinaryCoverageReader(const BinaryCoverageReader &) = delete; @@ -212,6 +220,7 @@ class BinaryCoverageReader : public CoverageMappingReader { static Expected<std::unique_ptr<BinaryCoverageReader>> createCoverageReaderFromBuffer( StringRef Coverage, FuncRecordsStorage &&FuncRecords, + CoverageMapCopyStorage &&CoverageMap, std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir = ""); diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index bc4e780fb67a60..8881bffe41c57c 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -894,13 +894,15 @@ static Error readCoverageMappingData( Expected<std::unique_ptr<BinaryCoverageReader>> BinaryCoverageReader::createCoverageReaderFromBuffer( StringRef Coverage, FuncRecordsStorage &&FuncRecords, + CoverageMapCopyStorage &&CoverageMap, std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir) { if (ProfileNamesPtr == nullptr) return make_error<CoverageMapError>(coveragemap_error::malformed, "Caller must provide ProfileNames"); - std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader( - std::move(ProfileNamesPtr), std::move(FuncRecords))); + std::unique_ptr<BinaryCoverageReader> Reader( + new BinaryCoverageReader(std::move(ProfileNamesPtr), + std::move(FuncRecords), std::move(CoverageMap))); InstrProfSymtab &ProfileNames = *Reader->ProfileNames; StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer(); if (BytesInAddress == 4 && Endian == llvm::endianness::little) { @@ -1035,8 +1037,8 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { MemoryBuffer::getMemBuffer(Data); return BinaryCoverageReader::createCoverageReaderFromBuffer( - CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames), - BytesInAddress, Endian, CompilationDir); + CoverageMapping, std::move(CoverageRecords), nullptr, + std::move(ProfileNames), BytesInAddress, Endian, CompilationDir); } /// Find all sections that match \p IPSK name. There may be more than one if @@ -1136,6 +1138,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> CoverageMapCopy; + if (!isAddrAligned(Align(8), CoverageMapping.data())) { + CoverageMapCopy = MemoryBuffer::getMemBufferCopy(CoverageMapping); + CoverageMapping = CoverageMapCopy->getBuffer(); + } + // Look for the coverage records section (Version4 only). auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun); @@ -1184,8 +1195,8 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, *BinaryID = getBuildID(OF.get()); return BinaryCoverageReader::createCoverageReaderFromBuffer( - CoverageMapping, std::move(FuncRecords), std::move(ProfileNames), - BytesInAddress, Endian, CompilationDir); + CoverageMapping, std::move(FuncRecords), std::move(CoverageMapCopy), + std::move(ProfileNames), BytesInAddress, Endian, CompilationDir); } /// Determine whether \p Arch is invalid or empty, given \p Bin. >From 0529ec71c8c97b14791e9f32e8d55af816d9e6a3 Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sat, 5 Oct 2024 17:33:58 +0000 Subject: [PATCH 6/7] [llvm-cov][WebAssembly] Read `__llvm_prf_names` from data segments On WebAssembly, most coverage metadata contents read by llvm-cov (like `__llvm_covmap` and `__llvm_covfun`) are stored in custom sections because they are not referenced at runtime. However, `__llvm_prf_names` is referenced at runtime by the profile runtime library and is read by llvm-cov post-processing tools, so it needs to be stored in a data segment, which is allocatable at runtime and accessible by tools as long as "name" section is present in the binary. This patch changes the way llvm-cov reads `__llvm_prf_names` on WebAssembly. Instead of looking for a section, it looks for a data segment with the same name. --- .../Coverage/CoverageMappingReader.cpp | 64 +++++++++++++++--- .../llvm-cov/Inputs/binary-formats.v6.wasm32 | Bin 0 -> 87825 bytes .../Inputs/binary-formats.wasm.proftext | 4 ++ llvm/test/tools/llvm-cov/binary-formats.c | 7 ++ 4 files changed, 66 insertions(+), 9 deletions(-) create mode 100755 llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.wasm32 create mode 100644 llvm/test/tools/llvm-cov/Inputs/binary-formats.wasm.proftext diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 8881bffe41c57c..461fc43d32f8df 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" @@ -1077,6 +1079,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 = "", @@ -1107,23 +1156,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); diff --git a/llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.wasm32 b/llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.wasm32 new file mode 100755 index 0000000000000000000000000000000000000000..96b3a62acb7a5b270334a002451ab1b01cf95679 GIT binary patch literal 87825 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 literal 0 HcmV?d00001 diff --git a/llvm/test/tools/llvm-cov/Inputs/binary-formats.wasm.proftext b/llvm/test/tools/llvm-cov/Inputs/binary-formats.wasm.proftext new file mode 100644 index 00000000000000..20fc3816c2255a --- /dev/null +++ b/llvm/test/tools/llvm-cov/Inputs/binary-formats.wasm.proftext @@ -0,0 +1,4 @@ +__main_argc_argv +0x0 +1 +100 diff --git a/llvm/test/tools/llvm-cov/binary-formats.c b/llvm/test/tools/llvm-cov/binary-formats.c index a5bfc012860ec3..bb61b288cfc62e 100644 --- a/llvm/test/tools/llvm-cov/binary-formats.c +++ b/llvm/test/tools/llvm-cov/binary-formats.c @@ -10,4 +10,11 @@ int main(int argc, const char *argv[]) {} // RUN: llvm-cov show %S/Inputs/binary-formats.v3.macho64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s // RUN: llvm-cov show %S/Inputs/binary-formats.v6.linux64l -instr-profile %t.profdata -path-equivalence=/tmp,%S %s | FileCheck %s +// RUN: llvm-profdata merge %S/Inputs/binary-formats.wasm.proftext -o %t.wasm.profdata +// NOTE: The wasm binary is built with the following command: +// clang -target wasm32-unknown-wasi %s -o %S/Inputs/binary-formats.v6.wasm32 \ +// -mllvm -enable-name-compression=false \ +// -fprofile-instr-generate -fcoverage-mapping -lwasi-emulated-getpid -lwasi-emulated-mman +// RUN: llvm-cov show %S/Inputs/binary-formats.v6.wasm32 -instr-profile %t.wasm.profdata -path-equivalence=/tmp,%S %s | FileCheck %s + // RUN: llvm-cov export %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata | FileCheck %S/Inputs/binary-formats.canonical.json >From 779d88cc084648c73b0fb53a0e0fb02b65cfb676 Mon Sep 17 00:00:00 2001 From: Yuta Saito <kateinoigaku...@gmail.com> Date: Sun, 6 Oct 2024 04:22:12 +0000 Subject: [PATCH 7/7] [clang][WebAssembly] Link with profile runtime libraries if requested This patch teaches the WebAssembly toolchain to link with the profile runtime libraries if profile instrumentation is requested. With this change, the following command will work with profile rt installed: ``` $ clang -target wasm32-unknown-wasi -fprofile-instr-generate \ -lwasi-emulated-getpid -lwasi-emulated-mman -o foo.wasm foo.c ``` --- clang/lib/Driver/ToolChains/WebAssembly.cpp | 2 ++ 1 file changed, 2 insertions(+) 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()); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits