786 lines · cpp
1//===-- HexagonAsmBackend.cpp - Hexagon Assembler Backend -----------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "HexagonFixupKinds.h"10#include "MCTargetDesc/HexagonBaseInfo.h"11#include "MCTargetDesc/HexagonMCChecker.h"12#include "MCTargetDesc/HexagonMCCodeEmitter.h"13#include "MCTargetDesc/HexagonMCInstrInfo.h"14#include "MCTargetDesc/HexagonMCShuffler.h"15#include "MCTargetDesc/HexagonMCTargetDesc.h"16#include "llvm/MC/MCAsmBackend.h"17#include "llvm/MC/MCAssembler.h"18#include "llvm/MC/MCContext.h"19#include "llvm/MC/MCELFObjectWriter.h"20#include "llvm/MC/MCInstrInfo.h"21#include "llvm/MC/MCObjectWriter.h"22#include "llvm/MC/MCSubtargetInfo.h"23#include "llvm/MC/TargetRegistry.h"24#include "llvm/Support/Debug.h"25#include "llvm/Support/EndianStream.h"26 27#include <sstream>28 29using namespace llvm;30using namespace Hexagon;31 32#define DEBUG_TYPE "hexagon-asm-backend"33 34static cl::opt<bool> DisableFixup35 ("mno-fixup", cl::desc("Disable fixing up resolved relocations for Hexagon"));36 37namespace {38 39class HexagonAsmBackend : public MCAsmBackend {40 uint8_t OSABI;41 StringRef CPU;42 mutable uint64_t relaxedCnt;43 mutable MCInst RelaxedMCB;44 std::unique_ptr <MCInstrInfo> MCII;45 std::unique_ptr <MCInst *> RelaxTarget;46 MCInst * Extender;47 unsigned MaxPacketSize;48 49 void ReplaceInstruction(MCCodeEmitter &E, MCFragment &RF, MCInst &HMB) const {50 SmallVector<MCFixup, 4> Fixups;51 SmallString<256> Code;52 E.encodeInstruction(HMB, Code, Fixups, *RF.getSubtargetInfo());53 54 // Update the fragment.55 RF.setInst(HMB);56 RF.setVarContents(Code);57 RF.setVarFixups(Fixups);58 }59 60public:61 HexagonAsmBackend(const Target &T, const Triple &TT, uint8_t OSABI,62 StringRef CPU)63 : MCAsmBackend(llvm::endianness::little), OSABI(OSABI), CPU(CPU),64 relaxedCnt(0), MCII(T.createMCInstrInfo()), RelaxTarget(new MCInst *),65 Extender(nullptr), MaxPacketSize(HexagonMCInstrInfo::packetSize(CPU)) {}66 67 std::unique_ptr<MCObjectTargetWriter>68 createObjectTargetWriter() const override {69 return createHexagonELFObjectWriter(OSABI, CPU);70 }71 72 void setExtender(MCContext &Context) const {73 if (Extender == nullptr)74 const_cast<HexagonAsmBackend *>(this)->Extender = Context.createMCInst();75 }76 77 MCInst *takeExtender() const {78 assert(Extender != nullptr);79 MCInst * Result = Extender;80 const_cast<HexagonAsmBackend *>(this)->Extender = nullptr;81 return Result;82 }83 84 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override {85 // clang-format off86 const static MCFixupKindInfo Infos[Hexagon::NumTargetFixupKinds] = {87 // This table *must* be in same the order of fixup_* kinds in88 // HexagonFixupKinds.h.89 //90 // namei offset bits flags91 { "fixup_Hexagon_B22_PCREL", 0, 32, 0 },92 { "fixup_Hexagon_B15_PCREL", 0, 32, 0 },93 { "fixup_Hexagon_B7_PCREL", 0, 32, 0 },94 { "fixup_Hexagon_LO16", 0, 32, 0 },95 { "fixup_Hexagon_HI16", 0, 32, 0 },96 { "fixup_Hexagon_32", 0, 32, 0 },97 { "fixup_Hexagon_16", 0, 32, 0 },98 { "fixup_Hexagon_8", 0, 32, 0 },99 { "fixup_Hexagon_GPREL16_0", 0, 32, 0 },100 { "fixup_Hexagon_GPREL16_1", 0, 32, 0 },101 { "fixup_Hexagon_GPREL16_2", 0, 32, 0 },102 { "fixup_Hexagon_GPREL16_3", 0, 32, 0 },103 { "fixup_Hexagon_HL16", 0, 32, 0 },104 { "fixup_Hexagon_B13_PCREL", 0, 32, 0 },105 { "fixup_Hexagon_B9_PCREL", 0, 32, 0 },106 { "fixup_Hexagon_B32_PCREL_X", 0, 32, 0 },107 { "fixup_Hexagon_32_6_X", 0, 32, 0 },108 { "fixup_Hexagon_B22_PCREL_X", 0, 32, 0 },109 { "fixup_Hexagon_B15_PCREL_X", 0, 32, 0 },110 { "fixup_Hexagon_B13_PCREL_X", 0, 32, 0 },111 { "fixup_Hexagon_B9_PCREL_X", 0, 32, 0 },112 { "fixup_Hexagon_B7_PCREL_X", 0, 32, 0 },113 { "fixup_Hexagon_16_X", 0, 32, 0 },114 { "fixup_Hexagon_12_X", 0, 32, 0 },115 { "fixup_Hexagon_11_X", 0, 32, 0 },116 { "fixup_Hexagon_10_X", 0, 32, 0 },117 { "fixup_Hexagon_9_X", 0, 32, 0 },118 { "fixup_Hexagon_8_X", 0, 32, 0 },119 { "fixup_Hexagon_7_X", 0, 32, 0 },120 { "fixup_Hexagon_6_X", 0, 32, 0 },121 { "fixup_Hexagon_32_PCREL", 0, 32, 0 },122 { "fixup_Hexagon_COPY", 0, 32, 0 },123 { "fixup_Hexagon_GLOB_DAT", 0, 32, 0 },124 { "fixup_Hexagon_JMP_SLOT", 0, 32, 0 },125 { "fixup_Hexagon_RELATIVE", 0, 32, 0 },126 { "fixup_Hexagon_PLT_B22_PCREL", 0, 32, 0 },127 { "fixup_Hexagon_GOTREL_LO16", 0, 32, 0 },128 { "fixup_Hexagon_GOTREL_HI16", 0, 32, 0 },129 { "fixup_Hexagon_GOTREL_32", 0, 32, 0 },130 { "fixup_Hexagon_GOT_LO16", 0, 32, 0 },131 { "fixup_Hexagon_GOT_HI16", 0, 32, 0 },132 { "fixup_Hexagon_GOT_32", 0, 32, 0 },133 { "fixup_Hexagon_GOT_16", 0, 32, 0 },134 { "fixup_Hexagon_DTPMOD_32", 0, 32, 0 },135 { "fixup_Hexagon_DTPREL_LO16", 0, 32, 0 },136 { "fixup_Hexagon_DTPREL_HI16", 0, 32, 0 },137 { "fixup_Hexagon_DTPREL_32", 0, 32, 0 },138 { "fixup_Hexagon_DTPREL_16", 0, 32, 0 },139 { "fixup_Hexagon_GD_PLT_B22_PCREL",0, 32, 0 },140 { "fixup_Hexagon_LD_PLT_B22_PCREL",0, 32, 0 },141 { "fixup_Hexagon_GD_GOT_LO16", 0, 32, 0 },142 { "fixup_Hexagon_GD_GOT_HI16", 0, 32, 0 },143 { "fixup_Hexagon_GD_GOT_32", 0, 32, 0 },144 { "fixup_Hexagon_GD_GOT_16", 0, 32, 0 },145 { "fixup_Hexagon_LD_GOT_LO16", 0, 32, 0 },146 { "fixup_Hexagon_LD_GOT_HI16", 0, 32, 0 },147 { "fixup_Hexagon_LD_GOT_32", 0, 32, 0 },148 { "fixup_Hexagon_LD_GOT_16", 0, 32, 0 },149 { "fixup_Hexagon_IE_LO16", 0, 32, 0 },150 { "fixup_Hexagon_IE_HI16", 0, 32, 0 },151 { "fixup_Hexagon_IE_32", 0, 32, 0 },152 { "fixup_Hexagon_IE_16", 0, 32, 0 },153 { "fixup_Hexagon_IE_GOT_LO16", 0, 32, 0 },154 { "fixup_Hexagon_IE_GOT_HI16", 0, 32, 0 },155 { "fixup_Hexagon_IE_GOT_32", 0, 32, 0 },156 { "fixup_Hexagon_IE_GOT_16", 0, 32, 0 },157 { "fixup_Hexagon_TPREL_LO16", 0, 32, 0 },158 { "fixup_Hexagon_TPREL_HI16", 0, 32, 0 },159 { "fixup_Hexagon_TPREL_32", 0, 32, 0 },160 { "fixup_Hexagon_TPREL_16", 0, 32, 0 },161 { "fixup_Hexagon_6_PCREL_X", 0, 32, 0 },162 { "fixup_Hexagon_GOTREL_32_6_X", 0, 32, 0 },163 { "fixup_Hexagon_GOTREL_16_X", 0, 32, 0 },164 { "fixup_Hexagon_GOTREL_11_X", 0, 32, 0 },165 { "fixup_Hexagon_GOT_32_6_X", 0, 32, 0 },166 { "fixup_Hexagon_GOT_16_X", 0, 32, 0 },167 { "fixup_Hexagon_GOT_11_X", 0, 32, 0 },168 { "fixup_Hexagon_DTPREL_32_6_X", 0, 32, 0 },169 { "fixup_Hexagon_DTPREL_16_X", 0, 32, 0 },170 { "fixup_Hexagon_DTPREL_11_X", 0, 32, 0 },171 { "fixup_Hexagon_GD_GOT_32_6_X", 0, 32, 0 },172 { "fixup_Hexagon_GD_GOT_16_X", 0, 32, 0 },173 { "fixup_Hexagon_GD_GOT_11_X", 0, 32, 0 },174 { "fixup_Hexagon_LD_GOT_32_6_X", 0, 32, 0 },175 { "fixup_Hexagon_LD_GOT_16_X", 0, 32, 0 },176 { "fixup_Hexagon_LD_GOT_11_X", 0, 32, 0 },177 { "fixup_Hexagon_IE_32_6_X", 0, 32, 0 },178 { "fixup_Hexagon_IE_16_X", 0, 32, 0 },179 { "fixup_Hexagon_IE_GOT_32_6_X", 0, 32, 0 },180 { "fixup_Hexagon_IE_GOT_16_X", 0, 32, 0 },181 { "fixup_Hexagon_IE_GOT_11_X", 0, 32, 0 },182 { "fixup_Hexagon_TPREL_32_6_X", 0, 32, 0 },183 { "fixup_Hexagon_TPREL_16_X", 0, 32, 0 },184 { "fixup_Hexagon_TPREL_11_X", 0, 32, 0 },185 { "fixup_Hexagon_GD_PLT_B22_PCREL_X", 0, 32, 0 },186 { "fixup_Hexagon_GD_PLT_B32_PCREL_X", 0, 32, 0 },187 { "fixup_Hexagon_LD_PLT_B22_PCREL_X", 0, 32, 0 },188 { "fixup_Hexagon_LD_PLT_B32_PCREL_X", 0, 32, 0 },189 };190 // clang-format on191 192 if (Kind < FirstTargetFixupKind)193 return MCAsmBackend::getFixupKindInfo(Kind);194 195 assert(unsigned(Kind - FirstTargetFixupKind) <196 Hexagon::NumTargetFixupKinds &&197 "Invalid kind!");198 return Infos[Kind - FirstTargetFixupKind];199 }200 201 bool shouldForceRelocation(const MCFixup &Fixup) {202 switch(Fixup.getKind()) {203 default:204 llvm_unreachable("Unknown Fixup Kind!");205 206 case fixup_Hexagon_LO16:207 case fixup_Hexagon_HI16:208 case fixup_Hexagon_16:209 case fixup_Hexagon_8:210 case fixup_Hexagon_GPREL16_0:211 case fixup_Hexagon_GPREL16_1:212 case fixup_Hexagon_GPREL16_2:213 case fixup_Hexagon_GPREL16_3:214 case fixup_Hexagon_HL16:215 case fixup_Hexagon_32_6_X:216 case fixup_Hexagon_16_X:217 case fixup_Hexagon_12_X:218 case fixup_Hexagon_11_X:219 case fixup_Hexagon_10_X:220 case fixup_Hexagon_9_X:221 case fixup_Hexagon_8_X:222 case fixup_Hexagon_7_X:223 case fixup_Hexagon_6_X:224 case fixup_Hexagon_COPY:225 case fixup_Hexagon_GLOB_DAT:226 case fixup_Hexagon_JMP_SLOT:227 case fixup_Hexagon_RELATIVE:228 case fixup_Hexagon_PLT_B22_PCREL:229 case fixup_Hexagon_GOTREL_LO16:230 case fixup_Hexagon_GOTREL_HI16:231 case fixup_Hexagon_GOTREL_32:232 case fixup_Hexagon_GOT_LO16:233 case fixup_Hexagon_GOT_HI16:234 case fixup_Hexagon_GOT_32:235 case fixup_Hexagon_GOT_16:236 case fixup_Hexagon_DTPMOD_32:237 case fixup_Hexagon_DTPREL_LO16:238 case fixup_Hexagon_DTPREL_HI16:239 case fixup_Hexagon_DTPREL_32:240 case fixup_Hexagon_DTPREL_16:241 case fixup_Hexagon_GD_PLT_B22_PCREL:242 case fixup_Hexagon_LD_PLT_B22_PCREL:243 case fixup_Hexagon_GD_GOT_LO16:244 case fixup_Hexagon_GD_GOT_HI16:245 case fixup_Hexagon_GD_GOT_32:246 case fixup_Hexagon_GD_GOT_16:247 case fixup_Hexagon_LD_GOT_LO16:248 case fixup_Hexagon_LD_GOT_HI16:249 case fixup_Hexagon_LD_GOT_32:250 case fixup_Hexagon_LD_GOT_16:251 case fixup_Hexagon_IE_LO16:252 case fixup_Hexagon_IE_HI16:253 case fixup_Hexagon_IE_32:254 case fixup_Hexagon_IE_16:255 case fixup_Hexagon_IE_GOT_LO16:256 case fixup_Hexagon_IE_GOT_HI16:257 case fixup_Hexagon_IE_GOT_32:258 case fixup_Hexagon_IE_GOT_16:259 case fixup_Hexagon_TPREL_LO16:260 case fixup_Hexagon_TPREL_HI16:261 case fixup_Hexagon_TPREL_32:262 case fixup_Hexagon_TPREL_16:263 case fixup_Hexagon_GOTREL_32_6_X:264 case fixup_Hexagon_GOTREL_16_X:265 case fixup_Hexagon_GOTREL_11_X:266 case fixup_Hexagon_GOT_32_6_X:267 case fixup_Hexagon_GOT_16_X:268 case fixup_Hexagon_GOT_11_X:269 case fixup_Hexagon_DTPREL_32_6_X:270 case fixup_Hexagon_DTPREL_16_X:271 case fixup_Hexagon_DTPREL_11_X:272 case fixup_Hexagon_GD_GOT_32_6_X:273 case fixup_Hexagon_GD_GOT_16_X:274 case fixup_Hexagon_GD_GOT_11_X:275 case fixup_Hexagon_LD_GOT_32_6_X:276 case fixup_Hexagon_LD_GOT_16_X:277 case fixup_Hexagon_LD_GOT_11_X:278 case fixup_Hexagon_IE_32_6_X:279 case fixup_Hexagon_IE_16_X:280 case fixup_Hexagon_IE_GOT_32_6_X:281 case fixup_Hexagon_IE_GOT_16_X:282 case fixup_Hexagon_IE_GOT_11_X:283 case fixup_Hexagon_TPREL_32_6_X:284 case fixup_Hexagon_TPREL_16_X:285 case fixup_Hexagon_TPREL_11_X:286 case fixup_Hexagon_32_PCREL:287 case fixup_Hexagon_6_PCREL_X:288 case fixup_Hexagon_23_REG:289 case fixup_Hexagon_27_REG:290 case fixup_Hexagon_GD_PLT_B22_PCREL_X:291 case fixup_Hexagon_GD_PLT_B32_PCREL_X:292 case fixup_Hexagon_LD_PLT_B22_PCREL_X:293 case fixup_Hexagon_LD_PLT_B32_PCREL_X:294 // These relocations should always have a relocation recorded295 return true;296 297 case fixup_Hexagon_B22_PCREL:298 //IsResolved = false;299 break;300 301 case fixup_Hexagon_B13_PCREL:302 case fixup_Hexagon_B13_PCREL_X:303 case fixup_Hexagon_B32_PCREL_X:304 case fixup_Hexagon_B22_PCREL_X:305 case fixup_Hexagon_B15_PCREL:306 case fixup_Hexagon_B15_PCREL_X:307 case fixup_Hexagon_B9_PCREL:308 case fixup_Hexagon_B9_PCREL_X:309 case fixup_Hexagon_B7_PCREL:310 case fixup_Hexagon_B7_PCREL_X:311 if (DisableFixup)312 return true;313 break;314 315 case FK_Data_1:316 case FK_Data_2:317 case FK_Data_4:318 case fixup_Hexagon_32:319 // Leave these relocations alone as they are used for EH.320 return false;321 }322 return false;323 }324 325 /// getFixupKindNumBytes - The number of bytes the fixup may change.326 static unsigned getFixupKindNumBytes(unsigned Kind) {327 switch (Kind) {328 default:329 return 0;330 331 case FK_Data_1:332 return 1;333 case FK_Data_2:334 return 2;335 case FK_Data_4: // this later gets mapped to R_HEX_32 or R_HEX_32_PCREL336 case fixup_Hexagon_32:337 case fixup_Hexagon_B32_PCREL_X:338 case fixup_Hexagon_B22_PCREL:339 case fixup_Hexagon_B22_PCREL_X:340 case fixup_Hexagon_B15_PCREL:341 case fixup_Hexagon_B15_PCREL_X:342 case fixup_Hexagon_B13_PCREL:343 case fixup_Hexagon_B13_PCREL_X:344 case fixup_Hexagon_B9_PCREL:345 case fixup_Hexagon_B9_PCREL_X:346 case fixup_Hexagon_B7_PCREL:347 case fixup_Hexagon_B7_PCREL_X:348 case fixup_Hexagon_GD_PLT_B32_PCREL_X:349 case fixup_Hexagon_LD_PLT_B32_PCREL_X:350 return 4;351 }352 }353 354 // Make up for left shift when encoding the operand.355 static uint64_t adjustFixupValue(MCFixupKind Kind, uint64_t Value) {356 switch((unsigned)Kind) {357 default:358 break;359 360 case fixup_Hexagon_B7_PCREL:361 case fixup_Hexagon_B9_PCREL:362 case fixup_Hexagon_B13_PCREL:363 case fixup_Hexagon_B15_PCREL:364 case fixup_Hexagon_B22_PCREL:365 Value >>= 2;366 break;367 368 case fixup_Hexagon_B7_PCREL_X:369 case fixup_Hexagon_B9_PCREL_X:370 case fixup_Hexagon_B13_PCREL_X:371 case fixup_Hexagon_B15_PCREL_X:372 case fixup_Hexagon_B22_PCREL_X:373 Value &= 0x3f;374 break;375 376 case fixup_Hexagon_B32_PCREL_X:377 case fixup_Hexagon_GD_PLT_B32_PCREL_X:378 case fixup_Hexagon_LD_PLT_B32_PCREL_X:379 Value >>= 6;380 break;381 }382 return (Value);383 }384 385 void HandleFixupError(const int bits, const int align_bits,386 const int64_t FixupValue, const char *fixupStr) const {387 // Error: value 1124 out of range: -1024-1023 when resolving388 // symbol in file xprtsock.S389 const APInt IntMin = APInt::getSignedMinValue(bits+align_bits);390 const APInt IntMax = APInt::getSignedMaxValue(bits+align_bits);391 std::stringstream errStr;392 errStr << "\nError: value " <<393 FixupValue <<394 " out of range: " <<395 IntMin.getSExtValue() <<396 "-" <<397 IntMax.getSExtValue() <<398 " when resolving " <<399 fixupStr <<400 " fixup\n";401 llvm_unreachable(errStr.str().c_str());402 }403 404 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &,405 uint8_t *Data, uint64_t FixupValue, bool IsResolved) override;406 407 bool isInstRelaxable(MCInst const &HMI) const {408 const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(*MCII, HMI);409 bool Relaxable = false;410 // Branches and loop-setup insns are handled as necessary by relaxation.411 if (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ ||412 (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCJ &&413 MCID.isBranch()) ||414 (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNCJ &&415 MCID.isBranch()) ||416 (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR &&417 HMI.getOpcode() != Hexagon::C4_addipc))418 if (HexagonMCInstrInfo::isExtendable(*MCII, HMI)) {419 Relaxable = true;420 MCOperand const &Operand =421 HMI.getOperand(HexagonMCInstrInfo::getExtendableOp(*MCII, HMI));422 if (HexagonMCInstrInfo::mustNotExtend(*Operand.getExpr()))423 Relaxable = false;424 }425 426 return Relaxable;427 }428 429 bool mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand> Operands,430 const MCSubtargetInfo &STI) const override {431 RelaxedMCB.clear();432 RelaxedMCB.setOpcode(Opcode);433 RelaxedMCB.setOperands(Operands);434 return true;435 }436 437 /// fixupNeedsRelaxation - Target specific predicate for whether a given438 /// fixup requires the associated instruction to be relaxed.439 bool fixupNeedsRelaxationAdvanced(const MCFragment &F, const MCFixup &Fixup,440 const MCValue &, uint64_t Value,441 bool Resolved) const override {442 MCInst const &MCB = RelaxedMCB;443 assert(HexagonMCInstrInfo::isBundle(MCB));444 445 *RelaxTarget = nullptr;446 MCInst &MCI = const_cast<MCInst &>(HexagonMCInstrInfo::instruction(447 MCB, (Fixup.getOffset() - F.getFixedSize()) / HEXAGON_INSTR_SIZE));448 bool Relaxable = isInstRelaxable(MCI);449 if (Relaxable == false)450 return false;451 // If we cannot resolve the fixup value, it requires relaxation.452 if (!Resolved) {453 switch (Fixup.getKind()) {454 case fixup_Hexagon_B22_PCREL:455 // GetFixupCount assumes B22 won't relax456 [[fallthrough]];457 default:458 return false;459 break;460 case fixup_Hexagon_B13_PCREL:461 case fixup_Hexagon_B15_PCREL:462 case fixup_Hexagon_B9_PCREL:463 case fixup_Hexagon_B7_PCREL: {464 if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {465 ++relaxedCnt;466 *RelaxTarget = &MCI;467 setExtender(getContext());468 return true;469 } else {470 return false;471 }472 break;473 }474 }475 }476 477 MCFixupKind Kind = Fixup.getKind();478 int64_t sValue = Value;479 int64_t maxValue;480 481 switch ((unsigned)Kind) {482 case fixup_Hexagon_B7_PCREL:483 maxValue = 1 << 8;484 break;485 case fixup_Hexagon_B9_PCREL:486 maxValue = 1 << 10;487 break;488 case fixup_Hexagon_B15_PCREL:489 maxValue = 1 << 16;490 break;491 case fixup_Hexagon_B22_PCREL:492 maxValue = 1 << 23;493 break;494 default:495 maxValue = INT64_MAX;496 break;497 }498 499 bool isFarAway = -maxValue > sValue || sValue > maxValue - 1;500 501 if (isFarAway) {502 if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) {503 ++relaxedCnt;504 *RelaxTarget = &MCI;505 setExtender(getContext());506 return true;507 }508 }509 510 return false;511 }512 513 void relaxInstruction(MCInst &Inst,514 const MCSubtargetInfo &STI) const override {515 assert(HexagonMCInstrInfo::isBundle(Inst) &&516 "Hexagon relaxInstruction only works on bundles");517 518 MCInst Res;519 Res.setOpcode(Hexagon::BUNDLE);520 Res.addOperand(MCOperand::createImm(Inst.getOperand(0).getImm()));521 // Copy the results into the bundle.522 bool Update = false;523 for (auto &I : HexagonMCInstrInfo::bundleInstructions(Inst)) {524 MCInst &CrntHMI = const_cast<MCInst &>(*I.getInst());525 526 // if immediate extender needed, add it in527 if (*RelaxTarget == &CrntHMI) {528 Update = true;529 assert((HexagonMCInstrInfo::bundleSize(Res) < HEXAGON_PACKET_SIZE) &&530 "No room to insert extender for relaxation");531 532 MCInst *HMIx = takeExtender();533 *HMIx = HexagonMCInstrInfo::deriveExtender(534 *MCII, CrntHMI,535 HexagonMCInstrInfo::getExtendableOperand(*MCII, CrntHMI));536 Res.addOperand(MCOperand::createInst(HMIx));537 *RelaxTarget = nullptr;538 }539 // now copy over the original instruction(the one we may have extended)540 Res.addOperand(MCOperand::createInst(I.getInst()));541 }542 543 Inst = std::move(Res);544 (void)Update;545 assert(Update && "Didn't find relaxation target");546 }547 548 bool writeNopData(raw_ostream &OS, uint64_t Count,549 const MCSubtargetInfo *STI) const override {550 static const uint32_t Nopcode = 0x7f000000, // Hard-coded NOP.551 ParseIn = 0x00004000, // In packet parse-bits.552 ParseEnd = 0x0000c000; // End of packet parse-bits.553 554 while (Count % HEXAGON_INSTR_SIZE) {555 LLVM_DEBUG(dbgs() << "Alignment not a multiple of the instruction size:"556 << Count % HEXAGON_INSTR_SIZE << "/"557 << HEXAGON_INSTR_SIZE << "\n");558 --Count;559 OS << '\0';560 }561 562 while (Count) {563 Count -= HEXAGON_INSTR_SIZE;564 // Close the packet whenever a multiple of the maximum packet size remains565 uint32_t ParseBits = (Count % (MaxPacketSize * HEXAGON_INSTR_SIZE)) ?566 ParseIn : ParseEnd;567 support::endian::write<uint32_t>(OS, Nopcode | ParseBits, Endian);568 }569 return true;570 }571 572 bool finishLayout() const override {573 SmallVector<MCFragment *> Frags;574 for (MCSection &Sec : *Asm) {575 Frags.clear();576 for (MCFragment &F : Sec)577 Frags.push_back(&F);578 for (size_t J = 0, E = Frags.size(); J != E; ++J) {579 switch (Frags[J]->getKind()) {580 default:581 break;582 case MCFragment::FT_Align: {583 auto Size = Asm->computeFragmentSize(*Frags[J]);584 for (auto K = J; K != 0 && Size >= HEXAGON_PACKET_SIZE;) {585 --K;586 switch (Frags[K]->getKind()) {587 default:588 break;589 case MCFragment::FT_Align: {590 // Don't pad before other alignments591 Size = 0;592 break;593 }594 case MCFragment::FT_Relaxable: {595 MCContext &Context = getContext();596 auto &RF = *Frags[K];597 MCInst Inst = RF.getInst();598 599 const bool WouldTraverseLabel = llvm::any_of(600 Asm->symbols(), [&RF, &Inst, Asm = Asm](MCSymbol const &sym) {601 uint64_t Offset = 0;602 const bool HasOffset = Asm->getSymbolOffset(sym, Offset);603 const unsigned PacketSizeBytes =604 HexagonMCInstrInfo::bundleSize(Inst) *605 HEXAGON_INSTR_SIZE;606 const bool OffsetPastSym =607 Offset <= Asm->getFragmentOffset(RF) + PacketSizeBytes;608 return !sym.isVariable() && Offset != 0 && HasOffset &&609 OffsetPastSym;610 });611 if (WouldTraverseLabel) {612 Size = 0;613 break;614 }615 616 while (Size > 0 &&617 HexagonMCInstrInfo::bundleSize(Inst) < MaxPacketSize) {618 MCInst *Nop = Context.createMCInst();619 Nop->setOpcode(Hexagon::A2_nop);620 Inst.addOperand(MCOperand::createInst(Nop));621 Size -= 4;622 if (!HexagonMCChecker(623 Context, *MCII, *RF.getSubtargetInfo(), Inst,624 *Context.getRegisterInfo(), false)625 .check()) {626 Inst.erase(Inst.end() - 1);627 Size = 0;628 }629 }630 bool Error = HexagonMCShuffle(Context, true, *MCII,631 *RF.getSubtargetInfo(), Inst);632 //assert(!Error);633 (void)Error;634 ReplaceInstruction(Asm->getEmitter(), RF, Inst);635 Size = 0; // Only look back one instruction636 break;637 }638 }639 }640 }641 }642 }643 }644 return true;645 }646}; // class HexagonAsmBackend647 648} // namespace649 650void HexagonAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,651 const MCValue &Target, uint8_t *InstAddr,652 uint64_t FixupValue, bool IsResolved) {653 if (IsResolved && shouldForceRelocation(Fixup))654 IsResolved = false;655 maybeAddReloc(F, Fixup, Target, FixupValue, IsResolved);656 // When FixupValue is 0 the relocation is external and there657 // is nothing for us to do.658 if (!FixupValue)659 return;660 661 MCFixupKind Kind = Fixup.getKind();662 uint64_t Value;663 uint32_t InstMask;664 uint32_t Reloc;665 666 // LLVM gives us an encoded value, we have to convert it back667 // to a real offset before we can use it.668 unsigned NumBytes = getFixupKindNumBytes(Kind);669 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&670 "Invalid fixup offset!");671 672 Value = adjustFixupValue(Kind, FixupValue);673 if (!Value)674 return;675 int sValue = (int)Value;676 677 switch ((unsigned)Kind) {678 default:679 return;680 681 case fixup_Hexagon_B7_PCREL:682 if (!(isIntN(7, sValue)))683 HandleFixupError(7, 2, (int64_t)FixupValue, "B7_PCREL");684 [[fallthrough]];685 case fixup_Hexagon_B7_PCREL_X:686 InstMask = 0x00001f18; // Word32_B7687 Reloc = (((Value >> 2) & 0x1f) << 8) | // Value 6-2 = Target 12-8688 ((Value & 0x3) << 3); // Value 1-0 = Target 4-3689 break;690 691 case fixup_Hexagon_B9_PCREL:692 if (!(isIntN(9, sValue)))693 HandleFixupError(9, 2, (int64_t)FixupValue, "B9_PCREL");694 [[fallthrough]];695 case fixup_Hexagon_B9_PCREL_X:696 InstMask = 0x003000fe; // Word32_B9697 Reloc = (((Value >> 7) & 0x3) << 20) | // Value 8-7 = Target 21-20698 ((Value & 0x7f) << 1); // Value 6-0 = Target 7-1699 break;700 701 // Since the existing branches that use this relocation cannot be702 // extended, they should only be fixed up if the target is within range.703 case fixup_Hexagon_B13_PCREL:704 if (!(isIntN(13, sValue)))705 HandleFixupError(13, 2, (int64_t)FixupValue, "B13_PCREL");706 [[fallthrough]];707 case fixup_Hexagon_B13_PCREL_X:708 InstMask = 0x00202ffe; // Word32_B13709 Reloc = (((Value >> 12) & 0x1) << 21) | // Value 12 = Target 21710 (((Value >> 11) & 0x1) << 13) | // Value 11 = Target 13711 ((Value & 0x7ff) << 1); // Value 10-0 = Target 11-1712 break;713 714 case fixup_Hexagon_B15_PCREL:715 if (!(isIntN(15, sValue)))716 HandleFixupError(15, 2, (int64_t)FixupValue, "B15_PCREL");717 [[fallthrough]];718 case fixup_Hexagon_B15_PCREL_X:719 InstMask = 0x00df20fe; // Word32_B15720 Reloc = (((Value >> 13) & 0x3) << 22) | // Value 14-13 = Target 23-22721 (((Value >> 8) & 0x1f) << 16) | // Value 12-8 = Target 20-16722 (((Value >> 7) & 0x1) << 13) | // Value 7 = Target 13723 ((Value & 0x7f) << 1); // Value 6-0 = Target 7-1724 break;725 726 case fixup_Hexagon_B22_PCREL:727 if (!(isIntN(22, sValue)))728 HandleFixupError(22, 2, (int64_t)FixupValue, "B22_PCREL");729 [[fallthrough]];730 case fixup_Hexagon_B22_PCREL_X:731 InstMask = 0x01ff3ffe; // Word32_B22732 Reloc = (((Value >> 13) & 0x1ff) << 16) | // Value 21-13 = Target 24-16733 ((Value & 0x1fff) << 1); // Value 12-0 = Target 13-1734 break;735 736 case fixup_Hexagon_B32_PCREL_X:737 InstMask = 0x0fff3fff; // Word32_X26738 Reloc = (((Value >> 14) & 0xfff) << 16) | // Value 25-14 = Target 27-16739 (Value & 0x3fff); // Value 13-0 = Target 13-0740 break;741 742 case FK_Data_1:743 case FK_Data_2:744 case FK_Data_4:745 case fixup_Hexagon_32:746 InstMask = 0xffffffff; // Word32747 Reloc = Value;748 break;749 }750 751 LLVM_DEBUG(dbgs() << "Name=" << getFixupKindInfo(Kind).Name << "("752 << (unsigned)Kind << ")\n");753 LLVM_DEBUG(754 uint32_t OldData = 0; for (unsigned i = 0; i < NumBytes; i++) OldData |=755 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));756 dbgs() << "\tBValue=0x"; dbgs().write_hex(Value) << ": AValue=0x";757 dbgs().write_hex(FixupValue) << ": Offset=" << Fixup.getOffset()758 << ": Size=" << F.getSize() << ": OInst=0x";759 dbgs().write_hex(OldData) << ": Reloc=0x"; dbgs().write_hex(Reloc););760 761 // For each byte of the fragment that the fixup touches, mask in the762 // bits from the fixup value. The Value has been "split up" into the763 // appropriate bitfields above.764 for (unsigned i = 0; i < NumBytes; i++) {765 InstAddr[i] &= uint8_t(~InstMask >> (i * 8)) & 0xff; // Clear reloc bits766 InstAddr[i] |= uint8_t(Reloc >> (i * 8)) & 0xff; // Apply new reloc767 }768 769 LLVM_DEBUG(uint32_t NewData = 0;770 for (unsigned i = 0; i < NumBytes; i++) NewData |=771 (InstAddr[i] << (i * 8)) & (0xff << (i * 8));772 dbgs() << ": NInst=0x"; dbgs().write_hex(NewData) << "\n";);773}774 775// MCAsmBackend776MCAsmBackend *llvm::createHexagonAsmBackend(Target const &T,777 const MCSubtargetInfo &STI,778 MCRegisterInfo const & /*MRI*/,779 const MCTargetOptions &Options) {780 const Triple &TT = STI.getTargetTriple();781 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());782 783 StringRef CPUString = Hexagon_MC::selectHexagonCPU(STI.getCPU());784 return new HexagonAsmBackend(T, TT, OSABI, CPUString);785}786