105ac43feSDan Gohman //===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===//
205ac43feSDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
605ac43feSDan Gohman //
705ac43feSDan Gohman //===----------------------------------------------------------------------===//
805ac43feSDan Gohman ///
905ac43feSDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file implements the WebAssemblyAsmBackend class.
1105ac43feSDan Gohman ///
1205ac43feSDan Gohman //===----------------------------------------------------------------------===//
1305ac43feSDan Gohman
14d934cb88SDan Gohman #include "MCTargetDesc/WebAssemblyFixupKinds.h"
156bda14b3SChandler Carruth #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
1605ac43feSDan Gohman #include "llvm/MC/MCAsmBackend.h"
1705ac43feSDan Gohman #include "llvm/MC/MCAssembler.h"
1805ac43feSDan Gohman #include "llvm/MC/MCDirectives.h"
1905ac43feSDan Gohman #include "llvm/MC/MCExpr.h"
2005ac43feSDan Gohman #include "llvm/MC/MCFixupKindInfo.h"
2105ac43feSDan Gohman #include "llvm/MC/MCObjectWriter.h"
2205ac43feSDan Gohman #include "llvm/MC/MCSubtargetInfo.h"
2305ac43feSDan Gohman #include "llvm/MC/MCSymbol.h"
24d37dc2f7SDan Gohman #include "llvm/MC/MCWasmObjectWriter.h"
2505ac43feSDan Gohman #include "llvm/Support/ErrorHandling.h"
2605ac43feSDan Gohman #include "llvm/Support/raw_ostream.h"
27cf2a9e28SSam Clegg
2805ac43feSDan Gohman using namespace llvm;
2905ac43feSDan Gohman
3005ac43feSDan Gohman namespace {
3118eafb6cSDan Gohman
3205ac43feSDan Gohman class WebAssemblyAsmBackend final : public MCAsmBackend {
3305ac43feSDan Gohman bool Is64Bit;
34da84b688SDan Gohman bool IsEmscripten;
3505ac43feSDan Gohman
3605ac43feSDan Gohman public:
WebAssemblyAsmBackend(bool Is64Bit,bool IsEmscripten)37da84b688SDan Gohman explicit WebAssemblyAsmBackend(bool Is64Bit, bool IsEmscripten)
38da84b688SDan Gohman : MCAsmBackend(support::little), Is64Bit(Is64Bit),
39da84b688SDan Gohman IsEmscripten(IsEmscripten) {}
4005ac43feSDan Gohman
getNumFixupKinds() const41d934cb88SDan Gohman unsigned getNumFixupKinds() const override {
42d934cb88SDan Gohman return WebAssembly::NumTargetFixupKinds;
43d934cb88SDan Gohman }
44d934cb88SDan Gohman
45d934cb88SDan Gohman const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
46d934cb88SDan Gohman
47d2c9ec7bSDerek Schuff void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
48d2c9ec7bSDerek Schuff const MCValue &Target, MutableArrayRef<char> Data,
493c9c1064SIlya Biryukov uint64_t Value, bool IsPCRel,
503c9c1064SIlya Biryukov const MCSubtargetInfo *STI) const override;
5105ac43feSDan Gohman
52dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter>
53dcd7d6c3SPeter Collingbourne createObjectTargetWriter() const override;
5405ac43feSDan Gohman
5505ac43feSDan Gohman // No instruction requires relaxation
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const5605ac43feSDan Gohman bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
5705ac43feSDan Gohman const MCRelaxableFragment *DF,
5805ac43feSDan Gohman const MCAsmLayout &Layout) const override {
5905ac43feSDan Gohman return false;
6005ac43feSDan Gohman }
6105ac43feSDan Gohman
62*e63455d5SPeter Smith bool writeNopData(raw_ostream &OS, uint64_t Count,
63*e63455d5SPeter Smith const MCSubtargetInfo *STI) const override;
6405ac43feSDan Gohman };
6505ac43feSDan Gohman
66d934cb88SDan Gohman const MCFixupKindInfo &
getFixupKindInfo(MCFixupKind Kind) const67d934cb88SDan Gohman WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
68d934cb88SDan Gohman const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
69d934cb88SDan Gohman // This table *must* be in the order that the fixup_* kinds are defined in
70d934cb88SDan Gohman // WebAssemblyFixupKinds.h.
71d934cb88SDan Gohman //
72d934cb88SDan Gohman // Name Offset (bits) Size (bits) Flags
73a5e175c6SSam Clegg {"fixup_sleb128_i32", 0, 5 * 8, 0},
74a5e175c6SSam Clegg {"fixup_sleb128_i64", 0, 10 * 8, 0},
75a5e175c6SSam Clegg {"fixup_uleb128_i32", 0, 5 * 8, 0},
76d9e0bbd1SWouter van Oortmerssen {"fixup_uleb128_i64", 0, 10 * 8, 0},
77d934cb88SDan Gohman };
78d934cb88SDan Gohman
79d934cb88SDan Gohman if (Kind < FirstTargetFixupKind)
80d934cb88SDan Gohman return MCAsmBackend::getFixupKindInfo(Kind);
81d934cb88SDan Gohman
82d934cb88SDan Gohman assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
83d934cb88SDan Gohman "Invalid kind!");
84d934cb88SDan Gohman return Infos[Kind - FirstTargetFixupKind];
85d934cb88SDan Gohman }
86d934cb88SDan Gohman
writeNopData(raw_ostream & OS,uint64_t Count,const MCSubtargetInfo * STI) const87*e63455d5SPeter Smith bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
88*e63455d5SPeter Smith const MCSubtargetInfo *STI) const {
8918c56a07SHeejin Ahn for (uint64_t I = 0; I < Count; ++I)
90571a3301SPeter Collingbourne OS << char(WebAssembly::Nop);
913acb187dSDan Gohman
923acb187dSDan Gohman return true;
9305ac43feSDan Gohman }
9405ac43feSDan Gohman
applyFixup(const MCAssembler & Asm,const MCFixup & Fixup,const MCValue & Target,MutableArrayRef<char> Data,uint64_t Value,bool IsPCRel,const MCSubtargetInfo * STI) const95d2c9ec7bSDerek Schuff void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm,
96d2c9ec7bSDerek Schuff const MCFixup &Fixup,
97d2c9ec7bSDerek Schuff const MCValue &Target,
98ef581757SReid Kleckner MutableArrayRef<char> Data,
993c9c1064SIlya Biryukov uint64_t Value, bool IsPCRel,
1003c9c1064SIlya Biryukov const MCSubtargetInfo *STI) const {
10105ac43feSDan Gohman const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
102a39ca601SDan Gohman assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
103a39ca601SDan Gohman
10418eafb6cSDan Gohman unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
105938ff9f0SDan Gohman if (Value == 0)
10605ac43feSDan Gohman return; // Doesn't change encoding.
10705ac43feSDan Gohman
10805ac43feSDan Gohman // Shift the value into position.
10905ac43feSDan Gohman Value <<= Info.TargetOffset;
11005ac43feSDan Gohman
11105ac43feSDan Gohman unsigned Offset = Fixup.getOffset();
112ef581757SReid Kleckner assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
11305ac43feSDan Gohman
11405ac43feSDan Gohman // For each byte of the fragment that the fixup touches, mask in the
11505ac43feSDan Gohman // bits from the fixup value.
11618c56a07SHeejin Ahn for (unsigned I = 0; I != NumBytes; ++I)
11718c56a07SHeejin Ahn Data[Offset + I] |= uint8_t((Value >> (I * 8)) & 0xff);
11805ac43feSDan Gohman }
11905ac43feSDan Gohman
120dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const121dcd7d6c3SPeter Collingbourne WebAssemblyAsmBackend::createObjectTargetWriter() const {
122da84b688SDan Gohman return createWebAssemblyWasmObjectWriter(Is64Bit, IsEmscripten);
12305ac43feSDan Gohman }
12472f19241SDerek Schuff
12505ac43feSDan Gohman } // end anonymous namespace
12605ac43feSDan Gohman
createWebAssemblyAsmBackend(const Triple & TT)127cceedf79SDan Gohman MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
128da84b688SDan Gohman return new WebAssemblyAsmBackend(TT.isArch64Bit(), TT.isOSEmscripten());
12905ac43feSDan Gohman }
130