1 | //===-- PPCMCInstLower.cpp - Convert PPC 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 PPC MachineInstrs to their corresponding |
10 | // MCInst records. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "MCTargetDesc/PPCMCExpr.h" |
15 | #include "PPC.h" |
16 | #include "PPCMachineFunctionInfo.h" |
17 | #include "PPCSubtarget.h" |
18 | #include "llvm/ADT/SmallString.h" |
19 | #include "llvm/ADT/Twine.h" |
20 | #include "llvm/CodeGen/AsmPrinter.h" |
21 | #include "llvm/CodeGen/MachineFunction.h" |
22 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" |
23 | #include "llvm/CodeGen/TargetLowering.h" |
24 | #include "llvm/IR/DataLayout.h" |
25 | #include "llvm/IR/GlobalValue.h" |
26 | #include "llvm/IR/Mangler.h" |
27 | #include "llvm/IR/Module.h" |
28 | #include "llvm/MC/MCAsmInfo.h" |
29 | #include "llvm/MC/MCExpr.h" |
30 | #include "llvm/MC/MCInst.h" |
31 | #include "llvm/Target/TargetLoweringObjectFile.h" |
32 | using namespace llvm; |
33 | |
34 | static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, |
35 | AsmPrinter &AP) { |
36 | if (MO.isGlobal()) { |
37 | // Get the symbol from the global, accounting for XCOFF-specific |
38 | // intricacies (see TargetLoweringObjectFileXCOFF::getTargetSymbol). |
39 | const GlobalValue *GV = MO.getGlobal(); |
40 | return AP.getSymbol(GV); |
41 | } |
42 | |
43 | assert(MO.isSymbol() && "Isn't a symbol reference" ); |
44 | |
45 | SmallString<128> Name; |
46 | const DataLayout &DL = AP.getDataLayout(); |
47 | Mangler::getNameWithPrefix(OutName&: Name, GVName: MO.getSymbolName(), DL); |
48 | |
49 | MCContext &Ctx = AP.OutContext; |
50 | MCSymbol *Sym = Ctx.getOrCreateSymbol(Name); |
51 | return Sym; |
52 | } |
53 | |
54 | static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, |
55 | AsmPrinter &Printer) { |
56 | MCContext &Ctx = Printer.OutContext; |
57 | MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; |
58 | |
59 | unsigned access = MO.getTargetFlags(); |
60 | |
61 | switch (access) { |
62 | case PPCII::MO_TPREL_LO: |
63 | RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO; |
64 | break; |
65 | case PPCII::MO_TPREL_HA: |
66 | RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA; |
67 | break; |
68 | case PPCII::MO_DTPREL_LO: |
69 | RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO; |
70 | break; |
71 | case PPCII::MO_TLSLD_LO: |
72 | RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO; |
73 | break; |
74 | case PPCII::MO_TOC_LO: |
75 | RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO; |
76 | break; |
77 | case PPCII::MO_TLS: |
78 | RefKind = MCSymbolRefExpr::VK_PPC_TLS; |
79 | break; |
80 | case PPCII::MO_TLS_PCREL_FLAG: |
81 | RefKind = MCSymbolRefExpr::VK_PPC_TLS_PCREL; |
82 | break; |
83 | } |
84 | |
85 | const TargetMachine &TM = Printer.TM; |
86 | const MachineInstr *MI = MO.getParent(); |
87 | const MachineFunction *MF = MI->getMF(); |
88 | |
89 | if (MO.getTargetFlags() == PPCII::MO_PLT) |
90 | RefKind = MCSymbolRefExpr::VK_PLT; |
91 | else if (MO.getTargetFlags() == PPCII::MO_PCREL_FLAG) |
92 | RefKind = MCSymbolRefExpr::VK_PCREL; |
93 | else if (MO.getTargetFlags() == PPCII::MO_GOT_PCREL_FLAG) |
94 | RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; |
95 | else if (MO.getTargetFlags() == PPCII::MO_TPREL_PCREL_FLAG) |
96 | RefKind = MCSymbolRefExpr::VK_TPREL; |
97 | else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) |
98 | RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; |
99 | else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSLD_PCREL_FLAG) |
100 | RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_PCREL; |
101 | else if (MO.getTargetFlags() == PPCII::MO_GOT_TPREL_PCREL_FLAG) |
102 | RefKind = MCSymbolRefExpr::VK_PPC_GOT_TPREL_PCREL; |
103 | else if (MO.getTargetFlags() == PPCII::MO_TPREL_FLAG || |
104 | MO.getTargetFlags() == PPCII::MO_TLSLD_FLAG) { |
105 | assert(MO.isGlobal() && "Only expecting a global MachineOperand here!" ); |
106 | TLSModel::Model Model = TM.getTLSModel(GV: MO.getGlobal()); |
107 | const PPCFunctionInfo *FuncInfo = MF->getInfo<PPCFunctionInfo>(); |
108 | // For the local-[exec|dynamic] TLS model, we may generate the offset from |
109 | // the TLS base as an immediate operand (instead of using a TOC entry). Set |
110 | // the relocation type in case the result is used for purposes other than a |
111 | // TOC reference. In TOC reference cases, this result is discarded. |
112 | if (Model == TLSModel::LocalExec) |
113 | RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLE; |
114 | else if (Model == TLSModel::LocalDynamic && |
115 | FuncInfo->isAIXFuncUseTLSIEForLD()) |
116 | // On AIX, TLS model opt may have turned local-dynamic accesses into |
117 | // initial-exec accesses. |
118 | RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSIE; |
119 | else if (Model == TLSModel::LocalDynamic) |
120 | RefKind = MCSymbolRefExpr::VK_PPC_AIX_TLSLD; |
121 | } |
122 | |
123 | const Module *M = MF->getFunction().getParent(); |
124 | const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); |
125 | |
126 | unsigned MIOpcode = MI->getOpcode(); |
127 | assert((Subtarget->isUsingPCRelativeCalls() || MIOpcode != PPC::BL8_NOTOC) && |
128 | "BL8_NOTOC is only valid when using PC Relative Calls." ); |
129 | if (Subtarget->isUsingPCRelativeCalls()) { |
130 | if (MIOpcode == PPC::TAILB || MIOpcode == PPC::TAILB8 || |
131 | MIOpcode == PPC::TCRETURNdi || MIOpcode == PPC::TCRETURNdi8 || |
132 | MIOpcode == PPC::BL8_NOTOC || MIOpcode == PPC::BL8_NOTOC_RM) { |
133 | RefKind = MCSymbolRefExpr::VK_PPC_NOTOC; |
134 | } |
135 | if (MO.getTargetFlags() == PPCII::MO_PCREL_OPT_FLAG) |
136 | RefKind = MCSymbolRefExpr::VK_PPC_PCREL_OPT; |
137 | } |
138 | |
139 | const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind: RefKind, Ctx); |
140 | // If -msecure-plt -fPIC, add 32768 to symbol. |
141 | if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && |
142 | M->getPICLevel() == PICLevel::BigPIC && |
143 | MO.getTargetFlags() == PPCII::MO_PLT) |
144 | Expr = |
145 | MCBinaryExpr::createAdd(LHS: Expr, RHS: MCConstantExpr::create(Value: 32768, Ctx), Ctx); |
146 | |
147 | if (!MO.isJTI() && MO.getOffset()) |
148 | Expr = MCBinaryExpr::createAdd(LHS: Expr, |
149 | RHS: MCConstantExpr::create(Value: MO.getOffset(), Ctx), |
150 | Ctx); |
151 | |
152 | // Subtract off the PIC base if required. |
153 | if (MO.getTargetFlags() == PPCII::MO_PIC_FLAG || |
154 | MO.getTargetFlags() == PPCII::MO_PIC_HA_FLAG || |
155 | MO.getTargetFlags() == PPCII::MO_PIC_LO_FLAG) { |
156 | const MachineFunction *MF = MO.getParent()->getParent()->getParent(); |
157 | |
158 | const MCExpr *PB = MCSymbolRefExpr::create(Symbol: MF->getPICBaseSymbol(), Ctx); |
159 | Expr = MCBinaryExpr::createSub(LHS: Expr, RHS: PB, Ctx); |
160 | } |
161 | |
162 | // Add ha16() / lo16() markers if required. |
163 | switch (access) { |
164 | case PPCII::MO_LO: |
165 | case PPCII::MO_PIC_LO_FLAG: |
166 | Expr = PPCMCExpr::createLo(Expr, Ctx); |
167 | break; |
168 | case PPCII::MO_HA: |
169 | case PPCII::MO_PIC_HA_FLAG: |
170 | Expr = PPCMCExpr::createHa(Expr, Ctx); |
171 | break; |
172 | } |
173 | |
174 | return MCOperand::createExpr(Val: Expr); |
175 | } |
176 | |
177 | void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, |
178 | AsmPrinter &AP) { |
179 | OutMI.setOpcode(MI->getOpcode()); |
180 | |
181 | for (const MachineOperand &MO : MI->operands()) { |
182 | MCOperand MCOp; |
183 | if (LowerPPCMachineOperandToMCOperand(MO, OutMO&: MCOp, AP)) |
184 | OutMI.addOperand(Op: MCOp); |
185 | } |
186 | } |
187 | |
188 | bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO, |
189 | MCOperand &OutMO, AsmPrinter &AP) { |
190 | switch (MO.getType()) { |
191 | default: |
192 | llvm_unreachable("unknown operand type" ); |
193 | case MachineOperand::MO_Register: |
194 | assert(!MO.getSubReg() && "Subregs should be eliminated!" ); |
195 | assert(MO.getReg() > PPC::NoRegister && |
196 | MO.getReg() < PPC::NUM_TARGET_REGS && |
197 | "Invalid register for this target!" ); |
198 | // Ignore all implicit register operands. |
199 | if (MO.isImplicit()) |
200 | return false; |
201 | OutMO = MCOperand::createReg(Reg: MO.getReg()); |
202 | return true; |
203 | case MachineOperand::MO_Immediate: |
204 | OutMO = MCOperand::createImm(Val: MO.getImm()); |
205 | return true; |
206 | case MachineOperand::MO_MachineBasicBlock: |
207 | OutMO = MCOperand::createExpr( |
208 | Val: MCSymbolRefExpr::create(Symbol: MO.getMBB()->getSymbol(), Ctx&: AP.OutContext)); |
209 | return true; |
210 | case MachineOperand::MO_GlobalAddress: |
211 | case MachineOperand::MO_ExternalSymbol: |
212 | OutMO = GetSymbolRef(MO, Symbol: GetSymbolFromOperand(MO, AP), Printer&: AP); |
213 | return true; |
214 | case MachineOperand::MO_JumpTableIndex: |
215 | OutMO = GetSymbolRef(MO, Symbol: AP.GetJTISymbol(JTID: MO.getIndex()), Printer&: AP); |
216 | return true; |
217 | case MachineOperand::MO_ConstantPoolIndex: |
218 | OutMO = GetSymbolRef(MO, Symbol: AP.GetCPISymbol(CPID: MO.getIndex()), Printer&: AP); |
219 | return true; |
220 | case MachineOperand::MO_BlockAddress: |
221 | OutMO = |
222 | GetSymbolRef(MO, Symbol: AP.GetBlockAddressSymbol(BA: MO.getBlockAddress()), Printer&: AP); |
223 | return true; |
224 | case MachineOperand::MO_MCSymbol: |
225 | OutMO = GetSymbolRef(MO, Symbol: MO.getMCSymbol(), Printer&: AP); |
226 | return true; |
227 | case MachineOperand::MO_RegisterMask: |
228 | return false; |
229 | } |
230 | } |
231 | |