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)
76 {
"fixup_t2_ldst_pcrel_12", 0, 32,
81 {
"fixup_t2_pcrel_10", 0, 32,
85 {
"fixup_t2_pcrel_9", 0, 32,
88 {
"fixup_arm_ldst_abs_12", 0, 32, 0},
89 {
"fixup_thumb_adr_pcrel_10", 0, 8,
93 {
"fixup_t2_adr_pcrel_12", 0, 32,
105 {
"fixup_arm_thumb_blx", 0, 32,
109 {
"fixup_arm_thumb_cp", 0, 8,
115 {
"fixup_arm_movt_hi16", 0, 20, 0},
116 {
"fixup_arm_movw_lo16", 0, 20, 0},
117 {
"fixup_t2_movt_hi16", 0, 20, 0},
118 {
"fixup_t2_movw_lo16", 0, 20, 0},
119 {
"fixup_arm_thumb_upper_8_15", 0, 8, 0},
120 {
"fixup_arm_thumb_upper_0_7", 0, 8, 0},
121 {
"fixup_arm_thumb_lower_8_15", 0, 8, 0},
122 {
"fixup_arm_thumb_lower_0_7", 0, 8, 0},
123 {
"fixup_arm_mod_imm", 0, 12, 0},
124 {
"fixup_t2_so_imm", 0, 26, 0},
129 {
"fixup_bfcsel_else_target", 0, 32, 0},
138 {
"fixup_t2_ldst_pcrel_12", 0, 32,
143 {
"fixup_t2_pcrel_10", 0, 32,
147 {
"fixup_t2_pcrel_9", 0, 32,
150 {
"fixup_arm_ldst_abs_12", 0, 32, 0},
151 {
"fixup_thumb_adr_pcrel_10", 8, 8,
155 {
"fixup_t2_adr_pcrel_12", 0, 32,
167 {
"fixup_arm_thumb_blx", 0, 32,
171 {
"fixup_arm_thumb_cp", 8, 8,
177 {
"fixup_arm_movt_hi16", 12, 20, 0},
178 {
"fixup_arm_movw_lo16", 12, 20, 0},
179 {
"fixup_t2_movt_hi16", 12, 20, 0},
180 {
"fixup_t2_movw_lo16", 12, 20, 0},
181 {
"fixup_arm_thumb_upper_8_15", 24, 8, 0},
182 {
"fixup_arm_thumb_upper_0_7", 24, 8, 0},
183 {
"fixup_arm_thumb_lower_8_15", 24, 8, 0},
184 {
"fixup_arm_thumb_lower_0_7", 24, 8, 0},
185 {
"fixup_arm_mod_imm", 20, 12, 0},
186 {
"fixup_t2_so_imm", 26, 6, 0},
191 {
"fixup_bfcsel_else_target", 0, 32, 0},
225 bool HasThumb2 = STI.
hasFeature(ARM::FeatureThumb2);
226 bool HasV8MBaselineOps = STI.
hasFeature(ARM::HasV8MBaselineOps);
234 return HasThumb2 ? (
unsigned)ARM::t2LDRpci :
Op;
238 return HasV8MBaselineOps ? (
unsigned)ARM::t2B :
Op;
255 if (Offset < Min || Offset > Max)
256 return "out of range pc-relative fixup value";
262 switch (
Fixup.getTargetKind()) {
272 return "out of range pc-relative fixup value";
284 return "out of range pc-relative fixup value";
293 return "misaligned pc-relative fixup value";
295 return "out of range pc-relative fixup value";
304 return "will be converted to nop";
329 return "out of range label-relative fixup value";
360 RelaxedOp == ARM::tHINT) {
366 Inst = std::move(Res);
377 const uint16_t Thumb1_16bitNopEncoding = 0x46c0;
378 const uint16_t Thumb2_16bitNopEncoding = 0xbf00;
379 const uint32_t ARMv4_NopEncoding = 0xe1a00000;
380 const uint32_t ARMv6T2_NopEncoding = 0xe320f000;
383 hasNOP(STI) ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;
385 for (
uint64_t i = 0; i != NumNops; ++i)
393 hasNOP(STI) ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;
395 for (
uint64_t i = 0; i != NumNops; ++i)
417 if (IsLittleEndian) {
421 Swapped |= (
Value & 0x0000FFFF) << 16;
428 bool IsLittleEndian) {
431 if (IsLittleEndian) {
432 Value = (SecondHalf & 0xFFFF) << 16;
433 Value |= (FirstHalf & 0xFFFF);
435 Value = (SecondHalf & 0xFFFF);
436 Value |= (FirstHalf & 0xFFFF) << 16;
447 unsigned Kind =
Fixup.getKind();
455 if (
A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&
A->getSymbol()) &&
456 A->getSymbol().isExternal() &&
480 unsigned Hi4 = (
Value & 0xF000) >> 12;
481 unsigned Lo12 =
Value & 0x0FFF;
484 Value = (Hi4 << 16) | (Lo12);
493 unsigned Hi4 = (
Value & 0xF000) >> 12;
494 unsigned i = (
Value & 0x800) >> 11;
495 unsigned Mid3 = (
Value & 0x700) >> 8;
496 unsigned Lo8 =
Value & 0x0FF;
501 Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
506 return (
Value & 0xff000000) >> 24;
510 return (
Value & 0x00ff0000) >> 16;
514 return (
Value & 0x0000ff00) >> 8;
517 return Value & 0x000000ff;
528 if ((int64_t)
Value < 0) {
536 Value |= isAdd << 23;
549 if ((int64_t)
Value < 0) {
564 if ((int64_t)
Value < 0) {
570 out |= (
Value & 0x800) << 15;
571 out |= (
Value & 0x700) << 4;
572 out |= (
Value & 0x0FF);
585 dyn_cast<MCSymbolRefExpr>(
Fixup.getValue()))
588 return 0xffffff & ((
Value - 8) >> 2);
595 "cannot perform a PC-relative fixup with a non-zero "
599 if (!isInt<25>(
Value)) {
607 bool I =
Value & 0x800000;
608 bool J1 =
Value & 0x400000;
609 bool J2 =
Value & 0x200000;
616 out |= (
Value & 0x1FF800) << 5;
617 out |= (
Value & 0x0007FF);
623 if (!isInt<21>(
Value)) {
631 out |= (
Value & 0x80000) << 7;
632 out |= (
Value & 0x40000) >> 7;
633 out |= (
Value & 0x20000) >> 4;
634 out |= (
Value & 0x1F800) << 5;
635 out |= (
Value & 0x007FF);
640 if (!isInt<25>(
Value - 4) ||
644 !isInt<23>(
Value - 4))) {
653 "cannot perform a PC-relative fixup with a non-zero "
670 uint32_t signBit = (offset & 0x800000) >> 23;
671 uint32_t I1Bit = (offset & 0x400000) >> 22;
672 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
673 uint32_t I2Bit = (offset & 0x200000) >> 21;
674 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
675 uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
676 uint32_t imm11Bits = (offset & 0x000007FF);
690 "cannot perform a PC-relative fixup with a non-zero "
705 if (
Value % 4 != 0) {
712 dyn_cast<MCSymbolRefExpr>(
Fixup.getValue()))
715 uint32_t signBit = (offset & 0x400000) >> 22;
716 uint32_t I1Bit = (offset & 0x200000) >> 21;
717 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
718 uint32_t I2Bit = (offset & 0x100000) >> 20;
719 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
720 uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
721 uint32_t imm10LBits = (offset & 0x3FF);
734 if (!STI->
hasFeature(ARM::FeatureThumb2) && IsResolved) {
736 if (FixupDiagnostic) {
742 return ((
Value - 4) >> 2) & 0xff;
747 if ((int64_t)Value < 2 || Value > 0x82 ||
Value & 1) {
754 return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
762 if (FixupDiagnostic) {
767 return ((
Value - 4) >> 1) & 0x7ff;
773 if (FixupDiagnostic) {
778 return ((
Value - 4) >> 1) & 0xff;
783 if ((int64_t)
Value < 0) {
793 return Value | (isAdd << 23);
803 if ((int64_t)
Value < 0) {
813 Value |= isAdd << 23;
830 if ((int64_t)
Value < 0) {
844 Value |= isAdd << 23;
862 if ((int64_t)
Value < 0) {
872 EncValue |= (
Value & 0x800) << 15;
873 EncValue |= (
Value & 0x700) << 4;
874 EncValue |= (
Value & 0xff);
879 if (FixupDiagnostic) {
890 if (FixupDiagnostic) {
897 out |= (((
Value - 4) >> 1) & 0x1) << 11;
898 out |= (((
Value - 4) >> 1) & 0x7fe);
899 out |= (((
Value - 4) >> 1) & HighBitMask) << 5;
909 if (FixupDiagnostic) {
919 if (FixupDiagnostic) {
926 real_value = -real_value;
927 out |= ((real_value >> 1) & 0x1) << 11;
928 out |= ((real_value >> 1) & 0x7fe);
940 const unsigned FixupKind =
Fixup.getKind();
944 assert(
Sym &&
"How did we resolve this?");
951 if (
Sym->isExternal())
956 if (
Sym &&
Sym->isELF()) {
957 unsigned Type = cast<MCSymbolELF>(
Sym)->getType();
1111 unsigned Kind =
Fixup.getKind();
1124 unsigned FullSizeBytes;
1128 assert(NumBytes <= FullSizeBytes &&
"Invalid fixup size!");
1134 for (
unsigned i = 0; i != NumBytes; ++i) {
1188 unsigned CFARegister = ARM::SP;
1189 int CFARegisterOffset = 0;
1192 int FloatRegCount = 0;
1196 switch (Inst.getOperation()) {
1198 CFARegisterOffset = Inst.getOffset();
1202 CFARegisterOffset = Inst.getOffset();
1209 if (ARMMCRegisterClasses[ARM::GPRRegClassID].
contains(Reg))
1210 RegOffsets[Reg] = Inst.getOffset();
1211 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].
contains(Reg)) {
1212 RegOffsets[Reg] = Inst.getOffset();
1216 llvm::dbgs() <<
".cfi_offset on unknown register="
1217 << Inst.getRegister() <<
"\n");
1228 <<
"CFI directive not compatible with compact "
1229 "unwind encoding, opcode="
1230 << uint8_t(Inst.getOperation()) <<
"\n");
1237 if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
1241 if (CFARegister != ARM::R7) {
1244 <<
" instead of r7\n");
1247 int StackAdjust = CFARegisterOffset - 8;
1248 if (RegOffsets.
lookup(ARM::LR) != (-4 - StackAdjust)) {
1251 <<
"LR not saved as standard frame, StackAdjust="
1253 <<
", CFARegisterOffset=" << CFARegisterOffset
1254 <<
", lr save at offset=" << RegOffsets[14] <<
"\n");
1257 if (RegOffsets.
lookup(ARM::R7) != (-8 - StackAdjust)) {
1259 llvm::dbgs() <<
"r7 not saved as standard frame\n");
1265 switch (StackAdjust) {
1269 CompactUnwindEncoding |= 0x00400000;
1272 CompactUnwindEncoding |= 0x00800000;
1275 CompactUnwindEncoding |= 0x00C00000;
1279 <<
".cfi_def_cfa stack adjust ("
1280 << StackAdjust <<
") out of range\n");
1297 int CurOffset = -8 - StackAdjust;
1298 for (
auto CSReg : GPRCSRegs) {
1303 int RegOffset =
Offset->second;
1304 if (RegOffset != CurOffset - 4) {
1307 << RegOffset <<
" but only supported at "
1308 << CurOffset <<
"\n");
1311 CompactUnwindEncoding |= CSReg.Encoding;
1316 if (FloatRegCount == 0)
1317 return CompactUnwindEncoding;
1320 CompactUnwindEncoding &=
~CU::UNWIND_ARM_MODE_MASK;
1325 if (FloatRegCount > 4) {
1327 llvm::dbgs() <<
"unsupported number of D registers saved ("
1328 << FloatRegCount <<
")\n");
1335 static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
1336 for (
int Idx = FloatRegCount - 1;
Idx >= 0; --
Idx) {
1340 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but "
1344 }
else if (
Offset->second != CurOffset - 8) {
1346 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but "
1348 <<
" saved at " <<
Offset->second
1349 <<
", expected at " << CurOffset - 8
1356 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 unsigned getFixupKindContainerSizeBytes(unsigned Kind)
getFixupKindContainerSizeBytes - The number of bytes of the container involved in big endian.
static MCAsmBackend * createARMAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options, llvm::endianness 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.
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)
uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const override
Generate compact unwind encoding for the function based on the CFI instructions.
const MachO::CPUSubTypeARM Subtype
std::optional< MCFixupKind > getFixupKind(StringRef Name) const override
Map a relocation name used in .reloc to a fixup kind.
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value) const override
Simple predicate for targets where !Resolved implies requiring relaxation.
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 hasNOP(const MCSubtargetInfo *STI) const
unsigned getRelaxedOpcode(unsigned Op, const MCSubtargetInfo &STI) const
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, const MCSubtargetInfo *STI) override
Hook to check if a relocation is needed for some target specific reason.
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 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.
This class represents an Operation in the Expression.
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.
const llvm::endianness Endian
bool isDarwinCanonicalPersonality(const MCSymbol *Sym) const
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Context object for machine code objects.
bool emitCompactUnwindNonCanonical() const
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.
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 isOSBinFormatCOFF() const
Tests whether the OS uses the COFF binary format.
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_thumb_upper_8_15
@ fixup_arm_thumb_lower_0_7
@ fixup_arm_pcrel_10_unscaled
@ fixup_arm_thumb_upper_0_7
@ fixup_bfcsel_else_target
@ fixup_arm_ldst_pcrel_12
@ fixup_arm_thumb_lower_8_15
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)
DWARFExpression::Operation Op
const MCSymbol * Personality
std::vector< MCCFIInstruction > Instructions
Target independent information on a fixup kind.
@ FKF_IsAlignedDownTo32Bits
Should this fixup kind force a 4-byte aligned effective PC value?
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...