diff options
Diffstat (limited to 'lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp')
-rw-r--r-- | lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp | 107 |
1 files changed, 100 insertions, 7 deletions
diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp index 97454a824a34..7c78285fbda4 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" +#include "MCTargetDesc/WebAssemblyFixupKinds.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" @@ -22,21 +23,22 @@ #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { -class WebAssemblyAsmBackend final : public MCAsmBackend { +class WebAssemblyAsmBackendELF final : public MCAsmBackend { bool Is64Bit; public: - explicit WebAssemblyAsmBackend(bool Is64Bit) + explicit WebAssemblyAsmBackendELF(bool Is64Bit) : MCAsmBackend(), Is64Bit(Is64Bit) {} - ~WebAssemblyAsmBackend() override {} + ~WebAssemblyAsmBackendELF() override {} void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value, bool IsPCRel) const override; + uint64_t Value, bool IsPCRel, MCContext &Ctx) const override; MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; @@ -61,6 +63,95 @@ public: bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; }; +class WebAssemblyAsmBackend final : public MCAsmBackend { + bool Is64Bit; + +public: + explicit WebAssemblyAsmBackend(bool Is64Bit) + : MCAsmBackend(), Is64Bit(Is64Bit) {} + ~WebAssemblyAsmBackend() override {} + + unsigned getNumFixupKinds() const override { + return WebAssembly::NumTargetFixupKinds; + } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel, MCContext &Ctx) const override; + + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; + + // No instruction requires relaxation + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + return false; + } + + bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } + + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override {} + + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; +}; + +bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count, + MCObjectWriter *OW) const { + for (uint64_t i = 0; i < Count; ++i) + OW->write8(WebAssembly::Nop); + + return true; +} + +void WebAssemblyAsmBackendELF::applyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value, + bool IsPCRel, MCContext &Ctx) const { + const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind()); + assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags"); + + unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8; + if (Value == 0) + return; // Doesn't change encoding. + + // Shift the value into position. + Value <<= Info.TargetOffset; + + unsigned Offset = Fixup.getOffset(); + assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); + + // For each byte of the fragment that the fixup touches, mask in the + // bits from the fixup value. + for (unsigned i = 0; i != NumBytes; ++i) + Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); +} + +MCObjectWriter * +WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const { + return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0); +} + +const MCFixupKindInfo & +WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { + const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = { + // This table *must* be in the order that the fixup_* kinds are defined in + // WebAssemblyFixupKinds.h. + // + // Name Offset (bits) Size (bits) Flags + { "fixup_code_sleb128_i32", 0, 5*8, 0 }, + { "fixup_code_sleb128_i64", 0, 10*8, 0 }, + { "fixup_code_uleb128_i32", 0, 5*8, 0 }, + }; + + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && + "Invalid kind!"); + return Infos[Kind - FirstTargetFixupKind]; +} + bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { if (Count == 0) @@ -74,11 +165,11 @@ bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, - bool IsPCRel) const { + bool IsPCRel, MCContext &Ctx) const { const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind()); assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags"); - unsigned NumBytes = (Info.TargetSize + 7) / 8; + unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8; if (Value == 0) return; // Doesn't change encoding. @@ -96,10 +187,12 @@ void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, MCObjectWriter * WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { - return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0); + return createWebAssemblyWasmObjectWriter(OS, Is64Bit); } } // end anonymous namespace MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) { + if (TT.isOSBinFormatELF()) + return new WebAssemblyAsmBackendELF(TT.isArch64Bit()); return new WebAssemblyAsmBackend(TT.isArch64Bit()); } |