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 "PPCTargetStreamer.h"
17#include "TargetInfo/PowerPCTargetInfo.h"
18#include "llvm/ADT/SmallPtrSet.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/BinaryFormat/ELF.h"
22#include "llvm/MC/MCAssembler.h"
23#include "llvm/MC/MCContext.h"
24#include "llvm/MC/MCDwarf.h"
25#include "llvm/MC/MCELFStreamer.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInstrInfo.h"
28#include "llvm/MC/MCRegisterInfo.h"
29#include "llvm/MC/MCStreamer.h"
30#include "llvm/MC/MCSubtargetInfo.h"
31#include "llvm/MC/MCSymbol.h"
32#include "llvm/MC/MCSymbolELF.h"
33#include "llvm/MC/MCSymbolXCOFF.h"
34#include "llvm/Support/Casting.h"
35#include "llvm/Support/CodeGen.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/FormattedStream.h"
38#include "llvm/Support/TargetRegistry.h"
39#include "llvm/Support/raw_ostream.h"
40
41using namespace llvm;
42
43#define GET_INSTRINFO_MC_DESC
44#include "PPCGenInstrInfo.inc"
45
46#define GET_SUBTARGETINFO_MC_DESC
47#include "PPCGenSubtargetInfo.inc"
48
49#define GET_REGINFO_MC_DESC
50#include "PPCGenRegisterInfo.inc"
51
52PPCTargetStreamer::PPCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
53
54// Pin the vtable to this file.
55PPCTargetStreamer::~PPCTargetStreamer() = default;
56
57static MCInstrInfo *createPPCMCInstrInfo() {
58  MCInstrInfo *X = new MCInstrInfo();
59  InitPPCMCInstrInfo(X);
60  return X;
61}
62
63static MCRegisterInfo *createPPCMCRegisterInfo(const Triple &TT) {
64  bool isPPC64 =
65      (TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le);
66  unsigned Flavour = isPPC64 ? 0 : 1;
67  unsigned RA = isPPC64 ? PPC::LR8 : PPC::LR;
68
69  MCRegisterInfo *X = new MCRegisterInfo();
70  InitPPCMCRegisterInfo(X, RA, Flavour, Flavour);
71  return X;
72}
73
74static MCSubtargetInfo *createPPCMCSubtargetInfo(const Triple &TT,
75                                                 StringRef CPU, StringRef FS) {
76  return createPPCMCSubtargetInfoImpl(TT, CPU, FS);
77}
78
79static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,
80                                     const Triple &TheTriple,
81                                     const MCTargetOptions &Options) {
82  bool isPPC64 = (TheTriple.getArch() == Triple::ppc64 ||
83                  TheTriple.getArch() == Triple::ppc64le);
84
85  MCAsmInfo *MAI;
86  if (TheTriple.isOSBinFormatXCOFF())
87    MAI = new PPCXCOFFMCAsmInfo(isPPC64, TheTriple);
88  else
89    MAI = new PPCELFMCAsmInfo(isPPC64, TheTriple);
90
91  // Initial state of the frame pointer is R1.
92  unsigned Reg = isPPC64 ? PPC::X1 : PPC::R1;
93  MCCFIInstruction Inst =
94      MCCFIInstruction::createDefCfa(nullptr, MRI.getDwarfRegNum(Reg, true), 0);
95  MAI->addInitialFrameState(Inst);
96
97  return MAI;
98}
99
100namespace {
101
102class PPCTargetAsmStreamer : public PPCTargetStreamer {
103  formatted_raw_ostream &OS;
104
105public:
106  PPCTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS)
107      : PPCTargetStreamer(S), OS(OS) {}
108
109  void emitTCEntry(const MCSymbol &S) override {
110    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
111    OS << "\t.tc ";
112    OS << (MAI->getSymbolsHaveSMC()
113               ? cast<MCSymbolXCOFF>(S).getUnqualifiedName()
114               : S.getName());
115    OS << "[TC],";
116    OS << S.getName();
117    OS << '\n';
118  }
119
120  void emitMachine(StringRef CPU) override {
121    OS << "\t.machine " << CPU << '\n';
122  }
123
124  void emitAbiVersion(int AbiVersion) override {
125    OS << "\t.abiversion " << AbiVersion << '\n';
126  }
127
128  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
129    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
130
131    OS << "\t.localentry\t";
132    S->print(OS, MAI);
133    OS << ", ";
134    LocalOffset->print(OS, MAI);
135    OS << '\n';
136  }
137};
138
139class PPCTargetELFStreamer : public PPCTargetStreamer {
140public:
141  PPCTargetELFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
142
143  MCELFStreamer &getStreamer() {
144    return static_cast<MCELFStreamer &>(Streamer);
145  }
146
147  void emitTCEntry(const MCSymbol &S) override {
148    // Creates a R_PPC64_TOC relocation
149    Streamer.EmitValueToAlignment(8);
150    Streamer.EmitSymbolValue(&S, 8);
151  }
152
153  void emitMachine(StringRef CPU) override {
154    // FIXME: Is there anything to do in here or does this directive only
155    // limit the parser?
156  }
157
158  void emitAbiVersion(int AbiVersion) override {
159    MCAssembler &MCA = getStreamer().getAssembler();
160    unsigned Flags = MCA.getELFHeaderEFlags();
161    Flags &= ~ELF::EF_PPC64_ABI;
162    Flags |= (AbiVersion & ELF::EF_PPC64_ABI);
163    MCA.setELFHeaderEFlags(Flags);
164  }
165
166  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
167    MCAssembler &MCA = getStreamer().getAssembler();
168
169    int64_t Res;
170    if (!LocalOffset->evaluateAsAbsolute(Res, MCA))
171      report_fatal_error(".localentry expression must be absolute.");
172
173    unsigned Encoded = ELF::encodePPC64LocalEntryOffset(Res);
174    if (Res != ELF::decodePPC64LocalEntryOffset(Encoded))
175      report_fatal_error(".localentry expression cannot be encoded.");
176
177    unsigned Other = S->getOther();
178    Other &= ~ELF::STO_PPC64_LOCAL_MASK;
179    Other |= Encoded;
180    S->setOther(Other);
181
182    // For GAS compatibility, unless we already saw a .abiversion directive,
183    // set e_flags to indicate ELFv2 ABI.
184    unsigned Flags = MCA.getELFHeaderEFlags();
185    if ((Flags & ELF::EF_PPC64_ABI) == 0)
186      MCA.setELFHeaderEFlags(Flags | 2);
187  }
188
189  void emitAssignment(MCSymbol *S, const MCExpr *Value) override {
190    auto *Symbol = cast<MCSymbolELF>(S);
191
192    // When encoding an assignment to set symbol A to symbol B, also copy
193    // the st_other bits encoding the local entry point offset.
194    if (copyLocalEntry(Symbol, Value))
195      UpdateOther.insert(Symbol);
196    else
197      UpdateOther.erase(Symbol);
198  }
199
200  void finish() override {
201    for (auto *Sym : UpdateOther)
202      if (Sym->isVariable())
203        copyLocalEntry(Sym, Sym->getVariableValue());
204  }
205
206private:
207  SmallPtrSet<MCSymbolELF *, 32> UpdateOther;
208
209  bool copyLocalEntry(MCSymbolELF *D, const MCExpr *S) {
210    auto *Ref = dyn_cast<const MCSymbolRefExpr>(S);
211    if (!Ref)
212      return false;
213    const auto &RhsSym = cast<MCSymbolELF>(Ref->getSymbol());
214    unsigned Other = D->getOther();
215    Other &= ~ELF::STO_PPC64_LOCAL_MASK;
216    Other |= RhsSym.getOther() & ELF::STO_PPC64_LOCAL_MASK;
217    D->setOther(Other);
218    return true;
219  }
220};
221
222class PPCTargetMachOStreamer : public PPCTargetStreamer {
223public:
224  PPCTargetMachOStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
225
226  void emitTCEntry(const MCSymbol &S) override {
227    llvm_unreachable("Unknown pseudo-op: .tc");
228  }
229
230  void emitMachine(StringRef CPU) override {
231    // FIXME: We should update the CPUType, CPUSubType in the Object file if
232    // the new values are different from the defaults.
233  }
234
235  void emitAbiVersion(int AbiVersion) override {
236    llvm_unreachable("Unknown pseudo-op: .abiversion");
237  }
238
239  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
240    llvm_unreachable("Unknown pseudo-op: .localentry");
241  }
242};
243
244class PPCTargetXCOFFStreamer : public PPCTargetStreamer {
245public:
246  PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
247
248  void emitTCEntry(const MCSymbol &S) override {
249    const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
250    const unsigned PointerSize = MAI->getCodePointerSize();
251    Streamer.EmitValueToAlignment(PointerSize);
252    Streamer.EmitSymbolValue(&S, PointerSize);
253  }
254
255  void emitMachine(StringRef CPU) override {
256    llvm_unreachable("Machine pseudo-ops are invalid for XCOFF.");
257  }
258
259  void emitAbiVersion(int AbiVersion) override {
260    llvm_unreachable("ABI-version pseudo-ops are invalid for XCOFF.");
261  }
262
263  void emitLocalEntry(MCSymbolELF *S, const MCExpr *LocalOffset) override {
264    llvm_unreachable("Local-entry pseudo-ops are invalid for XCOFF.");
265  }
266};
267
268} // end anonymous namespace
269
270static MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S,
271                                                 formatted_raw_ostream &OS,
272                                                 MCInstPrinter *InstPrint,
273                                                 bool isVerboseAsm) {
274  return new PPCTargetAsmStreamer(S, OS);
275}
276
277static MCTargetStreamer *
278createObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
279  const Triple &TT = STI.getTargetTriple();
280  if (TT.isOSBinFormatELF())
281    return new PPCTargetELFStreamer(S);
282  if (TT.isOSBinFormatXCOFF())
283    return new PPCTargetXCOFFStreamer(S);
284  return new PPCTargetMachOStreamer(S);
285}
286
287static MCInstPrinter *createPPCMCInstPrinter(const Triple &T,
288                                             unsigned SyntaxVariant,
289                                             const MCAsmInfo &MAI,
290                                             const MCInstrInfo &MII,
291                                             const MCRegisterInfo &MRI) {
292  return new PPCInstPrinter(MAI, MII, MRI, T);
293}
294
295extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
296  for (Target *T :
297       {&getThePPC32Target(), &getThePPC64Target(), &getThePPC64LETarget()}) {
298    // Register the MC asm info.
299    RegisterMCAsmInfoFn C(*T, createPPCMCAsmInfo);
300
301    // Register the MC instruction info.
302    TargetRegistry::RegisterMCInstrInfo(*T, createPPCMCInstrInfo);
303
304    // Register the MC register info.
305    TargetRegistry::RegisterMCRegInfo(*T, createPPCMCRegisterInfo);
306
307    // Register the MC subtarget info.
308    TargetRegistry::RegisterMCSubtargetInfo(*T, createPPCMCSubtargetInfo);
309
310    // Register the MC Code Emitter
311    TargetRegistry::RegisterMCCodeEmitter(*T, createPPCMCCodeEmitter);
312
313    // Register the asm backend.
314    TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);
315
316    // Register the object target streamer.
317    TargetRegistry::RegisterObjectTargetStreamer(*T,
318                                                 createObjectTargetStreamer);
319
320    // Register the asm target streamer.
321    TargetRegistry::RegisterAsmTargetStreamer(*T, createAsmTargetStreamer);
322
323    // Register the MCInstPrinter.
324    TargetRegistry::RegisterMCInstPrinter(*T, createPPCMCInstPrinter);
325  }
326}
327