Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[🍒 stable/20240723] [Coverage][WebAssembly] Add initial support for WebAssembly/WASI #9418

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,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());

Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,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})
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
${LOONGARCH64} ${RISCV64})
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/cmake/config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,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)
Expand Down
24 changes: 24 additions & 0 deletions compiler-rt/lib/profile/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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}
Expand All @@ -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}
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/profile/GCDAProfiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ void llvm_reset_counters(void) {
}
}

#if !defined(_WIN32)
#if !defined(_WIN32) && !defined(__wasm__)
COMPILER_RT_VISIBILITY
pid_t __gcov_fork() {
pid_t parent_pid = getpid();
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/profile/InstrProfilingFile.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(__wasi__)
#include <signal.h>
#endif
#ifdef _MSC_VER
/* For _alloca. */
#include <malloc.h>
Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/lib/profile/InstrProfilingPlatformLinux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/lib/profile/InstrProfilingPlatformOther.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/profile/InstrProfilingPort.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
18 changes: 14 additions & 4 deletions compiler-rt/lib/profile/InstrProfilingUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
#include <sys/utsname.h>
#endif

#if !defined(__wasi__)
#include <signal.h>
#endif
#include <stdlib.h>
#include <string.h>

Expand Down Expand Up @@ -153,9 +155,12 @@ COMPILER_RT_VISIBILITY int lprofLockFd(int fd) {
}
}
return 0;
#else
#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32)
// Windows doesn't have flock but WindowsMMap.h provides a shim
flock(fd, LOCK_EX);
return 0;
#else
return 0;
#endif
}

Expand All @@ -178,9 +183,12 @@ COMPILER_RT_VISIBILITY int lprofUnlockFd(int fd) {
}
}
return 0;
#else
#elif defined(COMPILER_RT_HAS_FLOCK) || defined(_WIN32)
// Windows doesn't have flock but WindowsMMap.h provides a shim
flock(fd, LOCK_UN);
return 0;
#else
return 0;
#endif
}

Expand Down Expand Up @@ -332,6 +340,8 @@ COMPILER_RT_VISIBILITY void lprofInstallSignalHandler(int sig,
if (err == SIG_ERR)
PROF_WARN("Unable to install an exit signal handler for %d (errno = %d).\n",
sig, errno);
#elif defined(__wasi__)
// WASI doesn't support signal.
#else
struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
Expand Down Expand Up @@ -372,8 +382,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();
Expand Down
31 changes: 31 additions & 0 deletions lld/test/wasm/custom-section-align.s
Original file line number Diff line number Diff line change
@@ -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'
1 change: 1 addition & 0 deletions lld/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ add_lld_library(lldWasm
Object
Option
Passes
ProfileData
Support
TargetParser

Expand Down
10 changes: 6 additions & 4 deletions lld/wasm/InputChunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 16 additions & 2 deletions lld/wasm/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -520,10 +533,11 @@ void ObjFile::parse(bool ignoreComdats) {
dataSection = &section;
} 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);
Expand Down
1 change: 1 addition & 0 deletions lld/wasm/OutputSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ void CustomSection::finalizeContents() {

for (InputChunk *section : inputSections) {
assert(!section->discarded);
payloadSize = alignTo(payloadSize, section->alignment);
section->outSecOff = payloadSize;
payloadSize += section->getSize();
}
Expand Down
13 changes: 11 additions & 2 deletions llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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 = "");

Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2173,7 +2173,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 = "";
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/MC/MCContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,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);
Expand Down
Loading