blob: 226a3b35f2cf865a7e93b915cd645639f2744b16 [file] [log] [blame]
Dan Gohman05ac43f2015-12-17 01:39:00 +00001//===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief This file implements the WebAssemblyAsmBackend class.
12///
13//===----------------------------------------------------------------------===//
14
Dan Gohmand934cb82017-02-24 23:18:00 +000015#include "MCTargetDesc/WebAssemblyFixupKinds.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000016#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Dan Gohman05ac43f2015-12-17 01:39:00 +000017#include "llvm/MC/MCAsmBackend.h"
18#include "llvm/MC/MCAssembler.h"
19#include "llvm/MC/MCDirectives.h"
20#include "llvm/MC/MCELFObjectWriter.h"
21#include "llvm/MC/MCExpr.h"
22#include "llvm/MC/MCFixupKindInfo.h"
23#include "llvm/MC/MCObjectWriter.h"
24#include "llvm/MC/MCSubtargetInfo.h"
25#include "llvm/MC/MCSymbol.h"
Dan Gohmand37dc2f2017-02-27 22:41:39 +000026#include "llvm/MC/MCWasmObjectWriter.h"
Dan Gohman05ac43f2015-12-17 01:39:00 +000027#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/raw_ostream.h"
29using namespace llvm;
30
31namespace {
Dan Gohman18eafb62017-02-22 01:23:18 +000032class WebAssemblyAsmBackendELF final : public MCAsmBackend {
33 bool Is64Bit;
34
35public:
36 explicit WebAssemblyAsmBackendELF(bool Is64Bit)
37 : MCAsmBackend(), Is64Bit(Is64Bit) {}
38 ~WebAssemblyAsmBackendELF() override {}
39
Derek Schuffd2c9ec72017-06-24 01:00:43 +000040 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
41 const MCValue &Target, MutableArrayRef<char> Data,
42 uint64_t Value, bool IsPCRel) const override;
Dan Gohman18eafb62017-02-22 01:23:18 +000043
Derek Schuff669300d2017-10-10 17:31:43 +000044 std::unique_ptr<MCObjectWriter>
45 createObjectWriter(raw_pwrite_stream &OS) const override;
Dan Gohman18eafb62017-02-22 01:23:18 +000046
47 // No instruction requires relaxation
48 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
49 const MCRelaxableFragment *DF,
50 const MCAsmLayout &Layout) const override {
51 return false;
52 }
53
54 unsigned getNumFixupKinds() const override {
55 // We currently just use the generic fixups in MCFixup.h and don't have any
56 // target-specific fixups.
57 return 0;
58 }
59
60 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
61
62 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
63 MCInst &Res) const override {}
64
65 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
66};
67
Dan Gohman05ac43f2015-12-17 01:39:00 +000068class WebAssemblyAsmBackend final : public MCAsmBackend {
69 bool Is64Bit;
70
71public:
72 explicit WebAssemblyAsmBackend(bool Is64Bit)
73 : MCAsmBackend(), Is64Bit(Is64Bit) {}
74 ~WebAssemblyAsmBackend() override {}
75
Dan Gohmand934cb82017-02-24 23:18:00 +000076 unsigned getNumFixupKinds() const override {
77 return WebAssembly::NumTargetFixupKinds;
78 }
79
80 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
81
Derek Schuffd2c9ec72017-06-24 01:00:43 +000082 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
83 const MCValue &Target, MutableArrayRef<char> Data,
84 uint64_t Value, bool IsPCRel) const override;
Dan Gohman05ac43f2015-12-17 01:39:00 +000085
Derek Schuff669300d2017-10-10 17:31:43 +000086 std::unique_ptr<MCObjectWriter>
87 createObjectWriter(raw_pwrite_stream &OS) const override;
Dan Gohman05ac43f2015-12-17 01:39:00 +000088
89 // No instruction requires relaxation
90 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
91 const MCRelaxableFragment *DF,
92 const MCAsmLayout &Layout) const override {
93 return false;
94 }
95
Dan Gohman05ac43f2015-12-17 01:39:00 +000096 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
97
Nirav Dave86030622016-07-11 14:23:53 +000098 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
99 MCInst &Res) const override {}
Dan Gohman05ac43f2015-12-17 01:39:00 +0000100
101 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
102};
103
Dan Gohman18eafb62017-02-22 01:23:18 +0000104bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count,
105 MCObjectWriter *OW) const {
106 for (uint64_t i = 0; i < Count; ++i)
107 OW->write8(WebAssembly::Nop);
108
109 return true;
110}
111
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000112void WebAssemblyAsmBackendELF::applyFixup(const MCAssembler &Asm,
113 const MCFixup &Fixup,
114 const MCValue &Target,
Reid Kleckneref581752017-06-22 01:07:05 +0000115 MutableArrayRef<char> Data,
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000116 uint64_t Value, bool IsPCRel) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000117 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
118 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
119
120 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
121 if (Value == 0)
122 return; // Doesn't change encoding.
123
124 // Shift the value into position.
125 Value <<= Info.TargetOffset;
126
127 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000128 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman18eafb62017-02-22 01:23:18 +0000129
130 // For each byte of the fragment that the fixup touches, mask in the
131 // bits from the fixup value.
132 for (unsigned i = 0; i != NumBytes; ++i)
133 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
134}
135
Derek Schuff669300d2017-10-10 17:31:43 +0000136std::unique_ptr<MCObjectWriter>
Dan Gohman18eafb62017-02-22 01:23:18 +0000137WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
138 return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
139}
140
Dan Gohmand934cb82017-02-24 23:18:00 +0000141const MCFixupKindInfo &
142WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
143 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
144 // This table *must* be in the order that the fixup_* kinds are defined in
145 // WebAssemblyFixupKinds.h.
146 //
147 // Name Offset (bits) Size (bits) Flags
148 { "fixup_code_sleb128_i32", 0, 5*8, 0 },
149 { "fixup_code_sleb128_i64", 0, 10*8, 0 },
150 { "fixup_code_uleb128_i32", 0, 5*8, 0 },
151 };
152
153 if (Kind < FirstTargetFixupKind)
154 return MCAsmBackend::getFixupKindInfo(Kind);
155
156 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
157 "Invalid kind!");
158 return Infos[Kind - FirstTargetFixupKind];
159}
160
Dan Gohman05ac43f2015-12-17 01:39:00 +0000161bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
162 MCObjectWriter *OW) const {
163 if (Count == 0)
164 return true;
165
Dan Gohman3acb1872016-10-24 23:27:49 +0000166 for (uint64_t i = 0; i < Count; ++i)
167 OW->write8(WebAssembly::Nop);
168
169 return true;
Dan Gohman05ac43f2015-12-17 01:39:00 +0000170}
171
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000172void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm,
173 const MCFixup &Fixup,
174 const MCValue &Target,
Reid Kleckneref581752017-06-22 01:07:05 +0000175 MutableArrayRef<char> Data,
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000176 uint64_t Value, bool IsPCRel) const {
Dan Gohman05ac43f2015-12-17 01:39:00 +0000177 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
Dan Gohmana39ca602016-01-13 19:31:57 +0000178 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
179
Dan Gohman18eafb62017-02-22 01:23:18 +0000180 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
Dan Gohman938ff9f2016-01-13 19:29:37 +0000181 if (Value == 0)
Dan Gohman05ac43f2015-12-17 01:39:00 +0000182 return; // Doesn't change encoding.
183
184 // Shift the value into position.
185 Value <<= Info.TargetOffset;
186
187 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000188 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman05ac43f2015-12-17 01:39:00 +0000189
190 // For each byte of the fragment that the fixup touches, mask in the
191 // bits from the fixup value.
192 for (unsigned i = 0; i != NumBytes; ++i)
193 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
194}
195
Derek Schuff669300d2017-10-10 17:31:43 +0000196std::unique_ptr<MCObjectWriter>
Dan Gohman05ac43f2015-12-17 01:39:00 +0000197WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000198 return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
Dan Gohman05ac43f2015-12-17 01:39:00 +0000199}
200} // end anonymous namespace
201
Dan Gohmancceedf72016-01-08 00:43:54 +0000202MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
Dan Gohman18eafb62017-02-22 01:23:18 +0000203 if (TT.isOSBinFormatELF())
204 return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
Dan Gohman05ac43f2015-12-17 01:39:00 +0000205 return new WebAssemblyAsmBackend(TT.isArch64Bit());
206}