1 //===- HexagonMCInstLower.cpp - Convert Hexagon MachineInstr to an MCInst -===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains code to lower Hexagon MachineInstrs to their corresponding
12 //===----------------------------------------------------------------------===//
14 #include "HexagonAsmPrinter.h"
15 #include "MCTargetDesc/HexagonMCExpr.h"
16 #include "MCTargetDesc/HexagonMCInstrInfo.h"
17 #include "MCTargetDesc/HexagonMCTargetDesc.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/APInt.h"
20 #include "llvm/CodeGen/MachineBasicBlock.h"
21 #include "llvm/CodeGen/MachineInstr.h"
22 #include "llvm/CodeGen/MachineOperand.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCExpr.h"
26 #include "llvm/MC/MCInst.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/raw_ostream.h"
35 void HexagonLowerToMC(const MCInstrInfo
&MCII
, const MachineInstr
*MI
,
36 MCInst
&MCB
, HexagonAsmPrinter
&AP
);
38 } // end namespace llvm
40 static MCOperand
GetSymbolRef(const MachineOperand
&MO
, const MCSymbol
*Symbol
,
41 HexagonAsmPrinter
&Printer
, bool MustExtend
) {
42 MCContext
&MC
= Printer
.OutContext
;
45 // Populate the relocation type based on Hexagon target flags
47 MCSymbolRefExpr::VariantKind RelocationType
;
48 switch (MO
.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended
) {
50 RelocationType
= MCSymbolRefExpr::VK_None
;
52 case HexagonII::MO_PCREL
:
53 RelocationType
= MCSymbolRefExpr::VK_PCREL
;
55 case HexagonII::MO_GOT
:
56 RelocationType
= MCSymbolRefExpr::VK_GOT
;
58 case HexagonII::MO_LO16
:
59 RelocationType
= MCSymbolRefExpr::VK_Hexagon_LO16
;
61 case HexagonII::MO_HI16
:
62 RelocationType
= MCSymbolRefExpr::VK_Hexagon_HI16
;
64 case HexagonII::MO_GPREL
:
65 RelocationType
= MCSymbolRefExpr::VK_Hexagon_GPREL
;
67 case HexagonII::MO_GDGOT
:
68 RelocationType
= MCSymbolRefExpr::VK_Hexagon_GD_GOT
;
70 case HexagonII::MO_GDPLT
:
71 RelocationType
= MCSymbolRefExpr::VK_Hexagon_GD_PLT
;
73 case HexagonII::MO_IE
:
74 RelocationType
= MCSymbolRefExpr::VK_Hexagon_IE
;
76 case HexagonII::MO_IEGOT
:
77 RelocationType
= MCSymbolRefExpr::VK_Hexagon_IE_GOT
;
79 case HexagonII::MO_TPREL
:
80 RelocationType
= MCSymbolRefExpr::VK_TPREL
;
84 ME
= MCSymbolRefExpr::create(Symbol
, RelocationType
, MC
);
86 if (!MO
.isJTI() && MO
.getOffset())
87 ME
= MCBinaryExpr::createAdd(ME
, MCConstantExpr::create(MO
.getOffset(), MC
),
90 ME
= HexagonMCExpr::create(ME
, MC
);
91 HexagonMCInstrInfo::setMustExtend(*ME
, MustExtend
);
92 return MCOperand::createExpr(ME
);
95 // Create an MCInst from a MachineInstr
96 void llvm::HexagonLowerToMC(const MCInstrInfo
&MCII
, const MachineInstr
*MI
,
97 MCInst
&MCB
, HexagonAsmPrinter
&AP
) {
98 if (MI
->getOpcode() == Hexagon::ENDLOOP0
) {
99 HexagonMCInstrInfo::setInnerLoop(MCB
);
102 if (MI
->getOpcode() == Hexagon::ENDLOOP1
) {
103 HexagonMCInstrInfo::setOuterLoop(MCB
);
106 if (MI
->getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER
) {
107 AP
.EmitSled(*MI
, HexagonAsmPrinter::SledKind::FUNCTION_ENTER
);
110 if (MI
->getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT
) {
111 AP
.EmitSled(*MI
, HexagonAsmPrinter::SledKind::FUNCTION_EXIT
);
114 if (MI
->getOpcode() == Hexagon::PATCHABLE_TAIL_CALL
) {
115 AP
.EmitSled(*MI
, HexagonAsmPrinter::SledKind::TAIL_CALL
);
119 MCInst
*MCI
= AP
.OutContext
.createMCInst();
120 MCI
->setOpcode(MI
->getOpcode());
121 assert(MCI
->getOpcode() == static_cast<unsigned>(MI
->getOpcode()) &&
122 "MCI opcode should have been set on construction");
124 for (const MachineOperand
&MO
: MI
->operands()) {
126 bool MustExtend
= MO
.getTargetFlags() & HexagonII::HMOTF_ConstExtended
;
128 switch (MO
.getType()) {
131 llvm_unreachable("unknown operand type");
132 case MachineOperand::MO_RegisterMask
:
134 case MachineOperand::MO_Register
:
135 // Ignore all implicit register operands.
138 MCO
= MCOperand::createReg(MO
.getReg());
140 case MachineOperand::MO_FPImmediate
: {
141 APFloat Val
= MO
.getFPImm()->getValueAPF();
142 // FP immediates are used only when setting GPRs, so they may be dealt
143 // with like regular immediates from this point on.
144 auto Expr
= HexagonMCExpr::create(
145 MCConstantExpr::create(*Val
.bitcastToAPInt().getRawData(),
148 HexagonMCInstrInfo::setMustExtend(*Expr
, MustExtend
);
149 MCO
= MCOperand::createExpr(Expr
);
152 case MachineOperand::MO_Immediate
: {
153 auto Expr
= HexagonMCExpr::create(
154 MCConstantExpr::create(MO
.getImm(), AP
.OutContext
), AP
.OutContext
);
155 HexagonMCInstrInfo::setMustExtend(*Expr
, MustExtend
);
156 MCO
= MCOperand::createExpr(Expr
);
159 case MachineOperand::MO_MachineBasicBlock
: {
160 MCExpr
const *Expr
= MCSymbolRefExpr::create(MO
.getMBB()->getSymbol(),
162 Expr
= HexagonMCExpr::create(Expr
, AP
.OutContext
);
163 HexagonMCInstrInfo::setMustExtend(*Expr
, MustExtend
);
164 MCO
= MCOperand::createExpr(Expr
);
167 case MachineOperand::MO_GlobalAddress
:
168 MCO
= GetSymbolRef(MO
, AP
.getSymbol(MO
.getGlobal()), AP
, MustExtend
);
170 case MachineOperand::MO_ExternalSymbol
:
171 MCO
= GetSymbolRef(MO
, AP
.GetExternalSymbolSymbol(MO
.getSymbolName()),
174 case MachineOperand::MO_JumpTableIndex
:
175 MCO
= GetSymbolRef(MO
, AP
.GetJTISymbol(MO
.getIndex()), AP
, MustExtend
);
177 case MachineOperand::MO_ConstantPoolIndex
:
178 MCO
= GetSymbolRef(MO
, AP
.GetCPISymbol(MO
.getIndex()), AP
, MustExtend
);
180 case MachineOperand::MO_BlockAddress
:
181 MCO
= GetSymbolRef(MO
, AP
.GetBlockAddressSymbol(MO
.getBlockAddress()), AP
,
186 MCI
->addOperand(MCO
);
188 AP
.HexagonProcessInstruction(*MCI
, *MI
);
189 HexagonMCInstrInfo::extendIfNeeded(AP
.OutContext
, MCII
, MCB
, *MCI
);
190 MCB
.addOperand(MCOperand::createInst(MCI
));