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