1 //===-- PPCMCTargetDesc.cpp - PowerPC Target Descriptions -----------------===//
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 provides PowerPC specific target descriptions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "MCTargetDesc/PPCMCTargetDesc.h"
14 #include "MCTargetDesc/PPCInstPrinter.h"
15 #include "MCTargetDesc/PPCMCAsmInfo.h"
16 #include "PPCELFStreamer.h"
17 #include "PPCTargetStreamer.h"
18 #include "PPCXCOFFStreamer.h"
19 #include "TargetInfo/PowerPCTargetInfo.h"
20 #include "llvm/ADT/SmallPtrSet.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Triple.h"
23 #include "llvm/BinaryFormat/ELF.h"
24 #include "llvm/MC/MCAsmBackend.h"
25 #include "llvm/MC/MCAssembler.h"
26 #include "llvm/MC/MCCodeEmitter.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCDwarf.h"
29 #include "llvm/MC/MCELFStreamer.h"
30 #include "llvm/MC/MCExpr.h"
31 #include "llvm/MC/MCInstrAnalysis.h"
32 #include "llvm/MC/MCInstrInfo.h"
33 #include "llvm/MC/MCObjectWriter.h"
34 #include "llvm/MC/MCRegisterInfo.h"
35 #include "llvm/MC/MCSectionXCOFF.h"
36 #include "llvm/MC/MCStreamer.h"
37 #include "llvm/MC/MCSubtargetInfo.h"
38 #include "llvm/MC/MCSymbol.h"
39 #include "llvm/MC/MCSymbolELF.h"
40 #include "llvm/MC/MCSymbolXCOFF.h"
41 #include "llvm/MC/TargetRegistry.h"
42 #include "llvm/Support/Casting.h"
43 #include "llvm/Support/CodeGen.h"
44 #include "llvm/Support/ErrorHandling.h"
45 #include "llvm/Support/FormattedStream.h"
46 #include "llvm/Support/raw_ostream.h"
47
48 using namespace llvm;
49
50 #define GET_INSTRINFO_MC_DESC
51 #define ENABLE_INSTR_PREDICATE_VERIFIER
52 #include "PPCGenInstrInfo.inc"
53
54 #define GET_SUBTARGETINFO_MC_DESC
55 #include "PPCGenSubtargetInfo.inc"
56
57 #define GET_REGINFO_MC_DESC
58 #include "PPCGenRegisterInfo.inc"
59
PPCTargetStreamer(MCStreamer & S)60 PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
61
62 // Pin the vtable to this file.
63 PPCTargetStreamer::~PPCTargetStreamer() = default;
64
createPPCMCInstrInfo()65 static MCInstrInfo *createPPCMCInstrInfo() {
66 MCInstrInfo *X = new MCInstrInfo();
67 InitPPCMCInstrInfo(X);
68 return X;
69 }
70
createPPCMCRegisterInfo(const Triple & TT)71 static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {
72 bool isPPC64 =
73 (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);
74 unsigned Flavour = isPPC64 ? 0 : 1;
75 unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;
76
77 MCRegisterInfo *X = new MCRegisterInfo();
78 InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);
79 return X;
80 }
81
createPPCMCSubtargetInfo(const Triple & TT,StringRef CPU,StringRef FS)82 static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,
83 StringRef CPU, StringRef FS) {
84 // Set some default feature to MC layer.
85 std::string FullFS = std::string(FS);
86
87 if (TT.isOSAIX()) {
88 if (!FullFS.empty())
89 FullFS = "+aix," + FullFS;
90 else
91 FullFS = "+aix";
92 }
93
94 return createPPCMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, FullFS);
95 }
96
createPPCMCAsmInfo(const MCRegisterInfo & MRI,const Triple & TheTriple,const MCTargetOptions & Options)97 static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,
98 const Triple &TheTriple,
99 const MCTargetOptions &Options) {
100 bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
101 TheTriple.getArch() == Triple::ppc64le);
102
103 MCAsmInfo *MAI;
104 if (TheTriple.isOSBinFormatXCOFF())
105 MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);
106 else
107 MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);
108
109 // Initial state of the frame pointer is R1.
110 unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;
111 MCCFIInstruction Inst =
112 MCCFIInstruction::cfiDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);
113 MAI->addInitialFrameState(Inst);
114
115 return MAI;
116 }
117
118 static MCStreamer *
createPPCELFStreamer(const Triple & T,MCContext & Context,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && Emitter,bool RelaxAll)119 createPPCELFStreamer(const Triple &T, MCContext &Context,
120 std::unique_ptr<MCAsmBackend> &&MAB,
121 std::unique_ptr<MCObjectWriter> &&OW,
122 std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
123 return createPPCELFStreamer(Context, std::move(MAB), std::move(OW),
124 std::move(Emitter));
125 }
126
createPPCXCOFFStreamer(const Triple & T,MCContext & Context,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && Emitter,bool RelaxAll)127 static MCStreamer *createPPCXCOFFStreamer(
128 const Triple &T, MCContext &Context, std::unique_ptr<MCAsmBackend> &&MAB,
129 std::unique_ptr<MCObjectWriter> &&OW,
130 std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
131 return createPPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
132 std::move(Emitter));
133 }
134
135 namespace {
136
137 class PPCTargetAsmStreamer : public PPCTargetStreamer {
138 formatted_raw_ostream &OS;
139
140 public:
PPCTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream & OS)141 PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)
142 : PPCTargetStreamer(S), OS(OS) {}
143
emitTCEntry(const MCSymbol & S,MCSymbolRefExpr::VariantKind Kind)144 void emitTCEntry(const MCSymbol &S,
145 MCSymbolRefExpr::VariantKind Kind) override {
146 if (const MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(&S)) {
147 MCSymbolXCOFF *TCSym =
148 cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
149 ->getQualNameSymbol();
150 // If the variant kind is VK_PPC_AIX_TLSGDM the entry represents the
151 // region handle for the symbol, we add the relocation specifier @m.
152 // If the variant kind is VK_PPC_AIX_TLSGD the entry represents the
153 // variable offset for the symbol, we add the relocation specifier @gd.
154 if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
155 Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM)
156 OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
157 << MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
158 else
159 OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << '\n';
160
161 if (TCSym->hasRename())
162 Streamer.emitXCOFFRenameDirective(TCSym, TCSym->getSymbolTableName());
163 return;
164 }
165
166 OS << "\t.tc " << S.getName() << "[TC]," << S.getName() << '\n';
167 }
168
emitMachine(StringRef CPU)169 void emitMachine(StringRef CPU) override {
170 OS << "\t.machine " << CPU << '\n';
171 }
172
emitAbiVersion(int AbiVersion)173 void emitAbiVersion(int AbiVersion) override {
174 OS << "\t.abiversion " << AbiVersion << '\n';
175 }
176
emitLocalEntry(MCSymbolELF * S,const MCExpr * LocalOffset)177 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
178 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
179
180 OS << "\t.localentry\t";
181 S->print(OS, MAI);
182 OS << ", ";
183 LocalOffset->print(OS, MAI);
184 OS << '\n';
185 }
186 };
187
188 class PPCTargetELFStreamer : public PPCTargetStreamer {
189 public:
PPCTargetELFStreamer(MCStreamer & S)190 PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
191
getStreamer()192 MCELFStreamer &getStreamer() {
193 return static_cast<MCELFStreamer &>(Streamer);
194 }
195
emitTCEntry(const MCSymbol & S,MCSymbolRefExpr::VariantKind Kind)196 void emitTCEntry(const MCSymbol &S,
197 MCSymbolRefExpr::VariantKind Kind) override {
198 // Creates a R_PPC64_TOC relocation
199 Streamer.emitValueToAlignment(Align(8));
200 Streamer.emitSymbolValue(&S, 8);
201 }
202
emitMachine(StringRef CPU)203 void emitMachine(StringRef CPU) override {
204 // FIXME: Is there anything to do in here or does this directive only
205 // limit the parser?
206 }
207
emitAbiVersion(int AbiVersion)208 void emitAbiVersion(int AbiVersion) override {
209 MCAssembler &MCA = getStreamer().getAssembler();
210 unsigned Flags = MCA.getELFHeaderEFlags();
211 Flags &= ~ELF::EF_PPC64_ABI;
212 Flags |= (AbiVersion & ELF::EF_PPC64_ABI);
213 MCA.setELFHeaderEFlags(Flags);
214 }
215
emitLocalEntry(MCSymbolELF * S,const MCExpr * LocalOffset)216 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
217 MCAssembler &MCA = getStreamer().getAssembler();
218
219 // encodePPC64LocalEntryOffset will report an error if it cannot
220 // encode LocalOffset.
221 unsigned Encoded = encodePPC64LocalEntryOffset(LocalOffset);
222
223 unsigned Other = S->getOther();
224 Other &= ~ELF::STO_PPC64_LOCAL_MASK;
225 Other |= Encoded;
226 S->setOther(Other);
227
228 // For GAS compatibility, unless we already saw a .abiversion directive,
229 // set e_flags to indicate ELFv2 ABI.
230 unsigned Flags = MCA.getELFHeaderEFlags();
231 if ((Flags & ELF::EF_PPC64_ABI) == 0)
232 MCA.setELFHeaderEFlags(Flags | 2);
233 }
234
emitAssignment(MCSymbol * S,const MCExpr * Value)235 void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
236 auto *Symbol = cast<MCSymbolELF>(S);
237
238 // When encoding an assignment to set symbol A to symbol B, also copy
239 // the st_other bits encoding the local entry point offset.
240 if (copyLocalEntry(Symbol, Value))
241 UpdateOther.insert(Symbol);
242 else
243 UpdateOther.erase(Symbol);
244 }
245
finish()246 void finish() override {
247 for (auto *Sym : UpdateOther)
248 if (Sym->isVariable())
249 copyLocalEntry(Sym, Sym->getVariableValue());
250
251 // Clear the set of symbols that needs to be updated so the streamer can
252 // be reused without issues.
253 UpdateOther.clear();
254 }
255
256 private:
257 SmallPtrSet<MCSymbolELF *, 32> UpdateOther;
258
copyLocalEntry(MCSymbolELF * D,const MCExpr * S)259 bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {
260 auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);
261 if (!Ref)
262 return false;
263 const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol());
264 unsigned Other = D->getOther();
265 Other &= ~ELF::STO_PPC64_LOCAL_MASK;
266 Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
267 D->setOther(Other);
268 return true;
269 }
270
encodePPC64LocalEntryOffset(const MCExpr * LocalOffset)271 unsigned encodePPC64LocalEntryOffset(const MCExpr *LocalOffset) {
272 MCAssembler &MCA = getStreamer().getAssembler();
273 int64_t Offset;
274 if (!LocalOffset->evaluateAsAbsolute(Offset, MCA))
275 MCA.getContext().reportError(LocalOffset->getLoc(),
276 ".localentry expression must be absolute");
277
278 switch (Offset) {
279 default:
280 MCA.getContext().reportError(
281 LocalOffset->getLoc(), ".localentry expression must be a power of 2");
282 return 0;
283 case 0:
284 return 0;
285 case 1:
286 return 1 << ELF::STO_PPC64_LOCAL_BIT;
287 case 4:
288 case 8:
289 case 16:
290 case 32:
291 case 64:
292 return Log2_32(Offset) << ELF::STO_PPC64_LOCAL_BIT;
293 }
294 }
295 };
296
297 class PPCTargetMachOStreamer : public PPCTargetStreamer {
298 public:
PPCTargetMachOStreamer(MCStreamer & S)299 PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
300
emitTCEntry(const MCSymbol & S,MCSymbolRefExpr::VariantKind Kind)301 void emitTCEntry(const MCSymbol &S,
302 MCSymbolRefExpr::VariantKind Kind) override {
303 llvm_unreachable("Unknown pseudo-op: .tc");
304 }
305
emitMachine(StringRef CPU)306 void emitMachine(StringRef CPU) override {
307 // FIXME: We should update the CPUType, CPUSubType in the Object file if
308 // the new values are different from the defaults.
309 }
310
emitAbiVersion(int AbiVersion)311 void emitAbiVersion(int AbiVersion) override {
312 llvm_unreachable("Unknown pseudo-op: .abiversion");
313 }
314
emitLocalEntry(MCSymbolELF * S,const MCExpr * LocalOffset)315 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
316 llvm_unreachable("Unknown pseudo-op: .localentry");
317 }
318 };
319
320 class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
321 public:
PPCTargetXCOFFStreamer(MCStreamer & S)322 PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
323
emitTCEntry(const MCSymbol & S,MCSymbolRefExpr::VariantKind Kind)324 void emitTCEntry(const MCSymbol &S,
325 MCSymbolRefExpr::VariantKind Kind) override {
326 const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
327 const unsigned PointerSize = MAI->getCodePointerSize();
328 Streamer.emitValueToAlignment(Align(PointerSize));
329 Streamer.emitValue(MCSymbolRefExpr::create(&S, Kind, Streamer.getContext()),
330 PointerSize);
331 }
332
emitMachine(StringRef CPU)333 void emitMachine(StringRef CPU) override {
334 llvm_unreachable("Machine pseudo-ops are invalid for XCOFF.");
335 }
336
emitAbiVersion(int AbiVersion)337 void emitAbiVersion(int AbiVersion) override {
338 llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");
339 }
340
emitLocalEntry(MCSymbolELF * S,const MCExpr * LocalOffset)341 void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
342 llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");
343 }
344 };
345
346 } // end anonymous namespace
347
createAsmTargetStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter * InstPrint,bool isVerboseAsm)348 static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
349 formatted_raw_ostream &OS,
350 MCInstPrinter *InstPrint,
351 bool isVerboseAsm) {
352 return new PPCTargetAsmStreamer(S, OS);
353 }
354
createNullTargetStreamer(MCStreamer & S)355 static MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) {
356 return new PPCTargetStreamer(S);
357 }
358
359 static MCTargetStreamer *
createObjectTargetStreamer(MCStreamer & S,const MCSubtargetInfo & STI)360 createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
361 const Triple &TT = STI.getTargetTriple();
362 if (TT.isOSBinFormatELF())
363 return new PPCTargetELFStreamer(S);
364 if (TT.isOSBinFormatXCOFF())
365 return new PPCTargetXCOFFStreamer(S);
366 return new PPCTargetMachOStreamer(S);
367 }
368
createPPCMCInstPrinter(const Triple & T,unsigned SyntaxVariant,const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)369 static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,
370 unsigned SyntaxVariant,
371 const MCAsmInfo &MAI,
372 const MCInstrInfo &MII,
373 const MCRegisterInfo &MRI) {
374 return new PPCInstPrinter(MAI, MII, MRI, T);
375 }
376
377 namespace {
378
379 class PPCMCInstrAnalysis : public MCInstrAnalysis {
380 public:
PPCMCInstrAnalysis(const MCInstrInfo * Info)381 explicit PPCMCInstrAnalysis(const MCInstrInfo *Info)
382 : MCInstrAnalysis(Info) {}
383
evaluateBranch(const MCInst & Inst,uint64_t Addr,uint64_t Size,uint64_t & Target) const384 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
385 uint64_t &Target) const override {
386 unsigned NumOps = Inst.getNumOperands();
387 if (NumOps == 0 ||
388 Info->get(Inst.getOpcode()).operands()[NumOps - 1].OperandType !=
389 MCOI::OPERAND_PCREL)
390 return false;
391 Target = Addr + Inst.getOperand(NumOps - 1).getImm() * Size;
392 return true;
393 }
394 };
395
396 } // end anonymous namespace
397
createPPCMCInstrAnalysis(const MCInstrInfo * Info)398 static MCInstrAnalysis *createPPCMCInstrAnalysis(const MCInstrInfo *Info) {
399 return new PPCMCInstrAnalysis(Info);
400 }
401
LLVMInitializePowerPCTargetMC()402 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
403 for (Target *T : {&getThePPC32Target(), &getThePPC32LETarget(),
404 &getThePPC64Target(), &getThePPC64LETarget()}) {
405 // Register the MC asm info.
406 RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);
407
408 // Register the MC instruction info.
409 TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);
410
411 // Register the MC register info.
412 TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);
413
414 // Register the MC subtarget info.
415 TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);
416
417 // Register the MC instruction analyzer.
418 TargetRegistry::RegisterMCInstrAnalysis(*T, createPPCMCInstrAnalysis);
419
420 // Register the MC Code Emitter
421 TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);
422
423 // Register the asm backend.
424 TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);
425
426 // Register the elf streamer.
427 TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);
428
429 // Register the XCOFF streamer.
430 TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);
431
432 // Register the object target streamer.
433 TargetRegistry::RegisterObjectTargetStreamer(*T,
434 createObjectTargetStreamer);
435
436 // Register the asm target streamer.
437 TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);
438
439 // Register the null target streamer.
440 TargetRegistry::RegisterNullTargetStreamer(*T, createNullTargetStreamer);
441
442 // Register the MCInstPrinter.
443 TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);
444 }
445 }
446