17d523365SDimitry Andric //===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===//
27d523365SDimitry Andric //
37d523365SDimitry Andric //                     The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric ///
107d523365SDimitry Andric /// \file
11*4ba319b5SDimitry Andric /// This file implements the WebAssemblyAsmBackend class.
127d523365SDimitry Andric ///
137d523365SDimitry Andric //===----------------------------------------------------------------------===//
147d523365SDimitry Andric 
157a7e6055SDimitry Andric #include "MCTargetDesc/WebAssemblyFixupKinds.h"
16db17bf38SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
177d523365SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
187d523365SDimitry Andric #include "llvm/MC/MCAssembler.h"
197d523365SDimitry Andric #include "llvm/MC/MCDirectives.h"
207d523365SDimitry Andric #include "llvm/MC/MCExpr.h"
217d523365SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
227d523365SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
237d523365SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
247d523365SDimitry Andric #include "llvm/MC/MCSymbol.h"
257a7e6055SDimitry Andric #include "llvm/MC/MCWasmObjectWriter.h"
267d523365SDimitry Andric #include "llvm/Support/ErrorHandling.h"
277d523365SDimitry Andric #include "llvm/Support/raw_ostream.h"
28*4ba319b5SDimitry Andric 
297d523365SDimitry Andric using namespace llvm;
307d523365SDimitry Andric 
317d523365SDimitry Andric namespace {
327d523365SDimitry Andric 
337a7e6055SDimitry Andric class WebAssemblyAsmBackend final : public MCAsmBackend {
347a7e6055SDimitry Andric   bool Is64Bit;
357a7e6055SDimitry Andric 
367a7e6055SDimitry Andric public:
WebAssemblyAsmBackend(bool Is64Bit)377a7e6055SDimitry Andric   explicit WebAssemblyAsmBackend(bool Is64Bit)
38*4ba319b5SDimitry Andric       : MCAsmBackend(support::little), Is64Bit(Is64Bit) {}
~WebAssemblyAsmBackend()397a7e6055SDimitry Andric   ~WebAssemblyAsmBackend() override {}
407a7e6055SDimitry Andric 
getNumFixupKinds() const417a7e6055SDimitry Andric   unsigned getNumFixupKinds() const override {
427a7e6055SDimitry Andric     return WebAssembly::NumTargetFixupKinds;
437a7e6055SDimitry Andric   }
447a7e6055SDimitry Andric 
457a7e6055SDimitry Andric   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
467a7e6055SDimitry Andric 
47edd7eaddSDimitry Andric   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
48edd7eaddSDimitry Andric                   const MCValue &Target, MutableArrayRef<char> Data,
49*4ba319b5SDimitry Andric                   uint64_t Value, bool IsPCRel,
50*4ba319b5SDimitry Andric                   const MCSubtargetInfo *STI) const override;
517a7e6055SDimitry Andric 
52*4ba319b5SDimitry Andric   std::unique_ptr<MCObjectTargetWriter>
53*4ba319b5SDimitry Andric   createObjectTargetWriter() const override;
547a7e6055SDimitry Andric 
557a7e6055SDimitry Andric   // No instruction requires relaxation
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const567a7e6055SDimitry Andric   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
577a7e6055SDimitry Andric                             const MCRelaxableFragment *DF,
587a7e6055SDimitry Andric                             const MCAsmLayout &Layout) const override {
597a7e6055SDimitry Andric     return false;
607a7e6055SDimitry Andric   }
617a7e6055SDimitry Andric 
mayNeedRelaxation(const MCInst & Inst,const MCSubtargetInfo & STI) const62*4ba319b5SDimitry Andric   bool mayNeedRelaxation(const MCInst &Inst,
63*4ba319b5SDimitry Andric                          const MCSubtargetInfo &STI) const override {
64*4ba319b5SDimitry Andric     return false;
65*4ba319b5SDimitry Andric   }
667a7e6055SDimitry Andric 
relaxInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,MCInst & Res) const677a7e6055SDimitry Andric   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
687a7e6055SDimitry Andric                         MCInst &Res) const override {}
697a7e6055SDimitry Andric 
70*4ba319b5SDimitry Andric   bool writeNopData(raw_ostream &OS, uint64_t Count) const override;
717a7e6055SDimitry Andric };
727a7e6055SDimitry Andric 
737a7e6055SDimitry Andric const MCFixupKindInfo &
getFixupKindInfo(MCFixupKind Kind) const747a7e6055SDimitry Andric WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
757a7e6055SDimitry Andric   const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
767a7e6055SDimitry Andric       // This table *must* be in the order that the fixup_* kinds are defined in
777a7e6055SDimitry Andric       // WebAssemblyFixupKinds.h.
787a7e6055SDimitry Andric       //
797a7e6055SDimitry Andric       // Name                     Offset (bits) Size (bits)     Flags
807a7e6055SDimitry Andric       {"fixup_code_sleb128_i32", 0, 5 * 8, 0},
817a7e6055SDimitry Andric       {"fixup_code_sleb128_i64", 0, 10 * 8, 0},
827a7e6055SDimitry Andric       {"fixup_code_uleb128_i32", 0, 5 * 8, 0},
837a7e6055SDimitry Andric   };
847a7e6055SDimitry Andric 
857a7e6055SDimitry Andric   if (Kind < FirstTargetFixupKind)
867a7e6055SDimitry Andric     return MCAsmBackend::getFixupKindInfo(Kind);
877a7e6055SDimitry Andric 
887a7e6055SDimitry Andric   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
897a7e6055SDimitry Andric          "Invalid kind!");
907a7e6055SDimitry Andric   return Infos[Kind - FirstTargetFixupKind];
917a7e6055SDimitry Andric }
927a7e6055SDimitry Andric 
writeNopData(raw_ostream & OS,uint64_t Count) const93*4ba319b5SDimitry Andric bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS,
94*4ba319b5SDimitry Andric                                          uint64_t Count) const {
95d88c1a5aSDimitry Andric   for (uint64_t i = 0; i < Count; ++i)
96*4ba319b5SDimitry Andric     OS << char(WebAssembly::Nop);
97d88c1a5aSDimitry Andric 
98d88c1a5aSDimitry Andric   return true;
997d523365SDimitry Andric }
1007d523365SDimitry Andric 
applyFixup(const MCAssembler & Asm,const MCFixup & Fixup,const MCValue & Target,MutableArrayRef<char> Data,uint64_t Value,bool IsPCRel,const MCSubtargetInfo * STI) const101edd7eaddSDimitry Andric void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm,
102edd7eaddSDimitry Andric                                        const MCFixup &Fixup,
103edd7eaddSDimitry Andric                                        const MCValue &Target,
104edd7eaddSDimitry Andric                                        MutableArrayRef<char> Data,
105*4ba319b5SDimitry Andric                                        uint64_t Value, bool IsPCRel,
106*4ba319b5SDimitry Andric                                        const MCSubtargetInfo *STI) const {
1077d523365SDimitry Andric   const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
1083ca95b02SDimitry Andric   assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
1093ca95b02SDimitry Andric 
1107a7e6055SDimitry Andric   unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
1113ca95b02SDimitry Andric   if (Value == 0)
1127d523365SDimitry Andric     return; // Doesn't change encoding.
1137d523365SDimitry Andric 
1147d523365SDimitry Andric   // Shift the value into position.
1157d523365SDimitry Andric   Value <<= Info.TargetOffset;
1167d523365SDimitry Andric 
1177d523365SDimitry Andric   unsigned Offset = Fixup.getOffset();
118edd7eaddSDimitry Andric   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
1197d523365SDimitry Andric 
1207d523365SDimitry Andric   // For each byte of the fragment that the fixup touches, mask in the
1217d523365SDimitry Andric   // bits from the fixup value.
1227d523365SDimitry Andric   for (unsigned i = 0; i != NumBytes; ++i)
1237d523365SDimitry Andric     Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
1247d523365SDimitry Andric }
1257d523365SDimitry Andric 
126*4ba319b5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createObjectTargetWriter() const127*4ba319b5SDimitry Andric WebAssemblyAsmBackend::createObjectTargetWriter() const {
128*4ba319b5SDimitry Andric   return createWebAssemblyWasmObjectWriter(Is64Bit);
1297d523365SDimitry Andric }
130*4ba319b5SDimitry Andric 
1317d523365SDimitry Andric } // end anonymous namespace
1327d523365SDimitry Andric 
createWebAssemblyAsmBackend(const Triple & TT)133444ed5c5SDimitry Andric MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
1347d523365SDimitry Andric   return new WebAssemblyAsmBackend(TT.isArch64Bit());
1357d523365SDimitry Andric }
136