blob: 16d5e51770fcdbc4977e6cd8357eeb68dc9a025e [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
15#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Dan Gohmand934cb82017-02-24 23:18:00 +000016#include "MCTargetDesc/WebAssemblyFixupKinds.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
40 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
41 uint64_t Value, bool IsPCRel) const override;
42
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
Dan Gohman05ac43f2015-12-17 01:39:00 +000080 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
81 uint64_t Value, bool IsPCRel) const override;
82
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
108void WebAssemblyAsmBackendELF::applyFixup(const MCFixup &Fixup, char *Data,
109 unsigned DataSize, uint64_t Value,
110 bool IsPCRel) const {
111 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
112 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
113
114 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
115 if (Value == 0)
116 return; // Doesn't change encoding.
117
118 // Shift the value into position.
119 Value <<= Info.TargetOffset;
120
121 unsigned Offset = Fixup.getOffset();
122 assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
123
124 // For each byte of the fragment that the fixup touches, mask in the
125 // bits from the fixup value.
126 for (unsigned i = 0; i != NumBytes; ++i)
127 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
128}
129
130MCObjectWriter *
131WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
132 return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
133}
134
Dan Gohmand934cb82017-02-24 23:18:00 +0000135const MCFixupKindInfo &
136WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
137 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
138 // This table *must* be in the order that the fixup_* kinds are defined in
139 // WebAssemblyFixupKinds.h.
140 //
141 // Name Offset (bits) Size (bits) Flags
142 { "fixup_code_sleb128_i32", 0, 5*8, 0 },
143 { "fixup_code_sleb128_i64", 0, 10*8, 0 },
144 { "fixup_code_uleb128_i32", 0, 5*8, 0 },
145 };
146
147 if (Kind < FirstTargetFixupKind)
148 return MCAsmBackend::getFixupKindInfo(Kind);
149
150 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
151 "Invalid kind!");
152 return Infos[Kind - FirstTargetFixupKind];
153}
154
Dan Gohman05ac43f2015-12-17 01:39:00 +0000155bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
156 MCObjectWriter *OW) const {
157 if (Count == 0)
158 return true;
159
Dan Gohman3acb1872016-10-24 23:27:49 +0000160 for (uint64_t i = 0; i < Count; ++i)
161 OW->write8(WebAssembly::Nop);
162
163 return true;
Dan Gohman05ac43f2015-12-17 01:39:00 +0000164}
165
166void WebAssemblyAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
167 unsigned DataSize, uint64_t Value,
168 bool IsPCRel) const {
169 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
Dan Gohmana39ca602016-01-13 19:31:57 +0000170 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
171
Dan Gohman18eafb62017-02-22 01:23:18 +0000172 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
Dan Gohman938ff9f2016-01-13 19:29:37 +0000173 if (Value == 0)
Dan Gohman05ac43f2015-12-17 01:39:00 +0000174 return; // Doesn't change encoding.
175
176 // Shift the value into position.
177 Value <<= Info.TargetOffset;
178
179 unsigned Offset = Fixup.getOffset();
180 assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!");
181
182 // For each byte of the fragment that the fixup touches, mask in the
183 // bits from the fixup value.
184 for (unsigned i = 0; i != NumBytes; ++i)
185 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
186}
187
188MCObjectWriter *
189WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000190 return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
Dan Gohman05ac43f2015-12-17 01:39:00 +0000191}
192} // end anonymous namespace
193
Dan Gohmancceedf72016-01-08 00:43:54 +0000194MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
Dan Gohman18eafb62017-02-22 01:23:18 +0000195 if (TT.isOSBinFormatELF())
196 return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
Dan Gohman05ac43f2015-12-17 01:39:00 +0000197 return new WebAssemblyAsmBackend(TT.isArch64Bit());
198}