LLVM  14.0.0git
WebAssemblyMCCodeEmitter.cpp
Go to the documentation of this file.
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 
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/Statistic.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCFixup.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCRegisterInfo.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/LEB128.h"
29 
30 using namespace llvm;
31 
32 #define DEBUG_TYPE "mccodeemitter"
33 
34 STATISTIC(MCNumEmitted, "Number of MC instructions emitted.");
35 STATISTIC(MCNumFixups, "Number of MC fixups created.");
36 
37 namespace {
38 class WebAssemblyMCCodeEmitter final : public MCCodeEmitter {
39  const MCInstrInfo &MCII;
40 
41  // Implementation generated by tablegen.
42  uint64_t getBinaryCodeForInstr(const MCInst &MI,
44  const MCSubtargetInfo &STI) const;
45 
46  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
48  const MCSubtargetInfo &STI) const override;
49 
50 public:
51  WebAssemblyMCCodeEmitter(const MCInstrInfo &MCII) : MCII(MCII) {}
52 };
53 } // end anonymous namespace
54 
56  return new WebAssemblyMCCodeEmitter(MCII);
57 }
58 
59 void WebAssemblyMCCodeEmitter::encodeInstruction(
61  const MCSubtargetInfo &STI) const {
62  uint64_t Start = OS.tell();
63 
64  uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
65  if (Binary < (1 << 8)) {
66  OS << uint8_t(Binary);
67  } else if (Binary < (1 << 16)) {
68  OS << uint8_t(Binary >> 8);
69  encodeULEB128(uint8_t(Binary), OS);
70  } else if (Binary < (1 << 24)) {
71  OS << uint8_t(Binary >> 16);
72  encodeULEB128(uint16_t(Binary), OS);
73  } else {
74  llvm_unreachable("Very large (prefix + 3 byte) opcodes not supported");
75  }
76 
77  // For br_table instructions, encode the size of the table. In the MCInst,
78  // there's an index operand (if not a stack instruction), one operand for
79  // each table entry, and the default operand.
80  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
81  MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
82  encodeULEB128(MI.getNumOperands() - 1, OS);
83  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
84  MI.getOpcode() == WebAssembly::BR_TABLE_I64)
85  encodeULEB128(MI.getNumOperands() - 2, OS);
86 
87  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
88  for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
89  const MCOperand &MO = MI.getOperand(I);
90  if (MO.isReg()) {
91  /* nothing to encode */
92 
93  } else if (MO.isImm()) {
94  if (I < Desc.getNumOperands()) {
95  const MCOperandInfo &Info = Desc.OpInfo[I];
96  LLVM_DEBUG(dbgs() << "Encoding immediate: type="
97  << int(Info.OperandType) << "\n");
98  switch (Info.OperandType) {
100  encodeSLEB128(int32_t(MO.getImm()), OS);
101  break;
103  encodeULEB128(uint32_t(MO.getImm()), OS);
104  break;
106  encodeSLEB128(int64_t(MO.getImm()), OS);
107  break;
110  OS << uint8_t(MO.getImm());
111  break;
113  support::endian::write<uint8_t>(OS, MO.getImm(), support::little);
114  break;
116  support::endian::write<uint16_t>(OS, MO.getImm(), support::little);
117  break;
119  support::endian::write<uint32_t>(OS, MO.getImm(), support::little);
120  break;
122  support::endian::write<uint64_t>(OS, MO.getImm(), support::little);
123  break;
125  llvm_unreachable("wasm globals should only be accessed symbolicly");
126  default:
127  encodeULEB128(uint64_t(MO.getImm()), OS);
128  }
129  } else {
130  encodeULEB128(uint64_t(MO.getImm()), OS);
131  }
132 
133  } else if (MO.isSFPImm()) {
134  uint32_t F = MO.getSFPImm();
135  support::endian::write<uint32_t>(OS, F, support::little);
136  } else if (MO.isDFPImm()) {
137  uint64_t D = MO.getDFPImm();
138  support::endian::write<uint64_t>(OS, D, support::little);
139  } else if (MO.isExpr()) {
140  const MCOperandInfo &Info = Desc.OpInfo[I];
142  size_t PaddedSize = 5;
143  switch (Info.OperandType) {
146  break;
149  PaddedSize = 10;
150  break;
159  break;
162  PaddedSize = 10;
163  break;
164  default:
165  llvm_unreachable("unexpected symbolic operand kind");
166  }
167  Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
168  FixupKind, MI.getLoc()));
169  ++MCNumFixups;
170  encodeULEB128(0, OS, PaddedSize);
171  } else {
172  llvm_unreachable("unexpected operand kind");
173  }
174  }
175 
176  ++MCNumEmitted; // Keep track of the # of mi's emitted.
177 }
178 
179 #include "WebAssemblyGenMCCodeEmitter.inc"
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:135
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:102
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::WebAssembly::OPERAND_HEAPTYPE
@ OPERAND_HEAPTYPE
heap type immediate for ref.null.
Definition: WebAssemblyMCTargetDesc.h:82
llvm::FixupKind
static Lanai::Fixups FixupKind(const MCExpr *Expr)
Definition: LanaiMCCodeEmitter.cpp:90
llvm::MCOperand::isReg
bool isReg() const
Definition: MCInst.h:61
llvm::WebAssembly::OPERAND_TABLE
@ OPERAND_TABLE
32-bit unsigned table number.
Definition: WebAssemblyMCTargetDesc.h:80
llvm::WebAssembly::fixup_uleb128_i64
@ fixup_uleb128_i64
Definition: WebAssemblyFixupKinds.h:20
MCCodeEmitter.h
Statistic.h
llvm::MCFixup::create
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
llvm::WebAssembly::OPERAND_VEC_I32IMM
@ OPERAND_VEC_I32IMM
32-bit vector lane immediate
Definition: WebAssemblyMCTargetDesc.h:60
llvm::WebAssembly::OPERAND_OFFSET32
@ OPERAND_OFFSET32
32-bit unsigned memory offsets.
Definition: WebAssemblyMCTargetDesc.h:66
llvm::WebAssembly::OPERAND_GLOBAL
@ OPERAND_GLOBAL
Global index.
Definition: WebAssemblyMCTargetDesc.h:46
llvm::WebAssembly::fixup_uleb128_i32
@ fixup_uleb128_i32
Definition: WebAssemblyFixupKinds.h:19
llvm::MCOperand::getSFPImm
uint32_t getSFPImm() const
Definition: MCInst.h:90
llvm::WebAssembly::OPERAND_SIGNATURE
@ OPERAND_SIGNATURE
signature immediate for block/loop.
Definition: WebAssemblyMCTargetDesc.h:72
llvm::WebAssembly::OPERAND_TAG
@ OPERAND_TAG
Tag index.
Definition: WebAssemblyMCTargetDesc.h:76
STLExtras.h
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
llvm::MCOperand::isSFPImm
bool isSFPImm() const
Definition: MCInst.h:63
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:122
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::MCOperandInfo
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:83
llvm::WebAssembly::fixup_sleb128_i64
@ fixup_sleb128_i64
Definition: WebAssemblyFixupKinds.h:18
llvm::WebAssembly::OPERAND_VEC_I64IMM
@ OPERAND_VEC_I64IMM
64-bit vector lane immediate
Definition: WebAssemblyMCTargetDesc.h:62
llvm::encodeSLEB128
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
Definition: LEB128.h:23
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::support::little
@ little
Definition: Endian.h:27
llvm::createWebAssemblyMCCodeEmitter
MCCodeEmitter * createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII)
Definition: WebAssemblyMCCodeEmitter.cpp:55
MCInstrInfo.h
llvm::MCOperand::getImm
int64_t getImm() const
Definition: MCInst.h:80
MCSymbol.h
MCInst.h
llvm::MCInstrDesc
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:195
llvm::AArch64::Fixups
Fixups
Definition: AArch64FixupKinds.h:17
MCSubtargetInfo.h
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
WebAssemblyMCTargetDesc.h
llvm::MCOperand::isImm
bool isImm() const
Definition: MCInst.h:62
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
LEB128.h
I
#define I(x, y, z)
Definition: MD5.cpp:59
MCRegisterInfo.h
llvm::MCInstrDesc::OpInfo
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:206
llvm::WebAssembly::OPERAND_FUNCTION32
@ OPERAND_FUNCTION32
32-bit unsigned function indices.
Definition: WebAssemblyMCTargetDesc.h:64
llvm::WebAssembly::fixup_sleb128_i32
@ fixup_sleb128_i32
Definition: WebAssemblyFixupKinds.h:17
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
uint32_t
MCFixup.h
llvm::WebAssembly::OPERAND_TYPEINDEX
@ OPERAND_TYPEINDEX
type signature immediate for call_indirect.
Definition: WebAssemblyMCTargetDesc.h:74
llvm::MCInstrInfo
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:25
EndianStream.h
uint16_t
llvm::WebAssembly::OPERAND_VEC_I16IMM
@ OPERAND_VEC_I16IMM
16-bit vector lane immediate
Definition: WebAssemblyMCTargetDesc.h:58
llvm::MCCodeEmitter
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
llvm::MCOperand::getExpr
const MCExpr * getExpr() const
Definition: MCInst.h:114
llvm::MCOperand::isExpr
bool isExpr() const
Definition: MCInst.h:65
llvm::MCFixupKind
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
llvm::WebAssembly::OPERAND_OFFSET64
@ OPERAND_OFFSET64
64-bit unsigned memory offsets.
Definition: WebAssemblyMCTargetDesc.h:68
llvm::MCOperand::getDFPImm
uint64_t getDFPImm() const
Definition: MCInst.h:100
llvm::WebAssembly::OPERAND_I64IMM
@ OPERAND_I64IMM
64-bit integer immediates.
Definition: WebAssemblyMCTargetDesc.h:50
llvm::encodeULEB128
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
llvm::MCOperand
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
llvm::WebAssembly::OPERAND_VEC_I8IMM
@ OPERAND_VEC_I8IMM
8-bit vector lane immediate
Definition: WebAssemblyMCTargetDesc.h:56
raw_ostream.h
llvm::MCSubtargetInfo
Generic base class for all target subtargets.
Definition: MCSubtargetInfo.h:75
llvm::MCInstrDesc::getNumOperands
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:228
llvm::WebAssembly::OPERAND_I32IMM
@ OPERAND_I32IMM
32-bit integer immediates.
Definition: WebAssemblyMCTargetDesc.h:48
llvm::MCOperand::isDFPImm
bool isDFPImm() const
Definition: MCInst.h:64
Debug.h
WebAssemblyFixupKinds.h