xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
10b57cec5SDimitry Andric //===-- ARMAsmBackend.cpp - ARM Assembler Backend -------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/ARMAsmBackend.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/ARMAsmBackendDarwin.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/ARMAsmBackendELF.h"
130b57cec5SDimitry Andric #include "MCTargetDesc/ARMAsmBackendWinCOFF.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/ARMFixupKinds.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCTargetDesc.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
180b57cec5SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCSectionELF.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
310fca6ea1SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
330b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
340b57cec5SDimitry Andric #include "llvm/Support/EndianStream.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Support/Format.h"
370b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric namespace {
410b57cec5SDimitry Andric class ARMELFObjectWriter : public MCELFObjectTargetWriter {
420b57cec5SDimitry Andric public:
430b57cec5SDimitry Andric   ARMELFObjectWriter(uint8_t OSABI)
440b57cec5SDimitry Andric       : MCELFObjectTargetWriter(/*Is64Bit*/ false, OSABI, ELF::EM_ARM,
450b57cec5SDimitry Andric                                 /*HasRelocationAddend*/ false) {}
460b57cec5SDimitry Andric };
470b57cec5SDimitry Andric } // end anonymous namespace
480b57cec5SDimitry Andric 
49bdd1243dSDimitry Andric std::optional<MCFixupKind> ARMAsmBackend::getFixupKind(StringRef Name) const {
50bdd1243dSDimitry Andric   return std::nullopt;
51349cc55cSDimitry Andric }
520b57cec5SDimitry Andric 
53bdd1243dSDimitry Andric std::optional<MCFixupKind>
54bdd1243dSDimitry Andric ARMAsmBackendELF::getFixupKind(StringRef Name) const {
555ffd83dbSDimitry Andric   unsigned Type = llvm::StringSwitch<unsigned>(Name)
565ffd83dbSDimitry Andric #define ELF_RELOC(X, Y) .Case(#X, Y)
575ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELFRelocs/ARM.def"
585ffd83dbSDimitry Andric #undef ELF_RELOC
59fe6060f1SDimitry Andric                       .Case("BFD_RELOC_NONE", ELF::R_ARM_NONE)
60fe6060f1SDimitry Andric                       .Case("BFD_RELOC_8", ELF::R_ARM_ABS8)
61fe6060f1SDimitry Andric                       .Case("BFD_RELOC_16", ELF::R_ARM_ABS16)
62fe6060f1SDimitry Andric                       .Case("BFD_RELOC_32", ELF::R_ARM_ABS32)
635ffd83dbSDimitry Andric                       .Default(-1u);
645ffd83dbSDimitry Andric   if (Type == -1u)
65bdd1243dSDimitry Andric     return std::nullopt;
665ffd83dbSDimitry Andric   return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric const MCFixupKindInfo &ARMAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
700b57cec5SDimitry Andric   const static MCFixupKindInfo InfosLE[ARM::NumTargetFixupKinds] = {
710b57cec5SDimitry Andric       // This table *must* be in the order that the fixup_* kinds are defined in
720b57cec5SDimitry Andric       // ARMFixupKinds.h.
730b57cec5SDimitry Andric       //
740b57cec5SDimitry Andric       // Name                      Offset (bits) Size (bits)     Flags
755f757f3fSDimitry Andric       {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
760b57cec5SDimitry Andric       {"fixup_t2_ldst_pcrel_12", 0, 32,
775f757f3fSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
785f757f3fSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
795f757f3fSDimitry Andric       {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
807a6dacacSDimitry Andric       {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
810b57cec5SDimitry Andric       {"fixup_t2_pcrel_10", 0, 32,
820b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
830b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
840b57cec5SDimitry Andric       {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
850b57cec5SDimitry Andric       {"fixup_t2_pcrel_9", 0, 32,
867a6dacacSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
877a6dacacSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
88fe6060f1SDimitry Andric       {"fixup_arm_ldst_abs_12", 0, 32, 0},
890b57cec5SDimitry Andric       {"fixup_thumb_adr_pcrel_10", 0, 8,
905f757f3fSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
915f757f3fSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
925f757f3fSDimitry Andric       {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
930b57cec5SDimitry Andric       {"fixup_t2_adr_pcrel_12", 0, 32,
945f757f3fSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
955f757f3fSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
960b57cec5SDimitry Andric       {"fixup_arm_condbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
970b57cec5SDimitry Andric       {"fixup_arm_uncondbranch", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
980b57cec5SDimitry Andric       {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
990b57cec5SDimitry Andric       {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1000b57cec5SDimitry Andric       {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
1010b57cec5SDimitry Andric       {"fixup_arm_uncondbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
1020b57cec5SDimitry Andric       {"fixup_arm_condbl", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
1030b57cec5SDimitry Andric       {"fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel},
1040b57cec5SDimitry Andric       {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1050b57cec5SDimitry Andric       {"fixup_arm_thumb_blx", 0, 32,
1060b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1070b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1080b57cec5SDimitry Andric       {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
1090b57cec5SDimitry Andric       {"fixup_arm_thumb_cp", 0, 8,
1100b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1110b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1120b57cec5SDimitry Andric       {"fixup_arm_thumb_bcc", 0, 8, MCFixupKindInfo::FKF_IsPCRel},
1130b57cec5SDimitry Andric       // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16
1140b57cec5SDimitry Andric       // - 19.
1150b57cec5SDimitry Andric       {"fixup_arm_movt_hi16", 0, 20, 0},
1160b57cec5SDimitry Andric       {"fixup_arm_movw_lo16", 0, 20, 0},
1170b57cec5SDimitry Andric       {"fixup_t2_movt_hi16", 0, 20, 0},
1180b57cec5SDimitry Andric       {"fixup_t2_movw_lo16", 0, 20, 0},
11906c3fb27SDimitry Andric       {"fixup_arm_thumb_upper_8_15", 0, 8, 0},
12006c3fb27SDimitry Andric       {"fixup_arm_thumb_upper_0_7", 0, 8, 0},
12106c3fb27SDimitry Andric       {"fixup_arm_thumb_lower_8_15", 0, 8, 0},
12206c3fb27SDimitry Andric       {"fixup_arm_thumb_lower_0_7", 0, 8, 0},
1230b57cec5SDimitry Andric       {"fixup_arm_mod_imm", 0, 12, 0},
1240b57cec5SDimitry Andric       {"fixup_t2_so_imm", 0, 26, 0},
1250b57cec5SDimitry Andric       {"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1260b57cec5SDimitry Andric       {"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1270b57cec5SDimitry Andric       {"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1280b57cec5SDimitry Andric       {"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1290b57cec5SDimitry Andric       {"fixup_bfcsel_else_target", 0, 32, 0},
1300b57cec5SDimitry Andric       {"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
131fe6060f1SDimitry Andric       {"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}};
1320b57cec5SDimitry Andric   const static MCFixupKindInfo InfosBE[ARM::NumTargetFixupKinds] = {
1330b57cec5SDimitry Andric       // This table *must* be in the order that the fixup_* kinds are defined in
1340b57cec5SDimitry Andric       // ARMFixupKinds.h.
1350b57cec5SDimitry Andric       //
1360b57cec5SDimitry Andric       // Name                      Offset (bits) Size (bits)     Flags
1375f757f3fSDimitry Andric       {"fixup_arm_ldst_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1380b57cec5SDimitry Andric       {"fixup_t2_ldst_pcrel_12", 0, 32,
1395f757f3fSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1405f757f3fSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1415f757f3fSDimitry Andric       {"fixup_arm_pcrel_10_unscaled", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1427a6dacacSDimitry Andric       {"fixup_arm_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1430b57cec5SDimitry Andric       {"fixup_t2_pcrel_10", 0, 32,
1440b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1450b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1460b57cec5SDimitry Andric       {"fixup_arm_pcrel_9", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1470b57cec5SDimitry Andric       {"fixup_t2_pcrel_9", 0, 32,
1487a6dacacSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1497a6dacacSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
150fe6060f1SDimitry Andric       {"fixup_arm_ldst_abs_12", 0, 32, 0},
1510b57cec5SDimitry Andric       {"fixup_thumb_adr_pcrel_10", 8, 8,
1527a6dacacSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1537a6dacacSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1547a6dacacSDimitry Andric       {"fixup_arm_adr_pcrel_12", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1550b57cec5SDimitry Andric       {"fixup_t2_adr_pcrel_12", 0, 32,
1567a6dacacSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1577a6dacacSDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1580b57cec5SDimitry Andric       {"fixup_arm_condbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
1590b57cec5SDimitry Andric       {"fixup_arm_uncondbranch", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
1600b57cec5SDimitry Andric       {"fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1610b57cec5SDimitry Andric       {"fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1620b57cec5SDimitry Andric       {"fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
1630b57cec5SDimitry Andric       {"fixup_arm_uncondbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
1640b57cec5SDimitry Andric       {"fixup_arm_condbl", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
1650b57cec5SDimitry Andric       {"fixup_arm_blx", 8, 24, MCFixupKindInfo::FKF_IsPCRel},
1660b57cec5SDimitry Andric       {"fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1670b57cec5SDimitry Andric       {"fixup_arm_thumb_blx", 0, 32,
1680b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1690b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1700b57cec5SDimitry Andric       {"fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
1710b57cec5SDimitry Andric       {"fixup_arm_thumb_cp", 8, 8,
1720b57cec5SDimitry Andric        MCFixupKindInfo::FKF_IsPCRel |
1730b57cec5SDimitry Andric            MCFixupKindInfo::FKF_IsAlignedDownTo32Bits},
1740b57cec5SDimitry Andric       {"fixup_arm_thumb_bcc", 8, 8, MCFixupKindInfo::FKF_IsPCRel},
1750b57cec5SDimitry Andric       // movw / movt: 16-bits immediate but scattered into two chunks 0 - 12, 16
1760b57cec5SDimitry Andric       // - 19.
1770b57cec5SDimitry Andric       {"fixup_arm_movt_hi16", 12, 20, 0},
1780b57cec5SDimitry Andric       {"fixup_arm_movw_lo16", 12, 20, 0},
1790b57cec5SDimitry Andric       {"fixup_t2_movt_hi16", 12, 20, 0},
1800b57cec5SDimitry Andric       {"fixup_t2_movw_lo16", 12, 20, 0},
18106c3fb27SDimitry Andric       {"fixup_arm_thumb_upper_8_15", 24, 8, 0},
18206c3fb27SDimitry Andric       {"fixup_arm_thumb_upper_0_7", 24, 8, 0},
18306c3fb27SDimitry Andric       {"fixup_arm_thumb_lower_8_15", 24, 8, 0},
18406c3fb27SDimitry Andric       {"fixup_arm_thumb_lower_0_7", 24, 8, 0},
1850b57cec5SDimitry Andric       {"fixup_arm_mod_imm", 20, 12, 0},
1860b57cec5SDimitry Andric       {"fixup_t2_so_imm", 26, 6, 0},
1870b57cec5SDimitry Andric       {"fixup_bf_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1880b57cec5SDimitry Andric       {"fixup_bf_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1890b57cec5SDimitry Andric       {"fixup_bfl_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1900b57cec5SDimitry Andric       {"fixup_bfc_target", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
1910b57cec5SDimitry Andric       {"fixup_bfcsel_else_target", 0, 32, 0},
1920b57cec5SDimitry Andric       {"fixup_wls", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
193fe6060f1SDimitry Andric       {"fixup_le", 0, 32, MCFixupKindInfo::FKF_IsPCRel}};
1940b57cec5SDimitry Andric 
1955ffd83dbSDimitry Andric   // Fixup kinds from .reloc directive are like R_ARM_NONE. They do not require
1965ffd83dbSDimitry Andric   // any extra processing.
1975ffd83dbSDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
1985ffd83dbSDimitry Andric     return MCAsmBackend::getFixupKindInfo(FK_NONE);
1995ffd83dbSDimitry Andric 
2000b57cec5SDimitry Andric   if (Kind < FirstTargetFixupKind)
2010b57cec5SDimitry Andric     return MCAsmBackend::getFixupKindInfo(Kind);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
2040b57cec5SDimitry Andric          "Invalid kind!");
2055f757f3fSDimitry Andric   return (Endian == llvm::endianness::little
2065f757f3fSDimitry Andric               ? InfosLE
2070b57cec5SDimitry Andric               : InfosBE)[Kind - FirstTargetFixupKind];
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric void ARMAsmBackend::handleAssemblerFlag(MCAssemblerFlag Flag) {
2110b57cec5SDimitry Andric   switch (Flag) {
2120b57cec5SDimitry Andric   default:
2130b57cec5SDimitry Andric     break;
2140b57cec5SDimitry Andric   case MCAF_Code16:
2150b57cec5SDimitry Andric     setIsThumb(true);
2160b57cec5SDimitry Andric     break;
2170b57cec5SDimitry Andric   case MCAF_Code32:
2180b57cec5SDimitry Andric     setIsThumb(false);
2190b57cec5SDimitry Andric     break;
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric unsigned ARMAsmBackend::getRelaxedOpcode(unsigned Op,
2240b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI) const {
22506c3fb27SDimitry Andric   bool HasThumb2 = STI.hasFeature(ARM::FeatureThumb2);
22606c3fb27SDimitry Andric   bool HasV8MBaselineOps = STI.hasFeature(ARM::HasV8MBaselineOps);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   switch (Op) {
2290b57cec5SDimitry Andric   default:
2300b57cec5SDimitry Andric     return Op;
2310b57cec5SDimitry Andric   case ARM::tBcc:
2320b57cec5SDimitry Andric     return HasThumb2 ? (unsigned)ARM::t2Bcc : Op;
2330b57cec5SDimitry Andric   case ARM::tLDRpci:
2340b57cec5SDimitry Andric     return HasThumb2 ? (unsigned)ARM::t2LDRpci : Op;
2350b57cec5SDimitry Andric   case ARM::tADR:
2360b57cec5SDimitry Andric     return HasThumb2 ? (unsigned)ARM::t2ADR : Op;
2370b57cec5SDimitry Andric   case ARM::tB:
2380b57cec5SDimitry Andric     return HasV8MBaselineOps ? (unsigned)ARM::t2B : Op;
2390b57cec5SDimitry Andric   case ARM::tCBZ:
2400b57cec5SDimitry Andric     return ARM::tHINT;
2410b57cec5SDimitry Andric   case ARM::tCBNZ:
2420b57cec5SDimitry Andric     return ARM::tHINT;
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric bool ARMAsmBackend::mayNeedRelaxation(const MCInst &Inst,
2470b57cec5SDimitry Andric                                       const MCSubtargetInfo &STI) const {
2480b57cec5SDimitry Andric   if (getRelaxedOpcode(Inst.getOpcode(), STI) != Inst.getOpcode())
2490b57cec5SDimitry Andric     return true;
2500b57cec5SDimitry Andric   return false;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric static const char *checkPCRelOffset(uint64_t Value, int64_t Min, int64_t Max) {
2540b57cec5SDimitry Andric   int64_t Offset = int64_t(Value) - 4;
2550b57cec5SDimitry Andric   if (Offset < Min || Offset > Max)
2560b57cec5SDimitry Andric     return "out of range pc-relative fixup value";
2570b57cec5SDimitry Andric   return nullptr;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric const char *ARMAsmBackend::reasonForFixupRelaxation(const MCFixup &Fixup,
2610b57cec5SDimitry Andric                                                     uint64_t Value) const {
2628bcb0991SDimitry Andric   switch (Fixup.getTargetKind()) {
2630b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_br: {
2640b57cec5SDimitry Andric     // Relaxing tB to t2B. tB has a signed 12-bit displacement with the
2650b57cec5SDimitry Andric     // low bit being an implied zero. There's an implied +4 offset for the
2660b57cec5SDimitry Andric     // branch, so we adjust the other way here to determine what's
2670b57cec5SDimitry Andric     // encodable.
2680b57cec5SDimitry Andric     //
2690b57cec5SDimitry Andric     // Relax if the value is too big for a (signed) i8.
2700b57cec5SDimitry Andric     int64_t Offset = int64_t(Value) - 4;
2710b57cec5SDimitry Andric     if (Offset > 2046 || Offset < -2048)
2720b57cec5SDimitry Andric       return "out of range pc-relative fixup value";
2730b57cec5SDimitry Andric     break;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bcc: {
2760b57cec5SDimitry Andric     // Relaxing tBcc to t2Bcc. tBcc has a signed 9-bit displacement with the
2770b57cec5SDimitry Andric     // low bit being an implied zero. There's an implied +4 offset for the
2780b57cec5SDimitry Andric     // branch, so we adjust the other way here to determine what's
2790b57cec5SDimitry Andric     // encodable.
2800b57cec5SDimitry Andric     //
2810b57cec5SDimitry Andric     // Relax if the value is too big for a (signed) i8.
2820b57cec5SDimitry Andric     int64_t Offset = int64_t(Value) - 4;
2830b57cec5SDimitry Andric     if (Offset > 254 || Offset < -256)
2840b57cec5SDimitry Andric       return "out of range pc-relative fixup value";
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric   case ARM::fixup_thumb_adr_pcrel_10:
2880b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cp: {
2890b57cec5SDimitry Andric     // If the immediate is negative, greater than 1020, or not a multiple
2900b57cec5SDimitry Andric     // of four, the wide version of the instruction must be used.
2910b57cec5SDimitry Andric     int64_t Offset = int64_t(Value) - 4;
2920b57cec5SDimitry Andric     if (Offset & 3)
2930b57cec5SDimitry Andric       return "misaligned pc-relative fixup value";
2940b57cec5SDimitry Andric     else if (Offset > 1020 || Offset < 0)
2950b57cec5SDimitry Andric       return "out of range pc-relative fixup value";
2960b57cec5SDimitry Andric     break;
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cb: {
2990b57cec5SDimitry Andric     // If we have a Thumb CBZ or CBNZ instruction and its target is the next
3000b57cec5SDimitry Andric     // instruction it is actually out of range for the instruction.
3010b57cec5SDimitry Andric     // It will be changed to a NOP.
3020b57cec5SDimitry Andric     int64_t Offset = (Value & ~1);
3030b57cec5SDimitry Andric     if (Offset == 2)
3040b57cec5SDimitry Andric       return "will be converted to nop";
3050b57cec5SDimitry Andric     break;
3060b57cec5SDimitry Andric   }
3070b57cec5SDimitry Andric   case ARM::fixup_bf_branch:
3080b57cec5SDimitry Andric     return checkPCRelOffset(Value, 0, 30);
3090b57cec5SDimitry Andric   case ARM::fixup_bf_target:
3100b57cec5SDimitry Andric     return checkPCRelOffset(Value, -0x10000, +0xfffe);
3110b57cec5SDimitry Andric   case ARM::fixup_bfl_target:
3120b57cec5SDimitry Andric     return checkPCRelOffset(Value, -0x40000, +0x3fffe);
3130b57cec5SDimitry Andric   case ARM::fixup_bfc_target:
3140b57cec5SDimitry Andric     return checkPCRelOffset(Value, -0x1000, +0xffe);
3150b57cec5SDimitry Andric   case ARM::fixup_wls:
3160b57cec5SDimitry Andric     return checkPCRelOffset(Value, 0, +0xffe);
3170b57cec5SDimitry Andric   case ARM::fixup_le:
3180b57cec5SDimitry Andric     // The offset field in the LE and LETP instructions is an 11-bit
3190b57cec5SDimitry Andric     // value shifted left by 2 (i.e. 0,2,4,...,4094), and it is
3200b57cec5SDimitry Andric     // interpreted as a negative offset from the value read from pc,
3210b57cec5SDimitry Andric     // i.e. from instruction_address+4.
3220b57cec5SDimitry Andric     //
3230b57cec5SDimitry Andric     // So an LE instruction can in principle address the instruction
3240b57cec5SDimitry Andric     // immediately after itself, or (not very usefully) the address
3250b57cec5SDimitry Andric     // half way through the 4-byte LE.
3260b57cec5SDimitry Andric     return checkPCRelOffset(Value, -0xffe, 0);
3270b57cec5SDimitry Andric   case ARM::fixup_bfcsel_else_target: {
3280b57cec5SDimitry Andric     if (Value != 2 && Value != 4)
3290b57cec5SDimitry Andric       return "out of range label-relative fixup value";
3300b57cec5SDimitry Andric     break;
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   default:
3340b57cec5SDimitry Andric     llvm_unreachable("Unexpected fixup kind in reasonForFixupRelaxation()!");
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric   return nullptr;
3370b57cec5SDimitry Andric }
3380b57cec5SDimitry Andric 
3390fca6ea1SDimitry Andric bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
3400fca6ea1SDimitry Andric                                          uint64_t Value) const {
3410b57cec5SDimitry Andric   return reasonForFixupRelaxation(Fixup, Value);
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
3445ffd83dbSDimitry Andric void ARMAsmBackend::relaxInstruction(MCInst &Inst,
3455ffd83dbSDimitry Andric                                      const MCSubtargetInfo &STI) const {
3460b57cec5SDimitry Andric   unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode(), STI);
3470b57cec5SDimitry Andric 
348349cc55cSDimitry Andric   // Return a diagnostic if we get here w/ a bogus instruction.
3490b57cec5SDimitry Andric   if (RelaxedOp == Inst.getOpcode()) {
3500b57cec5SDimitry Andric     SmallString<256> Tmp;
3510b57cec5SDimitry Andric     raw_svector_ostream OS(Tmp);
3520b57cec5SDimitry Andric     Inst.dump_pretty(OS);
3530b57cec5SDimitry Andric     OS << "\n";
3540b57cec5SDimitry Andric     report_fatal_error("unexpected instruction to relax: " + OS.str());
3550b57cec5SDimitry Andric   }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   // If we are changing Thumb CBZ or CBNZ instruction to a NOP, aka tHINT, we
3580b57cec5SDimitry Andric   // have to change the operands too.
3590b57cec5SDimitry Andric   if ((Inst.getOpcode() == ARM::tCBZ || Inst.getOpcode() == ARM::tCBNZ) &&
3600b57cec5SDimitry Andric       RelaxedOp == ARM::tHINT) {
3615ffd83dbSDimitry Andric     MCInst Res;
3620b57cec5SDimitry Andric     Res.setOpcode(RelaxedOp);
3630b57cec5SDimitry Andric     Res.addOperand(MCOperand::createImm(0));
3640b57cec5SDimitry Andric     Res.addOperand(MCOperand::createImm(14));
3650b57cec5SDimitry Andric     Res.addOperand(MCOperand::createReg(0));
3665ffd83dbSDimitry Andric     Inst = std::move(Res);
3670b57cec5SDimitry Andric     return;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   // The rest of instructions we're relaxing have the same operands.
3710b57cec5SDimitry Andric   // We just need to update to the proper opcode.
3725ffd83dbSDimitry Andric   Inst.setOpcode(RelaxedOp);
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
375349cc55cSDimitry Andric bool ARMAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
376349cc55cSDimitry Andric                                  const MCSubtargetInfo *STI) const {
3770b57cec5SDimitry Andric   const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8
3780b57cec5SDimitry Andric   const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP
3790b57cec5SDimitry Andric   const uint32_t ARMv4_NopEncoding = 0xe1a00000;   // using MOV r0,r0
3800b57cec5SDimitry Andric   const uint32_t ARMv6T2_NopEncoding = 0xe320f000; // NOP
3810b57cec5SDimitry Andric   if (isThumb()) {
3820b57cec5SDimitry Andric     const uint16_t nopEncoding =
383349cc55cSDimitry Andric         hasNOP(STI) ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;
3840b57cec5SDimitry Andric     uint64_t NumNops = Count / 2;
3850b57cec5SDimitry Andric     for (uint64_t i = 0; i != NumNops; ++i)
3860b57cec5SDimitry Andric       support::endian::write(OS, nopEncoding, Endian);
3870b57cec5SDimitry Andric     if (Count & 1)
3880b57cec5SDimitry Andric       OS << '\0';
3890b57cec5SDimitry Andric     return true;
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   // ARM mode
3920b57cec5SDimitry Andric   const uint32_t nopEncoding =
393349cc55cSDimitry Andric       hasNOP(STI) ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;
3940b57cec5SDimitry Andric   uint64_t NumNops = Count / 4;
3950b57cec5SDimitry Andric   for (uint64_t i = 0; i != NumNops; ++i)
3960b57cec5SDimitry Andric     support::endian::write(OS, nopEncoding, Endian);
3970b57cec5SDimitry Andric   // FIXME: should this function return false when unable to write exactly
3980b57cec5SDimitry Andric   // 'Count' bytes with NOP encodings?
3990b57cec5SDimitry Andric   switch (Count % 4) {
4000b57cec5SDimitry Andric   default:
4010b57cec5SDimitry Andric     break; // No leftover bytes to write
4020b57cec5SDimitry Andric   case 1:
4030b57cec5SDimitry Andric     OS << '\0';
4040b57cec5SDimitry Andric     break;
4050b57cec5SDimitry Andric   case 2:
4060b57cec5SDimitry Andric     OS.write("\0\0", 2);
4070b57cec5SDimitry Andric     break;
4080b57cec5SDimitry Andric   case 3:
4090b57cec5SDimitry Andric     OS.write("\0\0\xa0", 3);
4100b57cec5SDimitry Andric     break;
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   return true;
4140b57cec5SDimitry Andric }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian) {
4170b57cec5SDimitry Andric   if (IsLittleEndian) {
4180b57cec5SDimitry Andric     // Note that the halfwords are stored high first and low second in thumb;
4190b57cec5SDimitry Andric     // so we need to swap the fixup value here to map properly.
4200b57cec5SDimitry Andric     uint32_t Swapped = (Value & 0xFFFF0000) >> 16;
4210b57cec5SDimitry Andric     Swapped |= (Value & 0x0000FFFF) << 16;
4220b57cec5SDimitry Andric     return Swapped;
4230b57cec5SDimitry Andric   } else
4240b57cec5SDimitry Andric     return Value;
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf,
4280b57cec5SDimitry Andric                               bool IsLittleEndian) {
4290b57cec5SDimitry Andric   uint32_t Value;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   if (IsLittleEndian) {
4320b57cec5SDimitry Andric     Value = (SecondHalf & 0xFFFF) << 16;
4330b57cec5SDimitry Andric     Value |= (FirstHalf & 0xFFFF);
4340b57cec5SDimitry Andric   } else {
4350b57cec5SDimitry Andric     Value = (SecondHalf & 0xFFFF);
4360b57cec5SDimitry Andric     Value |= (FirstHalf & 0xFFFF) << 16;
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   return Value;
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm,
4430b57cec5SDimitry Andric                                          const MCFixup &Fixup,
4440b57cec5SDimitry Andric                                          const MCValue &Target, uint64_t Value,
4450b57cec5SDimitry Andric                                          bool IsResolved, MCContext &Ctx,
4460b57cec5SDimitry Andric                                          const MCSubtargetInfo* STI) const {
4470b57cec5SDimitry Andric   unsigned Kind = Fixup.getKind();
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   // MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT
4500b57cec5SDimitry Andric   // and .word relocations they put the Thumb bit into the addend if possible.
4510b57cec5SDimitry Andric   // Other relocation types don't want this bit though (branches couldn't encode
4520b57cec5SDimitry Andric   // it if it *was* present, and no other relocations exist) and it can
4530b57cec5SDimitry Andric   // interfere with checking valid expressions.
4540b57cec5SDimitry Andric   if (const MCSymbolRefExpr *A = Target.getSymA()) {
4550b57cec5SDimitry Andric     if (A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&A->getSymbol()) &&
4560b57cec5SDimitry Andric         A->getSymbol().isExternal() &&
4570b57cec5SDimitry Andric         (Kind == FK_Data_4 || Kind == ARM::fixup_arm_movw_lo16 ||
4580b57cec5SDimitry Andric          Kind == ARM::fixup_arm_movt_hi16 || Kind == ARM::fixup_t2_movw_lo16 ||
4590b57cec5SDimitry Andric          Kind == ARM::fixup_t2_movt_hi16))
4600b57cec5SDimitry Andric       Value |= 1;
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   switch (Kind) {
4640b57cec5SDimitry Andric   default:
4650b57cec5SDimitry Andric     return 0;
4660b57cec5SDimitry Andric   case FK_Data_1:
4670b57cec5SDimitry Andric   case FK_Data_2:
4680b57cec5SDimitry Andric   case FK_Data_4:
4690b57cec5SDimitry Andric     return Value;
4700b57cec5SDimitry Andric   case FK_SecRel_2:
4710b57cec5SDimitry Andric     return Value;
4720b57cec5SDimitry Andric   case FK_SecRel_4:
4730b57cec5SDimitry Andric     return Value;
4740b57cec5SDimitry Andric   case ARM::fixup_arm_movt_hi16:
4750b57cec5SDimitry Andric     assert(STI != nullptr);
4760b57cec5SDimitry Andric     if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())
4770b57cec5SDimitry Andric       Value >>= 16;
478bdd1243dSDimitry Andric     [[fallthrough]];
4790b57cec5SDimitry Andric   case ARM::fixup_arm_movw_lo16: {
4800b57cec5SDimitry Andric     unsigned Hi4 = (Value & 0xF000) >> 12;
4810b57cec5SDimitry Andric     unsigned Lo12 = Value & 0x0FFF;
4820b57cec5SDimitry Andric     // inst{19-16} = Hi4;
4830b57cec5SDimitry Andric     // inst{11-0} = Lo12;
4840b57cec5SDimitry Andric     Value = (Hi4 << 16) | (Lo12);
4850b57cec5SDimitry Andric     return Value;
4860b57cec5SDimitry Andric   }
4870b57cec5SDimitry Andric   case ARM::fixup_t2_movt_hi16:
4880b57cec5SDimitry Andric     assert(STI != nullptr);
4890b57cec5SDimitry Andric     if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())
4900b57cec5SDimitry Andric       Value >>= 16;
491bdd1243dSDimitry Andric     [[fallthrough]];
4920b57cec5SDimitry Andric   case ARM::fixup_t2_movw_lo16: {
4930b57cec5SDimitry Andric     unsigned Hi4 = (Value & 0xF000) >> 12;
4940b57cec5SDimitry Andric     unsigned i = (Value & 0x800) >> 11;
4950b57cec5SDimitry Andric     unsigned Mid3 = (Value & 0x700) >> 8;
4960b57cec5SDimitry Andric     unsigned Lo8 = Value & 0x0FF;
4970b57cec5SDimitry Andric     // inst{19-16} = Hi4;
4980b57cec5SDimitry Andric     // inst{26} = i;
4990b57cec5SDimitry Andric     // inst{14-12} = Mid3;
5000b57cec5SDimitry Andric     // inst{7-0} = Lo8;
5010b57cec5SDimitry Andric     Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
5025f757f3fSDimitry Andric     return swapHalfWords(Value, Endian == llvm::endianness::little);
5030b57cec5SDimitry Andric   }
50406c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_8_15:
50506c3fb27SDimitry Andric     if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())
50606c3fb27SDimitry Andric       return (Value & 0xff000000) >> 24;
50706c3fb27SDimitry Andric     return Value & 0xff;
50806c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_0_7:
50906c3fb27SDimitry Andric     if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())
51006c3fb27SDimitry Andric       return (Value & 0x00ff0000) >> 16;
51106c3fb27SDimitry Andric     return Value & 0xff;
51206c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_8_15:
51306c3fb27SDimitry Andric     if (IsResolved || !STI->getTargetTriple().isOSBinFormatELF())
51406c3fb27SDimitry Andric       return (Value & 0x0000ff00) >> 8;
51506c3fb27SDimitry Andric     return Value & 0xff;
51606c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_0_7:
51706c3fb27SDimitry Andric     return Value & 0x000000ff;
5180b57cec5SDimitry Andric   case ARM::fixup_arm_ldst_pcrel_12:
5190b57cec5SDimitry Andric     // ARM PC-relative values are offset by 8.
5200b57cec5SDimitry Andric     Value -= 4;
521bdd1243dSDimitry Andric     [[fallthrough]];
522fe6060f1SDimitry Andric   case ARM::fixup_t2_ldst_pcrel_12:
5230b57cec5SDimitry Andric     // Offset by 4, adjusted by two due to the half-word ordering of thumb.
5240b57cec5SDimitry Andric     Value -= 4;
525bdd1243dSDimitry Andric     [[fallthrough]];
526fe6060f1SDimitry Andric   case ARM::fixup_arm_ldst_abs_12: {
5270b57cec5SDimitry Andric     bool isAdd = true;
5280b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
5290b57cec5SDimitry Andric       Value = -Value;
5300b57cec5SDimitry Andric       isAdd = false;
5310b57cec5SDimitry Andric     }
5320b57cec5SDimitry Andric     if (Value >= 4096) {
5330b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
5340b57cec5SDimitry Andric       return 0;
5350b57cec5SDimitry Andric     }
5360b57cec5SDimitry Andric     Value |= isAdd << 23;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     // Same addressing mode as fixup_arm_pcrel_10,
5390b57cec5SDimitry Andric     // but with 16-bit halfwords swapped.
5400b57cec5SDimitry Andric     if (Kind == ARM::fixup_t2_ldst_pcrel_12)
5415f757f3fSDimitry Andric       return swapHalfWords(Value, Endian == llvm::endianness::little);
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric     return Value;
5440b57cec5SDimitry Andric   }
5450b57cec5SDimitry Andric   case ARM::fixup_arm_adr_pcrel_12: {
5460b57cec5SDimitry Andric     // ARM PC-relative values are offset by 8.
5470b57cec5SDimitry Andric     Value -= 8;
5480b57cec5SDimitry Andric     unsigned opc = 4; // bits {24-21}. Default to add: 0b0100
5490b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
5500b57cec5SDimitry Andric       Value = -Value;
5510b57cec5SDimitry Andric       opc = 2; // 0b0010
5520b57cec5SDimitry Andric     }
5530b57cec5SDimitry Andric     if (ARM_AM::getSOImmVal(Value) == -1) {
5540b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
5550b57cec5SDimitry Andric       return 0;
5560b57cec5SDimitry Andric     }
5570b57cec5SDimitry Andric     // Encode the immediate and shift the opcode into place.
5580b57cec5SDimitry Andric     return ARM_AM::getSOImmVal(Value) | (opc << 21);
5590b57cec5SDimitry Andric   }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   case ARM::fixup_t2_adr_pcrel_12: {
5620b57cec5SDimitry Andric     Value -= 4;
5630b57cec5SDimitry Andric     unsigned opc = 0;
5640b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
5650b57cec5SDimitry Andric       Value = -Value;
5660b57cec5SDimitry Andric       opc = 5;
5670b57cec5SDimitry Andric     }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric     uint32_t out = (opc << 21);
5700b57cec5SDimitry Andric     out |= (Value & 0x800) << 15;
5710b57cec5SDimitry Andric     out |= (Value & 0x700) << 4;
5720b57cec5SDimitry Andric     out |= (Value & 0x0FF);
5730b57cec5SDimitry Andric 
5745f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   case ARM::fixup_arm_condbranch:
5780b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbranch:
5790b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbl:
5800b57cec5SDimitry Andric   case ARM::fixup_arm_condbl:
5810b57cec5SDimitry Andric   case ARM::fixup_arm_blx:
5820b57cec5SDimitry Andric     // These values don't encode the low two bits since they're always zero.
5830b57cec5SDimitry Andric     // Offset by 8 just as above.
5840b57cec5SDimitry Andric     if (const MCSymbolRefExpr *SRE =
5850b57cec5SDimitry Andric             dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
5860b57cec5SDimitry Andric       if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL)
5870b57cec5SDimitry Andric         return 0;
5880b57cec5SDimitry Andric     return 0xffffff & ((Value - 8) >> 2);
5890b57cec5SDimitry Andric   case ARM::fixup_t2_uncondbranch: {
5900b57cec5SDimitry Andric     Value = Value - 4;
5910b57cec5SDimitry Andric     if (!isInt<25>(Value)) {
5920b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
5930b57cec5SDimitry Andric       return 0;
5940b57cec5SDimitry Andric     }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric     Value >>= 1; // Low bit is not encoded.
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric     uint32_t out = 0;
5990b57cec5SDimitry Andric     bool I = Value & 0x800000;
6000b57cec5SDimitry Andric     bool J1 = Value & 0x400000;
6010b57cec5SDimitry Andric     bool J2 = Value & 0x200000;
6020b57cec5SDimitry Andric     J1 ^= I;
6030b57cec5SDimitry Andric     J2 ^= I;
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric     out |= I << 26;                 // S bit
6060b57cec5SDimitry Andric     out |= !J1 << 13;               // J1 bit
6070b57cec5SDimitry Andric     out |= !J2 << 11;               // J2 bit
6080b57cec5SDimitry Andric     out |= (Value & 0x1FF800) << 5; // imm6 field
6090b57cec5SDimitry Andric     out |= (Value & 0x0007FF);      // imm11 field
6100b57cec5SDimitry Andric 
6115f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric   case ARM::fixup_t2_condbranch: {
6140b57cec5SDimitry Andric     Value = Value - 4;
6150b57cec5SDimitry Andric     if (!isInt<21>(Value)) {
6160b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
6170b57cec5SDimitry Andric       return 0;
6180b57cec5SDimitry Andric     }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric     Value >>= 1; // Low bit is not encoded.
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric     uint64_t out = 0;
6230b57cec5SDimitry Andric     out |= (Value & 0x80000) << 7; // S bit
6240b57cec5SDimitry Andric     out |= (Value & 0x40000) >> 7; // J2 bit
6250b57cec5SDimitry Andric     out |= (Value & 0x20000) >> 4; // J1 bit
6260b57cec5SDimitry Andric     out |= (Value & 0x1F800) << 5; // imm6 field
6270b57cec5SDimitry Andric     out |= (Value & 0x007FF);      // imm11 field
6280b57cec5SDimitry Andric 
6295f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bl: {
6320b57cec5SDimitry Andric     if (!isInt<25>(Value - 4) ||
63306c3fb27SDimitry Andric         (!STI->hasFeature(ARM::FeatureThumb2) &&
63406c3fb27SDimitry Andric          !STI->hasFeature(ARM::HasV8MBaselineOps) &&
63506c3fb27SDimitry Andric          !STI->hasFeature(ARM::HasV6MOps) &&
6360b57cec5SDimitry Andric          !isInt<23>(Value - 4))) {
6370b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "Relocation out of range");
6380b57cec5SDimitry Andric       return 0;
6390b57cec5SDimitry Andric     }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric     // The value doesn't encode the low bit (always zero) and is offset by
6420b57cec5SDimitry Andric     // four. The 32-bit immediate value is encoded as
6430b57cec5SDimitry Andric     //   imm32 = SignExtend(S:I1:I2:imm10:imm11:0)
6440b57cec5SDimitry Andric     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
6450b57cec5SDimitry Andric     // The value is encoded into disjoint bit positions in the destination
6460b57cec5SDimitry Andric     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
6470b57cec5SDimitry Andric     // J = either J1 or J2 bit
6480b57cec5SDimitry Andric     //
6490b57cec5SDimitry Andric     //   BL:  xxxxxSIIIIIIIIII xxJxJIIIIIIIIIII
6500b57cec5SDimitry Andric     //
6510b57cec5SDimitry Andric     // Note that the halfwords are stored high first, low second; so we need
6520b57cec5SDimitry Andric     // to transpose the fixup value here to map properly.
6530b57cec5SDimitry Andric     uint32_t offset = (Value - 4) >> 1;
6540b57cec5SDimitry Andric     uint32_t signBit = (offset & 0x800000) >> 23;
6550b57cec5SDimitry Andric     uint32_t I1Bit = (offset & 0x400000) >> 22;
6560b57cec5SDimitry Andric     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
6570b57cec5SDimitry Andric     uint32_t I2Bit = (offset & 0x200000) >> 21;
6580b57cec5SDimitry Andric     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
6590b57cec5SDimitry Andric     uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
6600b57cec5SDimitry Andric     uint32_t imm11Bits = (offset & 0x000007FF);
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric     uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
6630b57cec5SDimitry Andric     uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
6640b57cec5SDimitry Andric                            (uint16_t)imm11Bits);
6655f757f3fSDimitry Andric     return joinHalfWords(FirstHalf, SecondHalf,
6665f757f3fSDimitry Andric                          Endian == llvm::endianness::little);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_blx: {
6690b57cec5SDimitry Andric     // The value doesn't encode the low two bits (always zero) and is offset by
6700b57cec5SDimitry Andric     // four (see fixup_arm_thumb_cp). The 32-bit immediate value is encoded as
6710b57cec5SDimitry Andric     //   imm32 = SignExtend(S:I1:I2:imm10H:imm10L:00)
6720b57cec5SDimitry Andric     // where I1 = NOT(J1 ^ S) and I2 = NOT(J2 ^ S).
6730b57cec5SDimitry Andric     // The value is encoded into disjoint bit positions in the destination
6740b57cec5SDimitry Andric     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit,
6750b57cec5SDimitry Andric     // J = either J1 or J2 bit, 0 = zero.
6760b57cec5SDimitry Andric     //
6770b57cec5SDimitry Andric     //   BLX: xxxxxSIIIIIIIIII xxJxJIIIIIIIIII0
6780b57cec5SDimitry Andric     //
6790b57cec5SDimitry Andric     // Note that the halfwords are stored high first, low second; so we need
6800b57cec5SDimitry Andric     // to transpose the fixup value here to map properly.
6810b57cec5SDimitry Andric     if (Value % 4 != 0) {
6820b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "misaligned ARM call destination");
6830b57cec5SDimitry Andric       return 0;
6840b57cec5SDimitry Andric     }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     uint32_t offset = (Value - 4) >> 2;
6870b57cec5SDimitry Andric     if (const MCSymbolRefExpr *SRE =
6880b57cec5SDimitry Andric             dyn_cast<MCSymbolRefExpr>(Fixup.getValue()))
6890b57cec5SDimitry Andric       if (SRE->getKind() == MCSymbolRefExpr::VK_TLSCALL)
6900b57cec5SDimitry Andric         offset = 0;
6910b57cec5SDimitry Andric     uint32_t signBit = (offset & 0x400000) >> 22;
6920b57cec5SDimitry Andric     uint32_t I1Bit = (offset & 0x200000) >> 21;
6930b57cec5SDimitry Andric     uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
6940b57cec5SDimitry Andric     uint32_t I2Bit = (offset & 0x100000) >> 20;
6950b57cec5SDimitry Andric     uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
6960b57cec5SDimitry Andric     uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
6970b57cec5SDimitry Andric     uint32_t imm10LBits = (offset & 0x3FF);
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric     uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
7000b57cec5SDimitry Andric     uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
7010b57cec5SDimitry Andric                            ((uint16_t)imm10LBits) << 1);
7025f757f3fSDimitry Andric     return joinHalfWords(FirstHalf, SecondHalf,
7035f757f3fSDimitry Andric                          Endian == llvm::endianness::little);
7040b57cec5SDimitry Andric   }
7050b57cec5SDimitry Andric   case ARM::fixup_thumb_adr_pcrel_10:
7060b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cp:
7070b57cec5SDimitry Andric     // On CPUs supporting Thumb2, this will be relaxed to an ldr.w, otherwise we
7080b57cec5SDimitry Andric     // could have an error on our hands.
7090b57cec5SDimitry Andric     assert(STI != nullptr);
71006c3fb27SDimitry Andric     if (!STI->hasFeature(ARM::FeatureThumb2) && IsResolved) {
7110b57cec5SDimitry Andric       const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
7120b57cec5SDimitry Andric       if (FixupDiagnostic) {
7130b57cec5SDimitry Andric         Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
7140b57cec5SDimitry Andric         return 0;
7150b57cec5SDimitry Andric       }
7160b57cec5SDimitry Andric     }
7170b57cec5SDimitry Andric     // Offset by 4, and don't encode the low two bits.
7180b57cec5SDimitry Andric     return ((Value - 4) >> 2) & 0xff;
7190b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cb: {
7200b57cec5SDimitry Andric     // CB instructions can only branch to offsets in [4, 126] in multiples of 2
7210b57cec5SDimitry Andric     // so ensure that the raw value LSB is zero and it lies in [2, 130].
7220b57cec5SDimitry Andric     // An offset of 2 will be relaxed to a NOP.
7230b57cec5SDimitry Andric     if ((int64_t)Value < 2 || Value > 0x82 || Value & 1) {
7240b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
7250b57cec5SDimitry Andric       return 0;
7260b57cec5SDimitry Andric     }
7270b57cec5SDimitry Andric     // Offset by 4 and don't encode the lower bit, which is always 0.
7280b57cec5SDimitry Andric     // FIXME: diagnose if no Thumb2
7290b57cec5SDimitry Andric     uint32_t Binary = (Value - 4) >> 1;
7300b57cec5SDimitry Andric     return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
7310b57cec5SDimitry Andric   }
7320b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_br:
7330b57cec5SDimitry Andric     // Offset by 4 and don't encode the lower bit, which is always 0.
7340b57cec5SDimitry Andric     assert(STI != nullptr);
73506c3fb27SDimitry Andric     if (!STI->hasFeature(ARM::FeatureThumb2) &&
73606c3fb27SDimitry Andric         !STI->hasFeature(ARM::HasV8MBaselineOps)) {
7370b57cec5SDimitry Andric       const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
7380b57cec5SDimitry Andric       if (FixupDiagnostic) {
7390b57cec5SDimitry Andric         Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
7400b57cec5SDimitry Andric         return 0;
7410b57cec5SDimitry Andric       }
7420b57cec5SDimitry Andric     }
7430b57cec5SDimitry Andric     return ((Value - 4) >> 1) & 0x7ff;
7440b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bcc:
7450b57cec5SDimitry Andric     // Offset by 4 and don't encode the lower bit, which is always 0.
7460b57cec5SDimitry Andric     assert(STI != nullptr);
74706c3fb27SDimitry Andric     if (!STI->hasFeature(ARM::FeatureThumb2)) {
7480b57cec5SDimitry Andric       const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
7490b57cec5SDimitry Andric       if (FixupDiagnostic) {
7500b57cec5SDimitry Andric         Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
7510b57cec5SDimitry Andric         return 0;
7520b57cec5SDimitry Andric       }
7530b57cec5SDimitry Andric     }
7540b57cec5SDimitry Andric     return ((Value - 4) >> 1) & 0xff;
7550b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10_unscaled: {
7560b57cec5SDimitry Andric     Value = Value - 8; // ARM fixups offset by an additional word and don't
7570b57cec5SDimitry Andric                        // need to adjust for the half-word ordering.
7580b57cec5SDimitry Andric     bool isAdd = true;
7590b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
7600b57cec5SDimitry Andric       Value = -Value;
7610b57cec5SDimitry Andric       isAdd = false;
7620b57cec5SDimitry Andric     }
7630b57cec5SDimitry Andric     // The value has the low 4 bits encoded in [3:0] and the high 4 in [11:8].
7640b57cec5SDimitry Andric     if (Value >= 256) {
7650b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
7660b57cec5SDimitry Andric       return 0;
7670b57cec5SDimitry Andric     }
7680b57cec5SDimitry Andric     Value = (Value & 0xf) | ((Value & 0xf0) << 4);
7690b57cec5SDimitry Andric     return Value | (isAdd << 23);
7700b57cec5SDimitry Andric   }
7710b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10:
7720b57cec5SDimitry Andric     Value = Value - 4; // ARM fixups offset by an additional word and don't
7730b57cec5SDimitry Andric                        // need to adjust for the half-word ordering.
774bdd1243dSDimitry Andric     [[fallthrough]];
7750b57cec5SDimitry Andric   case ARM::fixup_t2_pcrel_10: {
7760b57cec5SDimitry Andric     // Offset by 4, adjusted by two due to the half-word ordering of thumb.
7770b57cec5SDimitry Andric     Value = Value - 4;
7780b57cec5SDimitry Andric     bool isAdd = true;
7790b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
7800b57cec5SDimitry Andric       Value = -Value;
7810b57cec5SDimitry Andric       isAdd = false;
7820b57cec5SDimitry Andric     }
7830b57cec5SDimitry Andric     // These values don't encode the low two bits since they're always zero.
7840b57cec5SDimitry Andric     Value >>= 2;
7850b57cec5SDimitry Andric     if (Value >= 256) {
7860b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
7870b57cec5SDimitry Andric       return 0;
7880b57cec5SDimitry Andric     }
7890b57cec5SDimitry Andric     Value |= isAdd << 23;
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric     // Same addressing mode as fixup_arm_pcrel_10, but with 16-bit halfwords
7920b57cec5SDimitry Andric     // swapped.
7930b57cec5SDimitry Andric     if (Kind == ARM::fixup_t2_pcrel_10)
7945f757f3fSDimitry Andric       return swapHalfWords(Value, Endian == llvm::endianness::little);
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric     return Value;
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_9:
7990b57cec5SDimitry Andric     Value = Value - 4; // ARM fixups offset by an additional word and don't
8000b57cec5SDimitry Andric                        // need to adjust for the half-word ordering.
801bdd1243dSDimitry Andric     [[fallthrough]];
8020b57cec5SDimitry Andric   case ARM::fixup_t2_pcrel_9: {
8030b57cec5SDimitry Andric     // Offset by 4, adjusted by two due to the half-word ordering of thumb.
8040b57cec5SDimitry Andric     Value = Value - 4;
8050b57cec5SDimitry Andric     bool isAdd = true;
8060b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
8070b57cec5SDimitry Andric       Value = -Value;
8080b57cec5SDimitry Andric       isAdd = false;
8090b57cec5SDimitry Andric     }
8100b57cec5SDimitry Andric     // These values don't encode the low bit since it's always zero.
8110b57cec5SDimitry Andric     if (Value & 1) {
8120b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "invalid value for this fixup");
8130b57cec5SDimitry Andric       return 0;
8140b57cec5SDimitry Andric     }
8150b57cec5SDimitry Andric     Value >>= 1;
8160b57cec5SDimitry Andric     if (Value >= 256) {
8170b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value");
8180b57cec5SDimitry Andric       return 0;
8190b57cec5SDimitry Andric     }
8200b57cec5SDimitry Andric     Value |= isAdd << 23;
8210b57cec5SDimitry Andric 
8220b57cec5SDimitry Andric     // Same addressing mode as fixup_arm_pcrel_9, but with 16-bit halfwords
8230b57cec5SDimitry Andric     // swapped.
8240b57cec5SDimitry Andric     if (Kind == ARM::fixup_t2_pcrel_9)
8255f757f3fSDimitry Andric       return swapHalfWords(Value, Endian == llvm::endianness::little);
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric     return Value;
8280b57cec5SDimitry Andric   }
8290b57cec5SDimitry Andric   case ARM::fixup_arm_mod_imm:
8300b57cec5SDimitry Andric     Value = ARM_AM::getSOImmVal(Value);
8310b57cec5SDimitry Andric     if (Value >> 12) {
8320b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value");
8330b57cec5SDimitry Andric       return 0;
8340b57cec5SDimitry Andric     }
8350b57cec5SDimitry Andric     return Value;
8360b57cec5SDimitry Andric   case ARM::fixup_t2_so_imm: {
8370b57cec5SDimitry Andric     Value = ARM_AM::getT2SOImmVal(Value);
8380b57cec5SDimitry Andric     if ((int64_t)Value < 0) {
8390b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range immediate fixup value");
8400b57cec5SDimitry Andric       return 0;
8410b57cec5SDimitry Andric     }
8420b57cec5SDimitry Andric     // Value will contain a 12-bit value broken up into a 4-bit shift in bits
8430b57cec5SDimitry Andric     // 11:8 and the 8-bit immediate in 0:7. The instruction has the immediate
8440b57cec5SDimitry Andric     // in 0:7. The 4-bit shift is split up into i:imm3 where i is placed at bit
8450b57cec5SDimitry Andric     // 10 of the upper half-word and imm3 is placed at 14:12 of the lower
8460b57cec5SDimitry Andric     // half-word.
8470b57cec5SDimitry Andric     uint64_t EncValue = 0;
8480b57cec5SDimitry Andric     EncValue |= (Value & 0x800) << 15;
8490b57cec5SDimitry Andric     EncValue |= (Value & 0x700) << 4;
8500b57cec5SDimitry Andric     EncValue |= (Value & 0xff);
8515f757f3fSDimitry Andric     return swapHalfWords(EncValue, Endian == llvm::endianness::little);
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric   case ARM::fixup_bf_branch: {
8540b57cec5SDimitry Andric     const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
8550b57cec5SDimitry Andric     if (FixupDiagnostic) {
8560b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
8570b57cec5SDimitry Andric       return 0;
8580b57cec5SDimitry Andric     }
8590b57cec5SDimitry Andric     uint32_t out = (((Value - 4) >> 1) & 0xf) << 23;
8605f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric   case ARM::fixup_bf_target:
8630b57cec5SDimitry Andric   case ARM::fixup_bfl_target:
8640b57cec5SDimitry Andric   case ARM::fixup_bfc_target: {
8650b57cec5SDimitry Andric     const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
8660b57cec5SDimitry Andric     if (FixupDiagnostic) {
8670b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
8680b57cec5SDimitry Andric       return 0;
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric     uint32_t out = 0;
8710b57cec5SDimitry Andric     uint32_t HighBitMask = (Kind == ARM::fixup_bf_target ? 0xf800 :
8720b57cec5SDimitry Andric                             Kind == ARM::fixup_bfl_target ? 0x3f800 : 0x800);
8730b57cec5SDimitry Andric     out |= (((Value - 4) >> 1) & 0x1) << 11;
8740b57cec5SDimitry Andric     out |= (((Value - 4) >> 1) & 0x7fe);
8750b57cec5SDimitry Andric     out |= (((Value - 4) >> 1) & HighBitMask) << 5;
8765f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
8770b57cec5SDimitry Andric   }
8780b57cec5SDimitry Andric   case ARM::fixup_bfcsel_else_target: {
8790b57cec5SDimitry Andric     // If this is a fixup of a branch future's else target then it should be a
8800b57cec5SDimitry Andric     // constant MCExpr representing the distance between the branch targetted
8810b57cec5SDimitry Andric     // and the instruction after that same branch.
8820b57cec5SDimitry Andric     Value = Target.getConstant();
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric     const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
8850b57cec5SDimitry Andric     if (FixupDiagnostic) {
8860b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
8870b57cec5SDimitry Andric       return 0;
8880b57cec5SDimitry Andric     }
8890b57cec5SDimitry Andric     uint32_t out = ((Value >> 2) & 1) << 17;
8905f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
8910b57cec5SDimitry Andric   }
8920b57cec5SDimitry Andric   case ARM::fixup_wls:
8930b57cec5SDimitry Andric   case ARM::fixup_le: {
8940b57cec5SDimitry Andric     const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
8950b57cec5SDimitry Andric     if (FixupDiagnostic) {
8960b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), FixupDiagnostic);
8970b57cec5SDimitry Andric       return 0;
8980b57cec5SDimitry Andric     }
8990b57cec5SDimitry Andric     uint64_t real_value = Value - 4;
9000b57cec5SDimitry Andric     uint32_t out = 0;
9010b57cec5SDimitry Andric     if (Kind == ARM::fixup_le)
9020b57cec5SDimitry Andric       real_value = -real_value;
9030b57cec5SDimitry Andric     out |= ((real_value >> 1) & 0x1) << 11;
9040b57cec5SDimitry Andric     out |= ((real_value >> 1) & 0x7fe);
9055f757f3fSDimitry Andric     return swapHalfWords(out, Endian == llvm::endianness::little);
9060b57cec5SDimitry Andric   }
9070b57cec5SDimitry Andric   }
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric bool ARMAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
9110b57cec5SDimitry Andric                                           const MCFixup &Fixup,
9125f757f3fSDimitry Andric                                           const MCValue &Target,
9135f757f3fSDimitry Andric                                           const MCSubtargetInfo *STI) {
9140b57cec5SDimitry Andric   const MCSymbolRefExpr *A = Target.getSymA();
9150b57cec5SDimitry Andric   const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
9160b57cec5SDimitry Andric   const unsigned FixupKind = Fixup.getKind();
9175ffd83dbSDimitry Andric   if (FixupKind >= FirstLiteralRelocationKind)
9180b57cec5SDimitry Andric     return true;
9190b57cec5SDimitry Andric   if (FixupKind == ARM::fixup_arm_thumb_bl) {
9200b57cec5SDimitry Andric     assert(Sym && "How did we resolve this?");
9210b57cec5SDimitry Andric 
9220b57cec5SDimitry Andric     // If the symbol is external the linker will handle it.
9230b57cec5SDimitry Andric     // FIXME: Should we handle it as an optimization?
9240b57cec5SDimitry Andric 
9250b57cec5SDimitry Andric     // If the symbol is out of range, produce a relocation and hope the
9260b57cec5SDimitry Andric     // linker can handle it. GNU AS produces an error in this case.
9270b57cec5SDimitry Andric     if (Sym->isExternal())
9280b57cec5SDimitry Andric       return true;
9290b57cec5SDimitry Andric   }
9300b57cec5SDimitry Andric   // Create relocations for unconditional branches to function symbols with
9310b57cec5SDimitry Andric   // different execution mode in ELF binaries.
9320b57cec5SDimitry Andric   if (Sym && Sym->isELF()) {
9330b57cec5SDimitry Andric     unsigned Type = cast<MCSymbolELF>(Sym)->getType();
9340b57cec5SDimitry Andric     if ((Type == ELF::STT_FUNC || Type == ELF::STT_GNU_IFUNC)) {
9350b57cec5SDimitry Andric       if (Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_uncondbranch))
9360b57cec5SDimitry Andric         return true;
9370b57cec5SDimitry Andric       if (!Asm.isThumbFunc(Sym) && (FixupKind == ARM::fixup_arm_thumb_br ||
9380b57cec5SDimitry Andric                                     FixupKind == ARM::fixup_arm_thumb_bl ||
9390b57cec5SDimitry Andric                                     FixupKind == ARM::fixup_t2_condbranch ||
9400b57cec5SDimitry Andric                                     FixupKind == ARM::fixup_t2_uncondbranch))
9410b57cec5SDimitry Andric         return true;
9420b57cec5SDimitry Andric     }
9430b57cec5SDimitry Andric   }
9440b57cec5SDimitry Andric   // We must always generate a relocation for BL/BLX instructions if we have
9450b57cec5SDimitry Andric   // a symbol to reference, as the linker relies on knowing the destination
9460b57cec5SDimitry Andric   // symbol's thumb-ness to get interworking right.
9470b57cec5SDimitry Andric   if (A && (FixupKind == ARM::fixup_arm_thumb_blx ||
9480b57cec5SDimitry Andric             FixupKind == ARM::fixup_arm_blx ||
9490b57cec5SDimitry Andric             FixupKind == ARM::fixup_arm_uncondbl ||
9500b57cec5SDimitry Andric             FixupKind == ARM::fixup_arm_condbl))
9510b57cec5SDimitry Andric     return true;
9520b57cec5SDimitry Andric   return false;
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric /// getFixupKindNumBytes - The number of bytes the fixup may change.
9560b57cec5SDimitry Andric static unsigned getFixupKindNumBytes(unsigned Kind) {
9570b57cec5SDimitry Andric   switch (Kind) {
9580b57cec5SDimitry Andric   default:
9590b57cec5SDimitry Andric     llvm_unreachable("Unknown fixup kind!");
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   case FK_Data_1:
9620b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bcc:
9630b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cp:
9640b57cec5SDimitry Andric   case ARM::fixup_thumb_adr_pcrel_10:
96506c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_8_15:
96606c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_0_7:
96706c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_8_15:
96806c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_0_7:
9690b57cec5SDimitry Andric     return 1;
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   case FK_Data_2:
9720b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_br:
9730b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cb:
9740b57cec5SDimitry Andric   case ARM::fixup_arm_mod_imm:
9750b57cec5SDimitry Andric     return 2;
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10_unscaled:
9780b57cec5SDimitry Andric   case ARM::fixup_arm_ldst_pcrel_12:
9790b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10:
9800b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_9:
981fe6060f1SDimitry Andric   case ARM::fixup_arm_ldst_abs_12:
9820b57cec5SDimitry Andric   case ARM::fixup_arm_adr_pcrel_12:
9830b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbl:
9840b57cec5SDimitry Andric   case ARM::fixup_arm_condbl:
9850b57cec5SDimitry Andric   case ARM::fixup_arm_blx:
9860b57cec5SDimitry Andric   case ARM::fixup_arm_condbranch:
9870b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbranch:
9880b57cec5SDimitry Andric     return 3;
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric   case FK_Data_4:
9910b57cec5SDimitry Andric   case ARM::fixup_t2_ldst_pcrel_12:
9920b57cec5SDimitry Andric   case ARM::fixup_t2_condbranch:
9930b57cec5SDimitry Andric   case ARM::fixup_t2_uncondbranch:
9940b57cec5SDimitry Andric   case ARM::fixup_t2_pcrel_10:
9950b57cec5SDimitry Andric   case ARM::fixup_t2_pcrel_9:
9960b57cec5SDimitry Andric   case ARM::fixup_t2_adr_pcrel_12:
9970b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bl:
9980b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_blx:
9990b57cec5SDimitry Andric   case ARM::fixup_arm_movt_hi16:
10000b57cec5SDimitry Andric   case ARM::fixup_arm_movw_lo16:
10010b57cec5SDimitry Andric   case ARM::fixup_t2_movt_hi16:
10020b57cec5SDimitry Andric   case ARM::fixup_t2_movw_lo16:
10030b57cec5SDimitry Andric   case ARM::fixup_t2_so_imm:
10040b57cec5SDimitry Andric   case ARM::fixup_bf_branch:
10050b57cec5SDimitry Andric   case ARM::fixup_bf_target:
10060b57cec5SDimitry Andric   case ARM::fixup_bfl_target:
10070b57cec5SDimitry Andric   case ARM::fixup_bfc_target:
10080b57cec5SDimitry Andric   case ARM::fixup_bfcsel_else_target:
10090b57cec5SDimitry Andric   case ARM::fixup_wls:
10100b57cec5SDimitry Andric   case ARM::fixup_le:
10110b57cec5SDimitry Andric     return 4;
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   case FK_SecRel_2:
10140b57cec5SDimitry Andric     return 2;
10150b57cec5SDimitry Andric   case FK_SecRel_4:
10160b57cec5SDimitry Andric     return 4;
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric }
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric /// getFixupKindContainerSizeBytes - The number of bytes of the
10210b57cec5SDimitry Andric /// container involved in big endian.
10220b57cec5SDimitry Andric static unsigned getFixupKindContainerSizeBytes(unsigned Kind) {
10230b57cec5SDimitry Andric   switch (Kind) {
10240b57cec5SDimitry Andric   default:
10250b57cec5SDimitry Andric     llvm_unreachable("Unknown fixup kind!");
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   case FK_Data_1:
10280b57cec5SDimitry Andric     return 1;
10290b57cec5SDimitry Andric   case FK_Data_2:
10300b57cec5SDimitry Andric     return 2;
10310b57cec5SDimitry Andric   case FK_Data_4:
10320b57cec5SDimitry Andric     return 4;
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bcc:
10350b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cp:
10360b57cec5SDimitry Andric   case ARM::fixup_thumb_adr_pcrel_10:
10370b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_br:
10380b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_cb:
103906c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_8_15:
104006c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_upper_0_7:
104106c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_8_15:
104206c3fb27SDimitry Andric   case ARM::fixup_arm_thumb_lower_0_7:
10430b57cec5SDimitry Andric     // Instruction size is 2 bytes.
10440b57cec5SDimitry Andric     return 2;
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10_unscaled:
10470b57cec5SDimitry Andric   case ARM::fixup_arm_ldst_pcrel_12:
10480b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_10:
10490b57cec5SDimitry Andric   case ARM::fixup_arm_pcrel_9:
10500b57cec5SDimitry Andric   case ARM::fixup_arm_adr_pcrel_12:
10510b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbl:
10520b57cec5SDimitry Andric   case ARM::fixup_arm_condbl:
10530b57cec5SDimitry Andric   case ARM::fixup_arm_blx:
10540b57cec5SDimitry Andric   case ARM::fixup_arm_condbranch:
10550b57cec5SDimitry Andric   case ARM::fixup_arm_uncondbranch:
10560b57cec5SDimitry Andric   case ARM::fixup_t2_ldst_pcrel_12:
10570b57cec5SDimitry Andric   case ARM::fixup_t2_condbranch:
10580b57cec5SDimitry Andric   case ARM::fixup_t2_uncondbranch:
10590b57cec5SDimitry Andric   case ARM::fixup_t2_pcrel_10:
1060e8d8bef9SDimitry Andric   case ARM::fixup_t2_pcrel_9:
10610b57cec5SDimitry Andric   case ARM::fixup_t2_adr_pcrel_12:
10620b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_bl:
10630b57cec5SDimitry Andric   case ARM::fixup_arm_thumb_blx:
10640b57cec5SDimitry Andric   case ARM::fixup_arm_movt_hi16:
10650b57cec5SDimitry Andric   case ARM::fixup_arm_movw_lo16:
10660b57cec5SDimitry Andric   case ARM::fixup_t2_movt_hi16:
10670b57cec5SDimitry Andric   case ARM::fixup_t2_movw_lo16:
10680b57cec5SDimitry Andric   case ARM::fixup_arm_mod_imm:
10690b57cec5SDimitry Andric   case ARM::fixup_t2_so_imm:
10700b57cec5SDimitry Andric   case ARM::fixup_bf_branch:
10710b57cec5SDimitry Andric   case ARM::fixup_bf_target:
10720b57cec5SDimitry Andric   case ARM::fixup_bfl_target:
10730b57cec5SDimitry Andric   case ARM::fixup_bfc_target:
10740b57cec5SDimitry Andric   case ARM::fixup_bfcsel_else_target:
10750b57cec5SDimitry Andric   case ARM::fixup_wls:
10760b57cec5SDimitry Andric   case ARM::fixup_le:
10770b57cec5SDimitry Andric     // Instruction size is 4 bytes.
10780b57cec5SDimitry Andric     return 4;
10790b57cec5SDimitry Andric   }
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
10830b57cec5SDimitry Andric                                const MCValue &Target,
10840b57cec5SDimitry Andric                                MutableArrayRef<char> Data, uint64_t Value,
10850b57cec5SDimitry Andric                                bool IsResolved,
10860b57cec5SDimitry Andric                                const MCSubtargetInfo* STI) const {
10875ffd83dbSDimitry Andric   unsigned Kind = Fixup.getKind();
10885ffd83dbSDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
10895ffd83dbSDimitry Andric     return;
10900b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
10910b57cec5SDimitry Andric   Value = adjustFixupValue(Asm, Fixup, Target, Value, IsResolved, Ctx, STI);
10920b57cec5SDimitry Andric   if (!Value)
10930b57cec5SDimitry Andric     return; // Doesn't change encoding.
109404eeddc0SDimitry Andric   const unsigned NumBytes = getFixupKindNumBytes(Kind);
10950b57cec5SDimitry Andric 
10960b57cec5SDimitry Andric   unsigned Offset = Fixup.getOffset();
10970b57cec5SDimitry Andric   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   // Used to point to big endian bytes.
11000b57cec5SDimitry Andric   unsigned FullSizeBytes;
11015f757f3fSDimitry Andric   if (Endian == llvm::endianness::big) {
11025ffd83dbSDimitry Andric     FullSizeBytes = getFixupKindContainerSizeBytes(Kind);
11030b57cec5SDimitry Andric     assert((Offset + FullSizeBytes) <= Data.size() && "Invalid fixup size!");
11040b57cec5SDimitry Andric     assert(NumBytes <= FullSizeBytes && "Invalid fixup size!");
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   // For each byte of the fragment that the fixup touches, mask in the bits from
11080b57cec5SDimitry Andric   // the fixup value. The Value has been "split up" into the appropriate
11090b57cec5SDimitry Andric   // bitfields above.
11100b57cec5SDimitry Andric   for (unsigned i = 0; i != NumBytes; ++i) {
11115f757f3fSDimitry Andric     unsigned Idx =
11125f757f3fSDimitry Andric         Endian == llvm::endianness::little ? i : (FullSizeBytes - 1 - i);
11130b57cec5SDimitry Andric     Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
11140b57cec5SDimitry Andric   }
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric namespace CU {
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric /// Compact unwind encoding values.
11200b57cec5SDimitry Andric enum CompactUnwindEncodings {
11210b57cec5SDimitry Andric   UNWIND_ARM_MODE_MASK                         = 0x0F000000,
11220b57cec5SDimitry Andric   UNWIND_ARM_MODE_FRAME                        = 0x01000000,
11230b57cec5SDimitry Andric   UNWIND_ARM_MODE_FRAME_D                      = 0x02000000,
11240b57cec5SDimitry Andric   UNWIND_ARM_MODE_DWARF                        = 0x04000000,
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   UNWIND_ARM_FRAME_STACK_ADJUST_MASK           = 0x00C00000,
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric   UNWIND_ARM_FRAME_FIRST_PUSH_R4               = 0x00000001,
11290b57cec5SDimitry Andric   UNWIND_ARM_FRAME_FIRST_PUSH_R5               = 0x00000002,
11300b57cec5SDimitry Andric   UNWIND_ARM_FRAME_FIRST_PUSH_R6               = 0x00000004,
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   UNWIND_ARM_FRAME_SECOND_PUSH_R8              = 0x00000008,
11330b57cec5SDimitry Andric   UNWIND_ARM_FRAME_SECOND_PUSH_R9              = 0x00000010,
11340b57cec5SDimitry Andric   UNWIND_ARM_FRAME_SECOND_PUSH_R10             = 0x00000020,
11350b57cec5SDimitry Andric   UNWIND_ARM_FRAME_SECOND_PUSH_R11             = 0x00000040,
11360b57cec5SDimitry Andric   UNWIND_ARM_FRAME_SECOND_PUSH_R12             = 0x00000080,
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   UNWIND_ARM_FRAME_D_REG_COUNT_MASK            = 0x00000F00,
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric   UNWIND_ARM_DWARF_SECTION_OFFSET              = 0x00FFFFFF
11410b57cec5SDimitry Andric };
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric } // end CU namespace
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric /// Generate compact unwind encoding for the function based on the CFI
11460b57cec5SDimitry Andric /// instructions. If the CFI instructions describe a frame that cannot be
11470b57cec5SDimitry Andric /// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which
11480b57cec5SDimitry Andric /// tells the runtime to fallback and unwind using dwarf.
1149*36b606aeSDimitry Andric uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
115006c3fb27SDimitry Andric     const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const {
11510b57cec5SDimitry Andric   DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n");
11520b57cec5SDimitry Andric   // Only armv7k uses CFI based unwinding.
11530b57cec5SDimitry Andric   if (Subtype != MachO::CPU_SUBTYPE_ARM_V7K)
11540b57cec5SDimitry Andric     return 0;
11550b57cec5SDimitry Andric   // No .cfi directives means no frame.
115606c3fb27SDimitry Andric   ArrayRef<MCCFIInstruction> Instrs = FI->Instructions;
11570b57cec5SDimitry Andric   if (Instrs.empty())
11580b57cec5SDimitry Andric     return 0;
115906c3fb27SDimitry Andric   if (!isDarwinCanonicalPersonality(FI->Personality) &&
116006c3fb27SDimitry Andric       !Ctxt->emitCompactUnwindNonCanonical())
116106c3fb27SDimitry Andric     return CU::UNWIND_ARM_MODE_DWARF;
116206c3fb27SDimitry Andric 
11630b57cec5SDimitry Andric   // Start off assuming CFA is at SP+0.
11648bcb0991SDimitry Andric   unsigned CFARegister = ARM::SP;
11650b57cec5SDimitry Andric   int CFARegisterOffset = 0;
11660b57cec5SDimitry Andric   // Mark savable registers as initially unsaved
11670b57cec5SDimitry Andric   DenseMap<unsigned, int> RegOffsets;
11680b57cec5SDimitry Andric   int FloatRegCount = 0;
11690b57cec5SDimitry Andric   // Process each .cfi directive and build up compact unwind info.
117004eeddc0SDimitry Andric   for (const MCCFIInstruction &Inst : Instrs) {
11718bcb0991SDimitry Andric     unsigned Reg;
11720b57cec5SDimitry Andric     switch (Inst.getOperation()) {
11730b57cec5SDimitry Andric     case MCCFIInstruction::OpDefCfa: // DW_CFA_def_cfa
11745ffd83dbSDimitry Andric       CFARegisterOffset = Inst.getOffset();
11758bcb0991SDimitry Andric       CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true);
11760b57cec5SDimitry Andric       break;
11770b57cec5SDimitry Andric     case MCCFIInstruction::OpDefCfaOffset: // DW_CFA_def_cfa_offset
11785ffd83dbSDimitry Andric       CFARegisterOffset = Inst.getOffset();
11790b57cec5SDimitry Andric       break;
11800b57cec5SDimitry Andric     case MCCFIInstruction::OpDefCfaRegister: // DW_CFA_def_cfa_register
11818bcb0991SDimitry Andric       CFARegister = *MRI.getLLVMRegNum(Inst.getRegister(), true);
11820b57cec5SDimitry Andric       break;
11830b57cec5SDimitry Andric     case MCCFIInstruction::OpOffset: // DW_CFA_offset
11848bcb0991SDimitry Andric       Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true);
11850b57cec5SDimitry Andric       if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
11860b57cec5SDimitry Andric         RegOffsets[Reg] = Inst.getOffset();
11870b57cec5SDimitry Andric       else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
11880b57cec5SDimitry Andric         RegOffsets[Reg] = Inst.getOffset();
11890b57cec5SDimitry Andric         ++FloatRegCount;
11900b57cec5SDimitry Andric       } else {
11910b57cec5SDimitry Andric         DEBUG_WITH_TYPE("compact-unwind",
11920b57cec5SDimitry Andric                         llvm::dbgs() << ".cfi_offset on unknown register="
11930b57cec5SDimitry Andric                                      << Inst.getRegister() << "\n");
11940b57cec5SDimitry Andric         return CU::UNWIND_ARM_MODE_DWARF;
11950b57cec5SDimitry Andric       }
11960b57cec5SDimitry Andric       break;
11970b57cec5SDimitry Andric     case MCCFIInstruction::OpRelOffset: // DW_CFA_advance_loc
11980b57cec5SDimitry Andric       // Ignore
11990b57cec5SDimitry Andric       break;
12000b57cec5SDimitry Andric     default:
12010b57cec5SDimitry Andric       // Directive not convertable to compact unwind, bail out.
12020b57cec5SDimitry Andric       DEBUG_WITH_TYPE("compact-unwind",
12030b57cec5SDimitry Andric                       llvm::dbgs()
120406c3fb27SDimitry Andric                           << "CFI directive not compatible with compact "
12050fca6ea1SDimitry Andric                              "unwind encoding, opcode="
12060fca6ea1SDimitry Andric                           << uint8_t(Inst.getOperation()) << "\n");
12070b57cec5SDimitry Andric       return CU::UNWIND_ARM_MODE_DWARF;
12080b57cec5SDimitry Andric       break;
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric   }
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric   // If no frame set up, return no unwind info.
12130b57cec5SDimitry Andric   if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
12140b57cec5SDimitry Andric     return 0;
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric   // Verify standard frame (lr/r7) was used.
12170b57cec5SDimitry Andric   if (CFARegister != ARM::R7) {
12180b57cec5SDimitry Andric     DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "frame register is "
12190b57cec5SDimitry Andric                                                    << CFARegister
12200b57cec5SDimitry Andric                                                    << " instead of r7\n");
12210b57cec5SDimitry Andric     return CU::UNWIND_ARM_MODE_DWARF;
12220b57cec5SDimitry Andric   }
12230b57cec5SDimitry Andric   int StackAdjust = CFARegisterOffset - 8;
12240b57cec5SDimitry Andric   if (RegOffsets.lookup(ARM::LR) != (-4 - StackAdjust)) {
12250b57cec5SDimitry Andric     DEBUG_WITH_TYPE("compact-unwind",
12260b57cec5SDimitry Andric                     llvm::dbgs()
12270b57cec5SDimitry Andric                         << "LR not saved as standard frame, StackAdjust="
12280b57cec5SDimitry Andric                         << StackAdjust
12290b57cec5SDimitry Andric                         << ", CFARegisterOffset=" << CFARegisterOffset
12300b57cec5SDimitry Andric                         << ", lr save at offset=" << RegOffsets[14] << "\n");
12310b57cec5SDimitry Andric     return CU::UNWIND_ARM_MODE_DWARF;
12320b57cec5SDimitry Andric   }
12330b57cec5SDimitry Andric   if (RegOffsets.lookup(ARM::R7) != (-8 - StackAdjust)) {
12340b57cec5SDimitry Andric     DEBUG_WITH_TYPE("compact-unwind",
12350b57cec5SDimitry Andric                     llvm::dbgs() << "r7 not saved as standard frame\n");
12360b57cec5SDimitry Andric     return CU::UNWIND_ARM_MODE_DWARF;
12370b57cec5SDimitry Andric   }
12380b57cec5SDimitry Andric   uint32_t CompactUnwindEncoding = CU::UNWIND_ARM_MODE_FRAME;
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric   // If var-args are used, there may be a stack adjust required.
12410b57cec5SDimitry Andric   switch (StackAdjust) {
12420b57cec5SDimitry Andric   case 0:
12430b57cec5SDimitry Andric     break;
12440b57cec5SDimitry Andric   case 4:
12450b57cec5SDimitry Andric     CompactUnwindEncoding |= 0x00400000;
12460b57cec5SDimitry Andric     break;
12470b57cec5SDimitry Andric   case 8:
12480b57cec5SDimitry Andric     CompactUnwindEncoding |= 0x00800000;
12490b57cec5SDimitry Andric     break;
12500b57cec5SDimitry Andric   case 12:
12510b57cec5SDimitry Andric     CompactUnwindEncoding |= 0x00C00000;
12520b57cec5SDimitry Andric     break;
12530b57cec5SDimitry Andric   default:
12540b57cec5SDimitry Andric     DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs()
12550b57cec5SDimitry Andric                                           << ".cfi_def_cfa stack adjust ("
12560b57cec5SDimitry Andric                                           << StackAdjust << ") out of range\n");
12570b57cec5SDimitry Andric     return CU::UNWIND_ARM_MODE_DWARF;
12580b57cec5SDimitry Andric   }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   // If r6 is saved, it must be right below r7.
12610b57cec5SDimitry Andric   static struct {
12620b57cec5SDimitry Andric     unsigned Reg;
12630b57cec5SDimitry Andric     unsigned Encoding;
12640b57cec5SDimitry Andric   } GPRCSRegs[] = {{ARM::R6, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R6},
12650b57cec5SDimitry Andric                    {ARM::R5, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R5},
12660b57cec5SDimitry Andric                    {ARM::R4, CU::UNWIND_ARM_FRAME_FIRST_PUSH_R4},
12670b57cec5SDimitry Andric                    {ARM::R12, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R12},
12680b57cec5SDimitry Andric                    {ARM::R11, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R11},
12690b57cec5SDimitry Andric                    {ARM::R10, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R10},
12700b57cec5SDimitry Andric                    {ARM::R9, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R9},
12710b57cec5SDimitry Andric                    {ARM::R8, CU::UNWIND_ARM_FRAME_SECOND_PUSH_R8}};
12720b57cec5SDimitry Andric 
12730b57cec5SDimitry Andric   int CurOffset = -8 - StackAdjust;
12740b57cec5SDimitry Andric   for (auto CSReg : GPRCSRegs) {
12750b57cec5SDimitry Andric     auto Offset = RegOffsets.find(CSReg.Reg);
12760b57cec5SDimitry Andric     if (Offset == RegOffsets.end())
12770b57cec5SDimitry Andric       continue;
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric     int RegOffset = Offset->second;
12800b57cec5SDimitry Andric     if (RegOffset != CurOffset - 4) {
12810b57cec5SDimitry Andric       DEBUG_WITH_TYPE("compact-unwind",
12820b57cec5SDimitry Andric                       llvm::dbgs() << MRI.getName(CSReg.Reg) << " saved at "
12830b57cec5SDimitry Andric                                    << RegOffset << " but only supported at "
12840b57cec5SDimitry Andric                                    << CurOffset << "\n");
12850b57cec5SDimitry Andric       return CU::UNWIND_ARM_MODE_DWARF;
12860b57cec5SDimitry Andric     }
12870b57cec5SDimitry Andric     CompactUnwindEncoding |= CSReg.Encoding;
12880b57cec5SDimitry Andric     CurOffset -= 4;
12890b57cec5SDimitry Andric   }
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   // If no floats saved, we are done.
12920b57cec5SDimitry Andric   if (FloatRegCount == 0)
12930b57cec5SDimitry Andric     return CompactUnwindEncoding;
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   // Switch mode to include D register saving.
12960b57cec5SDimitry Andric   CompactUnwindEncoding &= ~CU::UNWIND_ARM_MODE_MASK;
12970b57cec5SDimitry Andric   CompactUnwindEncoding |= CU::UNWIND_ARM_MODE_FRAME_D;
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   // FIXME: supporting more than 4 saved D-registers compactly would be trivial,
13000b57cec5SDimitry Andric   // but needs coordination with the linker and libunwind.
13010b57cec5SDimitry Andric   if (FloatRegCount > 4) {
13020b57cec5SDimitry Andric     DEBUG_WITH_TYPE("compact-unwind",
13030b57cec5SDimitry Andric                     llvm::dbgs() << "unsupported number of D registers saved ("
13040b57cec5SDimitry Andric                                  << FloatRegCount << ")\n");
13050b57cec5SDimitry Andric       return CU::UNWIND_ARM_MODE_DWARF;
13060b57cec5SDimitry Andric   }
13070b57cec5SDimitry Andric 
13080b57cec5SDimitry Andric   // Floating point registers must either be saved sequentially, or we defer to
13090b57cec5SDimitry Andric   // DWARF. No gaps allowed here so check that each saved d-register is
13100b57cec5SDimitry Andric   // precisely where it should be.
13110b57cec5SDimitry Andric   static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
13120b57cec5SDimitry Andric   for (int Idx = FloatRegCount - 1; Idx >= 0; --Idx) {
13130b57cec5SDimitry Andric     auto Offset = RegOffsets.find(FPRCSRegs[Idx]);
13140b57cec5SDimitry Andric     if (Offset == RegOffsets.end()) {
13150b57cec5SDimitry Andric       DEBUG_WITH_TYPE("compact-unwind",
13160b57cec5SDimitry Andric                       llvm::dbgs() << FloatRegCount << " D-regs saved, but "
13170b57cec5SDimitry Andric                                    << MRI.getName(FPRCSRegs[Idx])
13180b57cec5SDimitry Andric                                    << " not saved\n");
13190b57cec5SDimitry Andric       return CU::UNWIND_ARM_MODE_DWARF;
13200b57cec5SDimitry Andric     } else if (Offset->second != CurOffset - 8) {
13210b57cec5SDimitry Andric       DEBUG_WITH_TYPE("compact-unwind",
13220b57cec5SDimitry Andric                       llvm::dbgs() << FloatRegCount << " D-regs saved, but "
13230b57cec5SDimitry Andric                                    << MRI.getName(FPRCSRegs[Idx])
13240b57cec5SDimitry Andric                                    << " saved at " << Offset->second
13250b57cec5SDimitry Andric                                    << ", expected at " << CurOffset - 8
13260b57cec5SDimitry Andric                                    << "\n");
13270b57cec5SDimitry Andric       return CU::UNWIND_ARM_MODE_DWARF;
13280b57cec5SDimitry Andric     }
13290b57cec5SDimitry Andric     CurOffset -= 8;
13300b57cec5SDimitry Andric   }
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
13330b57cec5SDimitry Andric }
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric static MCAsmBackend *createARMAsmBackend(const Target &T,
13360b57cec5SDimitry Andric                                          const MCSubtargetInfo &STI,
13370b57cec5SDimitry Andric                                          const MCRegisterInfo &MRI,
13380b57cec5SDimitry Andric                                          const MCTargetOptions &Options,
13395f757f3fSDimitry Andric                                          llvm::endianness Endian) {
13400b57cec5SDimitry Andric   const Triple &TheTriple = STI.getTargetTriple();
13410b57cec5SDimitry Andric   switch (TheTriple.getObjectFormat()) {
13420b57cec5SDimitry Andric   default:
13430b57cec5SDimitry Andric     llvm_unreachable("unsupported object format");
13445ffd83dbSDimitry Andric   case Triple::MachO:
13455ffd83dbSDimitry Andric     return new ARMAsmBackendDarwin(T, STI, MRI);
13460b57cec5SDimitry Andric   case Triple::COFF:
13470b57cec5SDimitry Andric     assert(TheTriple.isOSWindows() && "non-Windows ARM COFF is not supported");
1348349cc55cSDimitry Andric     return new ARMAsmBackendWinCOFF(T, STI.getTargetTriple().isThumb());
13490b57cec5SDimitry Andric   case Triple::ELF:
13500b57cec5SDimitry Andric     assert(TheTriple.isOSBinFormatELF() && "using ELF for non-ELF target");
13510fca6ea1SDimitry Andric     uint8_t OSABI = Options.FDPIC
13520fca6ea1SDimitry Andric                         ? ELF::ELFOSABI_ARM_FDPIC
13530fca6ea1SDimitry Andric                         : MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
1354349cc55cSDimitry Andric     return new ARMAsmBackendELF(T, STI.getTargetTriple().isThumb(), OSABI,
1355349cc55cSDimitry Andric                                 Endian);
13560b57cec5SDimitry Andric   }
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric MCAsmBackend *llvm::createARMLEAsmBackend(const Target &T,
13600b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
13610b57cec5SDimitry Andric                                           const MCRegisterInfo &MRI,
13620b57cec5SDimitry Andric                                           const MCTargetOptions &Options) {
13635f757f3fSDimitry Andric   return createARMAsmBackend(T, STI, MRI, Options, llvm::endianness::little);
13640b57cec5SDimitry Andric }
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric MCAsmBackend *llvm::createARMBEAsmBackend(const Target &T,
13670b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
13680b57cec5SDimitry Andric                                           const MCRegisterInfo &MRI,
13690b57cec5SDimitry Andric                                           const MCTargetOptions &Options) {
13705f757f3fSDimitry Andric   return createARMAsmBackend(T, STI, MRI, Options, llvm::endianness::big);
13710b57cec5SDimitry Andric }
1372