43 ARMELFObjectWriter(uint8_t OSABI)
53std::optional<MCFixupKind>
56#define ELF_RELOC(X, Y) .Case(#X, Y)
57#include "llvm/BinaryFormat/ELFRelocs/ARM.def"
59 .
Case(
"BFD_RELOC_NONE", ELF::R_ARM_NONE)
60 .
Case(
"BFD_RELOC_8", ELF::R_ARM_ABS8)
61 .
Case(
"BFD_RELOC_16", ELF::R_ARM_ABS16)
62 .
Case(
"BFD_RELOC_32", ELF::R_ARM_ABS32)
70 unsigned IsPCRelConstant =
77 {
"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant},
78 {
"fixup_t2_ldst_pcrel_12", 0, 32,
80 {
"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant},
81 {
"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant},
82 {
"fixup_t2_pcrel_10", 0, 32,
86 {
"fixup_t2_pcrel_9", 0, 32,
88 {
"fixup_arm_ldst_abs_12", 0, 32, 0},
89 {
"fixup_thumb_adr_pcrel_10", 0, 8,
91 {
"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant},
92 {
"fixup_t2_adr_pcrel_12", 0, 32,
103 {
"fixup_arm_thumb_blx", 0, 32,
107 {
"fixup_arm_thumb_cp", 0, 8,
113 {
"fixup_arm_movt_hi16", 0, 20, 0},
114 {
"fixup_arm_movw_lo16", 0, 20, 0},
115 {
"fixup_t2_movt_hi16", 0, 20, 0},
116 {
"fixup_t2_movw_lo16", 0, 20, 0},
117 {
"fixup_arm_mod_imm", 0, 12, 0},
118 {
"fixup_t2_so_imm", 0, 26, 0},
123 {
"fixup_bfcsel_else_target", 0, 32, 0},
131 {
"fixup_arm_ldst_pcrel_12", 0, 32, IsPCRelConstant},
132 {
"fixup_t2_ldst_pcrel_12", 0, 32,
134 {
"fixup_arm_pcrel_10_unscaled", 0, 32, IsPCRelConstant},
135 {
"fixup_arm_pcrel_10", 0, 32, IsPCRelConstant},
136 {
"fixup_t2_pcrel_10", 0, 32,
140 {
"fixup_t2_pcrel_9", 0, 32,
142 {
"fixup_arm_ldst_abs_12", 0, 32, 0},
143 {
"fixup_thumb_adr_pcrel_10", 8, 8,
145 {
"fixup_arm_adr_pcrel_12", 0, 32, IsPCRelConstant},
146 {
"fixup_t2_adr_pcrel_12", 0, 32,
157 {
"fixup_arm_thumb_blx", 0, 32,
161 {
"fixup_arm_thumb_cp", 8, 8,
167 {
"fixup_arm_movt_hi16", 12, 20, 0},
168 {
"fixup_arm_movw_lo16", 12, 20, 0},
169 {
"fixup_t2_movt_hi16", 12, 20, 0},
170 {
"fixup_t2_movw_lo16", 12, 20, 0},
171 {
"fixup_arm_mod_imm", 20, 12, 0},
172 {
"fixup_t2_so_imm", 26, 6, 0},
177 {
"fixup_bfcsel_else_target", 0, 32, 0},
210 bool HasThumb2 = STI.
hasFeature(ARM::FeatureThumb2);
211 bool HasV8MBaselineOps = STI.
hasFeature(ARM::HasV8MBaselineOps);
217 return HasThumb2 ? (
unsigned)ARM::t2Bcc : Op;
219 return HasThumb2 ? (
unsigned)ARM::t2LDRpci : Op;
221 return HasThumb2 ? (
unsigned)ARM::t2ADR : Op;
223 return HasV8MBaselineOps ? (
unsigned)ARM::t2B : Op;
240 if (Offset < Min || Offset > Max)
241 return "out of range pc-relative fixup value";
247 switch (
Fixup.getTargetKind()) {
257 return "out of range pc-relative fixup value";
269 return "out of range pc-relative fixup value";
278 return "misaligned pc-relative fixup value";
280 return "out of range pc-relative fixup value";
289 return "will be converted to nop";
314 return "out of range label-relative fixup value";
346 RelaxedOp == ARM::tHINT) {
352 Inst = std::move(Res);
363 const uint16_t Thumb1_16bitNopEncoding = 0x46c0;
364 const uint16_t Thumb2_16bitNopEncoding = 0xbf00;
365 const uint32_t ARMv4_NopEncoding = 0xe1a00000;
366 const uint32_t ARMv6T2_NopEncoding = 0xe320f000;
369 hasNOP(STI) ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;
371 for (
uint64_t i = 0; i != NumNops; ++i)
379 hasNOP(STI) ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;
381 for (
uint64_t i = 0; i != NumNops; ++i)
403 if (IsLittleEndian) {
407 Swapped |= (
Value & 0x0000FFFF) << 16;
414 bool IsLittleEndian) {
417 if (IsLittleEndian) {
418 Value = (SecondHalf & 0xFFFF) << 16;
419 Value |= (FirstHalf & 0xFFFF);
421 Value = (SecondHalf & 0xFFFF);
422 Value |= (FirstHalf & 0xFFFF) << 16;
433 unsigned Kind =
Fixup.getKind();
441 if (
A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&
A->getSymbol()) &&
442 A->getSymbol().isExternal() &&
466 unsigned Hi4 = (
Value & 0xF000) >> 12;
467 unsigned Lo12 =
Value & 0x0FFF;
470 Value = (Hi4 << 16) | (Lo12);
479 unsigned Hi4 = (
Value & 0xF000) >> 12;
480 unsigned i = (
Value & 0x800) >> 11;
481 unsigned Mid3 = (
Value & 0x700) >> 8;
482 unsigned Lo8 =
Value & 0x0FF;
487 Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
500 if ((int64_t)
Value < 0) {
508 Value |= isAdd << 23;
521 if ((int64_t)
Value < 0) {
536 if ((int64_t)
Value < 0) {
542 out |= (
Value & 0x800) << 15;
543 out |= (
Value & 0x700) << 4;
544 out |= (
Value & 0x0FF);
557 dyn_cast<MCSymbolRefExpr>(
Fixup.getValue()))
560 return 0xffffff & ((
Value - 8) >> 2);
563 if (!isInt<25>(
Value)) {
571 bool I =
Value & 0x800000;
572 bool J1 =
Value & 0x400000;
573 bool J2 =
Value & 0x200000;
580 out |= (
Value & 0x1FF800) << 5;
581 out |= (
Value & 0x0007FF);
587 if (!isInt<21>(
Value)) {
595 out |= (
Value & 0x80000) << 7;
596 out |= (
Value & 0x40000) >> 7;
597 out |= (
Value & 0x20000) >> 4;
598 out |= (
Value & 0x1F800) << 5;
599 out |= (
Value & 0x007FF);
604 if (!isInt<25>(
Value - 4) ||
608 !isInt<23>(
Value - 4))) {
626 uint32_t signBit = (offset & 0x800000) >> 23;
627 uint32_t I1Bit = (offset & 0x400000) >> 22;
628 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
629 uint32_t I2Bit = (offset & 0x200000) >> 21;
630 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
631 uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
632 uint32_t imm11Bits = (offset & 0x000007FF);
652 if (
Value % 4 != 0) {
659 dyn_cast<MCSymbolRefExpr>(
Fixup.getValue()))
662 uint32_t signBit = (offset & 0x400000) >> 22;
663 uint32_t I1Bit = (offset & 0x200000) >> 21;
664 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
665 uint32_t I2Bit = (offset & 0x100000) >> 20;
666 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
667 uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
668 uint32_t imm10LBits = (offset & 0x3FF);
680 if (!STI->
hasFeature(ARM::FeatureThumb2) && IsResolved) {
682 if (FixupDiagnostic) {
688 return ((
Value - 4) >> 2) & 0xff;
693 if ((int64_t)Value < 2 || Value > 0x82 ||
Value & 1) {
700 return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
708 if (FixupDiagnostic) {
713 return ((
Value - 4) >> 1) & 0x7ff;
719 if (FixupDiagnostic) {
724 return ((
Value - 4) >> 1) & 0xff;
729 if ((int64_t)
Value < 0) {
739 return Value | (isAdd << 23);
749 if ((int64_t)
Value < 0) {
759 Value |= isAdd << 23;
776 if ((int64_t)
Value < 0) {
790 Value |= isAdd << 23;
808 if ((int64_t)
Value < 0) {
818 EncValue |= (
Value & 0x800) << 15;
819 EncValue |= (
Value & 0x700) << 4;
820 EncValue |= (
Value & 0xff);
825 if (FixupDiagnostic) {
836 if (FixupDiagnostic) {
843 out |= (((
Value - 4) >> 1) & 0x1) << 11;
844 out |= (((
Value - 4) >> 1) & 0x7fe);
845 out |= (((
Value - 4) >> 1) & HighBitMask) << 5;
855 if (FixupDiagnostic) {
865 if (FixupDiagnostic) {
872 real_value = -real_value;
873 out |= ((real_value >> 1) & 0x1) << 11;
874 out |= ((real_value >> 1) & 0x7fe);
885 const unsigned FixupKind =
Fixup.getKind();
889 assert(
Sym &&
"How did we resolve this?");
896 if (
Sym->isExternal())
901 if (
Sym &&
Sym->isELF()) {
902 unsigned Type = cast<MCSymbolELF>(
Sym)->getType();
1048 unsigned Kind =
Fixup.getKind();
1061 unsigned FullSizeBytes;
1065 assert(NumBytes <= FullSizeBytes &&
"Invalid fixup size!");
1071 for (
unsigned i = 0; i != NumBytes; ++i) {
1119 unsigned CFARegister = ARM::SP;
1120 int CFARegisterOffset = 0;
1123 int FloatRegCount = 0;
1127 switch (Inst.getOperation()) {
1129 CFARegisterOffset = Inst.getOffset();
1133 CFARegisterOffset = Inst.getOffset();
1140 if (ARMMCRegisterClasses[ARM::GPRRegClassID].
contains(Reg))
1141 RegOffsets[Reg] = Inst.getOffset();
1142 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].
contains(Reg)) {
1143 RegOffsets[Reg] = Inst.getOffset();
1147 llvm::dbgs() <<
".cfi_offset on unknown register="
1148 << Inst.getRegister() <<
"\n");
1159 <<
"CFI directive not compatible with compact "
1160 "unwind encoding, opcode=" << Inst.getOperation()
1168 if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
1172 if (CFARegister != ARM::R7) {
1175 <<
" instead of r7\n");
1178 int StackAdjust = CFARegisterOffset - 8;
1179 if (RegOffsets.
lookup(ARM::LR) != (-4 - StackAdjust)) {
1182 <<
"LR not saved as standard frame, StackAdjust="
1184 <<
", CFARegisterOffset=" << CFARegisterOffset
1185 <<
", lr save at offset=" << RegOffsets[14] <<
"\n");
1188 if (RegOffsets.
lookup(ARM::R7) != (-8 - StackAdjust)) {
1190 llvm::dbgs() <<
"r7 not saved as standard frame\n");
1196 switch (StackAdjust) {
1200 CompactUnwindEncoding |= 0x00400000;
1203 CompactUnwindEncoding |= 0x00800000;
1206 CompactUnwindEncoding |= 0x00C00000;
1210 <<
".cfi_def_cfa stack adjust ("
1211 << StackAdjust <<
") out of range\n");
1228 int CurOffset = -8 - StackAdjust;
1229 for (
auto CSReg : GPRCSRegs) {
1234 int RegOffset =
Offset->second;
1235 if (RegOffset != CurOffset - 4) {
1238 << RegOffset <<
" but only supported at "
1239 << CurOffset <<
"\n");
1242 CompactUnwindEncoding |= CSReg.Encoding;
1247 if (FloatRegCount == 0)
1248 return CompactUnwindEncoding;
1251 CompactUnwindEncoding &=
~CU::UNWIND_ARM_MODE_MASK;
1256 if (FloatRegCount > 4) {
1258 llvm::dbgs() <<
"unsupported number of D registers saved ("
1259 << FloatRegCount <<
")\n");
1266 static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
1267 for (
int Idx = FloatRegCount - 1;
Idx >= 0; --
Idx) {
1271 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but "
1275 }
else if (
Offset->second != CurOffset - 8) {
1277 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but "
1279 <<
" saved at " <<
Offset->second
1280 <<
", expected at " << CurOffset - 8
1287 return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
unsigned const MachineRegisterInfo * MRI
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian)
static MCAsmBackend * createARMAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options, support::endianness Endian)
static unsigned getFixupKindContainerSizeBytes(unsigned Kind)
getFixupKindContainerSizeBytes - The number of bytes of the container involved in big endian.
static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, bool IsLittleEndian)
static const char * checkPCRelOffset(uint64_t Value, int64_t Min, int64_t Max)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
uint32_t generateCompactUnwindEncoding(ArrayRef< MCCFIInstruction > Instrs) const override
Generate compact unwind encoding for the function based on the CFI instructions.
const MachO::CPUSubTypeARM Subtype
const char * reasonForFixupRelaxation(const MCFixup &Fixup, uint64_t Value) const
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef< char > Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const override
Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...
const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const override
Get information on a fixup kind.
unsigned getNumFixupKinds() const override
Get the number of target specific fixup kinds.
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) override
Hook to check if a relocation is needed for some target specific reason.
bool hasNOP(const MCSubtargetInfo *STI) const
unsigned getRelaxedOpcode(unsigned Op, const MCSubtargetInfo &STI) const
unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, uint64_t Value, bool IsResolved, MCContext &Ctx, const MCSubtargetInfo *STI) const
bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const override
Write an (optimal) nop sequence of Count bytes to the given output.
std::optional< MCFixupKind > getFixupKind(StringRef Name) const override
Map a relocation name used in .reloc to a fixup kind.
void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override
Relax the instruction in the given fragment to the next wider instruction.
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override
Simple predicate for targets where !Resolved implies requiring relaxation.
bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override
Check whether the given instruction may need relaxation.
void handleAssemblerFlag(MCAssemblerFlag Flag) override
Handle any target-specific assembler flags. By default, do nothing.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
Generic interface to target specific assembler backends.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
const support::endianness Endian
Encapsulates the layout of an assembly file at a particular point in time.
Context object for machine code objects.
void reportError(SMLoc L, const Twine &Msg)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Instances of this class represent a single low-level machine instruction.
void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer=nullptr, StringRef Separator=" ", const MCRegisterInfo *RegInfo=nullptr) const
Dump the MCInst as prettily as possible using the additional MC structures, if given.
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
static MCOperand createReg(unsigned Reg)
static MCOperand createImm(int64_t Val)
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
std::optional< unsigned > getLLVMRegNum(unsigned RegNum, bool isEH) const
Map a dwarf register back to a target register.
const char * getName(MCRegister RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register.
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
Represent a reference to a symbol from inside an expression.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
This represents an "assembler immediate".
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef - Represent a constant reference to a string, i.e.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
bool isThumb() const
Tests whether the target is Thumb (little and big endian).
ObjectFormatType getObjectFormat() const
Get the object format for this triple.
OSType getOS() const
Get the parsed operating system type of this triple.
bool isOSWindows() const
Tests whether the OS is Windows.
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CompactUnwindEncodings
Compact unwind encoding values.
@ UNWIND_ARM_FRAME_SECOND_PUSH_R10
@ UNWIND_ARM_FRAME_FIRST_PUSH_R6
@ UNWIND_ARM_FRAME_SECOND_PUSH_R11
@ UNWIND_ARM_DWARF_SECTION_OFFSET
@ UNWIND_ARM_FRAME_FIRST_PUSH_R4
@ UNWIND_ARM_FRAME_SECOND_PUSH_R9
@ UNWIND_ARM_FRAME_SECOND_PUSH_R8
@ UNWIND_ARM_FRAME_STACK_ADJUST_MASK
@ UNWIND_ARM_FRAME_SECOND_PUSH_R12
@ UNWIND_ARM_FRAME_D_REG_COUNT_MASK
@ UNWIND_ARM_MODE_FRAME_D
@ UNWIND_ARM_FRAME_FIRST_PUSH_R5
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
@ fixup_thumb_adr_pcrel_10
@ fixup_arm_pcrel_10_unscaled
@ fixup_bfcsel_else_target
@ fixup_arm_ldst_pcrel_12
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
This is an optimization pass for GlobalISel generic memory operations.
MCAsmBackend * createARMBEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
MCAsmBackend * createARMLEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
MCFixupKind
Extensible enumeration to represent the type of a fixup.
@ FK_SecRel_2
A two-byte section relative fixup.
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_SecRel_4
A four-byte section relative fixup.
@ FK_Data_2
A two-byte fixup.
@ MCAF_Code16
.code16 (X86) / .code 16 (ARM)
@ MCAF_Code32
.code32 (X86) / .code 32 (ARM)
Target independent information on a fixup kind.
@ FKF_IsAlignedDownTo32Bits
Should this fixup kind force a 4-byte aligned effective PC value?
@ FKF_Constant
This fixup kind should be resolved if defined.
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...