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