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