1 //===-- HexagonMCTargetDesc.cpp - Hexagon 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 Hexagon specific target descriptions. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/HexagonMCTargetDesc.h" 14 #include "HexagonDepArch.h" 15 #include "HexagonTargetStreamer.h" 16 #include "MCTargetDesc/HexagonInstPrinter.h" 17 #include "MCTargetDesc/HexagonMCAsmInfo.h" 18 #include "MCTargetDesc/HexagonMCELFStreamer.h" 19 #include "MCTargetDesc/HexagonMCInstrInfo.h" 20 #include "TargetInfo/HexagonTargetInfo.h" 21 #include "llvm/ADT/StringExtras.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/BinaryFormat/ELF.h" 24 #include "llvm/MC/MCAsmBackend.h" 25 #include "llvm/MC/MCCodeEmitter.h" 26 #include "llvm/MC/MCContext.h" 27 #include "llvm/MC/MCDwarf.h" 28 #include "llvm/MC/MCELFStreamer.h" 29 #include "llvm/MC/MCInstrAnalysis.h" 30 #include "llvm/MC/MCInstrInfo.h" 31 #include "llvm/MC/MCObjectWriter.h" 32 #include "llvm/MC/MCRegisterInfo.h" 33 #include "llvm/MC/MCStreamer.h" 34 #include "llvm/MC/MCSubtargetInfo.h" 35 #include "llvm/Support/ErrorHandling.h" 36 #include "llvm/Support/TargetRegistry.h" 37 #include "llvm/Support/raw_ostream.h" 38 #include <cassert> 39 #include <cstdint> 40 #include <new> 41 #include <string> 42 43 using namespace llvm; 44 45 #define GET_INSTRINFO_MC_DESC 46 #include "HexagonGenInstrInfo.inc" 47 48 #define GET_SUBTARGETINFO_MC_DESC 49 #include "HexagonGenSubtargetInfo.inc" 50 51 #define GET_REGINFO_MC_DESC 52 #include "HexagonGenRegisterInfo.inc" 53 54 cl::opt<bool> llvm::HexagonDisableCompound 55 ("mno-compound", 56 cl::desc("Disable looking for compound instructions for Hexagon")); 57 58 cl::opt<bool> llvm::HexagonDisableDuplex 59 ("mno-pairing", 60 cl::desc("Disable looking for duplex instructions for Hexagon")); 61 62 namespace { // These flags are to be deprecated 63 cl::opt<bool> MV5("mv5", cl::Hidden, cl::desc("Build for Hexagon V5"), 64 cl::init(false)); 65 cl::opt<bool> MV55("mv55", cl::Hidden, cl::desc("Build for Hexagon V55"), 66 cl::init(false)); 67 cl::opt<bool> MV60("mv60", cl::Hidden, cl::desc("Build for Hexagon V60"), 68 cl::init(false)); 69 cl::opt<bool> MV62("mv62", cl::Hidden, cl::desc("Build for Hexagon V62"), 70 cl::init(false)); 71 cl::opt<bool> MV65("mv65", cl::Hidden, cl::desc("Build for Hexagon V65"), 72 cl::init(false)); 73 cl::opt<bool> MV66("mv66", cl::Hidden, cl::desc("Build for Hexagon V66"), 74 cl::init(false)); 75 76 cl::opt<Hexagon::ArchEnum> 77 EnableHVX("mhvx", 78 cl::desc("Enable Hexagon Vector eXtensions"), 79 cl::values( 80 clEnumValN(Hexagon::ArchEnum::V60, "v60", "Build for HVX v60"), 81 clEnumValN(Hexagon::ArchEnum::V62, "v62", "Build for HVX v62"), 82 clEnumValN(Hexagon::ArchEnum::V65, "v65", "Build for HVX v65"), 83 clEnumValN(Hexagon::ArchEnum::V66, "v66", "Build for HVX v66"), 84 // Sentinel for no value specified. 85 clEnumValN(Hexagon::ArchEnum::Generic, "", "")), 86 // Sentinel for flag not present. 87 cl::init(Hexagon::ArchEnum::NoArch), cl::ValueOptional); 88 } // namespace 89 90 static cl::opt<bool> 91 DisableHVX("mno-hvx", cl::Hidden, 92 cl::desc("Disable Hexagon Vector eXtensions")); 93 94 95 static StringRef DefaultArch = "hexagonv60"; 96 97 static StringRef HexagonGetArchVariant() { 98 if (MV5) 99 return "hexagonv5"; 100 if (MV55) 101 return "hexagonv55"; 102 if (MV60) 103 return "hexagonv60"; 104 if (MV62) 105 return "hexagonv62"; 106 if (MV65) 107 return "hexagonv65"; 108 if (MV66) 109 return "hexagonv66"; 110 return ""; 111 } 112 113 StringRef Hexagon_MC::selectHexagonCPU(StringRef CPU) { 114 StringRef ArchV = HexagonGetArchVariant(); 115 if (!ArchV.empty() && !CPU.empty()) { 116 if (ArchV != CPU) 117 report_fatal_error("conflicting architectures specified."); 118 return CPU; 119 } 120 if (ArchV.empty()) { 121 if (CPU.empty()) 122 CPU = DefaultArch; 123 return CPU; 124 } 125 return ArchV; 126 } 127 128 unsigned llvm::HexagonGetLastSlot() { return HexagonItinerariesV5FU::SLOT3; } 129 130 namespace { 131 132 class HexagonTargetAsmStreamer : public HexagonTargetStreamer { 133 public: 134 HexagonTargetAsmStreamer(MCStreamer &S, 135 formatted_raw_ostream &OS, 136 bool isVerboseAsm, 137 MCInstPrinter &IP) 138 : HexagonTargetStreamer(S) {} 139 140 void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS, 141 const MCInst &Inst, const MCSubtargetInfo &STI) override { 142 assert(HexagonMCInstrInfo::isBundle(Inst)); 143 assert(HexagonMCInstrInfo::bundleSize(Inst) <= HEXAGON_PACKET_SIZE); 144 std::string Buffer; 145 { 146 raw_string_ostream TempStream(Buffer); 147 InstPrinter.printInst(&Inst, TempStream, "", STI); 148 } 149 StringRef Contents(Buffer); 150 auto PacketBundle = Contents.rsplit('\n'); 151 auto HeadTail = PacketBundle.first.split('\n'); 152 StringRef Separator = "\n"; 153 StringRef Indent = "\t"; 154 OS << "\t{\n"; 155 while (!HeadTail.first.empty()) { 156 StringRef InstTxt; 157 auto Duplex = HeadTail.first.split('\v'); 158 if (!Duplex.second.empty()) { 159 OS << Indent << Duplex.first << Separator; 160 InstTxt = Duplex.second; 161 } else if (!HeadTail.first.trim().startswith("immext")) { 162 InstTxt = Duplex.first; 163 } 164 if (!InstTxt.empty()) 165 OS << Indent << InstTxt << Separator; 166 HeadTail = HeadTail.second.split('\n'); 167 } 168 169 if (HexagonMCInstrInfo::isMemReorderDisabled(Inst)) 170 OS << "\n\t} :mem_noshuf" << PacketBundle.second; 171 else 172 OS << "\t}" << PacketBundle.second; 173 } 174 }; 175 176 class HexagonTargetELFStreamer : public HexagonTargetStreamer { 177 public: 178 MCELFStreamer &getStreamer() { 179 return static_cast<MCELFStreamer &>(Streamer); 180 } 181 HexagonTargetELFStreamer(MCStreamer &S, MCSubtargetInfo const &STI) 182 : HexagonTargetStreamer(S) { 183 MCAssembler &MCA = getStreamer().getAssembler(); 184 MCA.setELFHeaderEFlags(Hexagon_MC::GetELFFlags(STI)); 185 } 186 187 188 void EmitCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, 189 unsigned ByteAlignment, 190 unsigned AccessSize) override { 191 HexagonMCELFStreamer &HexagonELFStreamer = 192 static_cast<HexagonMCELFStreamer &>(getStreamer()); 193 HexagonELFStreamer.HexagonMCEmitCommonSymbol(Symbol, Size, ByteAlignment, 194 AccessSize); 195 } 196 197 void EmitLocalCommonSymbolSorted(MCSymbol *Symbol, uint64_t Size, 198 unsigned ByteAlignment, 199 unsigned AccessSize) override { 200 HexagonMCELFStreamer &HexagonELFStreamer = 201 static_cast<HexagonMCELFStreamer &>(getStreamer()); 202 HexagonELFStreamer.HexagonMCEmitLocalCommonSymbol( 203 Symbol, Size, ByteAlignment, AccessSize); 204 } 205 }; 206 207 } // end anonymous namespace 208 209 llvm::MCInstrInfo *llvm::createHexagonMCInstrInfo() { 210 MCInstrInfo *X = new MCInstrInfo(); 211 InitHexagonMCInstrInfo(X); 212 return X; 213 } 214 215 static MCRegisterInfo *createHexagonMCRegisterInfo(const Triple &TT) { 216 MCRegisterInfo *X = new MCRegisterInfo(); 217 InitHexagonMCRegisterInfo(X, Hexagon::R31); 218 return X; 219 } 220 221 static MCAsmInfo *createHexagonMCAsmInfo(const MCRegisterInfo &MRI, 222 const Triple &TT) { 223 MCAsmInfo *MAI = new HexagonMCAsmInfo(TT); 224 225 // VirtualFP = (R30 + #0). 226 MCCFIInstruction Inst = 227 MCCFIInstruction::createDefCfa(nullptr, 228 MRI.getDwarfRegNum(Hexagon::R30, true), 0); 229 MAI->addInitialFrameState(Inst); 230 231 return MAI; 232 } 233 234 static MCInstPrinter *createHexagonMCInstPrinter(const Triple &T, 235 unsigned SyntaxVariant, 236 const MCAsmInfo &MAI, 237 const MCInstrInfo &MII, 238 const MCRegisterInfo &MRI) 239 { 240 if (SyntaxVariant == 0) 241 return new HexagonInstPrinter(MAI, MII, MRI); 242 else 243 return nullptr; 244 } 245 246 static MCTargetStreamer * 247 createMCAsmTargetStreamer(MCStreamer &S, formatted_raw_ostream &OS, 248 MCInstPrinter *IP, bool IsVerboseAsm) { 249 return new HexagonTargetAsmStreamer(S, OS, IsVerboseAsm, *IP); 250 } 251 252 static MCStreamer *createMCStreamer(Triple const &T, MCContext &Context, 253 std::unique_ptr<MCAsmBackend> &&MAB, 254 std::unique_ptr<MCObjectWriter> &&OW, 255 std::unique_ptr<MCCodeEmitter> &&Emitter, 256 bool RelaxAll) { 257 return createHexagonELFStreamer(T, Context, std::move(MAB), std::move(OW), 258 std::move(Emitter)); 259 } 260 261 static MCTargetStreamer * 262 createHexagonObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { 263 return new HexagonTargetELFStreamer(S, STI); 264 } 265 266 static void LLVM_ATTRIBUTE_UNUSED clearFeature(MCSubtargetInfo* STI, uint64_t F) { 267 if (STI->getFeatureBits()[F]) 268 STI->ToggleFeature(F); 269 } 270 271 static bool LLVM_ATTRIBUTE_UNUSED checkFeature(MCSubtargetInfo* STI, uint64_t F) { 272 return STI->getFeatureBits()[F]; 273 } 274 275 namespace { 276 std::string selectHexagonFS(StringRef CPU, StringRef FS) { 277 SmallVector<StringRef, 3> Result; 278 if (!FS.empty()) 279 Result.push_back(FS); 280 281 switch (EnableHVX) { 282 case Hexagon::ArchEnum::V5: 283 case Hexagon::ArchEnum::V55: 284 break; 285 case Hexagon::ArchEnum::V60: 286 Result.push_back("+hvxv60"); 287 break; 288 case Hexagon::ArchEnum::V62: 289 Result.push_back("+hvxv62"); 290 break; 291 case Hexagon::ArchEnum::V65: 292 Result.push_back("+hvxv65"); 293 break; 294 case Hexagon::ArchEnum::V66: 295 Result.push_back("+hvxv66"); 296 break; 297 case Hexagon::ArchEnum::Generic:{ 298 Result.push_back(StringSwitch<StringRef>(CPU) 299 .Case("hexagonv60", "+hvxv60") 300 .Case("hexagonv62", "+hvxv62") 301 .Case("hexagonv65", "+hvxv65") 302 .Case("hexagonv66", "+hvxv66")); 303 break; 304 } 305 case Hexagon::ArchEnum::NoArch: 306 // Sentinal if -mhvx isn't specified 307 break; 308 } 309 return join(Result.begin(), Result.end(), ","); 310 } 311 } 312 313 static bool isCPUValid(std::string CPU) 314 { 315 std::vector<std::string> table { 316 "generic", "hexagonv5", "hexagonv55", "hexagonv60", 317 "hexagonv62", "hexagonv65", "hexagonv66", 318 }; 319 320 return std::find(table.begin(), table.end(), CPU) != table.end(); 321 } 322 323 namespace { 324 std::pair<std::string, std::string> selectCPUAndFS(StringRef CPU, 325 StringRef FS) { 326 std::pair<std::string, std::string> Result; 327 Result.first = Hexagon_MC::selectHexagonCPU(CPU); 328 Result.second = selectHexagonFS(Result.first, FS); 329 return Result; 330 } 331 } 332 333 FeatureBitset Hexagon_MC::completeHVXFeatures(const FeatureBitset &S) { 334 using namespace Hexagon; 335 // Make sure that +hvx-length turns hvx on, and that "hvx" alone 336 // turns on hvxvNN, corresponding to the existing ArchVNN. 337 FeatureBitset FB = S; 338 unsigned CpuArch = ArchV5; 339 for (unsigned F : {ArchV66, ArchV65, ArchV62, ArchV60, ArchV55, ArchV5}) { 340 if (!FB.test(F)) 341 continue; 342 CpuArch = F; 343 break; 344 } 345 bool UseHvx = false; 346 for (unsigned F : {ExtensionHVX, ExtensionHVX64B, ExtensionHVX128B}) { 347 if (!FB.test(F)) 348 continue; 349 UseHvx = true; 350 break; 351 } 352 bool HasHvxVer = false; 353 for (unsigned F : {ExtensionHVXV60, ExtensionHVXV62, ExtensionHVXV65, 354 ExtensionHVXV66}) { 355 if (!FB.test(F)) 356 continue; 357 HasHvxVer = true; 358 UseHvx = true; 359 break; 360 } 361 362 if (!UseHvx || HasHvxVer) 363 return FB; 364 365 // HasHvxVer is false, and UseHvx is true. 366 switch (CpuArch) { 367 case ArchV66: 368 FB.set(ExtensionHVXV66); 369 LLVM_FALLTHROUGH; 370 case ArchV65: 371 FB.set(ExtensionHVXV65); 372 LLVM_FALLTHROUGH; 373 case ArchV62: 374 FB.set(ExtensionHVXV62); 375 LLVM_FALLTHROUGH; 376 case ArchV60: 377 FB.set(ExtensionHVXV60); 378 break; 379 } 380 return FB; 381 } 382 383 MCSubtargetInfo *Hexagon_MC::createHexagonMCSubtargetInfo(const Triple &TT, 384 StringRef CPU, 385 StringRef FS) { 386 std::pair<std::string, std::string> Features = selectCPUAndFS(CPU, FS); 387 StringRef CPUName = Features.first; 388 StringRef ArchFS = Features.second; 389 390 if (!isCPUValid(CPUName.str())) { 391 errs() << "error: invalid CPU \"" << CPUName.str().c_str() 392 << "\" specified\n"; 393 return nullptr; 394 } 395 396 MCSubtargetInfo *X = createHexagonMCSubtargetInfoImpl(TT, CPUName, ArchFS); 397 if (HexagonDisableDuplex) { 398 llvm::FeatureBitset Features = X->getFeatureBits(); 399 X->setFeatureBits(Features.reset(Hexagon::FeatureDuplex)); 400 } 401 402 X->setFeatureBits(completeHVXFeatures(X->getFeatureBits())); 403 return X; 404 } 405 406 unsigned Hexagon_MC::GetELFFlags(const MCSubtargetInfo &STI) { 407 static std::map<StringRef,unsigned> ElfFlags = { 408 {"hexagonv5", ELF::EF_HEXAGON_MACH_V5}, 409 {"hexagonv55", ELF::EF_HEXAGON_MACH_V55}, 410 {"hexagonv60", ELF::EF_HEXAGON_MACH_V60}, 411 {"hexagonv62", ELF::EF_HEXAGON_MACH_V62}, 412 {"hexagonv65", ELF::EF_HEXAGON_MACH_V65}, 413 {"hexagonv66", ELF::EF_HEXAGON_MACH_V66}, 414 }; 415 416 auto F = ElfFlags.find(STI.getCPU()); 417 assert(F != ElfFlags.end() && "Unrecognized Architecture"); 418 return F->second; 419 } 420 421 namespace { 422 class HexagonMCInstrAnalysis : public MCInstrAnalysis { 423 public: 424 HexagonMCInstrAnalysis(MCInstrInfo const *Info) : MCInstrAnalysis(Info) {} 425 426 bool isUnconditionalBranch(MCInst const &Inst) const override { 427 //assert(!HexagonMCInstrInfo::isBundle(Inst)); 428 return MCInstrAnalysis::isUnconditionalBranch(Inst); 429 } 430 431 bool isConditionalBranch(MCInst const &Inst) const override { 432 //assert(!HexagonMCInstrInfo::isBundle(Inst)); 433 return MCInstrAnalysis::isConditionalBranch(Inst); 434 } 435 436 bool evaluateBranch(MCInst const &Inst, uint64_t Addr, 437 uint64_t Size, uint64_t &Target) const override { 438 //assert(!HexagonMCInstrInfo::isBundle(Inst)); 439 if(!HexagonMCInstrInfo::isExtendable(*Info, Inst)) 440 return false; 441 auto const &Extended(HexagonMCInstrInfo::getExtendableOperand(*Info, Inst)); 442 assert(Extended.isExpr()); 443 int64_t Value; 444 if(!Extended.getExpr()->evaluateAsAbsolute(Value)) 445 return false; 446 Target = Value; 447 return true; 448 } 449 }; 450 } 451 452 static MCInstrAnalysis *createHexagonMCInstrAnalysis(const MCInstrInfo *Info) { 453 return new HexagonMCInstrAnalysis(Info); 454 } 455 456 // Force static initialization. 457 extern "C" void LLVMInitializeHexagonTargetMC() { 458 // Register the MC asm info. 459 RegisterMCAsmInfoFn X(getTheHexagonTarget(), createHexagonMCAsmInfo); 460 461 // Register the MC instruction info. 462 TargetRegistry::RegisterMCInstrInfo(getTheHexagonTarget(), 463 createHexagonMCInstrInfo); 464 465 // Register the MC register info. 466 TargetRegistry::RegisterMCRegInfo(getTheHexagonTarget(), 467 createHexagonMCRegisterInfo); 468 469 // Register the MC subtarget info. 470 TargetRegistry::RegisterMCSubtargetInfo(getTheHexagonTarget(), 471 Hexagon_MC::createHexagonMCSubtargetInfo); 472 473 // Register the MC Code Emitter 474 TargetRegistry::RegisterMCCodeEmitter(getTheHexagonTarget(), 475 createHexagonMCCodeEmitter); 476 477 // Register the asm backend 478 TargetRegistry::RegisterMCAsmBackend(getTheHexagonTarget(), 479 createHexagonAsmBackend); 480 481 482 // Register the MC instruction analyzer. 483 TargetRegistry::RegisterMCInstrAnalysis(getTheHexagonTarget(), 484 createHexagonMCInstrAnalysis); 485 486 // Register the obj streamer 487 TargetRegistry::RegisterELFStreamer(getTheHexagonTarget(), 488 createMCStreamer); 489 490 // Register the obj target streamer 491 TargetRegistry::RegisterObjectTargetStreamer(getTheHexagonTarget(), 492 createHexagonObjectTargetStreamer); 493 494 // Register the asm streamer 495 TargetRegistry::RegisterAsmTargetStreamer(getTheHexagonTarget(), 496 createMCAsmTargetStreamer); 497 498 // Register the MC Inst Printer 499 TargetRegistry::RegisterMCInstPrinter(getTheHexagonTarget(), 500 createHexagonMCInstPrinter); 501 } 502