1//===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the WebAssemblyAsmBackend class.
11///
12//===----------------------------------------------------------------------===//
13
14#include "MCTargetDesc/WebAssemblyFixupKinds.h"
15#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16#include "llvm/MC/MCAsmBackend.h"
17#include "llvm/MC/MCAssembler.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCFixupKindInfo.h"
20#include "llvm/MC/MCObjectWriter.h"
21#include "llvm/MC/MCSubtargetInfo.h"
22#include "llvm/MC/MCSymbol.h"
23#include "llvm/MC/MCValue.h"
24#include "llvm/MC/MCWasmObjectWriter.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace llvm;
28
29namespace {
30
31class WebAssemblyAsmBackend final : public MCAsmBackend {
32 bool Is64Bit;
33 bool IsEmscripten;
34
35public:
36 explicit WebAssemblyAsmBackend(bool Is64Bit, bool IsEmscripten)
37 : MCAsmBackend(llvm::endianness::little), Is64Bit(Is64Bit),
38 IsEmscripten(IsEmscripten) {}
39
40 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
41
42 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
43 MutableArrayRef<char> Data, uint64_t Value, bool) override;
44
45 std::unique_ptr<MCObjectTargetWriter>
46 createObjectTargetWriter() const override;
47
48 bool writeNopData(raw_ostream &OS, uint64_t Count,
49 const MCSubtargetInfo *STI) const override;
50};
51
52MCFixupKindInfo
53WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
54 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
55 // This table *must* be in the order that the fixup_* kinds are defined in
56 // WebAssemblyFixupKinds.h.
57 //
58 // Name Offset (bits) Size (bits) Flags
59 {.Name: "fixup_sleb128_i32", .TargetOffset: 0, .TargetSize: 5 * 8, .Flags: 0},
60 {.Name: "fixup_sleb128_i64", .TargetOffset: 0, .TargetSize: 10 * 8, .Flags: 0},
61 {.Name: "fixup_uleb128_i32", .TargetOffset: 0, .TargetSize: 5 * 8, .Flags: 0},
62 {.Name: "fixup_uleb128_i64", .TargetOffset: 0, .TargetSize: 10 * 8, .Flags: 0},
63 };
64
65 if (Kind < FirstTargetFixupKind)
66 return MCAsmBackend::getFixupKindInfo(Kind);
67
68 assert(unsigned(Kind - FirstTargetFixupKind) <
69 WebAssembly::NumTargetFixupKinds &&
70 "Invalid kind!");
71 return Infos[Kind - FirstTargetFixupKind];
72}
73
74bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
75 const MCSubtargetInfo *STI) const {
76 for (uint64_t I = 0; I < Count; ++I)
77 OS << char(WebAssembly::Nop);
78
79 return true;
80}
81
82void WebAssemblyAsmBackend::applyFixup(const MCFragment &F,
83 const MCFixup &Fixup,
84 const MCValue &Target,
85 MutableArrayRef<char> Data,
86 uint64_t Value, bool IsResolved) {
87 if (!IsResolved)
88 Asm->getWriter().recordRelocation(F, Fixup, Target, FixedValue&: Value);
89
90 MCFixupKindInfo Info = getFixupKindInfo(Kind: Fixup.getKind());
91 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
92
93 unsigned NumBytes = alignTo(Value: Info.TargetSize, Align: 8) / 8;
94 if (Value == 0)
95 return; // Doesn't change encoding.
96
97 // Shift the value into position.
98 Value <<= Info.TargetOffset;
99
100 unsigned Offset = Fixup.getOffset();
101 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
102
103 // For each byte of the fragment that the fixup touches, mask in the
104 // bits from the fixup value.
105 for (unsigned I = 0; I != NumBytes; ++I)
106 Data[Offset + I] |= uint8_t((Value >> (I * 8)) & 0xff);
107}
108
109std::unique_ptr<MCObjectTargetWriter>
110WebAssemblyAsmBackend::createObjectTargetWriter() const {
111 return createWebAssemblyWasmObjectWriter(Is64Bit, IsEmscripten);
112}
113
114} // end anonymous namespace
115
116MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
117 return new WebAssemblyAsmBackend(TT.isArch64Bit(), TT.isOSEmscripten());
118}
119