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