brintos

brintos / llvm-project-archived public Read only

0
0
Text · 50.7 KiB · cc21844 Raw
1393 lines · cpp
1//===-- ARMAsmBackend.cpp - ARM 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 "MCTargetDesc/ARMAsmBackend.h"10#include "MCTargetDesc/ARMAddressingModes.h"11#include "MCTargetDesc/ARMAsmBackendDarwin.h"12#include "MCTargetDesc/ARMAsmBackendELF.h"13#include "MCTargetDesc/ARMAsmBackendWinCOFF.h"14#include "MCTargetDesc/ARMFixupKinds.h"15#include "MCTargetDesc/ARMMCAsmInfo.h"16#include "MCTargetDesc/ARMMCTargetDesc.h"17#include "llvm/ADT/StringSwitch.h"18#include "llvm/BinaryFormat/ELF.h"19#include "llvm/BinaryFormat/MachO.h"20#include "llvm/MC/MCAsmBackend.h"21#include "llvm/MC/MCAssembler.h"22#include "llvm/MC/MCContext.h"23#include "llvm/MC/MCELFObjectWriter.h"24#include "llvm/MC/MCExpr.h"25#include "llvm/MC/MCObjectWriter.h"26#include "llvm/MC/MCRegisterInfo.h"27#include "llvm/MC/MCSubtargetInfo.h"28#include "llvm/MC/MCSymbolMachO.h"29#include "llvm/MC/MCTargetOptions.h"30#include "llvm/MC/MCValue.h"31#include "llvm/Support/Debug.h"32#include "llvm/Support/EndianStream.h"33#include "llvm/Support/ErrorHandling.h"34#include "llvm/Support/MathExtras.h"35#include "llvm/Support/raw_ostream.h"36using namespace llvm;37 38namespace {39class ARMELFObjectWriter : public MCELFObjectTargetWriter {40public:41  ARMELFObjectWriter(uint8_t OSABI)42      : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM,43                                /*HasRelocationAddend*/ false) {}44};45} // end anonymous namespace46 47std::optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const {48  return std::nullopt;49}50 51std::optional<MCFixupKind>52ARMAsmBackendELF::getFixupKind(StringRef Name) const {53  unsigned Type = llvm::StringSwitch<unsigned>(Name)54#define ELF_RELOC(X, Y) .Case(#X, Y)55#include "llvm/BinaryFormat/ELFRelocs/ARM.def"56#undef ELF_RELOC57                      .Case("BFD_RELOC_NONE", ELF::R_ARM_NONE)58                      .Case("BFD_RELOC_8", ELF::R_ARM_ABS8)59                      .Case("BFD_RELOC_16", ELF::R_ARM_ABS16)60                      .Case("BFD_RELOC_32", ELF::R_ARM_ABS32)61                      .Default(-1u);62  if (Type == -1u)63    return std::nullopt;64  return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);65}66 67MCFixupKindInfo ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {68  const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = {69      // This table *must* be in the order that the fixup_* kinds are defined in70      // ARMFixupKinds.h.71      //72      // Name                      Offset (bits) Size (bits)     Flags73      {"fixup_arm_ldst_pcrel_12", 0, 32, 0},74      {"fixup_t2_ldst_pcrel_12", 0, 32, 0},75      {"fixup_arm_pcrel_10_unscaled", 0, 32, 0},76      {"fixup_arm_pcrel_10", 0, 32, 0},77      {"fixup_t2_pcrel_10", 0, 32, 0},78      {"fixup_arm_pcrel_9", 0, 32, 0},79      {"fixup_t2_pcrel_9", 0, 32, 0},80      {"fixup_arm_ldst_abs_12", 0, 32, 0},81      {"fixup_thumb_adr_pcrel_10", 0, 8, 0},82      {"fixup_arm_adr_pcrel_12", 0, 32, 0},83      {"fixup_t2_adr_pcrel_12", 0, 32, 0},84      {"fixup_arm_condbranch", 0, 24, 0},85      {"fixup_arm_uncondbranch", 0, 24, 0},86      {"fixup_t2_condbranch", 0, 32, 0},87      {"fixup_t2_uncondbranch", 0, 32, 0},88      {"fixup_arm_thumb_br", 0, 16, 0},89      {"fixup_arm_uncondbl", 0, 24, 0},90      {"fixup_arm_condbl", 0, 24, 0},91      {"fixup_arm_blx", 0, 24, 0},92      {"fixup_arm_thumb_bl", 0, 32, 0},93      {"fixup_arm_thumb_blx", 0, 32, 0},94      {"fixup_arm_thumb_cb", 0, 16, 0},95      {"fixup_arm_thumb_cp", 0, 8, 0},96      {"fixup_arm_thumb_bcc", 0, 8, 0},97      // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 1698      // - 19.99      {"fixup_arm_movt_hi16", 0, 20, 0},100      {"fixup_arm_movw_lo16", 0, 20, 0},101      {"fixup_t2_movt_hi16", 0, 20, 0},102      {"fixup_t2_movw_lo16", 0, 20, 0},103      {"fixup_arm_thumb_upper_8_15", 0, 8, 0},104      {"fixup_arm_thumb_upper_0_7", 0, 8, 0},105      {"fixup_arm_thumb_lower_8_15", 0, 8, 0},106      {"fixup_arm_thumb_lower_0_7", 0, 8, 0},107      {"fixup_arm_mod_imm", 0, 12, 0},108      {"fixup_t2_so_imm", 0, 26, 0},109      {"fixup_bf_branch", 0, 32, 0},110      {"fixup_bf_target", 0, 32, 0},111      {"fixup_bfl_target", 0, 32, 0},112      {"fixup_bfc_target", 0, 32, 0},113      {"fixup_bfcsel_else_target", 0, 32, 0},114      {"fixup_wls", 0, 32, 0},115      {"fixup_le", 0, 32, 0},116  };117  const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {118      // This table *must* be in the order that the fixup_* kinds are defined in119      // ARMFixupKinds.h.120      //121      // Name                      Offset (bits) Size (bits)     Flags122      {"fixup_arm_ldst_pcrel_12", 0, 32, 0},123      {"fixup_t2_ldst_pcrel_12", 0, 32, 0},124      {"fixup_arm_pcrel_10_unscaled", 0, 32, 0},125      {"fixup_arm_pcrel_10", 0, 32, 0},126      {"fixup_t2_pcrel_10", 0, 32, 0},127      {"fixup_arm_pcrel_9", 0, 32, 0},128      {"fixup_t2_pcrel_9", 0, 32, 0},129      {"fixup_arm_ldst_abs_12", 0, 32, 0},130      {"fixup_thumb_adr_pcrel_10", 8, 8, 0},131      {"fixup_arm_adr_pcrel_12", 0, 32, 0},132      {"fixup_t2_adr_pcrel_12", 0, 32, 0},133      {"fixup_arm_condbranch", 8, 24, 0},134      {"fixup_arm_uncondbranch", 8, 24, 0},135      {"fixup_t2_condbranch", 0, 32, 0},136      {"fixup_t2_uncondbranch", 0, 32, 0},137      {"fixup_arm_thumb_br", 0, 16, 0},138      {"fixup_arm_uncondbl", 8, 24, 0},139      {"fixup_arm_condbl", 8, 24, 0},140      {"fixup_arm_blx", 8, 24, 0},141      {"fixup_arm_thumb_bl", 0, 32, 0},142      {"fixup_arm_thumb_blx", 0, 32, 0},143      {"fixup_arm_thumb_cb", 0, 16, 0},144      {"fixup_arm_thumb_cp", 8, 8, 0},145      {"fixup_arm_thumb_bcc", 8, 8, 0},146      // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16147      // - 19.148      {"fixup_arm_movt_hi16", 12, 20, 0},149      {"fixup_arm_movw_lo16", 12, 20, 0},150      {"fixup_t2_movt_hi16", 12, 20, 0},151      {"fixup_t2_movw_lo16", 12, 20, 0},152      {"fixup_arm_thumb_upper_8_15", 24, 8, 0},153      {"fixup_arm_thumb_upper_0_7", 24, 8, 0},154      {"fixup_arm_thumb_lower_8_15", 24, 8, 0},155      {"fixup_arm_thumb_lower_0_7", 24, 8, 0},156      {"fixup_arm_mod_imm", 20, 12, 0},157      {"fixup_t2_so_imm", 26, 6, 0},158      {"fixup_bf_branch", 0, 32, 0},159      {"fixup_bf_target", 0, 32, 0},160      {"fixup_bfl_target", 0, 32, 0},161      {"fixup_bfc_target", 0, 32, 0},162      {"fixup_bfcsel_else_target", 0, 32, 0},163      {"fixup_wls", 0, 32, 0},164      {"fixup_le", 0, 32, 0},165  };166 167  // Fixup kinds from .reloc directive are like R_ARM_NONE. They do not require168  // any extra processing.169  if (mc::isRelocation(Kind))170    return {};171 172  if (Kind < FirstTargetFixupKind)173    return MCAsmBackend::getFixupKindInfo(Kind);174 175  assert(unsigned(Kind - FirstTargetFixupKind) < ARM::NumTargetFixupKinds &&176         "Invalid kind!");177  return (Endian == llvm::endianness::little178              ? InfosLE179              : InfosBE)[Kind - FirstTargetFixupKind];180}181 182unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op,183                                         const MCSubtargetInfo &STI) const {184  bool HasThumb2 = STI.hasFeature(ARM::FeatureThumb2);185  bool HasV8MBaselineOps = STI.hasFeature(ARM::HasV8MBaselineOps);186 187  switch (Op) {188  default:189    return Op;190  case ARM::tBcc:191    return HasThumb2 ? (unsigned)ARM::t2Bcc : Op;192  case ARM::tLDRpci:193    return HasThumb2 ? (unsigned)ARM::t2LDRpci : Op;194  case ARM::tADR:195    return HasThumb2 ? (unsigned)ARM::t2ADR : Op;196  case ARM::tB:197    return HasV8MBaselineOps ? (unsigned)ARM::t2B : Op;198  case ARM::tCBZ:199    return ARM::tHINT;200  case ARM::tCBNZ:201    return ARM::tHINT;202  }203}204 205bool ARMAsmBackend::mayNeedRelaxation(unsigned Opcode, ArrayRef<MCOperand>,206                                      const MCSubtargetInfo &STI) const {207  return getRelaxedOpcode(Opcode, STI) != Opcode;208}209 210static const char *checkPCRelOffset(uint64_t Value, int64_t Min, int64_t Max) {211  int64_t Offset = int64_t(Value) - 4;212  if (Offset < Min || Offset > Max)213    return "out of range pc-relative fixup value";214  return nullptr;215}216 217const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup,218                                                    uint64_t Value) const {219  switch (Fixup.getKind()) {220  case ARM::fixup_arm_thumb_br: {221    // Relaxing tB to t2B. tB has a signed 12-bit displacement with the222    // low bit being an implied zero. There's an implied +4 offset for the223    // branch, so we adjust the other way here to determine what's224    // encodable.225    //226    // Relax if the value is too big for a (signed) i8.227    int64_t Offset = int64_t(Value) - 4;228    if (Offset > 2046 || Offset < -2048)229      return "out of range pc-relative fixup value";230    break;231  }232  case ARM::fixup_arm_thumb_bcc: {233    // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the234    // low bit being an implied zero. There's an implied +4 offset for the235    // branch, so we adjust the other way here to determine what's236    // encodable.237    //238    // Relax if the value is too big for a (signed) i8.239    int64_t Offset = int64_t(Value) - 4;240    if (Offset > 254 || Offset < -256)241      return "out of range pc-relative fixup value";242    break;243  }244  case ARM::fixup_thumb_adr_pcrel_10:245  case ARM::fixup_arm_thumb_cp: {246    // If the immediate is negative, greater than 1020, or not a multiple247    // of four, the wide version of the instruction must be used.248    int64_t Offset = int64_t(Value) - 4;249    if (Offset & 3)250      return "misaligned pc-relative fixup value";251    else if (Offset > 1020 || Offset < 0)252      return "out of range pc-relative fixup value";253    break;254  }255  case ARM::fixup_arm_thumb_cb: {256    // If we have a Thumb CBZ or CBNZ instruction and its target is the next257    // instruction it is actually out of range for the instruction.258    // It will be changed to a NOP.259    int64_t Offset = (Value & ~1);260    if (Offset == 2)261      return "will be converted to nop";262    break;263  }264  case ARM::fixup_bf_branch:265    return checkPCRelOffset(Value, 0, 30);266  case ARM::fixup_bf_target:267    return checkPCRelOffset(Value, -0x10000, +0xfffe);268  case ARM::fixup_bfl_target:269    return checkPCRelOffset(Value, -0x40000, +0x3fffe);270  case ARM::fixup_bfc_target:271    return checkPCRelOffset(Value, -0x1000, +0xffe);272  case ARM::fixup_wls:273    return checkPCRelOffset(Value, 0, +0xffe);274  case ARM::fixup_le:275    // The offset field in the LE and LETP instructions is an 11-bit276    // value shifted left by 2 (i.e. 0,2,4,...,4094), and it is277    // interpreted as a negative offset from the value read from pc,278    // i.e. from instruction_address+4.279    //280    // So an LE instruction can in principle address the instruction281    // immediately after itself, or (not very usefully) the address282    // half way through the 4-byte LE.283    return checkPCRelOffset(Value, -0xffe, 0);284  case ARM::fixup_bfcsel_else_target: {285    if (Value != 2 && Value != 4)286      return "out of range label-relative fixup value";287    break;288  }289 290  default:291    llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!");292  }293  return nullptr;294}295 296static bool needsInterworking(const MCAssembler &Asm, const MCSymbol *Sym,297                              unsigned FixupKind) {298  // Create relocations for unconditional branches to function symbols with299  // different execution mode in ELF binaries.300  if (!Sym || !Asm.getContext().isELF())301    return false;302  unsigned Type = static_cast<const MCSymbolELF *>(Sym)->getType();303  if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC)) {304    if (Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_uncondbranch))305      return true;306    if (!Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_thumb_br ||307                                  FixupKind == ARM::fixup_arm_thumb_bl ||308                                  FixupKind == ARM::fixup_t2_condbranch ||309                                  FixupKind == ARM::fixup_t2_uncondbranch))310      return true;311  }312  return false;313}314 315bool ARMAsmBackend::fixupNeedsRelaxationAdvanced(const MCFragment &,316                                                 const MCFixup &Fixup,317                                                 const MCValue &Target,318                                                 uint64_t Value,319                                                 bool Resolved) const {320  const MCSymbol *Sym = Target.getAddSym();321  if (needsInterworking(*Asm, Sym, Fixup.getKind()))322    return true;323 324  if (!Resolved)325    return true;326  return reasonForFixupRelaxation(Fixup, Value);327}328 329void ARMAsmBackend::relaxInstruction(MCInst &Inst,330                                     const MCSubtargetInfo &STI) const {331  unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode(), STI);332  assert(RelaxedOp != Inst.getOpcode());333 334  // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we335  // have to change the operands too.336  if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) &&337      RelaxedOp == ARM::tHINT) {338    MCInst Res;339    Res.setOpcode(RelaxedOp);340    Res.addOperand(MCOperand::createImm(0));341    Res.addOperand(MCOperand::createImm(14));342    Res.addOperand(MCOperand::createReg(0));343    Inst = std::move(Res);344    return;345  }346 347  // The rest of instructions we're relaxing have the same operands.348  // We just need to update to the proper opcode.349  Inst.setOpcode(RelaxedOp);350}351 352bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,353                                 const MCSubtargetInfo *STI) const {354  const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8355  const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP356  const uint32_t ARMv4_NopEncoding = 0xe1a00000;   // using MOV r0,r0357  const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP358  if (STI->hasFeature(ARM::ModeThumb)) {359    const uint16_t nopEncoding =360        hasNOP(STI) ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;361    uint64_t NumNops = Count / 2;362    for (uint64_t i = 0; i != NumNops; ++i)363      support::endian::write(OS, nopEncoding, Endian);364    if (Count & 1)365      OS << '\0';366    return true;367  }368  // ARM mode369  const uint32_t nopEncoding =370      hasNOP(STI) ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;371  uint64_t NumNops = Count / 4;372  for (uint64_t i = 0; i != NumNops; ++i)373    support::endian::write(OS, nopEncoding, Endian);374  // FIXME: should this function return false when unable to write exactly375  // 'Count' bytes with NOP encodings?376  switch (Count % 4) {377  default:378    break; // No leftover bytes to write379  case 1:380    OS << '\0';381    break;382  case 2:383    OS.write("\0\0", 2);384    break;385  case 3:386    OS.write("\0\0\xa0", 3);387    break;388  }389 390  return true;391}392 393static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) {394  if (IsLittleEndian) {395    // Note that the halfwords are stored high first and low second in thumb;396    // so we need to swap the fixup value here to map properly.397    uint32_t Swapped = (Value & 0xFFFF0000) >> 16;398    Swapped |= (Value & 0x0000FFFF) << 16;399    return Swapped;400  } else401    return Value;402}403 404static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf,405                              bool IsLittleEndian) {406  uint32_t Value;407 408  if (IsLittleEndian) {409    Value = (SecondHalf & 0xFFFF) << 16;410    Value |= (FirstHalf & 0xFFFF);411  } else {412    Value = (SecondHalf & 0xFFFF);413    Value |= (FirstHalf & 0xFFFF) << 16;414  }415 416  return Value;417}418 419unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,420                                         const MCFixup &Fixup,421                                         const MCValue &Target, uint64_t Value,422                                         bool IsResolved, MCContext &Ctx,423                                         const MCSubtargetInfo* STI) const {424  unsigned Kind = Fixup.getKind();425  int64_t Addend = Target.getConstant();426 427  // For MOVW/MOVT Instructions, the fixup value must already be within a428  // signed 16bit range.429  if ((Kind == ARM::fixup_arm_movw_lo16 || Kind == ARM::fixup_arm_movt_hi16 ||430       Kind == ARM::fixup_t2_movw_lo16 || Kind == ARM::fixup_t2_movt_hi16) &&431      !IsResolved && (Addend < minIntN(16) || Addend > maxIntN(16))) {432    Ctx.reportError(Fixup.getLoc(), "Relocation Not In Range");433    return 0;434  }435 436  // MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT437  // and .word relocations they put the Thumb bit into the addend if possible.438  // Other relocation types don't want this bit though (branches couldn't encode439  // it if it *was* present, and no other relocations exist) and it can440  // interfere with checking valid expressions.441  if (getContext().getObjectFileType() == MCContext::IsMachO) {442    if (auto *SA = static_cast<const MCSymbolMachO *>(Target.getAddSym())) {443      if (Asm.isThumbFunc(SA) && SA->isExternal() &&444          (Kind == FK_Data_4 || Kind == ARM::fixup_arm_movw_lo16 ||445           Kind == ARM::fixup_arm_movt_hi16 ||446           Kind == ARM::fixup_t2_movw_lo16 || Kind == ARM::fixup_t2_movt_hi16))447        Value |= 1;448    }449  }450 451  switch (Kind) {452  default:453    return 0;454  case FK_Data_1:455  case FK_Data_2:456  case FK_Data_4:457    return Value;458  case FK_SecRel_2:459    return Value;460  case FK_SecRel_4:461    return Value;462  case ARM::fixup_arm_movt_hi16:463    assert(STI != nullptr);464    if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())465      Value >>= 16;466    [[fallthrough]];467  case ARM::fixup_arm_movw_lo16: {468    unsigned Hi4 = (Value & 0xF000) >> 12;469    unsigned Lo12 = Value & 0x0FFF;470    // inst{19-16} = Hi4;471    // inst{11-0} = Lo12;472    Value = (Hi4 << 16) | (Lo12);473    return Value;474  }475  case ARM::fixup_t2_movt_hi16:476    assert(STI != nullptr);477    if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())478      Value >>= 16;479    [[fallthrough]];480  case ARM::fixup_t2_movw_lo16: {481    unsigned Hi4 = (Value & 0xF000) >> 12;482    unsigned i = (Value & 0x800) >> 11;483    unsigned Mid3 = (Value & 0x700) >> 8;484    unsigned Lo8 = Value & 0x0FF;485    // inst{19-16} = Hi4;486    // inst{26} = i;487    // inst{14-12} = Mid3;488    // inst{7-0} = Lo8;489    Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);490    return swapHalfWords(Value, Endian == llvm::endianness::little);491  }492  case ARM::fixup_arm_thumb_upper_8_15:493    if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())494      return (Value & 0xff000000) >> 24;495    return Value & 0xff;496  case ARM::fixup_arm_thumb_upper_0_7:497    if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())498      return (Value & 0x00ff0000) >> 16;499    return Value & 0xff;500  case ARM::fixup_arm_thumb_lower_8_15:501    if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())502      return (Value & 0x0000ff00) >> 8;503    return Value & 0xff;504  case ARM::fixup_arm_thumb_lower_0_7:505    return Value & 0x000000ff;506  case ARM::fixup_arm_ldst_pcrel_12:507    // ARM PC-relative values are offset by 8.508    Value -= 4;509    [[fallthrough]];510  case ARM::fixup_t2_ldst_pcrel_12:511    // Offset by 4, adjusted by two due to the half-word ordering of thumb.512    Value -= 4;513    [[fallthrough]];514  case ARM::fixup_arm_ldst_abs_12: {515    bool isAdd = true;516    if ((int64_t)Value < 0) {517      Value = -Value;518      isAdd = false;519    }520    if (Value >= 4096) {521      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");522      return 0;523    }524    Value |= isAdd << 23;525 526    // Same addressing mode as fixup_arm_pcrel_10,527    // but with 16-bit halfwords swapped.528    if (Kind == ARM::fixup_t2_ldst_pcrel_12)529      return swapHalfWords(Value, Endian == llvm::endianness::little);530 531    return Value;532  }533  case ARM::fixup_arm_adr_pcrel_12: {534    // ARM PC-relative values are offset by 8.535    Value -= 8;536    unsigned opc = 4; // bits {24-21}. Default to add: 0b0100537    if ((int64_t)Value < 0) {538      Value = -Value;539      opc = 2; // 0b0010540    }541    if (ARM_AM::getSOImmVal(Value) == -1) {542      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");543      return 0;544    }545    // Encode the immediate and shift the opcode into place.546    return ARM_AM::getSOImmVal(Value) | (opc << 21);547  }548 549  case ARM::fixup_t2_adr_pcrel_12: {550    Value -= 4;551    unsigned opc = 0;552    if ((int64_t)Value < 0) {553      Value = -Value;554      opc = 5;555    }556 557    uint32_t out = (opc << 21);558    out |= (Value & 0x800) << 15;559    out |= (Value & 0x700) << 4;560    out |= (Value & 0x0FF);561 562    return swapHalfWords(out, Endian == llvm::endianness::little);563  }564 565  case ARM::fixup_arm_condbranch:566  case ARM::fixup_arm_uncondbranch:567  case ARM::fixup_arm_uncondbl:568  case ARM::fixup_arm_condbl:569  case ARM::fixup_arm_blx:570    // Check that the relocation value is legal.571    Value -= 8;572    if (!isInt<26>(Value)) {573      Ctx.reportError(Fixup.getLoc(), "Relocation out of range");574      return 0;575    }576    // Alignment differs for blx. Because we are switching to thumb ISA, we use577    // 16-bit alignment. Otherwise, use 32-bit.578    if ((Kind == ARM::fixup_arm_blx && Value % 2 != 0) ||579        (Kind != ARM::fixup_arm_blx && Value % 4 != 0)) {580      Ctx.reportError(Fixup.getLoc(), "Relocation not aligned");581      return 0;582    }583 584    // These values don't encode the low two bits since they're always zero.585    // Offset by 8 just as above.586    if (const MCSymbolRefExpr *SRE =587            dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))588      if (SRE->getSpecifier() == ARM::S_TLSCALL)589        return 0;590    return 0xffffff & (Value >> 2);591  case ARM::fixup_t2_uncondbranch: {592    if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&593        Value != 4) {594      // MSVC link.exe and lld do not support this relocation type595      // with a non-zero offset. ("Value" is offset by 4 at this point.)596      Ctx.reportError(Fixup.getLoc(),597                      "cannot perform a PC-relative fixup with a non-zero "598                      "symbol offset");599    }600    Value = Value - 4;601    if (!isInt<25>(Value)) {602      Ctx.reportError(Fixup.getLoc(), "Relocation out of range");603      return 0;604    }605 606    Value >>= 1; // Low bit is not encoded.607 608    uint32_t out = 0;609    bool I = Value & 0x800000;610    bool J1 = Value & 0x400000;611    bool J2 = Value & 0x200000;612    J1 ^= I;613    J2 ^= I;614 615    out |= I << 26;                 // S bit616    out |= !J1 << 13;               // J1 bit617    out |= !J2 << 11;               // J2 bit618    out |= (Value & 0x1FF800) << 5; // imm6 field619    out |= (Value & 0x0007FF);      // imm11 field620 621    return swapHalfWords(out, Endian == llvm::endianness::little);622  }623  case ARM::fixup_t2_condbranch: {624    Value = Value - 4;625    if (!isInt<21>(Value)) {626      Ctx.reportError(Fixup.getLoc(), "Relocation out of range");627      return 0;628    }629 630    Value >>= 1; // Low bit is not encoded.631 632    uint64_t out = 0;633    out |= (Value & 0x80000) << 7; // S bit634    out |= (Value & 0x40000) >> 7; // J2 bit635    out |= (Value & 0x20000) >> 4; // J1 bit636    out |= (Value & 0x1F800) << 5; // imm6 field637    out |= (Value & 0x007FF);      // imm11 field638 639    return swapHalfWords(out, Endian == llvm::endianness::little);640  }641  case ARM::fixup_arm_thumb_bl: {642    if (!isInt<25>(Value - 4) ||643        (!STI->hasFeature(ARM::FeatureThumb2) &&644         !STI->hasFeature(ARM::HasV8MBaselineOps) &&645         !STI->hasFeature(ARM::HasV6MOps) &&646         !isInt<23>(Value - 4))) {647      Ctx.reportError(Fixup.getLoc(), "Relocation out of range");648      return 0;649    }650    if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&651        Value != 4) {652      // MSVC link.exe and lld do not support this relocation type653      // with a non-zero offset. ("Value" is offset by 4 at this point.)654      Ctx.reportError(Fixup.getLoc(),655                      "cannot perform a PC-relative fixup with a non-zero "656                      "symbol offset");657    }658 659    // The value doesn't encode the low bit (always zero) and is offset by660    // four. The 32-bit immediate value is encoded as661    //   imm32 = SignExtend(S:I1:I2:imm10:imm11:0)662    // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).663    // The value is encoded into disjoint bit positions in the destination664    // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,665    // J = either J1 or J2 bit666    //667    //   BL:  xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII668    //669    // Note that the halfwords are stored high first, low second; so we need670    // to transpose the fixup value here to map properly.671    uint32_t offset = (Value - 4) >> 1;672    uint32_t signBit = (offset & 0x800000) >> 23;673    uint32_t I1Bit = (offset & 0x400000) >> 22;674    uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;675    uint32_t I2Bit = (offset & 0x200000) >> 21;676    uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;677    uint32_t imm10Bits = (offset & 0x1FF800) >> 11;678    uint32_t imm11Bits = (offset & 0x000007FF);679 680    uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);681    uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |682                           (uint16_t)imm11Bits);683    return joinHalfWords(FirstHalf, SecondHalf,684                         Endian == llvm::endianness::little);685  }686  case ARM::fixup_arm_thumb_blx: {687    if (STI->getTargetTriple().isOSBinFormatCOFF() && !IsResolved &&688        Value != 4) {689      // MSVC link.exe and lld do not support this relocation type690      // with a non-zero offset. ("Value" is offset by 4 at this point.)691      Ctx.reportError(Fixup.getLoc(),692                      "cannot perform a PC-relative fixup with a non-zero "693                      "symbol offset");694    }695    // The value doesn't encode the low two bits (always zero) and is offset by696    // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as697    //   imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)698    // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).699    // The value is encoded into disjoint bit positions in the destination700    // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,701    // J = either J1 or J2 bit, 0 = zero.702    //703    //   BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0704    //705    // Note that the halfwords are stored high first, low second; so we need706    // to transpose the fixup value here to map properly.707    if (Value % 4 != 0) {708      Ctx.reportError(Fixup.getLoc(), "misaligned ARM call destination");709      return 0;710    }711 712    uint32_t offset = (Value - 4) >> 2;713    if (const MCSymbolRefExpr *SRE =714            dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))715      if (SRE->getSpecifier() == ARM::S_TLSCALL)716        offset = 0;717    uint32_t signBit = (offset & 0x400000) >> 22;718    uint32_t I1Bit = (offset & 0x200000) >> 21;719    uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;720    uint32_t I2Bit = (offset & 0x100000) >> 20;721    uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;722    uint32_t imm10HBits = (offset & 0xFFC00) >> 10;723    uint32_t imm10LBits = (offset & 0x3FF);724 725    uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);726    uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |727                           ((uint16_t)imm10LBits) << 1);728    return joinHalfWords(FirstHalf, SecondHalf,729                         Endian == llvm::endianness::little);730  }731  case ARM::fixup_thumb_adr_pcrel_10:732  case ARM::fixup_arm_thumb_cp:733    // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we734    // could have an error on our hands.735    assert(STI != nullptr);736    if (!STI->hasFeature(ARM::FeatureThumb2) && IsResolved) {737      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);738      if (FixupDiagnostic) {739        Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);740        return 0;741      }742    }743    // Offset by 4, and don't encode the low two bits.744    return ((Value - 4) >> 2) & 0xff;745  case ARM::fixup_arm_thumb_cb: {746    // CB instructions can only branch to offsets in [4, 126] in multiples of 2747    // so ensure that the raw value LSB is zero and it lies in [2, 130].748    // An offset of 2 will be relaxed to a NOP.749    if ((int64_t)Value < 2 || Value > 0x82 || Value & 1) {750      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");751      return 0;752    }753    // Offset by 4 and don't encode the lower bit, which is always 0.754    // FIXME: diagnose if no Thumb2755    uint32_t Binary = (Value - 4) >> 1;756    return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);757  }758  case ARM::fixup_arm_thumb_br:759    // Offset by 4 and don't encode the lower bit, which is always 0.760    assert(STI != nullptr);761    if (!STI->hasFeature(ARM::FeatureThumb2) &&762        !STI->hasFeature(ARM::HasV8MBaselineOps)) {763      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);764      if (FixupDiagnostic) {765        Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);766        return 0;767      }768    }769    return ((Value - 4) >> 1) & 0x7ff;770  case ARM::fixup_arm_thumb_bcc:771    // Offset by 4 and don't encode the lower bit, which is always 0.772    assert(STI != nullptr);773    if (!STI->hasFeature(ARM::FeatureThumb2)) {774      const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);775      if (FixupDiagnostic) {776        Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);777        return 0;778      }779    }780    return ((Value - 4) >> 1) & 0xff;781  case ARM::fixup_arm_pcrel_10_unscaled: {782    Value = Value - 8; // ARM fixups offset by an additional word and don't783                       // need to adjust for the half-word ordering.784    bool isAdd = true;785    if ((int64_t)Value < 0) {786      Value = -Value;787      isAdd = false;788    }789    // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8].790    if (Value >= 256) {791      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");792      return 0;793    }794    Value = (Value & 0xf) | ((Value & 0xf0) << 4);795    return Value | (isAdd << 23);796  }797  case ARM::fixup_arm_pcrel_10:798    Value = Value - 4; // ARM fixups offset by an additional word and don't799                       // need to adjust for the half-word ordering.800    [[fallthrough]];801  case ARM::fixup_t2_pcrel_10: {802    // Offset by 4, adjusted by two due to the half-word ordering of thumb.803    Value = Value - 4;804    bool isAdd = true;805    if ((int64_t)Value < 0) {806      Value = -Value;807      isAdd = false;808    }809    // These values don't encode the low two bits since they're always zero.810    Value >>= 2;811    if (Value >= 256) {812      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");813      return 0;814    }815    Value |= isAdd << 23;816 817    // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords818    // swapped.819    if (Kind == ARM::fixup_t2_pcrel_10)820      return swapHalfWords(Value, Endian == llvm::endianness::little);821 822    return Value;823  }824  case ARM::fixup_arm_pcrel_9:825    Value = Value - 4; // ARM fixups offset by an additional word and don't826                       // need to adjust for the half-word ordering.827    [[fallthrough]];828  case ARM::fixup_t2_pcrel_9: {829    // Offset by 4, adjusted by two due to the half-word ordering of thumb.830    Value = Value - 4;831    bool isAdd = true;832    if ((int64_t)Value < 0) {833      Value = -Value;834      isAdd = false;835    }836    // These values don't encode the low bit since it's always zero.837    if (Value & 1) {838      Ctx.reportError(Fixup.getLoc(), "invalid value for this fixup");839      return 0;840    }841    Value >>= 1;842    if (Value >= 256) {843      Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");844      return 0;845    }846    Value |= isAdd << 23;847 848    // Same addressing mode as fixup_arm_pcrel_9, but with 16-bit halfwords849    // swapped.850    if (Kind == ARM::fixup_t2_pcrel_9)851      return swapHalfWords(Value, Endian == llvm::endianness::little);852 853    return Value;854  }855  case ARM::fixup_arm_mod_imm:856    Value = ARM_AM::getSOImmVal(Value);857    if (Value >> 12) {858      Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value");859      return 0;860    }861    return Value;862  case ARM::fixup_t2_so_imm: {863    Value = ARM_AM::getT2SOImmVal(Value);864    if ((int64_t)Value < 0) {865      Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value");866      return 0;867    }868    // Value will contain a 12-bit value broken up into a 4-bit shift in bits869    // 11:8 and the 8-bit immediate in 0:7. The instruction has the immediate870    // in 0:7. The 4-bit shift is split up into i:imm3 where i is placed at bit871    // 10 of the upper half-word and imm3 is placed at 14:12 of the lower872    // half-word.873    uint64_t EncValue = 0;874    EncValue |= (Value & 0x800) << 15;875    EncValue |= (Value & 0x700) << 4;876    EncValue |= (Value & 0xff);877    return swapHalfWords(EncValue, Endian == llvm::endianness::little);878  }879  case ARM::fixup_bf_branch: {880    const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);881    if (FixupDiagnostic) {882      Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);883      return 0;884    }885    uint32_t out = (((Value - 4) >> 1) & 0xf) << 23;886    return swapHalfWords(out, Endian == llvm::endianness::little);887  }888  case ARM::fixup_bf_target:889  case ARM::fixup_bfl_target:890  case ARM::fixup_bfc_target: {891    const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);892    if (FixupDiagnostic) {893      Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);894      return 0;895    }896    uint32_t out = 0;897    uint32_t HighBitMask = (Kind == ARM::fixup_bf_target ? 0xf800 :898                            Kind == ARM::fixup_bfl_target ? 0x3f800 : 0x800);899    out |= (((Value - 4) >> 1) & 0x1) << 11;900    out |= (((Value - 4) >> 1) & 0x7fe);901    out |= (((Value - 4) >> 1) & HighBitMask) << 5;902    return swapHalfWords(out, Endian == llvm::endianness::little);903  }904  case ARM::fixup_bfcsel_else_target: {905    // If this is a fixup of a branch future's else target then it should be a906    // constant MCExpr representing the distance between the branch targetted907    // and the instruction after that same branch.908    Value = Target.getConstant();909 910    const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);911    if (FixupDiagnostic) {912      Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);913      return 0;914    }915    uint32_t out = ((Value >> 2) & 1) << 17;916    return swapHalfWords(out, Endian == llvm::endianness::little);917  }918  case ARM::fixup_wls:919  case ARM::fixup_le: {920    const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);921    if (FixupDiagnostic) {922      Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);923      return 0;924    }925    uint64_t real_value = Value - 4;926    uint32_t out = 0;927    if (Kind == ARM::fixup_le)928      real_value = -real_value;929    out |= ((real_value >> 1) & 0x1) << 11;930    out |= ((real_value >> 1) & 0x7fe);931    return swapHalfWords(out, Endian == llvm::endianness::little);932  }933  }934}935 936bool ARMAsmBackend::shouldForceRelocation(const MCFixup &Fixup,937                                          const MCValue &Target) {938  const MCSymbol *Sym = Target.getAddSym();939  const unsigned FixupKind = Fixup.getKind();940  // Create relocations for unconditional branches to function symbols with941  // different execution mode in ELF binaries.942  if (needsInterworking(*Asm, Sym, Fixup.getKind()))943    return true;944  // We must always generate a relocation for BL/BLX instructions if we have945  // a symbol to reference, as the linker relies on knowing the destination946  // symbol's thumb-ness to get interworking right.947  if (Sym && (FixupKind == ARM::fixup_arm_thumb_blx ||948              FixupKind == ARM::fixup_arm_blx ||949              FixupKind == ARM::fixup_arm_uncondbl ||950              FixupKind == ARM::fixup_arm_condbl))951    return true;952  return Target.getSpecifier();953}954 955/// getFixupKindNumBytes - The number of bytes the fixup may change.956static unsigned getFixupKindNumBytes(unsigned Kind) {957  switch (Kind) {958  default:959    llvm_unreachable("Unknown fixup kind!");960 961  case FK_Data_1:962  case ARM::fixup_arm_thumb_bcc:963  case ARM::fixup_arm_thumb_cp:964  case ARM::fixup_thumb_adr_pcrel_10:965  case ARM::fixup_arm_thumb_upper_8_15:966  case ARM::fixup_arm_thumb_upper_0_7:967  case ARM::fixup_arm_thumb_lower_8_15:968  case ARM::fixup_arm_thumb_lower_0_7:969    return 1;970 971  case FK_Data_2:972  case ARM::fixup_arm_thumb_br:973  case ARM::fixup_arm_thumb_cb:974  case ARM::fixup_arm_mod_imm:975    return 2;976 977  case ARM::fixup_arm_pcrel_10_unscaled:978  case ARM::fixup_arm_ldst_pcrel_12:979  case ARM::fixup_arm_pcrel_10:980  case ARM::fixup_arm_pcrel_9:981  case ARM::fixup_arm_ldst_abs_12:982  case ARM::fixup_arm_adr_pcrel_12:983  case ARM::fixup_arm_uncondbl:984  case ARM::fixup_arm_condbl:985  case ARM::fixup_arm_blx:986  case ARM::fixup_arm_condbranch:987  case ARM::fixup_arm_uncondbranch:988    return 3;989 990  case FK_Data_4:991  case ARM::fixup_t2_ldst_pcrel_12:992  case ARM::fixup_t2_condbranch:993  case ARM::fixup_t2_uncondbranch:994  case ARM::fixup_t2_pcrel_10:995  case ARM::fixup_t2_pcrel_9:996  case ARM::fixup_t2_adr_pcrel_12:997  case ARM::fixup_arm_thumb_bl:998  case ARM::fixup_arm_thumb_blx:999  case ARM::fixup_arm_movt_hi16:1000  case ARM::fixup_arm_movw_lo16:1001  case ARM::fixup_t2_movt_hi16:1002  case ARM::fixup_t2_movw_lo16:1003  case ARM::fixup_t2_so_imm:1004  case ARM::fixup_bf_branch:1005  case ARM::fixup_bf_target:1006  case ARM::fixup_bfl_target:1007  case ARM::fixup_bfc_target:1008  case ARM::fixup_bfcsel_else_target:1009  case ARM::fixup_wls:1010  case ARM::fixup_le:1011    return 4;1012 1013  case FK_SecRel_2:1014    return 2;1015  case FK_SecRel_4:1016    return 4;1017  }1018}1019 1020/// getFixupKindContainerSizeBytes - The number of bytes of the1021/// container involved in big endian.1022static unsigned getFixupKindContainerSizeBytes(unsigned Kind) {1023  switch (Kind) {1024  default:1025    llvm_unreachable("Unknown fixup kind!");1026 1027  case FK_Data_1:1028    return 1;1029  case FK_Data_2:1030    return 2;1031  case FK_Data_4:1032    return 4;1033 1034  case ARM::fixup_arm_thumb_bcc:1035  case ARM::fixup_arm_thumb_cp:1036  case ARM::fixup_thumb_adr_pcrel_10:1037  case ARM::fixup_arm_thumb_br:1038  case ARM::fixup_arm_thumb_cb:1039  case ARM::fixup_arm_thumb_upper_8_15:1040  case ARM::fixup_arm_thumb_upper_0_7:1041  case ARM::fixup_arm_thumb_lower_8_15:1042  case ARM::fixup_arm_thumb_lower_0_7:1043    // Instruction size is 2 bytes.1044    return 2;1045 1046  case ARM::fixup_arm_pcrel_10_unscaled:1047  case ARM::fixup_arm_ldst_pcrel_12:1048  case ARM::fixup_arm_pcrel_10:1049  case ARM::fixup_arm_pcrel_9:1050  case ARM::fixup_arm_adr_pcrel_12:1051  case ARM::fixup_arm_uncondbl:1052  case ARM::fixup_arm_condbl:1053  case ARM::fixup_arm_blx:1054  case ARM::fixup_arm_condbranch:1055  case ARM::fixup_arm_uncondbranch:1056  case ARM::fixup_t2_ldst_pcrel_12:1057  case ARM::fixup_t2_condbranch:1058  case ARM::fixup_t2_uncondbranch:1059  case ARM::fixup_t2_pcrel_10:1060  case ARM::fixup_t2_pcrel_9:1061  case ARM::fixup_t2_adr_pcrel_12:1062  case ARM::fixup_arm_thumb_bl:1063  case ARM::fixup_arm_thumb_blx:1064  case ARM::fixup_arm_movt_hi16:1065  case ARM::fixup_arm_movw_lo16:1066  case ARM::fixup_t2_movt_hi16:1067  case ARM::fixup_t2_movw_lo16:1068  case ARM::fixup_arm_mod_imm:1069  case ARM::fixup_t2_so_imm:1070  case ARM::fixup_bf_branch:1071  case ARM::fixup_bf_target:1072  case ARM::fixup_bfl_target:1073  case ARM::fixup_bfc_target:1074  case ARM::fixup_bfcsel_else_target:1075  case ARM::fixup_wls:1076  case ARM::fixup_le:1077    // Instruction size is 4 bytes.1078    return 4;1079  }1080}1081 1082std::optional<bool> ARMAsmBackend::evaluateFixup(const MCFragment &F,1083                                                 MCFixup &Fixup, MCValue &,1084                                                 uint64_t &Value) {1085  // For a few PC-relative fixups in Thumb mode, offsets need to be aligned1086  // down. We compensate here because the default handler's `Value` decrement1087  // doesn't account for this alignment.1088  switch (Fixup.getKind()) {1089  case ARM::fixup_t2_ldst_pcrel_12:1090  case ARM::fixup_t2_pcrel_10:1091  case ARM::fixup_t2_pcrel_9:1092  case ARM::fixup_thumb_adr_pcrel_10:1093  case ARM::fixup_t2_adr_pcrel_12:1094  case ARM::fixup_arm_thumb_blx:1095  case ARM::fixup_arm_thumb_cp:1096    Value = (Asm->getFragmentOffset(F) + Fixup.getOffset()) % 4;1097  }1098  return {};1099}1100 1101void ARMAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,1102                               const MCValue &Target, uint8_t *Data,1103                               uint64_t Value, bool IsResolved) {1104  if (IsResolved && shouldForceRelocation(Fixup, Target))1105    IsResolved = false;1106  maybeAddReloc(F, Fixup, Target, Value, IsResolved);1107  auto Kind = Fixup.getKind();1108  if (mc::isRelocation(Kind))1109    return;1110  MCContext &Ctx = getContext();1111  Value = adjustFixupValue(*Asm, Fixup, Target, Value, IsResolved, Ctx,1112                           getSubtargetInfo(F));1113  if (!Value)1114    return; // Doesn't change encoding.1115  const unsigned NumBytes = getFixupKindNumBytes(Kind);1116 1117  assert(Fixup.getOffset() + NumBytes <= F.getSize() &&1118         "Invalid fixup offset!");1119 1120  // Used to point to big endian bytes.1121  unsigned FullSizeBytes;1122  if (Endian == llvm::endianness::big) {1123    FullSizeBytes = getFixupKindContainerSizeBytes(Kind);1124    assert(Fixup.getOffset() + FullSizeBytes <= F.getSize() &&1125           "Invalid fixup size!");1126    assert(NumBytes <= FullSizeBytes && "Invalid fixup size!");1127  }1128 1129  // For each byte of the fragment that the fixup touches, mask in the bits from1130  // the fixup value. The Value has been "split up" into the appropriate1131  // bitfields above.1132  for (unsigned i = 0; i != NumBytes; ++i) {1133    unsigned Idx =1134        Endian == llvm::endianness::little ? i : (FullSizeBytes - 1 - i);1135    Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);1136  }1137}1138 1139namespace CU {1140 1141/// Compact unwind encoding values.1142enum CompactUnwindEncodings {1143  UNWIND_ARM_MODE_MASK                         = 0x0F000000,1144  UNWIND_ARM_MODE_FRAME                        = 0x01000000,1145  UNWIND_ARM_MODE_FRAME_D                      = 0x02000000,1146  UNWIND_ARM_MODE_DWARF                        = 0x04000000,1147 1148  UNWIND_ARM_FRAME_STACK_ADJUST_MASK           = 0x00C00000,1149 1150  UNWIND_ARM_FRAME_FIRST_PUSH_R4               = 0x00000001,1151  UNWIND_ARM_FRAME_FIRST_PUSH_R5               = 0x00000002,1152  UNWIND_ARM_FRAME_FIRST_PUSH_R6               = 0x00000004,1153 1154  UNWIND_ARM_FRAME_SECOND_PUSH_R8              = 0x00000008,1155  UNWIND_ARM_FRAME_SECOND_PUSH_R9              = 0x00000010,1156  UNWIND_ARM_FRAME_SECOND_PUSH_R10             = 0x00000020,1157  UNWIND_ARM_FRAME_SECOND_PUSH_R11             = 0x00000040,1158  UNWIND_ARM_FRAME_SECOND_PUSH_R12             = 0x00000080,1159 1160  UNWIND_ARM_FRAME_D_REG_COUNT_MASK            = 0x00000F00,1161 1162  UNWIND_ARM_DWARF_SECTION_OFFSET              = 0x00FFFFFF1163};1164 1165} // end CU namespace1166 1167/// Generate compact unwind encoding for the function based on the CFI1168/// instructions. If the CFI instructions describe a frame that cannot be1169/// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which1170/// tells the runtime to fallback and unwind using dwarf.1171uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(1172    const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const {1173  DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n");1174  // Only armv7k uses CFI based unwinding.1175  if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K)1176    return 0;1177  // No .cfi directives means no frame.1178  ArrayRef<MCCFIInstruction> Instrs = FI->Instructions;1179  if (Instrs.empty())1180    return 0;1181  if (!isDarwinCanonicalPersonality(FI->Personality) &&1182      !Ctxt->emitCompactUnwindNonCanonical())1183    return CU::UNWIND_ARM_MODE_DWARF;1184 1185  // Start off assuming CFA is at SP+0.1186  MCRegister CFARegister = ARM::SP;1187  int CFARegisterOffset = 0;1188  // Mark savable registers as initially unsaved1189  DenseMap<MCRegister, int> RegOffsets;1190  int FloatRegCount = 0;1191  // Process each .cfi directive and build up compact unwind info.1192  for (const MCCFIInstruction &Inst : Instrs) {1193    MCRegister Reg;1194    switch (Inst.getOperation()) {1195    case MCCFIInstruction::OpDefCfa: // DW_CFA_def_cfa1196      CFARegisterOffset = Inst.getOffset();1197      CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true);1198      break;1199    case MCCFIInstruction::OpDefCfaOffset: // DW_CFA_def_cfa_offset1200      CFARegisterOffset = Inst.getOffset();1201      break;1202    case MCCFIInstruction::OpDefCfaRegister: // DW_CFA_def_cfa_register1203      CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true);1204      break;1205    case MCCFIInstruction::OpOffset: // DW_CFA_offset1206      Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true);1207      if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))1208        RegOffsets[Reg] = Inst.getOffset();1209      else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {1210        RegOffsets[Reg] = Inst.getOffset();1211        ++FloatRegCount;1212      } else {1213        DEBUG_WITH_TYPE("compact-unwind",1214                        llvm::dbgs() << ".cfi_offset on unknown register="1215                                     << Inst.getRegister() << "\n");1216        return CU::UNWIND_ARM_MODE_DWARF;1217      }1218      break;1219    case MCCFIInstruction::OpRelOffset: // DW_CFA_advance_loc1220      // Ignore1221      break;1222    default:1223      // Directive not convertable to compact unwind, bail out.1224      DEBUG_WITH_TYPE("compact-unwind",1225                      llvm::dbgs()1226                          << "CFI directive not compatible with compact "1227                             "unwind encoding, opcode="1228                          << uint8_t(Inst.getOperation()) << "\n");1229      return CU::UNWIND_ARM_MODE_DWARF;1230      break;1231    }1232  }1233 1234  // If no frame set up, return no unwind info.1235  if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))1236    return 0;1237 1238  // Verify standard frame (lr/r7) was used.1239  if (CFARegister != ARM::R7) {1240    DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "frame register is "1241                                                   << CFARegister.id()1242                                                   << " instead of r7\n");1243    return CU::UNWIND_ARM_MODE_DWARF;1244  }1245  int StackAdjust = CFARegisterOffset - 8;1246  if (RegOffsets.lookup(ARM::LR) != (-4 - StackAdjust)) {1247    DEBUG_WITH_TYPE(1248        "compact-unwind",1249        llvm::dbgs() << "LR not saved as standard frame, StackAdjust="1250                     << StackAdjust1251                     << ", CFARegisterOffset=" << CFARegisterOffset1252                     << ", lr save at offset=" << RegOffsets[ARM::LR] << "\n");1253    return CU::UNWIND_ARM_MODE_DWARF;1254  }1255  if (RegOffsets.lookup(ARM::R7) != (-8 - StackAdjust)) {1256    DEBUG_WITH_TYPE("compact-unwind",1257                    llvm::dbgs() << "r7 not saved as standard frame\n");1258    return CU::UNWIND_ARM_MODE_DWARF;1259  }1260  uint32_t CompactUnwindEncoding = CU::UNWIND_ARM_MODE_FRAME;1261 1262  // If var-args are used, there may be a stack adjust required.1263  switch (StackAdjust) {1264  case 0:1265    break;1266  case 4:1267    CompactUnwindEncoding |= 0x00400000;1268    break;1269  case 8:1270    CompactUnwindEncoding |= 0x00800000;1271    break;1272  case 12:1273    CompactUnwindEncoding |= 0x00C00000;1274    break;1275  default:1276    DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs()1277                                          << ".cfi_def_cfa stack adjust ("1278                                          << StackAdjust << ") out of range\n");1279    return CU::UNWIND_ARM_MODE_DWARF;1280  }1281 1282  // If r6 is saved, it must be right below r7.1283  static struct {1284    unsigned Reg;1285    unsigned Encoding;1286  } GPRCSRegs[] = {{ARM::R6, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R6},1287                   {ARM::R5, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R5},1288                   {ARM::R4, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R4},1289                   {ARM::R12, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R12},1290                   {ARM::R11, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R11},1291                   {ARM::R10, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R10},1292                   {ARM::R9, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R9},1293                   {ARM::R8, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R8}};1294 1295  int CurOffset = -8 - StackAdjust;1296  for (auto CSReg : GPRCSRegs) {1297    auto Offset = RegOffsets.find(CSReg.Reg);1298    if (Offset == RegOffsets.end())1299      continue;1300 1301    int RegOffset = Offset->second;1302    if (RegOffset != CurOffset - 4) {1303      DEBUG_WITH_TYPE("compact-unwind",1304                      llvm::dbgs() << MRI.getName(CSReg.Reg) << " saved at "1305                                   << RegOffset << " but only supported at "1306                                   << CurOffset << "\n");1307      return CU::UNWIND_ARM_MODE_DWARF;1308    }1309    CompactUnwindEncoding |= CSReg.Encoding;1310    CurOffset -= 4;1311  }1312 1313  // If no floats saved, we are done.1314  if (FloatRegCount == 0)1315    return CompactUnwindEncoding;1316 1317  // Switch mode to include D register saving.1318  CompactUnwindEncoding &= ~CU::UNWIND_ARM_MODE_MASK;1319  CompactUnwindEncoding |= CU::UNWIND_ARM_MODE_FRAME_D;1320 1321  // FIXME: supporting more than 4 saved D-registers compactly would be trivial,1322  // but needs coordination with the linker and libunwind.1323  if (FloatRegCount > 4) {1324    DEBUG_WITH_TYPE("compact-unwind",1325                    llvm::dbgs() << "unsupported number of D registers saved ("1326                                 << FloatRegCount << ")\n");1327      return CU::UNWIND_ARM_MODE_DWARF;1328  }1329 1330  // Floating point registers must either be saved sequentially, or we defer to1331  // DWARF. No gaps allowed here so check that each saved d-register is1332  // precisely where it should be.1333  static MCPhysReg FPRCSRegs[] = {ARM::D8, ARM::D10, ARM::D12, ARM::D14};1334  for (int Idx = FloatRegCount - 1; Idx >= 0; --Idx) {1335    auto Offset = RegOffsets.find(FPRCSRegs[Idx]);1336    if (Offset == RegOffsets.end()) {1337      DEBUG_WITH_TYPE("compact-unwind",1338                      llvm::dbgs() << FloatRegCount << " D-regs saved, but "1339                                   << MRI.getName(FPRCSRegs[Idx])1340                                   << " not saved\n");1341      return CU::UNWIND_ARM_MODE_DWARF;1342    } else if (Offset->second != CurOffset - 8) {1343      DEBUG_WITH_TYPE("compact-unwind",1344                      llvm::dbgs() << FloatRegCount << " D-regs saved, but "1345                                   << MRI.getName(FPRCSRegs[Idx])1346                                   << " saved at " << Offset->second1347                                   << ", expected at " << CurOffset - 81348                                   << "\n");1349      return CU::UNWIND_ARM_MODE_DWARF;1350    }1351    CurOffset -= 8;1352  }1353 1354  return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);1355}1356 1357static MCAsmBackend *createARMAsmBackend(const Target &T,1358                                         const MCSubtargetInfo &STI,1359                                         const MCRegisterInfo &MRI,1360                                         const MCTargetOptions &Options,1361                                         llvm::endianness Endian) {1362  const Triple &TheTriple = STI.getTargetTriple();1363  switch (TheTriple.getObjectFormat()) {1364  default:1365    llvm_unreachable("unsupported object format");1366  case Triple::MachO:1367    return new ARMAsmBackendDarwin(T, STI, MRI);1368  case Triple::COFF:1369    assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");1370    return new ARMAsmBackendWinCOFF(T);1371  case Triple::ELF:1372    assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target");1373    uint8_t OSABI = Options.FDPIC1374                        ? static_cast<uint8_t>(ELF::ELFOSABI_ARM_FDPIC)1375                        : MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());1376    return new ARMAsmBackendELF(T, OSABI, Endian);1377  }1378}1379 1380MCAsmBackend *llvm::createARMLEAsmBackend(const Target &T,1381                                          const MCSubtargetInfo &STI,1382                                          const MCRegisterInfo &MRI,1383                                          const MCTargetOptions &Options) {1384  return createARMAsmBackend(T, STI, MRI, Options, llvm::endianness::little);1385}1386 1387MCAsmBackend *llvm::createARMBEAsmBackend(const Target &T,1388                                          const MCSubtargetInfo &STI,1389                                          const MCRegisterInfo &MRI,1390                                          const MCTargetOptions &Options) {1391  return createARMAsmBackend(T, STI, MRI, Options, llvm::endianness::big);1392}1393