xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonMCInstLower.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- HexagonMCInstLower.cpp - Convert Hexagon MachineInstr to an MCInst -===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file contains code to lower Hexagon MachineInstrs to their corresponding
10*0b57cec5SDimitry Andric // MCInst records.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "Hexagon.h"
15*0b57cec5SDimitry Andric #include "HexagonAsmPrinter.h"
16*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCExpr.h"
17*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
18*0b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h"
19*0b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
20*0b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
24*0b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
25*0b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
26*0b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
27*0b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
28*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
29*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
30*0b57cec5SDimitry Andric #include <cassert>
31*0b57cec5SDimitry Andric 
32*0b57cec5SDimitry Andric using namespace llvm;
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric namespace llvm {
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
37*0b57cec5SDimitry Andric                       MCInst &MCB, HexagonAsmPrinter &AP);
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric } // end namespace llvm
40*0b57cec5SDimitry Andric 
41*0b57cec5SDimitry Andric static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
42*0b57cec5SDimitry Andric                               HexagonAsmPrinter &Printer, bool MustExtend) {
43*0b57cec5SDimitry Andric   MCContext &MC = Printer.OutContext;
44*0b57cec5SDimitry Andric   const MCExpr *ME;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   // Populate the relocation type based on Hexagon target flags
47*0b57cec5SDimitry Andric   // set on an operand
48*0b57cec5SDimitry Andric   MCSymbolRefExpr::VariantKind RelocationType;
49*0b57cec5SDimitry Andric   switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) {
50*0b57cec5SDimitry Andric   default:
51*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_None;
52*0b57cec5SDimitry Andric     break;
53*0b57cec5SDimitry Andric   case HexagonII::MO_PCREL:
54*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_PCREL;
55*0b57cec5SDimitry Andric     break;
56*0b57cec5SDimitry Andric   case HexagonII::MO_GOT:
57*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_GOT;
58*0b57cec5SDimitry Andric     break;
59*0b57cec5SDimitry Andric   case HexagonII::MO_LO16:
60*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_LO16;
61*0b57cec5SDimitry Andric     break;
62*0b57cec5SDimitry Andric   case HexagonII::MO_HI16:
63*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_HI16;
64*0b57cec5SDimitry Andric     break;
65*0b57cec5SDimitry Andric   case HexagonII::MO_GPREL:
66*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_GPREL;
67*0b57cec5SDimitry Andric     break;
68*0b57cec5SDimitry Andric   case HexagonII::MO_GDGOT:
69*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_GOT;
70*0b57cec5SDimitry Andric     break;
71*0b57cec5SDimitry Andric   case HexagonII::MO_GDPLT:
72*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_GD_PLT;
73*0b57cec5SDimitry Andric     break;
74*0b57cec5SDimitry Andric   case HexagonII::MO_IE:
75*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_IE;
76*0b57cec5SDimitry Andric     break;
77*0b57cec5SDimitry Andric   case HexagonII::MO_IEGOT:
78*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_Hexagon_IE_GOT;
79*0b57cec5SDimitry Andric     break;
80*0b57cec5SDimitry Andric   case HexagonII::MO_TPREL:
81*0b57cec5SDimitry Andric     RelocationType = MCSymbolRefExpr::VK_TPREL;
82*0b57cec5SDimitry Andric     break;
83*0b57cec5SDimitry Andric   }
84*0b57cec5SDimitry Andric 
85*0b57cec5SDimitry Andric   ME = MCSymbolRefExpr::create(Symbol, RelocationType, MC);
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric   if (!MO.isJTI() && MO.getOffset())
88*0b57cec5SDimitry Andric     ME = MCBinaryExpr::createAdd(ME, MCConstantExpr::create(MO.getOffset(), MC),
89*0b57cec5SDimitry Andric                                  MC);
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric   ME = HexagonMCExpr::create(ME, MC);
92*0b57cec5SDimitry Andric   HexagonMCInstrInfo::setMustExtend(*ME, MustExtend);
93*0b57cec5SDimitry Andric   return MCOperand::createExpr(ME);
94*0b57cec5SDimitry Andric }
95*0b57cec5SDimitry Andric 
96*0b57cec5SDimitry Andric // Create an MCInst from a MachineInstr
97*0b57cec5SDimitry Andric void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
98*0b57cec5SDimitry Andric                             MCInst &MCB, HexagonAsmPrinter &AP) {
99*0b57cec5SDimitry Andric   if (MI->getOpcode() == Hexagon::ENDLOOP0) {
100*0b57cec5SDimitry Andric     HexagonMCInstrInfo::setInnerLoop(MCB);
101*0b57cec5SDimitry Andric     return;
102*0b57cec5SDimitry Andric   }
103*0b57cec5SDimitry Andric   if (MI->getOpcode() == Hexagon::ENDLOOP1) {
104*0b57cec5SDimitry Andric     HexagonMCInstrInfo::setOuterLoop(MCB);
105*0b57cec5SDimitry Andric     return;
106*0b57cec5SDimitry Andric   }
107*0b57cec5SDimitry Andric   MCInst *MCI = new (AP.OutContext) MCInst;
108*0b57cec5SDimitry Andric   MCI->setOpcode(MI->getOpcode());
109*0b57cec5SDimitry Andric   assert(MCI->getOpcode() == static_cast<unsigned>(MI->getOpcode()) &&
110*0b57cec5SDimitry Andric          "MCI opcode should have been set on construction");
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric   for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) {
113*0b57cec5SDimitry Andric     const MachineOperand &MO = MI->getOperand(i);
114*0b57cec5SDimitry Andric     MCOperand MCO;
115*0b57cec5SDimitry Andric     bool MustExtend = MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended;
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric     switch (MO.getType()) {
118*0b57cec5SDimitry Andric     default:
119*0b57cec5SDimitry Andric       MI->print(errs());
120*0b57cec5SDimitry Andric       llvm_unreachable("unknown operand type");
121*0b57cec5SDimitry Andric     case MachineOperand::MO_RegisterMask:
122*0b57cec5SDimitry Andric       continue;
123*0b57cec5SDimitry Andric     case MachineOperand::MO_Register:
124*0b57cec5SDimitry Andric       // Ignore all implicit register operands.
125*0b57cec5SDimitry Andric       if (MO.isImplicit())
126*0b57cec5SDimitry Andric         continue;
127*0b57cec5SDimitry Andric       MCO = MCOperand::createReg(MO.getReg());
128*0b57cec5SDimitry Andric       break;
129*0b57cec5SDimitry Andric     case MachineOperand::MO_FPImmediate: {
130*0b57cec5SDimitry Andric       APFloat Val = MO.getFPImm()->getValueAPF();
131*0b57cec5SDimitry Andric       // FP immediates are used only when setting GPRs, so they may be dealt
132*0b57cec5SDimitry Andric       // with like regular immediates from this point on.
133*0b57cec5SDimitry Andric       auto Expr = HexagonMCExpr::create(
134*0b57cec5SDimitry Andric           MCConstantExpr::create(*Val.bitcastToAPInt().getRawData(),
135*0b57cec5SDimitry Andric                                  AP.OutContext),
136*0b57cec5SDimitry Andric           AP.OutContext);
137*0b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend);
138*0b57cec5SDimitry Andric       MCO = MCOperand::createExpr(Expr);
139*0b57cec5SDimitry Andric       break;
140*0b57cec5SDimitry Andric     }
141*0b57cec5SDimitry Andric     case MachineOperand::MO_Immediate: {
142*0b57cec5SDimitry Andric       auto Expr = HexagonMCExpr::create(
143*0b57cec5SDimitry Andric           MCConstantExpr::create(MO.getImm(), AP.OutContext), AP.OutContext);
144*0b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend);
145*0b57cec5SDimitry Andric       MCO = MCOperand::createExpr(Expr);
146*0b57cec5SDimitry Andric       break;
147*0b57cec5SDimitry Andric     }
148*0b57cec5SDimitry Andric     case MachineOperand::MO_MachineBasicBlock: {
149*0b57cec5SDimitry Andric       MCExpr const *Expr = MCSymbolRefExpr::create(MO.getMBB()->getSymbol(),
150*0b57cec5SDimitry Andric                                                    AP.OutContext);
151*0b57cec5SDimitry Andric       Expr = HexagonMCExpr::create(Expr, AP.OutContext);
152*0b57cec5SDimitry Andric       HexagonMCInstrInfo::setMustExtend(*Expr, MustExtend);
153*0b57cec5SDimitry Andric       MCO = MCOperand::createExpr(Expr);
154*0b57cec5SDimitry Andric       break;
155*0b57cec5SDimitry Andric     }
156*0b57cec5SDimitry Andric     case MachineOperand::MO_GlobalAddress:
157*0b57cec5SDimitry Andric       MCO = GetSymbolRef(MO, AP.getSymbol(MO.getGlobal()), AP, MustExtend);
158*0b57cec5SDimitry Andric       break;
159*0b57cec5SDimitry Andric     case MachineOperand::MO_ExternalSymbol:
160*0b57cec5SDimitry Andric       MCO = GetSymbolRef(MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()),
161*0b57cec5SDimitry Andric                          AP, MustExtend);
162*0b57cec5SDimitry Andric       break;
163*0b57cec5SDimitry Andric     case MachineOperand::MO_JumpTableIndex:
164*0b57cec5SDimitry Andric       MCO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, MustExtend);
165*0b57cec5SDimitry Andric       break;
166*0b57cec5SDimitry Andric     case MachineOperand::MO_ConstantPoolIndex:
167*0b57cec5SDimitry Andric       MCO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, MustExtend);
168*0b57cec5SDimitry Andric       break;
169*0b57cec5SDimitry Andric     case MachineOperand::MO_BlockAddress:
170*0b57cec5SDimitry Andric       MCO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP,
171*0b57cec5SDimitry Andric                          MustExtend);
172*0b57cec5SDimitry Andric       break;
173*0b57cec5SDimitry Andric     }
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric     MCI->addOperand(MCO);
176*0b57cec5SDimitry Andric   }
177*0b57cec5SDimitry Andric   AP.HexagonProcessInstruction(*MCI, *MI);
178*0b57cec5SDimitry Andric   HexagonMCInstrInfo::extendIfNeeded(AP.OutContext, MCII, MCB, *MCI);
179*0b57cec5SDimitry Andric   MCB.addOperand(MCOperand::createInst(MCI));
180*0b57cec5SDimitry Andric }
181