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 "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" |
29 | #include <cassert> |
30 | |
31 | using namespace llvm; |
32 | |
33 | namespace llvm { |
34 | |
35 | void HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI, |
36 | MCInst &MCB, HexagonAsmPrinter &AP); |
37 | |
38 | } // end namespace llvm |
39 | |
40 | static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, |
41 | HexagonAsmPrinter &Printer, bool MustExtend) { |
42 | MCContext &MC = Printer.OutContext; |
43 | const MCExpr *ME; |
44 | |
45 | // Populate the relocation type based on Hexagon target flags |
46 | // set on an operand |
47 | HexagonMCExpr::VariantKind RelocationType; |
48 | switch (MO.getTargetFlags() & ~HexagonII::HMOTF_ConstExtended) { |
49 | default: |
50 | RelocationType = HexagonMCExpr::VK_None; |
51 | break; |
52 | case HexagonII::MO_PCREL: |
53 | RelocationType = HexagonMCExpr::VK_PCREL; |
54 | break; |
55 | case HexagonII::MO_GOT: |
56 | RelocationType = HexagonMCExpr::VK_GOT; |
57 | break; |
58 | case HexagonII::MO_LO16: |
59 | RelocationType = HexagonMCExpr::VK_LO16; |
60 | break; |
61 | case HexagonII::MO_HI16: |
62 | RelocationType = HexagonMCExpr::VK_HI16; |
63 | break; |
64 | case HexagonII::MO_GPREL: |
65 | RelocationType = HexagonMCExpr::VK_GPREL; |
66 | break; |
67 | case HexagonII::MO_GDGOT: |
68 | RelocationType = HexagonMCExpr::VK_GD_GOT; |
69 | break; |
70 | case HexagonII::MO_GDPLT: |
71 | RelocationType = HexagonMCExpr::VK_GD_PLT; |
72 | break; |
73 | case HexagonII::MO_IE: |
74 | RelocationType = HexagonMCExpr::VK_IE; |
75 | break; |
76 | case HexagonII::MO_IEGOT: |
77 | RelocationType = HexagonMCExpr::VK_IE_GOT; |
78 | break; |
79 | case HexagonII::MO_TPREL: |
80 | RelocationType = HexagonMCExpr::VK_TPREL; |
81 | break; |
82 | } |
83 | |
84 | ME = MCSymbolRefExpr::create(Symbol, specifier: RelocationType, Ctx&: MC); |
85 | |
86 | if (!MO.isJTI() && MO.getOffset()) |
87 | ME = MCBinaryExpr::createAdd(LHS: ME, RHS: MCConstantExpr::create(Value: MO.getOffset(), Ctx&: MC), |
88 | Ctx&: MC); |
89 | |
90 | ME = HexagonMCExpr::create(Expr: ME, Ctx&: MC); |
91 | HexagonMCInstrInfo::setMustExtend(Expr: *ME, Val: MustExtend); |
92 | return MCOperand::createExpr(Val: ME); |
93 | } |
94 | |
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); |
100 | return; |
101 | } |
102 | if (MI->getOpcode() == Hexagon::ENDLOOP1) { |
103 | HexagonMCInstrInfo::setOuterLoop(MCB); |
104 | return; |
105 | } |
106 | if (MI->getOpcode() == Hexagon::PATCHABLE_FUNCTION_ENTER) { |
107 | AP.EmitSled(MI: *MI, Kind: HexagonAsmPrinter::SledKind::FUNCTION_ENTER); |
108 | return; |
109 | } |
110 | if (MI->getOpcode() == Hexagon::PATCHABLE_FUNCTION_EXIT) { |
111 | AP.EmitSled(MI: *MI, Kind: HexagonAsmPrinter::SledKind::FUNCTION_EXIT); |
112 | return; |
113 | } |
114 | if (MI->getOpcode() == Hexagon::PATCHABLE_TAIL_CALL) { |
115 | AP.EmitSled(MI: *MI, Kind: HexagonAsmPrinter::SledKind::TAIL_CALL); |
116 | return; |
117 | } |
118 | |
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" ); |
123 | |
124 | for (const MachineOperand &MO : MI->operands()) { |
125 | MCOperand MCO; |
126 | bool MustExtend = MO.getTargetFlags() & HexagonII::HMOTF_ConstExtended; |
127 | |
128 | switch (MO.getType()) { |
129 | default: |
130 | MI->print(OS&: errs()); |
131 | llvm_unreachable("unknown operand type" ); |
132 | case MachineOperand::MO_RegisterMask: |
133 | continue; |
134 | case MachineOperand::MO_Register: |
135 | // Ignore all implicit register operands. |
136 | if (MO.isImplicit()) |
137 | continue; |
138 | MCO = MCOperand::createReg(Reg: MO.getReg()); |
139 | break; |
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 | Expr: MCConstantExpr::create(Value: *Val.bitcastToAPInt().getRawData(), |
146 | Ctx&: AP.OutContext), |
147 | Ctx&: AP.OutContext); |
148 | HexagonMCInstrInfo::setMustExtend(Expr: *Expr, Val: MustExtend); |
149 | MCO = MCOperand::createExpr(Val: Expr); |
150 | break; |
151 | } |
152 | case MachineOperand::MO_Immediate: { |
153 | auto Expr = HexagonMCExpr::create( |
154 | Expr: MCConstantExpr::create(Value: MO.getImm(), Ctx&: AP.OutContext), Ctx&: AP.OutContext); |
155 | HexagonMCInstrInfo::setMustExtend(Expr: *Expr, Val: MustExtend); |
156 | MCO = MCOperand::createExpr(Val: Expr); |
157 | break; |
158 | } |
159 | case MachineOperand::MO_MachineBasicBlock: { |
160 | MCExpr const *Expr = MCSymbolRefExpr::create(Symbol: MO.getMBB()->getSymbol(), |
161 | Ctx&: AP.OutContext); |
162 | Expr = HexagonMCExpr::create(Expr, Ctx&: AP.OutContext); |
163 | HexagonMCInstrInfo::setMustExtend(Expr: *Expr, Val: MustExtend); |
164 | MCO = MCOperand::createExpr(Val: Expr); |
165 | break; |
166 | } |
167 | case MachineOperand::MO_GlobalAddress: |
168 | MCO = GetSymbolRef(MO, Symbol: AP.getSymbol(GV: MO.getGlobal()), Printer&: AP, MustExtend); |
169 | break; |
170 | case MachineOperand::MO_ExternalSymbol: |
171 | MCO = GetSymbolRef(MO, Symbol: AP.GetExternalSymbolSymbol(Sym: MO.getSymbolName()), |
172 | Printer&: AP, MustExtend); |
173 | break; |
174 | case MachineOperand::MO_JumpTableIndex: |
175 | MCO = GetSymbolRef(MO, Symbol: AP.GetJTISymbol(JTID: MO.getIndex()), Printer&: AP, MustExtend); |
176 | break; |
177 | case MachineOperand::MO_ConstantPoolIndex: |
178 | MCO = GetSymbolRef(MO, Symbol: AP.GetCPISymbol(CPID: MO.getIndex()), Printer&: AP, MustExtend); |
179 | break; |
180 | case MachineOperand::MO_BlockAddress: |
181 | MCO = GetSymbolRef(MO, Symbol: AP.GetBlockAddressSymbol(BA: MO.getBlockAddress()), Printer&: AP, |
182 | MustExtend); |
183 | break; |
184 | } |
185 | |
186 | MCI->addOperand(Op: MCO); |
187 | } |
188 | AP.HexagonProcessInstruction(Inst&: *MCI, MBB: *MI); |
189 | HexagonMCInstrInfo::extendIfNeeded(Context&: AP.OutContext, MCII, MCB, MCI: *MCI); |
190 | MCB.addOperand(Op: MCOperand::createInst(Val: MCI)); |
191 | } |
192 | |