Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
35294 views
1
//=- WebAssemblyMCCodeEmitter.cpp - Convert WebAssembly code to machine code -//
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 WebAssemblyMCCodeEmitter class.
11
///
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/WebAssemblyFixupKinds.h"
15
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/ADT/Statistic.h"
18
#include "llvm/MC/MCCodeEmitter.h"
19
#include "llvm/MC/MCContext.h"
20
#include "llvm/MC/MCFixup.h"
21
#include "llvm/MC/MCInst.h"
22
#include "llvm/MC/MCInstrInfo.h"
23
#include "llvm/MC/MCRegisterInfo.h"
24
#include "llvm/MC/MCSubtargetInfo.h"
25
#include "llvm/MC/MCSymbol.h"
26
#include "llvm/Support/Debug.h"
27
#include "llvm/Support/EndianStream.h"
28
#include "llvm/Support/LEB128.h"
29
#include "llvm/Support/SMLoc.h"
30
#include "llvm/Support/raw_ostream.h"
31
32
using namespace llvm;
33
34
#define DEBUG_TYPE "mccodeemitter"
35
36
STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
37
STATISTIC(MCNumFixups, "Number of MC fixups created.");
38
39
namespace {
40
class WebAssemblyMCCodeEmitter final : public MCCodeEmitter {
41
const MCInstrInfo &MCII;
42
MCContext &Ctx;
43
// Implementation generated by tablegen.
44
uint64_t getBinaryCodeForInstr(const MCInst &MI,
45
SmallVectorImpl<MCFixup> &Fixups,
46
const MCSubtargetInfo &STI) const;
47
48
void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
49
SmallVectorImpl<MCFixup> &Fixups,
50
const MCSubtargetInfo &STI) const override;
51
52
public:
53
WebAssemblyMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
54
: MCII(MCII), Ctx{Ctx} {}
55
};
56
} // end anonymous namespace
57
58
MCCodeEmitter *llvm::createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII,
59
MCContext &Ctx) {
60
return new WebAssemblyMCCodeEmitter(MCII, Ctx);
61
}
62
63
void WebAssemblyMCCodeEmitter::encodeInstruction(
64
const MCInst &MI, SmallVectorImpl<char> &CB,
65
SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
66
raw_svector_ostream OS(CB);
67
uint64_t Start = OS.tell();
68
69
uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
70
if (Binary < (1 << 8)) {
71
OS << uint8_t(Binary);
72
} else if (Binary < (1 << 16)) {
73
OS << uint8_t(Binary >> 8);
74
encodeULEB128(uint8_t(Binary), OS);
75
} else if (Binary < (1 << 24)) {
76
OS << uint8_t(Binary >> 16);
77
encodeULEB128(uint16_t(Binary), OS);
78
} else {
79
llvm_unreachable("Very large (prefix + 3 byte) opcodes not supported");
80
}
81
82
// For br_table instructions, encode the size of the table. In the MCInst,
83
// there's an index operand (if not a stack instruction), one operand for
84
// each table entry, and the default operand.
85
if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
86
MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
87
encodeULEB128(MI.getNumOperands() - 1, OS);
88
if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
89
MI.getOpcode() == WebAssembly::BR_TABLE_I64)
90
encodeULEB128(MI.getNumOperands() - 2, OS);
91
92
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
93
for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
94
const MCOperand &MO = MI.getOperand(I);
95
if (MO.isReg()) {
96
/* nothing to encode */
97
98
} else if (MO.isImm()) {
99
if (I < Desc.getNumOperands()) {
100
const MCOperandInfo &Info = Desc.operands()[I];
101
LLVM_DEBUG(dbgs() << "Encoding immediate: type="
102
<< int(Info.OperandType) << "\n");
103
switch (Info.OperandType) {
104
case WebAssembly::OPERAND_I32IMM:
105
encodeSLEB128(int32_t(MO.getImm()), OS);
106
break;
107
case WebAssembly::OPERAND_OFFSET32:
108
encodeULEB128(uint32_t(MO.getImm()), OS);
109
break;
110
case WebAssembly::OPERAND_I64IMM:
111
encodeSLEB128(int64_t(MO.getImm()), OS);
112
break;
113
case WebAssembly::OPERAND_SIGNATURE:
114
case WebAssembly::OPERAND_VEC_I8IMM:
115
support::endian::write<uint8_t>(OS, MO.getImm(),
116
llvm::endianness::little);
117
break;
118
case WebAssembly::OPERAND_VEC_I16IMM:
119
support::endian::write<uint16_t>(OS, MO.getImm(),
120
llvm::endianness::little);
121
break;
122
case WebAssembly::OPERAND_VEC_I32IMM:
123
support::endian::write<uint32_t>(OS, MO.getImm(),
124
llvm::endianness::little);
125
break;
126
case WebAssembly::OPERAND_VEC_I64IMM:
127
support::endian::write<uint64_t>(OS, MO.getImm(),
128
llvm::endianness::little);
129
break;
130
case WebAssembly::OPERAND_GLOBAL:
131
Ctx.reportError(
132
SMLoc(),
133
Twine("Wasm globals should only be accessed symbolically!"));
134
break;
135
default:
136
encodeULEB128(uint64_t(MO.getImm()), OS);
137
}
138
} else {
139
encodeULEB128(uint64_t(MO.getImm()), OS);
140
}
141
142
} else if (MO.isSFPImm()) {
143
uint32_t F = MO.getSFPImm();
144
support::endian::write<uint32_t>(OS, F, llvm::endianness::little);
145
} else if (MO.isDFPImm()) {
146
uint64_t D = MO.getDFPImm();
147
support::endian::write<uint64_t>(OS, D, llvm::endianness::little);
148
} else if (MO.isExpr()) {
149
const MCOperandInfo &Info = Desc.operands()[I];
150
llvm::MCFixupKind FixupKind;
151
size_t PaddedSize = 5;
152
switch (Info.OperandType) {
153
case WebAssembly::OPERAND_I32IMM:
154
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32);
155
break;
156
case WebAssembly::OPERAND_I64IMM:
157
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64);
158
PaddedSize = 10;
159
break;
160
case WebAssembly::OPERAND_FUNCTION32:
161
case WebAssembly::OPERAND_TABLE:
162
case WebAssembly::OPERAND_OFFSET32:
163
case WebAssembly::OPERAND_SIGNATURE:
164
case WebAssembly::OPERAND_TYPEINDEX:
165
case WebAssembly::OPERAND_GLOBAL:
166
case WebAssembly::OPERAND_TAG:
167
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
168
break;
169
case WebAssembly::OPERAND_OFFSET64:
170
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
171
PaddedSize = 10;
172
break;
173
default:
174
llvm_unreachable("unexpected symbolic operand kind");
175
}
176
Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
177
FixupKind, MI.getLoc()));
178
++MCNumFixups;
179
encodeULEB128(0, OS, PaddedSize);
180
} else {
181
llvm_unreachable("unexpected operand kind");
182
}
183
}
184
185
++MCNumEmitted; // Keep track of the # of mi's emitted.
186
}
187
188
#include "WebAssemblyGenMCCodeEmitter.inc"
189
190