From 3b0b6ef667a50ba76f9efc77d7ef8cdcb2b50b94 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Tue, 9 Apr 2019 22:14:27 -0700 Subject: [PATCH 1/8] WebAssembly: enable Swift calling convention in ISelLowering, ignore hot/cold split directives --- lib/MC/MCWasmStreamer.cpp | 1 + lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp index 86fa7219785..76a6a375b43 100644 --- a/lib/MC/MCWasmStreamer.cpp +++ b/lib/MC/MCWasmStreamer.cpp @@ -88,6 +88,7 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { getAssembler().registerSymbol(*Symbol); switch (Attribute) { + case MCSA_Cold: case MCSA_LazyReference: case MCSA_Reference: case MCSA_SymbolResolver: diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index fccb456586e..e6bd1bc543e 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -623,7 +623,8 @@ static bool callingConvSupported(CallingConv::ID CallConv) { CallConv == CallingConv::Cold || CallConv == CallingConv::PreserveMost || CallConv == CallingConv::PreserveAll || - CallConv == CallingConv::CXX_FAST_TLS; + CallConv == CallingConv::CXX_FAST_TLS || + CallConv == CallingConv::Swift; } SDValue From 662f79af85fc63be21d454d610d1c2dc2ce614b1 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Wed, 10 Apr 2019 14:01:07 -0700 Subject: [PATCH 2/8] write Clang precompiled headers to a custom section This doesn't fix the alignment issue yet. See https://bugs.llvm.org/show_bug.cgi?id=35928 and https://reviews.llvm.org/D42233. --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 4 ++++ lib/MC/WasmObjectWriter.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 338ef97dc13..083776e2e4f 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1682,6 +1682,10 @@ static SectionKind getWasmKindForNamedSection(StringRef Name, SectionKind K) { if (K.isText()) return SectionKind::getText(); + // Clang precompiled header data isn't needed at runtime; use custom section + if (Name == "__clangast") + return SectionKind::getMetadata(); + // Otherwise, ignore whatever section type the generic impl detected and use // a plain data section. return SectionKind::getData(); diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 8743eb7ee3c..4abba3453d5 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -1128,6 +1128,10 @@ static bool isInSymtab(const MCSymbolWasm &Sym) { if (Sym.isSection()) return false; + // Clang's precompiled headers are in a separate custom section + if (Sym.getName() == "__clang_ast") + return false; + return true; } From f4445accb7c988718073c637ccaee5b46ca79249 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Wed, 10 Apr 2019 15:20:20 -0700 Subject: [PATCH 3/8] WebAssembly: pad __clangast section to 4 bytes Like Patcheng's https://reviews.llvm.org/D42233 but for Custom Sections instead padding for the padding gods. --- lib/MC/WasmObjectWriter.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 4abba3453d5..ef9788aa5f1 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -372,7 +372,15 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, Section.PayloadOffset = W.OS.tell(); // Custom sections in wasm also have a string identifier. - writeString(Name); + if (Name != "__clangast") { + writeString(Name); + } else { + // pad section start to nearest 4 bytes for Clang PCH + uint64_t MinLength = Section.PayloadOffset + 5ULL /* min ULEB128 length */ + Name.size(); + uint64_t RoundedUpLength = (MinLength + 3ULL) & ~3ULL; + encodeULEB128(Name.size(), W.OS, 5 + (RoundedUpLength - MinLength)); + W.OS << Name; + } // The position where the custom section starts. Section.ContentsOffset = W.OS.tell(); @@ -1046,8 +1054,16 @@ void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection, auto *Sec = CustomSection.Section; startCustomSection(Section, CustomSection.Name); - Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W.OS, Sec, Layout); + if (CustomSection.Name == "__clangast") { + // pad to nearest 4 bytes + uint64_t RoundedUp = (Section.ContentsOffset + 3ULL) & ~3ULL; + for (uint64_t Count = 0; Count < RoundedUp - Section.ContentsOffset; Count++) { + W.OS << char(0); + } + } + + Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset); + Asm.writeSectionData(W.OS, Sec, Layout); CustomSection.OutputContentsOffset = Section.ContentsOffset; CustomSection.OutputIndex = Section.Index; @@ -1365,6 +1381,10 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); } else if (WS.isData()) { + if (WS.getName() == "__clang_ast") + continue; + if (WS.isTemporary() && !WS.getSize()) + continue; if (!isInSymtab(WS)) continue; From e5a77982562068d7d47e81f988eeb091ddc69ac1 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Sun, 14 Apr 2019 18:43:02 -0700 Subject: [PATCH 4/8] WebAssembly: attempt to fix non-SymbolExpr relocations Also try hard to extract a symbol from a MCExpr when writing relocations I doubt this is the right way, but hey it emits an object now --- lib/MC/WasmObjectWriter.cpp | 48 +++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index ef9788aa5f1..e79c37840da 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -493,8 +493,8 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, if (SymA && SymA->isVariable()) { const MCExpr *Expr = SymA->getVariableValue(); - const auto *Inner = cast(Expr); - if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) + const auto *Inner = dyn_cast(Expr); + if (Inner && Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) llvm_unreachable("weakref used in reloc not yet implemented"); } @@ -556,6 +556,50 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, } } +// Write X as an (unsigned) LEB value at offset Offset in Stream, padded +// to allow patching. +static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, + uint64_t Offset) { + uint8_t Buffer[5]; + unsigned SizeLen = encodeULEB128(X, Buffer, 5); + assert(SizeLen == 5); + Stream.pwrite((char *)Buffer, SizeLen, Offset); +} + +// Write X as an signed LEB value at offset Offset in Stream, padded +// to allow patching. +static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, + uint64_t Offset) { + uint8_t Buffer[5]; + unsigned SizeLen = encodeSLEB128(X, Buffer, 5); + assert(SizeLen == 5); + Stream.pwrite((char *)Buffer, SizeLen, Offset); +} + +// Write X as a plain integer value at offset Offset in Stream. +static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) { + uint8_t Buffer[4]; + support::endian::write32le(Buffer, X); + Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); +} + +static const MCSymbolRefExpr* pullSymbol(const MCExpr *TheExpr) { + if (!TheExpr) return nullptr; + const MCSymbolRefExpr* S = dyn_cast(TheExpr); + if (S) return S; + const MCBinaryExpr* Expr = dyn_cast(TheExpr); + if (!Expr) return nullptr; + S = dyn_cast_or_null(Expr->getLHS()); + if (S) return S; + S = dyn_cast_or_null(Expr->getRHS()); + if (S) return S; + S = pullSymbol(Expr->getLHS()); + if (S) return S; + S = pullSymbol(Expr->getRHS()); + if (S) return S; + return nullptr; +} + static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) { const MCSymbolWasm* Ret = &Symbol; while (Ret->isVariable()) { From 0c8f940c5f50e05476108bb9dd39e92a110b5bc3 Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Wed, 1 May 2019 21:06:45 -0700 Subject: [PATCH 5/8] WebAssembly: add logging when I get a BinaryExpr I actually do need to know what's breaking. --- lib/MC/WasmObjectWriter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index e79c37840da..970b6c8be33 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -496,6 +496,10 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, const auto *Inner = dyn_cast(Expr); if (Inner && Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) llvm_unreachable("weakref used in reloc not yet implemented"); + if (!Inner) { + fprintf(stderr, "weak check failed to get an inner:\n"); + Expr->dump(); + } } // Put any constant offset in an addend. Offsets can be negative, and From d7a9e68a70c6229e698f19ec025232441180d6cf Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 2 May 2019 11:51:17 -0700 Subject: [PATCH 6/8] WebAssembly: properly handle MCBinaryExpr in aliased symbols Swift uses aliased symbols to refer to offsets within metadata structures. eg ``` @"$s12SwiftPrivate28_stdlib_ShardedAtomicCounterVN" = alias %swift.type, bitcast (i32* getelementptr inbounds (<{ i8**, i32, <{ i32, i32, i32, i32, i32, i32, i32 }>*, i32, i32 }>, <{ i8**, i32, <{ i32, i32, i32, i32, i32, i32, i32 }>*, i32, i32 }>* @"$s12SwiftPrivate28_stdlib_ShardedAtomicCounterVMf", i32 0, i32 1) to %swift.type*) ``` My previous commit only got the alias to refer to the correct target symbol, but not at the right offset. This commit properly emits these symbols. With this change, print("hello world") works but print() with anything else is still broken. --- lib/MC/WasmObjectWriter.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 970b6c8be33..d94591b27cd 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -1199,6 +1199,23 @@ static bool isInSymtab(const MCSymbolWasm &Sym) { return true; } +// SwiftWasm: takes a MCSymbolWasm that's an alias expression of the form +// ((targetSymbol + constantA) - constantB) + constantC...) +// return the final offset from targetSymbol. +// if no offset, returns 0. +static int64_t getAliasedSymbolOffset(const MCSymbolWasm &Symbol, + const MCAsmLayout &Layout) { + if (!Symbol.isVariable()) + return 0; + const MCExpr *Expr = Symbol.getVariableValue(); + MCValue Res; + if (!Expr->evaluateAsRelocatable(Res, &Layout, nullptr)) { + Expr->dump(); + report_fatal_error("Can't evaluate alias symbol expression"); + } + return Res.getConstant(); +} + uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) { uint64_t StartOffset = W.OS.tell(); @@ -1519,8 +1536,16 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); } else if (ResolvedSym->isData()) { assert(DataLocations.count(ResolvedSym) > 0); - const wasm::WasmDataReference &Ref = + // SwiftWasm: hack: grab the offset + // Swift has aliases of the form + // alias = ((symbol + constant) - constant) + // so we need to evaluate the constants here using MCExpr + // there's probably a proper way to do this. + int64_t Offset = getAliasedSymbolOffset(WS, Layout); + wasm::WasmDataReference Ref = DataLocations.find(ResolvedSym)->second; + Ref.Offset += Offset; + Ref.Size -= Offset; DataLocations[&WS] = Ref; LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); } else { From 0ed50bf80bc5c6e553ee2f03491a429902922eaf Mon Sep 17 00:00:00 2001 From: Zhuowei Zhang Date: Thu, 2 May 2019 11:54:29 -0700 Subject: [PATCH 7/8] Revert "WebAssembly: add logging when I get a BinaryExpr" Don't need the logging anymore This reverts commit 8b8f31fc13c02ad26ff1ef0c211753e8d339487f. --- lib/MC/WasmObjectWriter.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index d94591b27cd..164d9720cb2 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -496,10 +496,6 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, const auto *Inner = dyn_cast(Expr); if (Inner && Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) llvm_unreachable("weakref used in reloc not yet implemented"); - if (!Inner) { - fprintf(stderr, "weak check failed to get an inner:\n"); - Expr->dump(); - } } // Put any constant offset in an addend. Offsets can be negative, and From 25e97485dd0385210f3b6695236d9bde5a301387 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 15 Oct 2019 12:31:49 +0100 Subject: [PATCH 8/8] Fix MCWasmStreamer.cpp after merge conflict --- lib/MC/MCWasmStreamer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/MC/MCWasmStreamer.cpp b/lib/MC/MCWasmStreamer.cpp index 76a6a375b43..86fa7219785 100644 --- a/lib/MC/MCWasmStreamer.cpp +++ b/lib/MC/MCWasmStreamer.cpp @@ -88,7 +88,6 @@ bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { getAssembler().registerSymbol(*Symbol); switch (Attribute) { - case MCSA_Cold: case MCSA_LazyReference: case MCSA_Reference: case MCSA_SymbolResolver: