1 //===-- HexagonMCTargetDesc.cpp - Hexagon Target Descriptions -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides Hexagon specific target descriptions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "HexagonMCTargetDesc.h"
15 #include "Hexagon.h"
16 #include "HexagonMCAsmInfo.h"
17 #include "HexagonMCELFStreamer.h"
18 #include "MCTargetDesc/HexagonInstPrinter.h"
19 #include "llvm/MC/MCCodeGenInfo.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCELFStreamer.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCObjectStreamer.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MachineLocation.h"
28 #include "llvm/Support/ELF.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/TargetRegistry.h"
31 
32 using namespace llvm;
33 
34 #define GET_INSTRINFO_MC_DESC
35 #include "HexagonGenInstrInfo.inc"
36 
37 #define GET_SUBTARGETINFO_MC_DESC
38 #include "HexagonGenSubtargetInfo.inc"
39 
40 #define GET_REGINFO_MC_DESC
41 #include "HexagonGenRegisterInfo.inc"
42 
43 cl::opt<bool> llvm::HexagonDisableCompound
44   ("mno-compound",
45    cl::desc("Disable looking for compound instructions for Hexagon"));
46 
47 cl::opt<bool> llvm::HexagonDisableDuplex
48   ("mno-pairing",
49    cl::desc("Disable looking for duplex instructions for Hexagon"));
50 
selectHexagonCPU(const Triple & TT,StringRef CPU)51 StringRef HEXAGON_MC::selectHexagonCPU(const Triple &TT, StringRef CPU) {
52   if (CPU.empty())
53     CPU = "hexagonv60";
54   return CPU;
55 }
56 
createHexagonMCInstrInfo()57 MCInstrInfo *llvm::createHexagonMCInstrInfo() {
58   MCInstrInfo *X = new MCInstrInfo();
59   InitHexagonMCInstrInfo(X);
60   return X;
61 }
62 
createHexagonMCRegisterInfo(const Triple & TT)63 static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) {
64   MCRegisterInfo *X = new MCRegisterInfo();
65   InitHexagonMCRegisterInfo(X, Hexagon::R0);
66   return X;
67 }
68 
69 static MCSubtargetInfo *
createHexagonMCSubtargetInfo(const Triple & TT,StringRef CPU,StringRef FS)70 createHexagonMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
71   CPU = HEXAGON_MC::selectHexagonCPU(TT, CPU);
72   return createHexagonMCSubtargetInfoImpl(TT, CPU, FS);
73 }
74 
75 namespace {
76 class HexagonTargetAsmStreamer : public HexagonTargetStreamer {
77 public:
HexagonTargetAsmStreamer(MCStreamer & S,formatted_raw_ostream &,bool,MCInstPrinter &)78   HexagonTargetAsmStreamer(MCStreamer &S,
79                            formatted_raw_ostream &, bool,
80                            MCInstPrinter &)
81       : HexagonTargetStreamer(S) {}
prettyPrintAsm(MCInstPrinter & InstPrinter,raw_ostream & OS,const MCInst & Inst,const MCSubtargetInfo & STI)82   void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS,
83                       const MCInst &Inst, const MCSubtargetInfo &STI) override {
84     assert(HexagonMCInstrInfo::isBundle(Inst));
85     assert(HexagonMCInstrInfo::bundleSize(Inst) <= HEXAGON_PACKET_SIZE);
86     std::string Buffer;
87     {
88       raw_string_ostream TempStream(Buffer);
89       InstPrinter.printInst(&Inst, TempStream, "", STI);
90     }
91     StringRef Contents(Buffer);
92     auto PacketBundle = Contents.rsplit('\n');
93     auto HeadTail = PacketBundle.first.split('\n');
94     StringRef Separator = "\n";
95     StringRef Indent = "\t\t";
96     OS << "\t{\n";
97     while (!HeadTail.first.empty()) {
98       StringRef InstTxt;
99       auto Duplex = HeadTail.first.split('\v');
100       if (!Duplex.second.empty()) {
101         OS << Indent << Duplex.first << Separator;
102         InstTxt = Duplex.second;
103       } else if (!HeadTail.first.trim().startswith("immext")) {
104         InstTxt = Duplex.first;
105       }
106       if (!InstTxt.empty())
107         OS << Indent << InstTxt << Separator;
108       HeadTail = HeadTail.second.split('\n');
109     }
110     OS << "\t}" << PacketBundle.second;
111   }
112 };
113 }
114 
115 namespace {
116 class HexagonTargetELFStreamer : public HexagonTargetStreamer {
117 public:
getStreamer()118   MCELFStreamer &getStreamer() {
119     return static_cast<MCELFStreamer &>(Streamer);
120   }
HexagonTargetELFStreamer(MCStreamer & S,MCSubtargetInfo const & STI)121   HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI)
122       : HexagonTargetStreamer(S) {
123     auto Bits = STI.getFeatureBits();
124     unsigned Flags;
125     if (Bits.to_ullong() & llvm::Hexagon::ArchV5)
126       Flags = ELF::EF_HEXAGON_MACH_V5;
127     else
128       Flags = ELF::EF_HEXAGON_MACH_V4;
129     getStreamer().getAssembler().setELFHeaderEFlags(Flags);
130   }
EmitCommonSymbolSorted(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment,unsigned AccessSize)131   void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
132                               unsigned ByteAlignment,
133                               unsigned AccessSize) override {
134     HexagonMCELFStreamer &HexagonELFStreamer =
135         static_cast<HexagonMCELFStreamer &>(getStreamer());
136     HexagonELFStreamer.HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment,
137                                                  AccessSize);
138   }
EmitLocalCommonSymbolSorted(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment,unsigned AccessSize)139   void EmitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size,
140                                    unsigned ByteAlignment,
141                                    unsigned AccessSize) override {
142     HexagonMCELFStreamer &HexagonELFStreamer =
143         static_cast<HexagonMCELFStreamer &>(getStreamer());
144     HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol(
145         Symbol, Size, ByteAlignment, AccessSize);
146   }
147 };
148 }
149 
createHexagonMCAsmInfo(const MCRegisterInfo & MRI,const Triple & TT)150 static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI,
151                                          const Triple &TT) {
152   MCAsmInfo *MAI = new HexagonMCAsmInfo(TT);
153 
154   // VirtualFP = (R30 + #0).
155   MCCFIInstruction Inst =
156       MCCFIInstruction::createDefCfa(nullptr, Hexagon::R30, 0);
157   MAI->addInitialFrameState(Inst);
158 
159   return MAI;
160 }
161 
createHexagonMCCodeGenInfo(const Triple & TT,Reloc::Model RM,CodeModel::Model CM,CodeGenOpt::Level OL)162 static MCCodeGenInfo *createHexagonMCCodeGenInfo(const Triple &TT,
163                                                  Reloc::Model RM,
164                                                  CodeModel::Model CM,
165                                                  CodeGenOpt::Level OL) {
166   MCCodeGenInfo *X = new MCCodeGenInfo();
167   if (RM == Reloc::Default)
168     RM = Reloc::Static;
169   X->initMCCodeGenInfo(RM, CM, OL);
170   return X;
171 }
172 
createHexagonMCInstPrinter(const Triple & T,unsigned SyntaxVariant,const MCAsmInfo & MAI,const MCInstrInfo & MII,const MCRegisterInfo & MRI)173 static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T,
174                                                  unsigned SyntaxVariant,
175                                                  const MCAsmInfo &MAI,
176                                                  const MCInstrInfo &MII,
177                                                  const MCRegisterInfo &MRI) {
178   if (SyntaxVariant == 0)
179     return (new HexagonInstPrinter(MAI, MII, MRI));
180   else
181     return nullptr;
182 }
183 
createMCAsmTargetStreamer(MCStreamer & S,formatted_raw_ostream & OS,MCInstPrinter * InstPrint,bool IsVerboseAsm)184 static MCTargetStreamer *createMCAsmTargetStreamer(MCStreamer &S,
185                                                    formatted_raw_ostream &OS,
186                                                    MCInstPrinter *InstPrint,
187                                                    bool IsVerboseAsm) {
188   return new HexagonTargetAsmStreamer(S,  OS, IsVerboseAsm, *InstPrint);
189 }
190 
createMCStreamer(Triple const & T,MCContext & Context,MCAsmBackend & MAB,raw_pwrite_stream & OS,MCCodeEmitter * Emitter,bool RelaxAll)191 static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context,
192                                     MCAsmBackend &MAB, raw_pwrite_stream &OS,
193                                     MCCodeEmitter *Emitter, bool RelaxAll) {
194   return createHexagonELFStreamer(Context, MAB, OS, Emitter);
195 }
196 
197 static MCTargetStreamer *
createHexagonObjectTargetStreamer(MCStreamer & S,MCSubtargetInfo const & STI)198 createHexagonObjectTargetStreamer(MCStreamer &S, MCSubtargetInfo const &STI) {
199   return new HexagonTargetELFStreamer(S, STI);
200 }
201 
202 // Force static initialization.
LLVMInitializeHexagonTargetMC()203 extern "C" void LLVMInitializeHexagonTargetMC() {
204   // Register the MC asm info.
205   RegisterMCAsmInfoFn X(TheHexagonTarget, createHexagonMCAsmInfo);
206 
207   // Register the MC codegen info.
208   TargetRegistry::RegisterMCCodeGenInfo(TheHexagonTarget,
209                                         createHexagonMCCodeGenInfo);
210 
211   // Register the MC instruction info.
212   TargetRegistry::RegisterMCInstrInfo(TheHexagonTarget,
213                                       createHexagonMCInstrInfo);
214 
215   // Register the MC register info.
216   TargetRegistry::RegisterMCRegInfo(TheHexagonTarget,
217                                     createHexagonMCRegisterInfo);
218 
219   // Register the MC subtarget info.
220   TargetRegistry::RegisterMCSubtargetInfo(TheHexagonTarget,
221                                           createHexagonMCSubtargetInfo);
222 
223   // Register the MC Code Emitter
224   TargetRegistry::RegisterMCCodeEmitter(TheHexagonTarget,
225                                         createHexagonMCCodeEmitter);
226 
227   // Register the asm backend
228   TargetRegistry::RegisterMCAsmBackend(TheHexagonTarget,
229                                        createHexagonAsmBackend);
230 
231   // Register the obj streamer
232   TargetRegistry::RegisterELFStreamer(TheHexagonTarget, createMCStreamer);
233 
234   // Register the asm streamer
235   TargetRegistry::RegisterAsmTargetStreamer(TheHexagonTarget,
236                                             createMCAsmTargetStreamer);
237 
238   // Register the MC Inst Printer
239   TargetRegistry::RegisterMCInstPrinter(TheHexagonTarget,
240                                         createHexagonMCInstPrinter);
241 
242   TargetRegistry::RegisterObjectTargetStreamer(
243       TheHexagonTarget, createHexagonObjectTargetStreamer);
244 }
245