blob: 2e43c6a66253ac28e2192288eb0618f75a35366b [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
Reid Kleckneref581752017-06-22 01:07:05 +000040 void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
Alexander Kornienko014ac692017-04-05 11:50:43 +000041 uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
Dan Gohman18eafb62017-02-22 01:23:18 +000042
43 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
44
45 // No instruction requires relaxation
46 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
47 const MCRelaxableFragment *DF,
48 const MCAsmLayout &Layout) const override {
49 return false;
50 }
51
52 unsigned getNumFixupKinds() const override {
53 // We currently just use the generic fixups in MCFixup.h and don't have any
54 // target-specific fixups.
55 return 0;
56 }
57
58 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
59
60 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
61 MCInst &Res) const override {}
62
63 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
64};
65
Dan Gohman05ac43f2015-12-17 01:39:00 +000066class WebAssemblyAsmBackend final : public MCAsmBackend {
67 bool Is64Bit;
68
69public:
70 explicit WebAssemblyAsmBackend(bool Is64Bit)
71 : MCAsmBackend(), Is64Bit(Is64Bit) {}
72 ~WebAssemblyAsmBackend() override {}
73
Dan Gohmand934cb82017-02-24 23:18:00 +000074 unsigned getNumFixupKinds() const override {
75 return WebAssembly::NumTargetFixupKinds;
76 }
77
78 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
79
Reid Kleckneref581752017-06-22 01:07:05 +000080 void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data,
Alexander Kornienko014ac692017-04-05 11:50:43 +000081 uint64_t Value, bool IsPCRel, MCContext &Ctx) const override;
Dan Gohman05ac43f2015-12-17 01:39:00 +000082
83 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
84
85 // No instruction requires relaxation
86 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
87 const MCRelaxableFragment *DF,
88 const MCAsmLayout &Layout) const override {
89 return false;
90 }
91
Dan Gohman05ac43f2015-12-17 01:39:00 +000092 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
93
Nirav Dave86030622016-07-11 14:23:53 +000094 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
95 MCInst &Res) const override {}
Dan Gohman05ac43f2015-12-17 01:39:00 +000096
97 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
98};
99
Dan Gohman18eafb62017-02-22 01:23:18 +0000100bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count,
101 MCObjectWriter *OW) const {
102 for (uint64_t i = 0; i < Count; ++i)
103 OW->write8(WebAssembly::Nop);
104
105 return true;
106}
107
Reid Kleckneref581752017-06-22 01:07:05 +0000108void WebAssemblyAsmBackendELF::applyFixup(const MCFixup &Fixup,
109 MutableArrayRef<char> Data,
110 uint64_t Value, bool IsPCRel,
111 MCContext &Ctx) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000112 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
113 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
114
115 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
116 if (Value == 0)
117 return; // Doesn't change encoding.
118
119 // Shift the value into position.
120 Value <<= Info.TargetOffset;
121
122 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000123 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman18eafb62017-02-22 01:23:18 +0000124
125 // For each byte of the fragment that the fixup touches, mask in the
126 // bits from the fixup value.
127 for (unsigned i = 0; i != NumBytes; ++i)
128 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
129}
130
131MCObjectWriter *
132WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
133 return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
134}
135
Dan Gohmand934cb82017-02-24 23:18:00 +0000136const MCFixupKindInfo &
137WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
138 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
139 // This table *must* be in the order that the fixup_* kinds are defined in
140 // WebAssemblyFixupKinds.h.
141 //
142 // Name Offset (bits) Size (bits) Flags
143 { "fixup_code_sleb128_i32", 0, 5*8, 0 },
144 { "fixup_code_sleb128_i64", 0, 10*8, 0 },
145 { "fixup_code_uleb128_i32", 0, 5*8, 0 },
146 };
147
148 if (Kind < FirstTargetFixupKind)
149 return MCAsmBackend::getFixupKindInfo(Kind);
150
151 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
152 "Invalid kind!");
153 return Infos[Kind - FirstTargetFixupKind];
154}
155
Dan Gohman05ac43f2015-12-17 01:39:00 +0000156bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
157 MCObjectWriter *OW) const {
158 if (Count == 0)
159 return true;
160
Dan Gohman3acb1872016-10-24 23:27:49 +0000161 for (uint64_t i = 0; i < Count; ++i)
162 OW->write8(WebAssembly::Nop);
163
164 return true;
Dan Gohman05ac43f2015-12-17 01:39:00 +0000165}
166
Reid Kleckneref581752017-06-22 01:07:05 +0000167void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup,
168 MutableArrayRef<char> Data,
169 uint64_t Value, bool IsPCRel,
170 MCContext &Ctx) const {
Dan Gohman05ac43f2015-12-17 01:39:00 +0000171 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
Dan Gohmana39ca602016-01-13 19:31:57 +0000172 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
173
Dan Gohman18eafb62017-02-22 01:23:18 +0000174 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
Dan Gohman938ff9f2016-01-13 19:29:37 +0000175 if (Value == 0)
Dan Gohman05ac43f2015-12-17 01:39:00 +0000176 return; // Doesn't change encoding.
177
178 // Shift the value into position.
179 Value <<= Info.TargetOffset;
180
181 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000182 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman05ac43f2015-12-17 01:39:00 +0000183
184 // For each byte of the fragment that the fixup touches, mask in the
185 // bits from the fixup value.
186 for (unsigned i = 0; i != NumBytes; ++i)
187 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
188}
189
190MCObjectWriter *
191WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000192 return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
Dan Gohman05ac43f2015-12-17 01:39:00 +0000193}
194} // end anonymous namespace
195
Dan Gohmancceedf72016-01-08 00:43:54 +0000196MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
Dan Gohman18eafb62017-02-22 01:23:18 +0000197 if (TT.isOSBinFormatELF())
198 return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
Dan Gohman05ac43f2015-12-17 01:39:00 +0000199 return new WebAssemblyAsmBackend(TT.isArch64Bit());
200}