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