Skip to content

Commit c0b1b8b

Browse files
Merge pull request #9418 from kateinoigakukun/yt/cherry-pick-wasm-coverage-support
[🍒 stable/20240723] [Coverage][WebAssembly] Add initial support for WebAssembly/WASI
2 parents b55191a + 6efc1b4 commit c0b1b8b

25 files changed

+281
-54
lines changed

clang/lib/Driver/ToolChains/WebAssembly.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
155155
AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
156156
}
157157

158+
ToolChain.addProfileRTLibs(Args, CmdArgs);
159+
158160
CmdArgs.push_back("-o");
159161
CmdArgs.push_back(Output.getFilename());
160162

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64})
7171
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
7272
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
7373
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
74-
${RISCV32} ${RISCV64} ${LOONGARCH64})
74+
${RISCV32} ${RISCV64} ${LOONGARCH64} ${WASM32})
7575
set(ALL_CTX_PROFILE_SUPPORTED_ARCH ${X86_64})
7676
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
7777
${LOONGARCH64} ${RISCV64})

compiler-rt/cmake/config-ix.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ else()
816816
endif()
817817

818818
if (PROFILE_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND
819-
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX")
819+
OS_NAME MATCHES "Darwin|Linux|FreeBSD|Windows|Android|Fuchsia|SunOS|NetBSD|AIX|WASI")
820820
set(COMPILER_RT_HAS_PROFILE TRUE)
821821
else()
822822
set(COMPILER_RT_HAS_PROFILE FALSE)

compiler-rt/lib/profile/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ int main() {
3838
3939
" COMPILER_RT_TARGET_HAS_FCNTL_LCK)
4040

41+
CHECK_CXX_SOURCE_COMPILES("
42+
#include <sys/file.h>
43+
44+
int fd;
45+
int main() {
46+
flock(fd, LOCK_EX);
47+
return 0;
48+
}
49+
50+
" COMPILER_RT_TARGET_HAS_FLOCK)
51+
4152
CHECK_CXX_SOURCE_COMPILES("
4253
#include <sys/utsname.h>
4354
int main() {
@@ -93,6 +104,13 @@ if(FUCHSIA OR UNIX)
93104
-Wno-pedantic)
94105
endif()
95106

107+
if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
108+
set(EXTRA_FLAGS
109+
${EXTRA_FLAGS}
110+
-D_WASI_EMULATED_MMAN
111+
-D_WASI_EMULATED_GETPID)
112+
endif()
113+
96114
if(COMPILER_RT_TARGET_HAS_ATOMICS)
97115
set(EXTRA_FLAGS
98116
${EXTRA_FLAGS}
@@ -105,6 +123,12 @@ if(COMPILER_RT_TARGET_HAS_FCNTL_LCK)
105123
-DCOMPILER_RT_HAS_FCNTL_LCK=1)
106124
endif()
107125

126+
if(COMPILER_RT_TARGET_HAS_FLOCK)
127+
set(EXTRA_FLAGS
128+
${EXTRA_FLAGS}
129+
-DCOMPILER_RT_HAS_FLOCK=1)
130+
endif()
131+
108132
if(COMPILER_RT_TARGET_HAS_UNAME)
109133
set(EXTRA_FLAGS
110134
${EXTRA_FLAGS}

compiler-rt/lib/profile/GCDAProfiling.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ void llvm_reset_counters(void) {
584584
}
585585
}
586586

587-
#if !defined(_WIN32)
587+
#if !defined(_WIN32) && !defined(__wasm__)
588588
COMPILER_RT_VISIBILITY
589589
pid_t __gcov_fork() {
590590
pid_t parent_pid = getpid();

compiler-rt/lib/profile/InstrProfilingFile.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include <stdio.h>
1414
#include <stdlib.h>
1515
#include <string.h>
16+
#if !defined(__wasi__)
1617
#include <signal.h>
18+
#endif
1719
#ifdef _MSC_VER
1820
/* For _alloca. */
1921
#include <malloc.h>

compiler-rt/lib/profile/InstrProfilingPlatformLinux.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
|*
77
\*===----------------------------------------------------------------------===*/
88

9-
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
10-
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
11-
defined(_AIX)
9+
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
10+
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) || \
11+
defined(_AIX) || defined(__wasm__)
1212

13-
#if !defined(_AIX)
13+
#if !defined(_AIX) && !defined(__wasm__)
1414
#include <elf.h>
1515
#include <link.h>
1616
#endif

compiler-rt/lib/profile/InstrProfilingPlatformOther.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
#if !defined(__APPLE__) && !defined(__linux__) && !defined(__FreeBSD__) && \
1010
!defined(__Fuchsia__) && !(defined(__sun__) && defined(__svr4__)) && \
11-
!defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX)
11+
!defined(__NetBSD__) && !defined(_WIN32) && !defined(_AIX) && \
12+
!defined(__wasm__)
1213

1314
#include <stdlib.h>
1415
#include <stdio.h>

compiler-rt/lib/profile/InstrProfilingPort.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
#endif
5555

5656
#define COMPILER_RT_MAX_HOSTLEN 128
57-
#ifdef __ORBIS__
57+
#if defined(__ORBIS__) || defined(__wasi__)
5858
#define COMPILER_RT_GETHOSTNAME(Name, Len) ((void)(Name), (void)(Len), (-1))
5959
#else
6060
#define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)

compiler-rt/lib/profile/InstrProfilingUtil.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
#include <sys/utsname.h>
2626
#endif
2727

28+
#if !defined(__wasi__)
2829
#include <signal.h>
30+
#endif
2931
#include <stdlib.h>
3032
#include <string.h>
3133

@@ -153,9 +155,12 @@ COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
153155
}
154156
}
155157
return 0;
156-
#else
158+
#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32)
159+
// Windows doesn't have flock but WindowsMMap.h provides a shim
157160
flock(fd, LOCK_EX);
158161
return 0;
162+
#else
163+
return 0;
159164
#endif
160165
}
161166

@@ -178,9 +183,12 @@ COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
178183
}
179184
}
180185
return 0;
181-
#else
186+
#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32)
187+
// Windows doesn't have flock but WindowsMMap.h provides a shim
182188
flock(fd, LOCK_UN);
183189
return 0;
190+
#else
191+
return 0;
184192
#endif
185193
}
186194

@@ -332,6 +340,8 @@ COMPILER_RT_VISIBILITY void lprofInstallSignalHandler(int sig,
332340
if (err == SIG_ERR)
333341
PROF_WARN("Unable to install an exit signal handler for %d (errno = %d).\n",
334342
sig, errno);
343+
#elif defined(__wasi__)
344+
// WASI doesn't support signal.
335345
#else
336346
struct sigaction sigact;
337347
memset(&sigact, 0, sizeof(sigact));
@@ -372,8 +382,8 @@ COMPILER_RT_VISIBILITY void lprofRestoreSigKill(void) {
372382

373383
COMPILER_RT_VISIBILITY int lprofReleaseMemoryPagesToOS(uintptr_t Begin,
374384
uintptr_t End) {
375-
#if defined(__ve__)
376-
// VE doesn't support madvise.
385+
#if defined(__ve__) || defined(__wasi__)
386+
// VE and WASI doesn't support madvise.
377387
return 0;
378388
#else
379389
size_t PageSize = getpagesize();

lld/test/wasm/custom-section-align.s

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
2+
# RUN: wasm-ld --no-entry %t.o -o %t.wasm
3+
# RUN: obj2yaml %t.wasm | FileCheck %s
4+
5+
# Check that "__llvm_covfun" custom section is aligned to 8 bytes.
6+
7+
.section .custom_section.__llvm_covfun,"GR",@,__covrec_A
8+
.int32 1
9+
.int8 2
10+
# pad .int8 0
11+
# .int8 0
12+
# .int8 0
13+
14+
.section .custom_section.__llvm_covfun,"GR",@,__covrec_B
15+
.int32 3
16+
17+
# CHECK: - Type: CUSTOM
18+
# CHECK-NEXT: Name: __llvm_covfun
19+
# CHECK-NEXT: Payload: '010000000200000003000000'
20+
21+
# Check that regular custom sections are not aligned.
22+
.section .custom_section.foo,"GR",@,foo_A
23+
.int32 1
24+
.int8 2
25+
26+
.section .custom_section.foo,"GR",@,foo_B
27+
.int32 3
28+
29+
# CHECK: - Type: CUSTOM
30+
# CHECK-NEXT: Name: foo
31+
# CHECK-NEXT: Payload: '010000000203000000'

lld/wasm/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_lld_library(lldWasm
2828
Object
2929
Option
3030
Passes
31+
ProfileData
3132
Support
3233
TargetParser
3334

lld/wasm/InputChunks.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ class MergeInputChunk : public InputChunk {
177177
inputSectionOffset = seg.SectionOffset;
178178
}
179179

180-
MergeInputChunk(const WasmSection &s, ObjFile *f)
181-
: InputChunk(f, Merge, s.Name, 0, llvm::wasm::WASM_SEG_FLAG_STRINGS) {
180+
MergeInputChunk(const WasmSection &s, ObjFile *f, uint32_t alignment)
181+
: InputChunk(f, Merge, s.Name, alignment,
182+
llvm::wasm::WASM_SEG_FLAG_STRINGS) {
182183
assert(s.Type == llvm::wasm::WASM_SEC_CUSTOM);
183184
comdat = s.Comdat;
184185
rawData = s.Content;
@@ -234,6 +235,7 @@ class SyntheticMergedChunk : public InputChunk {
234235

235236
void addMergeChunk(MergeInputChunk *ms) {
236237
comdat = ms->getComdat();
238+
alignment = std::max(alignment, ms->alignment);
237239
ms->parent = this;
238240
chunks.push_back(ms);
239241
}
@@ -337,8 +339,8 @@ class SyntheticFunction : public InputFunction {
337339
// Represents a single Wasm Section within an input file.
338340
class InputSection : public InputChunk {
339341
public:
340-
InputSection(const WasmSection &s, ObjFile *f)
341-
: InputChunk(f, InputChunk::Section, s.Name),
342+
InputSection(const WasmSection &s, ObjFile *f, uint32_t alignment)
343+
: InputChunk(f, InputChunk::Section, s.Name, alignment),
342344
tombstoneValue(getTombstoneForSection(s.Name)), section(s) {
343345
assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM);
344346
comdat = section.Comdat;

lld/wasm/InputFiles.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/BinaryFormat/Wasm.h"
1919
#include "llvm/Object/Binary.h"
2020
#include "llvm/Object/Wasm.h"
21+
#include "llvm/ProfileData/InstrProf.h"
2122
#include "llvm/Support/Path.h"
2223
#include "llvm/Support/TarWriter.h"
2324
#include "llvm/Support/raw_ostream.h"
@@ -451,6 +452,18 @@ void SharedFile::parse() {
451452
}
452453
}
453454

455+
// Returns the alignment for a custom section. This is used to concatenate
456+
// custom sections with the same name into a single custom section.
457+
static uint32_t getCustomSectionAlignment(const WasmSection &sec) {
458+
// TODO: Add a section attribute for alignment in the linking spec.
459+
if (sec.Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm) ||
460+
sec.Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm)) {
461+
// llvm-cov assumes that coverage metadata sections are 8-byte aligned.
462+
return 8;
463+
}
464+
return 1;
465+
}
466+
454467
WasmFileBase::WasmFileBase(Kind k, MemoryBufferRef m) : InputFile(k, m) {
455468
// Parse a memory buffer as a wasm file.
456469
LLVM_DEBUG(dbgs() << "Reading object: " << toString(this) << "\n");
@@ -520,10 +533,11 @@ void ObjFile::parse(bool ignoreComdats) {
520533
dataSection = &section;
521534
} else if (section.Type == WASM_SEC_CUSTOM) {
522535
InputChunk *customSec;
536+
uint32_t alignment = getCustomSectionAlignment(section);
523537
if (shouldMerge(section))
524-
customSec = make<MergeInputChunk>(section, this);
538+
customSec = make<MergeInputChunk>(section, this, alignment);
525539
else
526-
customSec = make<InputSection>(section, this);
540+
customSec = make<InputSection>(section, this, alignment);
527541
customSec->discarded = isExcludedByComdat(customSec);
528542
customSections.emplace_back(customSec);
529543
customSections.back()->setRelocations(section.Relocations);

lld/wasm/OutputSections.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ void CustomSection::finalizeContents() {
249249

250250
for (InputChunk *section : inputSections) {
251251
assert(!section->discarded);
252+
payloadSize = alignTo(payloadSize, section->alignment);
252253
section->outSecOff = payloadSize;
253254
payloadSize += section->getSize();
254255
}

llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class BinaryCoverageReader : public CoverageMappingReader {
180180
};
181181

182182
using FuncRecordsStorage = std::unique_ptr<MemoryBuffer>;
183+
using CoverageMapCopyStorage = std::unique_ptr<MemoryBuffer>;
183184

184185
private:
185186
std::vector<std::string> Filenames;
@@ -195,9 +196,16 @@ class BinaryCoverageReader : public CoverageMappingReader {
195196
// D69471, which can split up function records into multiple sections on ELF.
196197
FuncRecordsStorage FuncRecords;
197198

199+
// Used to tie the lifetimes of an optional copy of the coverage mapping data
200+
// to the lifetime of this BinaryCoverageReader instance. Needed to support
201+
// Wasm object format, which might require realignment of section contents.
202+
CoverageMapCopyStorage CoverageMapCopy;
203+
198204
BinaryCoverageReader(std::unique_ptr<InstrProfSymtab> Symtab,
199-
FuncRecordsStorage &&FuncRecords)
200-
: ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)) {}
205+
FuncRecordsStorage &&FuncRecords,
206+
CoverageMapCopyStorage &&CoverageMapCopy)
207+
: ProfileNames(std::move(Symtab)), FuncRecords(std::move(FuncRecords)),
208+
CoverageMapCopy(std::move(CoverageMapCopy)) {}
201209

202210
public:
203211
BinaryCoverageReader(const BinaryCoverageReader &) = delete;
@@ -212,6 +220,7 @@ class BinaryCoverageReader : public CoverageMappingReader {
212220
static Expected<std::unique_ptr<BinaryCoverageReader>>
213221
createCoverageReaderFromBuffer(
214222
StringRef Coverage, FuncRecordsStorage &&FuncRecords,
223+
CoverageMapCopyStorage &&CoverageMap,
215224
std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
216225
llvm::endianness Endian, StringRef CompilationDir = "");
217226

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2173,7 +2173,11 @@ MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
21732173
// This could be avoided if all data segements (the wasm sense) were
21742174
// represented as their own sections (in the llvm sense).
21752175
// TODO(sbc): https://github.com/WebAssembly/tool-conventions/issues/138
2176-
if (Name == ".llvmcmd" || Name == ".llvmbc")
2176+
if (Name == getInstrProfSectionName(IPSK_covmap, Triple::Wasm,
2177+
/*AddSegmentInfo=*/false) ||
2178+
Name == getInstrProfSectionName(IPSK_covfun, Triple::Wasm,
2179+
/*AddSegmentInfo=*/false) ||
2180+
Name == ".llvmbc" || Name == ".llvmcmd")
21772181
Kind = SectionKind::getMetadata();
21782182

21792183
StringRef Group = "";

llvm/lib/MC/MCContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,11 @@ MCSectionWasm *MCContext::getWasmSection(const Twine &Section, SectionKind K,
756756
if (!Group.isTriviallyEmpty() && !Group.str().empty()) {
757757
GroupSym = cast<MCSymbolWasm>(getOrCreateSymbol(Group));
758758
GroupSym->setComdat(true);
759+
if (K.isMetadata() && !GroupSym->getType().has_value()) {
760+
// Comdat group symbol associated with a custom section is a section
761+
// symbol (not a data symbol).
762+
GroupSym->setType(wasm::WASM_SYMBOL_TYPE_SECTION);
763+
}
759764
}
760765

761766
return getWasmSection(Section, K, Flags, GroupSym, UniqueID);

0 commit comments

Comments
 (0)