blob: 1357cb5735f8aeaa4810de76feec1bbe1767c764 [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
44 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
45
46 // No instruction requires relaxation
47 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
48 const MCRelaxableFragment *DF,
49 const MCAsmLayout &Layout) const override {
50 return false;
51 }
52
53 unsigned getNumFixupKinds() const override {
54 // We currently just use the generic fixups in MCFixup.h and don't have any
55 // target-specific fixups.
56 return 0;
57 }
58
59 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
60
61 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
62 MCInst &Res) const override {}
63
64 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
65};
66
Dan Gohman05ac43f2015-12-17 01:39:00 +000067class WebAssemblyAsmBackend final : public MCAsmBackend {
68 bool Is64Bit;
69
70public:
71 explicit WebAssemblyAsmBackend(bool Is64Bit)
72 : MCAsmBackend(), Is64Bit(Is64Bit) {}
73 ~WebAssemblyAsmBackend() override {}
74
Dan Gohmand934cb82017-02-24 23:18:00 +000075 unsigned getNumFixupKinds() const override {
76 return WebAssembly::NumTargetFixupKinds;
77 }
78
79 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
80
Derek Schuffd2c9ec72017-06-24 01:00:43 +000081 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
82 const MCValue &Target, MutableArrayRef<char> Data,
83 uint64_t Value, bool IsPCRel) const override;
Dan Gohman05ac43f2015-12-17 01:39:00 +000084
85 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
86
87 // No instruction requires relaxation
88 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
89 const MCRelaxableFragment *DF,
90 const MCAsmLayout &Layout) const override {
91 return false;
92 }
93
Dan Gohman05ac43f2015-12-17 01:39:00 +000094 bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
95
Nirav Dave86030622016-07-11 14:23:53 +000096 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
97 MCInst &Res) const override {}
Dan Gohman05ac43f2015-12-17 01:39:00 +000098
99 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
100};
101
Dan Gohman18eafb62017-02-22 01:23:18 +0000102bool WebAssemblyAsmBackendELF::writeNopData(uint64_t Count,
103 MCObjectWriter *OW) const {
104 for (uint64_t i = 0; i < Count; ++i)
105 OW->write8(WebAssembly::Nop);
106
107 return true;
108}
109
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000110void WebAssemblyAsmBackendELF::applyFixup(const MCAssembler &Asm,
111 const MCFixup &Fixup,
112 const MCValue &Target,
Reid Kleckneref581752017-06-22 01:07:05 +0000113 MutableArrayRef<char> Data,
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000114 uint64_t Value, bool IsPCRel) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000115 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
116 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
117
118 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
119 if (Value == 0)
120 return; // Doesn't change encoding.
121
122 // Shift the value into position.
123 Value <<= Info.TargetOffset;
124
125 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000126 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman18eafb62017-02-22 01:23:18 +0000127
128 // For each byte of the fragment that the fixup touches, mask in the
129 // bits from the fixup value.
130 for (unsigned i = 0; i != NumBytes; ++i)
131 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
132}
133
134MCObjectWriter *
135WebAssemblyAsmBackendELF::createObjectWriter(raw_pwrite_stream &OS) const {
136 return createWebAssemblyELFObjectWriter(OS, Is64Bit, 0);
137}
138
Dan Gohmand934cb82017-02-24 23:18:00 +0000139const MCFixupKindInfo &
140WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
141 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {
142 // This table *must* be in the order that the fixup_* kinds are defined in
143 // WebAssemblyFixupKinds.h.
144 //
145 // Name Offset (bits) Size (bits) Flags
146 { "fixup_code_sleb128_i32", 0, 5*8, 0 },
147 { "fixup_code_sleb128_i64", 0, 10*8, 0 },
148 { "fixup_code_uleb128_i32", 0, 5*8, 0 },
149 };
150
151 if (Kind < FirstTargetFixupKind)
152 return MCAsmBackend::getFixupKindInfo(Kind);
153
154 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
155 "Invalid kind!");
156 return Infos[Kind - FirstTargetFixupKind];
157}
158
Dan Gohman05ac43f2015-12-17 01:39:00 +0000159bool WebAssemblyAsmBackend::writeNopData(uint64_t Count,
160 MCObjectWriter *OW) const {
161 if (Count == 0)
162 return true;
163
Dan Gohman3acb1872016-10-24 23:27:49 +0000164 for (uint64_t i = 0; i < Count; ++i)
165 OW->write8(WebAssembly::Nop);
166
167 return true;
Dan Gohman05ac43f2015-12-17 01:39:00 +0000168}
169
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000170void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm,
171 const MCFixup &Fixup,
172 const MCValue &Target,
Reid Kleckneref581752017-06-22 01:07:05 +0000173 MutableArrayRef<char> Data,
Derek Schuffd2c9ec72017-06-24 01:00:43 +0000174 uint64_t Value, bool IsPCRel) const {
Dan Gohman05ac43f2015-12-17 01:39:00 +0000175 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind());
Dan Gohmana39ca602016-01-13 19:31:57 +0000176 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags");
177
Dan Gohman18eafb62017-02-22 01:23:18 +0000178 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8;
Dan Gohman938ff9f2016-01-13 19:29:37 +0000179 if (Value == 0)
Dan Gohman05ac43f2015-12-17 01:39:00 +0000180 return; // Doesn't change encoding.
181
182 // Shift the value into position.
183 Value <<= Info.TargetOffset;
184
185 unsigned Offset = Fixup.getOffset();
Reid Kleckneref581752017-06-22 01:07:05 +0000186 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
Dan Gohman05ac43f2015-12-17 01:39:00 +0000187
188 // For each byte of the fragment that the fixup touches, mask in the
189 // bits from the fixup value.
190 for (unsigned i = 0; i != NumBytes; ++i)
191 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
192}
193
194MCObjectWriter *
195WebAssemblyAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
Dan Gohman18eafb62017-02-22 01:23:18 +0000196 return createWebAssemblyWasmObjectWriter(OS, Is64Bit);
Dan Gohman05ac43f2015-12-17 01:39:00 +0000197}
198} // end anonymous namespace
199
Dan Gohmancceedf72016-01-08 00:43:54 +0000200MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {
Dan Gohman18eafb62017-02-22 01:23:18 +0000201 if (TT.isOSBinFormatELF())
202 return new WebAssemblyAsmBackendELF(TT.isArch64Bit());
Dan Gohman05ac43f2015-12-17 01:39:00 +0000203 return new WebAssemblyAsmBackend(TT.isArch64Bit());
204}