LLVM  10.0.0svn
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 <= UINT8_MAX) {
66  OS << uint8_t(Binary);
67  } else {
68  assert(Binary <= UINT16_MAX && "Several-byte opcodes not supported yet");
69  OS << uint8_t(Binary >> 8);
70  encodeULEB128(uint8_t(Binary), OS);
71  }
72 
73  // For br_table instructions, encode the size of the table. In the MCInst,
74  // there's an index operand (if not a stack instruction), one operand for
75  // each table entry, and the default operand.
76  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
77  MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
78  encodeULEB128(MI.getNumOperands() - 1, OS);
79  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
80  MI.getOpcode() == WebAssembly::BR_TABLE_I64)
81  encodeULEB128(MI.getNumOperands() - 2, OS);
82 
83  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
84  for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
85  const MCOperand &MO = MI.getOperand(I);
86  if (MO.isReg()) {
87  /* nothing to encode */
88 
89  } else if (MO.isImm()) {
90  if (I < Desc.getNumOperands()) {
91  const MCOperandInfo &Info = Desc.OpInfo[I];
92  LLVM_DEBUG(dbgs() << "Encoding immediate: type="
93  << int(Info.OperandType) << "\n");
94  switch (Info.OperandType) {
96  encodeSLEB128(int32_t(MO.getImm()), OS);
97  break;
99  encodeULEB128(uint32_t(MO.getImm()), OS);
100  break;
102  encodeSLEB128(int64_t(MO.getImm()), OS);
103  break;
105  OS << uint8_t(MO.getImm());
106  break;
108  support::endian::write<uint8_t>(OS, MO.getImm(), support::little);
109  break;
111  support::endian::write<uint16_t>(OS, MO.getImm(), support::little);
112  break;
114  support::endian::write<uint32_t>(OS, MO.getImm(), support::little);
115  break;
117  support::endian::write<uint64_t>(OS, MO.getImm(), support::little);
118  break;
120  llvm_unreachable("wasm globals should only be accessed symbolicly");
121  default:
122  encodeULEB128(uint64_t(MO.getImm()), OS);
123  }
124  } else {
125  encodeULEB128(uint64_t(MO.getImm()), OS);
126  }
127 
128  } else if (MO.isFPImm()) {
129  const MCOperandInfo &Info = Desc.OpInfo[I];
131  // TODO: MC converts all floating point immediate operands to double.
132  // This is fine for numeric values, but may cause NaNs to change bits.
133  auto F = float(MO.getFPImm());
135  } else {
137  double D = MO.getFPImm();
139  }
140 
141  } else if (MO.isExpr()) {
142  const MCOperandInfo &Info = Desc.OpInfo[I];
144  size_t PaddedSize = 5;
145  switch (Info.OperandType) {
148  break;
151  PaddedSize = 10;
152  break;
159  break;
160  default:
161  llvm_unreachable("unexpected symbolic operand kind");
162  }
163  Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
164  FixupKind, MI.getLoc()));
165  ++MCNumFixups;
166  encodeULEB128(0, OS, PaddedSize);
167  } else {
168  llvm_unreachable("unexpected operand kind");
169  }
170  }
171 
172  ++MCNumEmitted; // Keep track of the # of mi's emitted.
173 }
174 
175 #include "WebAssemblyGenMCCodeEmitter.inc"
32-bit floating-point immediates.
bool isImm() const
Definition: MCInst.h:58
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
32-bit unsigned memory offsets.
bool isReg() const
Definition: MCInst.h:57
STATISTIC(NumFunctions, "Total number of functions")
F(f)
static Lanai::Fixups FixupKind(const MCExpr *Expr)
signature immediate for block/loop.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:211
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:78
const MCExpr * getExpr() const
Definition: MCInst.h:95
Analysis containing CSE Info
Definition: CSEInfo.cpp:20
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
int64_t getImm() const
Definition: MCInst.h:75
MCCodeEmitter * createWebAssemblyMCCodeEmitter(const MCInstrInfo &MCII)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool isFPImm() const
Definition: MCInst.h:59
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
This file provides WebAssembly-specific target descriptions.
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:23
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:22
bool isExpr() const
Definition: MCInst.h:60
void write< float >(raw_ostream &os, float value, endianness endian)
Definition: EndianStream.h:33
unsigned getNumOperands() const
Definition: MCInst.h:181
type signature immediate for call_indirect.
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:93
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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
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
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:179
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
SMLoc getLoc() const
Definition: MCInst.h:177
64-bit floating-point immediates.
32-bit unsigned function indices.
#define I(x, y, z)
Definition: MD5.cpp:58
Generic base class for all target subtargets.
void write< double >(raw_ostream &os, double value, endianness endian)
Definition: EndianStream.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:175
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:99
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
IRTranslator LLVM IR MI
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:66
unsigned getOpcode() const
Definition: MCInst.h:171
#define LLVM_DEBUG(X)
Definition: Debug.h:122
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
double getFPImm() const
Definition: MCInst.h:85