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