1*9880d681SAndroid Build Coastguard Worker //===-- WebAssemblyAsmPrinter.cpp - WebAssembly LLVM assembly writer ------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker ///
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief This file contains a printer that converts from our internal
12*9880d681SAndroid Build Coastguard Worker /// representation of machine-dependent LLVM code to the WebAssembly assembly
13*9880d681SAndroid Build Coastguard Worker /// language.
14*9880d681SAndroid Build Coastguard Worker ///
15*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
16*9880d681SAndroid Build Coastguard Worker
17*9880d681SAndroid Build Coastguard Worker #include "WebAssembly.h"
18*9880d681SAndroid Build Coastguard Worker #include "InstPrinter/WebAssemblyInstPrinter.h"
19*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
20*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
21*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMCInstLower.h"
22*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMachineFunctionInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyRegisterInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "WebAssemblySubtarget.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Analysis.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineConstantPool.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
37*9880d681SAndroid Build Coastguard Worker using namespace llvm;
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "asm-printer"
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker namespace {
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker class WebAssemblyAsmPrinter final : public AsmPrinter {
44*9880d681SAndroid Build Coastguard Worker const MachineRegisterInfo *MRI;
45*9880d681SAndroid Build Coastguard Worker const WebAssemblyFunctionInfo *MFI;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker public:
WebAssemblyAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)48*9880d681SAndroid Build Coastguard Worker WebAssemblyAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
49*9880d681SAndroid Build Coastguard Worker : AsmPrinter(TM, std::move(Streamer)), MRI(nullptr), MFI(nullptr) {}
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker private:
getPassName() const52*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
53*9880d681SAndroid Build Coastguard Worker return "WebAssembly Assembly Printer";
54*9880d681SAndroid Build Coastguard Worker }
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker //===------------------------------------------------------------------===//
57*9880d681SAndroid Build Coastguard Worker // MachineFunctionPass Implementation.
58*9880d681SAndroid Build Coastguard Worker //===------------------------------------------------------------------===//
59*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)60*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override {
61*9880d681SAndroid Build Coastguard Worker MRI = &MF.getRegInfo();
62*9880d681SAndroid Build Coastguard Worker MFI = MF.getInfo<WebAssemblyFunctionInfo>();
63*9880d681SAndroid Build Coastguard Worker return AsmPrinter::runOnMachineFunction(MF);
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker //===------------------------------------------------------------------===//
67*9880d681SAndroid Build Coastguard Worker // AsmPrinter Implementation.
68*9880d681SAndroid Build Coastguard Worker //===------------------------------------------------------------------===//
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker void EmitEndOfAsmFile(Module &M) override;
71*9880d681SAndroid Build Coastguard Worker void EmitJumpTableInfo() override;
72*9880d681SAndroid Build Coastguard Worker void EmitConstantPool() override;
73*9880d681SAndroid Build Coastguard Worker void EmitFunctionBodyStart() override;
74*9880d681SAndroid Build Coastguard Worker void EmitFunctionBodyEnd() override;
75*9880d681SAndroid Build Coastguard Worker void EmitInstruction(const MachineInstr *MI) override;
76*9880d681SAndroid Build Coastguard Worker const MCExpr *lowerConstant(const Constant *CV) override;
77*9880d681SAndroid Build Coastguard Worker bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
78*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant, const char *ExtraCode,
79*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) override;
80*9880d681SAndroid Build Coastguard Worker bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
81*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant, const char *ExtraCode,
82*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) override;
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker MVT getRegType(unsigned RegNo) const;
85*9880d681SAndroid Build Coastguard Worker const char *toString(MVT VT) const;
86*9880d681SAndroid Build Coastguard Worker std::string regToString(const MachineOperand &MO);
87*9880d681SAndroid Build Coastguard Worker WebAssemblyTargetStreamer *getTargetStreamer();
88*9880d681SAndroid Build Coastguard Worker };
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
93*9880d681SAndroid Build Coastguard Worker // Helpers.
94*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
95*9880d681SAndroid Build Coastguard Worker
getRegType(unsigned RegNo) const96*9880d681SAndroid Build Coastguard Worker MVT WebAssemblyAsmPrinter::getRegType(unsigned RegNo) const {
97*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *TRC = MRI->getRegClass(RegNo);
98*9880d681SAndroid Build Coastguard Worker for (MVT T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
99*9880d681SAndroid Build Coastguard Worker if (TRC->hasType(T))
100*9880d681SAndroid Build Coastguard Worker return T;
101*9880d681SAndroid Build Coastguard Worker DEBUG(errs() << "Unknown type for register number: " << RegNo);
102*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown register type");
103*9880d681SAndroid Build Coastguard Worker return MVT::Other;
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker
toString(MVT VT) const106*9880d681SAndroid Build Coastguard Worker const char *WebAssemblyAsmPrinter::toString(MVT VT) const {
107*9880d681SAndroid Build Coastguard Worker return WebAssembly::TypeToString(VT);
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
regToString(const MachineOperand & MO)110*9880d681SAndroid Build Coastguard Worker std::string WebAssemblyAsmPrinter::regToString(const MachineOperand &MO) {
111*9880d681SAndroid Build Coastguard Worker unsigned RegNo = MO.getReg();
112*9880d681SAndroid Build Coastguard Worker assert(TargetRegisterInfo::isVirtualRegister(RegNo) &&
113*9880d681SAndroid Build Coastguard Worker "Unlowered physical register encountered during assembly printing");
114*9880d681SAndroid Build Coastguard Worker assert(!MFI->isVRegStackified(RegNo));
115*9880d681SAndroid Build Coastguard Worker unsigned WAReg = MFI->getWAReg(RegNo);
116*9880d681SAndroid Build Coastguard Worker assert(WAReg != WebAssemblyFunctionInfo::UnusedReg);
117*9880d681SAndroid Build Coastguard Worker return '$' + utostr(WAReg);
118*9880d681SAndroid Build Coastguard Worker }
119*9880d681SAndroid Build Coastguard Worker
getTargetStreamer()120*9880d681SAndroid Build Coastguard Worker WebAssemblyTargetStreamer *WebAssemblyAsmPrinter::getTargetStreamer() {
121*9880d681SAndroid Build Coastguard Worker MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
122*9880d681SAndroid Build Coastguard Worker return static_cast<WebAssemblyTargetStreamer *>(TS);
123*9880d681SAndroid Build Coastguard Worker }
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
126*9880d681SAndroid Build Coastguard Worker // WebAssemblyAsmPrinter Implementation.
127*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
ComputeLegalValueVTs(const Function & F,const TargetMachine & TM,Type * Ty,SmallVectorImpl<MVT> & ValueVTs)128*9880d681SAndroid Build Coastguard Worker static void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM,
129*9880d681SAndroid Build Coastguard Worker Type *Ty, SmallVectorImpl<MVT> &ValueVTs) {
130*9880d681SAndroid Build Coastguard Worker const DataLayout &DL(F.getParent()->getDataLayout());
131*9880d681SAndroid Build Coastguard Worker const WebAssemblyTargetLowering &TLI =
132*9880d681SAndroid Build Coastguard Worker *TM.getSubtarget<WebAssemblySubtarget>(F).getTargetLowering();
133*9880d681SAndroid Build Coastguard Worker SmallVector<EVT, 4> VTs;
134*9880d681SAndroid Build Coastguard Worker ComputeValueVTs(TLI, DL, Ty, VTs);
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker for (EVT VT : VTs) {
137*9880d681SAndroid Build Coastguard Worker unsigned NumRegs = TLI.getNumRegisters(F.getContext(), VT);
138*9880d681SAndroid Build Coastguard Worker MVT RegisterVT = TLI.getRegisterType(F.getContext(), VT);
139*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i != NumRegs; ++i)
140*9880d681SAndroid Build Coastguard Worker ValueVTs.push_back(RegisterVT);
141*9880d681SAndroid Build Coastguard Worker }
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker
EmitEndOfAsmFile(Module & M)144*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
145*9880d681SAndroid Build Coastguard Worker for (const auto &F : M) {
146*9880d681SAndroid Build Coastguard Worker // Emit function type info for all undefined functions
147*9880d681SAndroid Build Coastguard Worker if (F.isDeclarationForLinker() && !F.isIntrinsic()) {
148*9880d681SAndroid Build Coastguard Worker SmallVector<MVT, 4> SignatureVTs;
149*9880d681SAndroid Build Coastguard Worker ComputeLegalValueVTs(F, TM, F.getReturnType(), SignatureVTs);
150*9880d681SAndroid Build Coastguard Worker size_t NumResults = SignatureVTs.size();
151*9880d681SAndroid Build Coastguard Worker if (SignatureVTs.size() > 1) {
152*9880d681SAndroid Build Coastguard Worker // WebAssembly currently can't lower returns of multiple values without
153*9880d681SAndroid Build Coastguard Worker // demoting to sret (see WebAssemblyTargetLowering::CanLowerReturn). So
154*9880d681SAndroid Build Coastguard Worker // replace multiple return values with a pointer parameter.
155*9880d681SAndroid Build Coastguard Worker SignatureVTs.clear();
156*9880d681SAndroid Build Coastguard Worker SignatureVTs.push_back(
157*9880d681SAndroid Build Coastguard Worker MVT::getIntegerVT(M.getDataLayout().getPointerSizeInBits()));
158*9880d681SAndroid Build Coastguard Worker NumResults = 0;
159*9880d681SAndroid Build Coastguard Worker }
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker for (auto &Arg : F.args()) {
162*9880d681SAndroid Build Coastguard Worker ComputeLegalValueVTs(F, TM, Arg.getType(), SignatureVTs);
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker getTargetStreamer()->emitIndirectFunctionType(F.getName(), SignatureVTs,
166*9880d681SAndroid Build Coastguard Worker NumResults);
167*9880d681SAndroid Build Coastguard Worker }
168*9880d681SAndroid Build Coastguard Worker }
169*9880d681SAndroid Build Coastguard Worker }
170*9880d681SAndroid Build Coastguard Worker
EmitConstantPool()171*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitConstantPool() {
172*9880d681SAndroid Build Coastguard Worker assert(MF->getConstantPool()->getConstants().empty() &&
173*9880d681SAndroid Build Coastguard Worker "WebAssembly disables constant pools");
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker
EmitJumpTableInfo()176*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitJumpTableInfo() {
177*9880d681SAndroid Build Coastguard Worker // Nothing to do; jump tables are incorporated into the instruction stream.
178*9880d681SAndroid Build Coastguard Worker }
179*9880d681SAndroid Build Coastguard Worker
EmitFunctionBodyStart()180*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitFunctionBodyStart() {
181*9880d681SAndroid Build Coastguard Worker if (!MFI->getParams().empty())
182*9880d681SAndroid Build Coastguard Worker getTargetStreamer()->emitParam(MFI->getParams());
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker SmallVector<MVT, 4> ResultVTs;
185*9880d681SAndroid Build Coastguard Worker const Function &F(*MF->getFunction());
186*9880d681SAndroid Build Coastguard Worker ComputeLegalValueVTs(F, TM, F.getReturnType(), ResultVTs);
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker // If the return type needs to be legalized it will get converted into
189*9880d681SAndroid Build Coastguard Worker // passing a pointer.
190*9880d681SAndroid Build Coastguard Worker if (ResultVTs.size() == 1)
191*9880d681SAndroid Build Coastguard Worker getTargetStreamer()->emitResult(ResultVTs);
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker bool AnyWARegs = false;
194*9880d681SAndroid Build Coastguard Worker SmallVector<MVT, 16> LocalTypes;
195*9880d681SAndroid Build Coastguard Worker for (unsigned Idx = 0, IdxE = MRI->getNumVirtRegs(); Idx != IdxE; ++Idx) {
196*9880d681SAndroid Build Coastguard Worker unsigned VReg = TargetRegisterInfo::index2VirtReg(Idx);
197*9880d681SAndroid Build Coastguard Worker unsigned WAReg = MFI->getWAReg(VReg);
198*9880d681SAndroid Build Coastguard Worker // Don't declare unused registers.
199*9880d681SAndroid Build Coastguard Worker if (WAReg == WebAssemblyFunctionInfo::UnusedReg)
200*9880d681SAndroid Build Coastguard Worker continue;
201*9880d681SAndroid Build Coastguard Worker // Don't redeclare parameters.
202*9880d681SAndroid Build Coastguard Worker if (WAReg < MFI->getParams().size())
203*9880d681SAndroid Build Coastguard Worker continue;
204*9880d681SAndroid Build Coastguard Worker // Don't declare stackified registers.
205*9880d681SAndroid Build Coastguard Worker if (int(WAReg) < 0)
206*9880d681SAndroid Build Coastguard Worker continue;
207*9880d681SAndroid Build Coastguard Worker LocalTypes.push_back(getRegType(VReg));
208*9880d681SAndroid Build Coastguard Worker AnyWARegs = true;
209*9880d681SAndroid Build Coastguard Worker }
210*9880d681SAndroid Build Coastguard Worker if (AnyWARegs)
211*9880d681SAndroid Build Coastguard Worker getTargetStreamer()->emitLocal(LocalTypes);
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Worker AsmPrinter::EmitFunctionBodyStart();
214*9880d681SAndroid Build Coastguard Worker }
215*9880d681SAndroid Build Coastguard Worker
EmitFunctionBodyEnd()216*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitFunctionBodyEnd() {
217*9880d681SAndroid Build Coastguard Worker getTargetStreamer()->emitEndFunc();
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
EmitInstruction(const MachineInstr * MI)220*9880d681SAndroid Build Coastguard Worker void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
221*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "EmitInstruction: " << *MI << '\n');
222*9880d681SAndroid Build Coastguard Worker
223*9880d681SAndroid Build Coastguard Worker switch (MI->getOpcode()) {
224*9880d681SAndroid Build Coastguard Worker case WebAssembly::ARGUMENT_I32:
225*9880d681SAndroid Build Coastguard Worker case WebAssembly::ARGUMENT_I64:
226*9880d681SAndroid Build Coastguard Worker case WebAssembly::ARGUMENT_F32:
227*9880d681SAndroid Build Coastguard Worker case WebAssembly::ARGUMENT_F64:
228*9880d681SAndroid Build Coastguard Worker // These represent values which are live into the function entry, so there's
229*9880d681SAndroid Build Coastguard Worker // no instruction to emit.
230*9880d681SAndroid Build Coastguard Worker break;
231*9880d681SAndroid Build Coastguard Worker case WebAssembly::FALLTHROUGH_RETURN_I32:
232*9880d681SAndroid Build Coastguard Worker case WebAssembly::FALLTHROUGH_RETURN_I64:
233*9880d681SAndroid Build Coastguard Worker case WebAssembly::FALLTHROUGH_RETURN_F32:
234*9880d681SAndroid Build Coastguard Worker case WebAssembly::FALLTHROUGH_RETURN_F64: {
235*9880d681SAndroid Build Coastguard Worker // These instructions represent the implicit return at the end of a
236*9880d681SAndroid Build Coastguard Worker // function body. The operand is always a pop.
237*9880d681SAndroid Build Coastguard Worker assert(MFI->isVRegStackified(MI->getOperand(0).getReg()));
238*9880d681SAndroid Build Coastguard Worker
239*9880d681SAndroid Build Coastguard Worker if (isVerbose()) {
240*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment("fallthrough-return: $pop" +
241*9880d681SAndroid Build Coastguard Worker utostr(MFI->getWARegStackId(
242*9880d681SAndroid Build Coastguard Worker MFI->getWAReg(MI->getOperand(0).getReg()))));
243*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker break;
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker case WebAssembly::FALLTHROUGH_RETURN_VOID:
248*9880d681SAndroid Build Coastguard Worker // This instruction represents the implicit return at the end of a
249*9880d681SAndroid Build Coastguard Worker // function body with no return value.
250*9880d681SAndroid Build Coastguard Worker if (isVerbose()) {
251*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment("fallthrough-return");
252*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker break;
255*9880d681SAndroid Build Coastguard Worker default: {
256*9880d681SAndroid Build Coastguard Worker WebAssemblyMCInstLower MCInstLowering(OutContext, *this);
257*9880d681SAndroid Build Coastguard Worker MCInst TmpInst;
258*9880d681SAndroid Build Coastguard Worker MCInstLowering.Lower(MI, TmpInst);
259*9880d681SAndroid Build Coastguard Worker EmitToStreamer(*OutStreamer, TmpInst);
260*9880d681SAndroid Build Coastguard Worker break;
261*9880d681SAndroid Build Coastguard Worker }
262*9880d681SAndroid Build Coastguard Worker }
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
lowerConstant(const Constant * CV)265*9880d681SAndroid Build Coastguard Worker const MCExpr *WebAssemblyAsmPrinter::lowerConstant(const Constant *CV) {
266*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
267*9880d681SAndroid Build Coastguard Worker if (GV->getValueType()->isFunctionTy())
268*9880d681SAndroid Build Coastguard Worker return MCSymbolRefExpr::create(
269*9880d681SAndroid Build Coastguard Worker getSymbol(GV), MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext);
270*9880d681SAndroid Build Coastguard Worker return AsmPrinter::lowerConstant(CV);
271*9880d681SAndroid Build Coastguard Worker }
272*9880d681SAndroid Build Coastguard Worker
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & OS)273*9880d681SAndroid Build Coastguard Worker bool WebAssemblyAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
274*9880d681SAndroid Build Coastguard Worker unsigned OpNo, unsigned AsmVariant,
275*9880d681SAndroid Build Coastguard Worker const char *ExtraCode,
276*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) {
277*9880d681SAndroid Build Coastguard Worker if (AsmVariant != 0)
278*9880d681SAndroid Build Coastguard Worker report_fatal_error("There are no defined alternate asm variants");
279*9880d681SAndroid Build Coastguard Worker
280*9880d681SAndroid Build Coastguard Worker // First try the generic code, which knows about modifiers like 'c' and 'n'.
281*9880d681SAndroid Build Coastguard Worker if (!AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, OS))
282*9880d681SAndroid Build Coastguard Worker return false;
283*9880d681SAndroid Build Coastguard Worker
284*9880d681SAndroid Build Coastguard Worker if (!ExtraCode) {
285*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(OpNo);
286*9880d681SAndroid Build Coastguard Worker switch (MO.getType()) {
287*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Immediate:
288*9880d681SAndroid Build Coastguard Worker OS << MO.getImm();
289*9880d681SAndroid Build Coastguard Worker return false;
290*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Register:
291*9880d681SAndroid Build Coastguard Worker OS << regToString(MO);
292*9880d681SAndroid Build Coastguard Worker return false;
293*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_GlobalAddress:
294*9880d681SAndroid Build Coastguard Worker getSymbol(MO.getGlobal())->print(OS, MAI);
295*9880d681SAndroid Build Coastguard Worker printOffset(MO.getOffset(), OS);
296*9880d681SAndroid Build Coastguard Worker return false;
297*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ExternalSymbol:
298*9880d681SAndroid Build Coastguard Worker GetExternalSymbolSymbol(MO.getSymbolName())->print(OS, MAI);
299*9880d681SAndroid Build Coastguard Worker printOffset(MO.getOffset(), OS);
300*9880d681SAndroid Build Coastguard Worker return false;
301*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MachineBasicBlock:
302*9880d681SAndroid Build Coastguard Worker MO.getMBB()->getSymbol()->print(OS, MAI);
303*9880d681SAndroid Build Coastguard Worker return false;
304*9880d681SAndroid Build Coastguard Worker default:
305*9880d681SAndroid Build Coastguard Worker break;
306*9880d681SAndroid Build Coastguard Worker }
307*9880d681SAndroid Build Coastguard Worker }
308*9880d681SAndroid Build Coastguard Worker
309*9880d681SAndroid Build Coastguard Worker return true;
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & OS)312*9880d681SAndroid Build Coastguard Worker bool WebAssemblyAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
313*9880d681SAndroid Build Coastguard Worker unsigned OpNo,
314*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant,
315*9880d681SAndroid Build Coastguard Worker const char *ExtraCode,
316*9880d681SAndroid Build Coastguard Worker raw_ostream &OS) {
317*9880d681SAndroid Build Coastguard Worker if (AsmVariant != 0)
318*9880d681SAndroid Build Coastguard Worker report_fatal_error("There are no defined alternate asm variants");
319*9880d681SAndroid Build Coastguard Worker
320*9880d681SAndroid Build Coastguard Worker if (!ExtraCode) {
321*9880d681SAndroid Build Coastguard Worker // TODO: For now, we just hard-code 0 as the constant offset; teach
322*9880d681SAndroid Build Coastguard Worker // SelectInlineAsmMemoryOperand how to do address mode matching.
323*9880d681SAndroid Build Coastguard Worker OS << "0(" + regToString(MI->getOperand(OpNo)) + ')';
324*9880d681SAndroid Build Coastguard Worker return false;
325*9880d681SAndroid Build Coastguard Worker }
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Worker return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, AsmVariant, ExtraCode, OS);
328*9880d681SAndroid Build Coastguard Worker }
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker // Force static initialization.
LLVMInitializeWebAssemblyAsmPrinter()331*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeWebAssemblyAsmPrinter() {
332*9880d681SAndroid Build Coastguard Worker RegisterAsmPrinter<WebAssemblyAsmPrinter> X(TheWebAssemblyTarget32);
333*9880d681SAndroid Build Coastguard Worker RegisterAsmPrinter<WebAssemblyAsmPrinter> Y(TheWebAssemblyTarget64);
334*9880d681SAndroid Build Coastguard Worker }
335