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..164d9720cb2 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(); @@ -485,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"); } @@ -548,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()) { @@ -1046,8 +1098,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; @@ -1128,9 +1188,30 @@ 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; } +// 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(); @@ -1361,6 +1442,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; @@ -1447,8 +1532,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 { 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