xref: /aosp_15_r20/external/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker // WebAssemblyMCInstLower.cpp - Convert WebAssembly MachineInstr to an MCInst //
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 code to lower WebAssembly MachineInstrs to their
12*9880d681SAndroid Build Coastguard Worker /// corresponding MCInst records.
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMCInstLower.h"
17*9880d681SAndroid Build Coastguard Worker #include "WebAssemblyMachineFunctionInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/AsmPrinter.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker using namespace llvm;
28*9880d681SAndroid Build Coastguard Worker 
29*9880d681SAndroid Build Coastguard Worker MCSymbol *
GetGlobalAddressSymbol(const MachineOperand & MO) const30*9880d681SAndroid Build Coastguard Worker WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
31*9880d681SAndroid Build Coastguard Worker   return Printer.getSymbol(MO.getGlobal());
32*9880d681SAndroid Build Coastguard Worker }
33*9880d681SAndroid Build Coastguard Worker 
GetExternalSymbolSymbol(const MachineOperand & MO) const34*9880d681SAndroid Build Coastguard Worker MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
35*9880d681SAndroid Build Coastguard Worker     const MachineOperand &MO) const {
36*9880d681SAndroid Build Coastguard Worker   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
37*9880d681SAndroid Build Coastguard Worker }
38*9880d681SAndroid Build Coastguard Worker 
LowerSymbolOperand(MCSymbol * Sym,int64_t Offset,bool IsFunc) const39*9880d681SAndroid Build Coastguard Worker MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
40*9880d681SAndroid Build Coastguard Worker                                                      int64_t Offset,
41*9880d681SAndroid Build Coastguard Worker                                                      bool IsFunc) const {
42*9880d681SAndroid Build Coastguard Worker   MCSymbolRefExpr::VariantKind VK =
43*9880d681SAndroid Build Coastguard Worker       IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION
44*9880d681SAndroid Build Coastguard Worker              : MCSymbolRefExpr::VK_None;
45*9880d681SAndroid Build Coastguard Worker   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   if (Offset != 0) {
48*9880d681SAndroid Build Coastguard Worker     if (IsFunc)
49*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Function addresses with offsets not supported");
50*9880d681SAndroid Build Coastguard Worker     Expr =
51*9880d681SAndroid Build Coastguard Worker         MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
52*9880d681SAndroid Build Coastguard Worker   }
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker   return MCOperand::createExpr(Expr);
55*9880d681SAndroid Build Coastguard Worker }
56*9880d681SAndroid Build Coastguard Worker 
Lower(const MachineInstr * MI,MCInst & OutMI) const57*9880d681SAndroid Build Coastguard Worker void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
58*9880d681SAndroid Build Coastguard Worker                                    MCInst &OutMI) const {
59*9880d681SAndroid Build Coastguard Worker   OutMI.setOpcode(MI->getOpcode());
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
62*9880d681SAndroid Build Coastguard Worker     const MachineOperand &MO = MI->getOperand(i);
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker     MCOperand MCOp;
65*9880d681SAndroid Build Coastguard Worker     switch (MO.getType()) {
66*9880d681SAndroid Build Coastguard Worker     default:
67*9880d681SAndroid Build Coastguard Worker       MI->dump();
68*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("unknown operand type");
69*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_MachineBasicBlock:
70*9880d681SAndroid Build Coastguard Worker       MI->dump();
71*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("MachineBasicBlock operand should have been rewritten");
72*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_Register: {
73*9880d681SAndroid Build Coastguard Worker       // Ignore all implicit register operands.
74*9880d681SAndroid Build Coastguard Worker       if (MO.isImplicit())
75*9880d681SAndroid Build Coastguard Worker         continue;
76*9880d681SAndroid Build Coastguard Worker       const WebAssemblyFunctionInfo &MFI =
77*9880d681SAndroid Build Coastguard Worker           *MI->getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
78*9880d681SAndroid Build Coastguard Worker       unsigned WAReg = MFI.getWAReg(MO.getReg());
79*9880d681SAndroid Build Coastguard Worker       MCOp = MCOperand::createReg(WAReg);
80*9880d681SAndroid Build Coastguard Worker       break;
81*9880d681SAndroid Build Coastguard Worker     }
82*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_Immediate:
83*9880d681SAndroid Build Coastguard Worker       MCOp = MCOperand::createImm(MO.getImm());
84*9880d681SAndroid Build Coastguard Worker       break;
85*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_FPImmediate: {
86*9880d681SAndroid Build Coastguard Worker       // TODO: MC converts all floating point immediate operands to double.
87*9880d681SAndroid Build Coastguard Worker       // This is fine for numeric values, but may cause NaNs to change bits.
88*9880d681SAndroid Build Coastguard Worker       const ConstantFP *Imm = MO.getFPImm();
89*9880d681SAndroid Build Coastguard Worker       if (Imm->getType()->isFloatTy())
90*9880d681SAndroid Build Coastguard Worker         MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat());
91*9880d681SAndroid Build Coastguard Worker       else if (Imm->getType()->isDoubleTy())
92*9880d681SAndroid Build Coastguard Worker         MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble());
93*9880d681SAndroid Build Coastguard Worker       else
94*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("unknown floating point immediate type");
95*9880d681SAndroid Build Coastguard Worker       break;
96*9880d681SAndroid Build Coastguard Worker     }
97*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_GlobalAddress:
98*9880d681SAndroid Build Coastguard Worker       assert(MO.getTargetFlags() == 0 &&
99*9880d681SAndroid Build Coastguard Worker              "WebAssembly does not use target flags on GlobalAddresses");
100*9880d681SAndroid Build Coastguard Worker       MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
101*9880d681SAndroid Build Coastguard Worker                                 MO.getGlobal()->getValueType()->isFunctionTy());
102*9880d681SAndroid Build Coastguard Worker       break;
103*9880d681SAndroid Build Coastguard Worker     case MachineOperand::MO_ExternalSymbol:
104*9880d681SAndroid Build Coastguard Worker       // The target flag indicates whether this is a symbol for a
105*9880d681SAndroid Build Coastguard Worker       // variable or a function.
106*9880d681SAndroid Build Coastguard Worker       assert((MO.getTargetFlags() & -2) == 0 &&
107*9880d681SAndroid Build Coastguard Worker              "WebAssembly uses only one target flag bit on ExternalSymbols");
108*9880d681SAndroid Build Coastguard Worker       MCOp = LowerSymbolOperand(GetExternalSymbolSymbol(MO), /*Offset=*/0,
109*9880d681SAndroid Build Coastguard Worker                                 MO.getTargetFlags() & 1);
110*9880d681SAndroid Build Coastguard Worker       break;
111*9880d681SAndroid Build Coastguard Worker     }
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker     OutMI.addOperand(MCOp);
114*9880d681SAndroid Build Coastguard Worker   }
115*9880d681SAndroid Build Coastguard Worker }
116