32#define DEBUG_TYPE "mccodeemitter"
34STATISTIC(MCNumEmitted,
"Number of MC instructions emitted.");
35STATISTIC(MCNumFixups,
"Number of MC fixups created.");
50 void encodeP2AlignAndMemOrder(
const MCInst &
MI,
unsigned P2AlignIdx,
60 : MCII(MCII), Ctx{Ctx} {}
66 return new WebAssemblyMCCodeEmitter(MCII, Ctx);
70 unsigned Opcode)
const {
73 if (Name.contains(
"RMW") || Name.contains(
"CMPXCHG"))
79void WebAssemblyMCCodeEmitter::encodeP2AlignAndMemOrder(
80 const MCInst &
MI,
unsigned P2AlignIdx,
const MCInstrDesc &
Desc,
81 const MCSubtargetInfo &STI, raw_ostream &OS,
82 SmallVectorImpl<MCFixup> &Fixups, uint64_t Start)
const {
83 uint64_t P2Align =
MI.getOperand(P2AlignIdx).getImm();
89 if (P2AlignIdx > 0 &&
Desc.operands()[P2AlignIdx - 1].OperandType ==
90 WebAssembly::OPERAND_MEMORDER) {
91 Order =
MI.getOperand(P2AlignIdx - 1).getImm();
94 "Non-default atomic ordering but feature not enabled");
105 getEncodedMemOrder(Order,
MI.getOpcode()),
110void WebAssemblyMCCodeEmitter::encodeInstruction(
111 const MCInst &
MI, SmallVectorImpl<char> &CB,
112 SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI)
const {
113 raw_svector_ostream OS(CB);
116 uint64_t
Binary = getBinaryCodeForInstr(
MI, Fixups, STI);
117 if (Binary < (1 << 8)) {
118 OS << uint8_t(Binary);
119 }
else if (Binary < (1 << 16)) {
120 OS << uint8_t(Binary >> 8);
122 }
else if (Binary < (1 << 24)) {
123 OS << uint8_t(Binary >> 16);
132 unsigned Opcode =
MI.getOpcode();
133 if (Opcode == WebAssembly::BR_TABLE_I32_S ||
134 Opcode == WebAssembly::BR_TABLE_I64_S)
136 if (Opcode == WebAssembly::BR_TABLE_I32 ||
137 Opcode == WebAssembly::BR_TABLE_I64)
140 const MCInstrDesc &
Desc = MCII.
get(Opcode);
141 for (
unsigned I = 0,
E =
MI.getNumOperands();
I <
E; ++
I) {
142 const MCOperand &MO =
MI.getOperand(
I);
146 }
else if (MO.
isImm()) {
147 if (
I <
Desc.getNumOperands()) {
148 const MCOperandInfo &
Info =
Desc.operands()[
I];
150 <<
int(
Info.OperandType) <<
"\n");
151 switch (
Info.OperandType) {
152 case WebAssembly::OPERAND_I32IMM:
155 case WebAssembly::OPERAND_P2ALIGN:
156 encodeP2AlignAndMemOrder(
MI,
I,
Desc, STI, OS, Fixups, Start);
158 case WebAssembly::OPERAND_OFFSET32:
161 case WebAssembly::OPERAND_I64IMM:
164 case WebAssembly::OPERAND_SIGNATURE:
165 case WebAssembly::OPERAND_VEC_I8IMM:
169 case WebAssembly::OPERAND_VALTYPE_LIST: {
174 if (
Count > uint64_t(
E -
I - 1))
176 "select t* operand count exceeds MCInst operand count");
178 for (uint64_t K = 0;
K <
Count; ++
K) {
180 int64_t Val =
MI.getOperand(
I).getImm();
186 case WebAssembly::OPERAND_MEMORDER: {
189 if (
I + 1 <
Desc.getNumOperands() &&
190 Desc.operands()[
I + 1].OperandType ==
191 WebAssembly::OPERAND_P2ALIGN)
193 uint8_t Val = getEncodedMemOrder(MO.
getImm(), Opcode);
197 assert(Opcode == WebAssembly::ATOMIC_FENCE_S);
202 case WebAssembly::OPERAND_VEC_I16IMM:
206 case WebAssembly::OPERAND_VEC_I32IMM:
210 case WebAssembly::OPERAND_VEC_I64IMM:
214 case WebAssembly::OPERAND_GLOBAL:
217 Twine(
"Wasm globals should only be accessed symbolically!"));
226 assert(WebAssembly::isBrTable(Opcode) ||
227 Opcode == WebAssembly::TRY_TABLE_S);
239 size_t PaddedSize = 5;
240 if (
I <
Desc.getNumOperands()) {
241 const MCOperandInfo &
Info =
Desc.operands()[
I];
242 switch (
Info.OperandType) {
243 case WebAssembly::OPERAND_I32IMM:
244 FixupKind = WebAssembly::fixup_sleb128_i32;
246 case WebAssembly::OPERAND_I64IMM:
247 FixupKind = WebAssembly::fixup_sleb128_i64;
250 case WebAssembly::OPERAND_FUNCTION32:
251 case WebAssembly::OPERAND_TABLE:
252 case WebAssembly::OPERAND_OFFSET32:
253 case WebAssembly::OPERAND_SIGNATURE:
254 case WebAssembly::OPERAND_TYPEINDEX:
255 case WebAssembly::OPERAND_GLOBAL:
256 case WebAssembly::OPERAND_TAG:
257 FixupKind = WebAssembly::fixup_uleb128_i32;
259 case WebAssembly::OPERAND_OFFSET64:
260 FixupKind = WebAssembly::fixup_uleb128_i64;
268 assert(Opcode == WebAssembly::TRY_TABLE_S);
269 FixupKind = WebAssembly::fixup_uleb128_i32;
283#include "WebAssemblyGenMCCodeEmitter.inc"
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This file provides WebAssembly-specific target descriptions.
MCCodeEmitter - Generic instruction encoding interface.
Context object for machine code objects.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
const MCExpr * getExpr() const
uint32_t getSFPImm() const
uint64_t getDFPImm() const
Generic base class for all target subtargets.
const FeatureBitset & getFeatureBits() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
@ WASM_MEM_ORDER_RMW_ACQ_REL
const unsigned WASM_MEMARG_HAS_MEM_ORDER
This is an optimization pass for GlobalISel generic memory operations.
MCCodeEmitter * createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static Lanai::Fixups FixupKind(const MCExpr *Expr)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.