44 ARMELFObjectWriter(uint8_t OSABI)
57 {
"fixup_t2_ldst_pcrel_12", 0, 32,
62 {
"fixup_t2_pcrel_10", 0, 32,
66 {
"fixup_t2_pcrel_9", 0, 32,
69 {
"fixup_thumb_adr_pcrel_10", 0, 8,
73 {
"fixup_t2_adr_pcrel_12", 0, 32,
85 {
"fixup_arm_thumb_blx", 0, 32,
89 {
"fixup_arm_thumb_cp", 0, 8,
95 {
"fixup_arm_movt_hi16", 0, 20, 0},
96 {
"fixup_arm_movw_lo16", 0, 20, 0},
97 {
"fixup_t2_movt_hi16", 0, 20, 0},
98 {
"fixup_t2_movw_lo16", 0, 20, 0},
99 {
"fixup_arm_mod_imm", 0, 12, 0},
100 {
"fixup_t2_so_imm", 0, 26, 0},
108 {
"fixup_t2_ldst_pcrel_12", 0, 32,
113 {
"fixup_t2_pcrel_10", 0, 32,
117 {
"fixup_t2_pcrel_9", 0, 32,
120 {
"fixup_thumb_adr_pcrel_10", 8, 8,
124 {
"fixup_t2_adr_pcrel_12", 0, 32,
136 {
"fixup_arm_thumb_blx", 0, 32,
140 {
"fixup_arm_thumb_cp", 8, 8,
146 {
"fixup_arm_movt_hi16", 12, 20, 0},
147 {
"fixup_arm_movw_lo16", 12, 20, 0},
148 {
"fixup_t2_movt_hi16", 12, 20, 0},
149 {
"fixup_t2_movw_lo16", 12, 20, 0},
150 {
"fixup_arm_mod_imm", 20, 12, 0},
151 {
"fixup_t2_so_imm", 26, 6, 0},
179 bool HasV8MBaselineOps = STI.
getFeatureBits()[ARM::HasV8MBaselineOps];
185 return HasThumb2 ? (
unsigned)ARM::t2Bcc : Op;
187 return HasThumb2 ? (
unsigned)ARM::t2LDRpci : Op;
189 return HasThumb2 ? (
unsigned)ARM::t2ADR : Op;
191 return HasV8MBaselineOps ? (
unsigned)ARM::t2B : Op;
207 uint64_t
Value)
const {
208 switch ((
unsigned)Fixup.
getKind()) {
216 int64_t
Offset = int64_t(Value) - 4;
217 if (Offset > 2046 || Offset < -2048)
218 return "out of range pc-relative fixup value";
228 int64_t
Offset = int64_t(Value) - 4;
229 if (Offset > 254 || Offset < -256)
230 return "out of range pc-relative fixup value";
237 int64_t
Offset = int64_t(Value) - 4;
239 return "misaligned pc-relative fixup value";
240 else if (Offset > 1020 || Offset < 0)
241 return "out of range pc-relative fixup value";
248 int64_t
Offset = (Value & ~1);
250 return "will be converted to nop";
262 return reasonForFixupRelaxation(Fixup, Value);
282 RelaxedOp == ARM::tHINT) {
297 const uint16_t Thumb1_16bitNopEncoding = 0x46c0;
298 const uint16_t Thumb2_16bitNopEncoding = 0xbf00;
299 const uint32_t ARMv4_NopEncoding = 0xe1a00000;
300 const uint32_t ARMv6T2_NopEncoding = 0xe320f000;
302 const uint16_t nopEncoding =
303 hasNOP() ? Thumb2_16bitNopEncoding : Thumb1_16bitNopEncoding;
304 uint64_t NumNops = Count / 2;
305 for (uint64_t i = 0; i != NumNops; ++i)
313 hasNOP() ? ARMv6T2_NopEncoding : ARMv4_NopEncoding;
314 uint64_t NumNops = Count / 4;
315 for (uint64_t i = 0; i != NumNops; ++i)
329 OS.
write(
"\0\0\xa0", 3);
337 if (IsLittleEndian) {
340 uint32_t Swapped = (Value & 0xFFFF0000) >> 16;
341 Swapped |= (Value & 0x0000FFFF) << 16;
348 bool IsLittleEndian) {
351 if (IsLittleEndian) {
352 Value = (SecondHalf & 0xFFFF) << 16;
353 Value |= (FirstHalf & 0xFFFF);
355 Value = (SecondHalf & 0xFFFF);
356 Value |= (FirstHalf & 0xFFFF) << 16;
375 if (A->hasSubsectionsViaSymbols() && Asm.
isThumbFunc(&A->getSymbol()) &&
376 A->getSymbol().isExternal() &&
401 unsigned Hi4 = (Value & 0xF000) >> 12;
402 unsigned Lo12 = Value & 0x0FFF;
405 Value = (Hi4 << 16) | (Lo12);
414 unsigned Hi4 = (Value & 0xF000) >> 12;
415 unsigned i = (Value & 0x800) >> 11;
416 unsigned Mid3 = (Value & 0x700) >> 8;
417 unsigned Lo8 = Value & 0x0FF;
422 Value = (Hi4 << 16) | (i << 26) | (Mid3 << 12) | (Lo8);
433 if ((int64_t)Value < 0) {
441 Value |= isAdd << 23;
454 if ((int64_t)Value < 0) {
469 if ((int64_t)Value < 0) {
475 out |= (Value & 0x800) << 15;
476 out |= (Value & 0x700) << 4;
477 out |= (Value & 0x0FF);
490 dyn_cast<MCSymbolRefExpr>(Fixup.
getValue()))
493 return 0xffffff & ((Value - 8) >> 2);
496 if (!isInt<25>(Value)) {
504 bool I = Value & 0x800000;
505 bool J1 = Value & 0x400000;
506 bool J2 = Value & 0x200000;
513 out |= (Value & 0x1FF800) << 5;
514 out |= (Value & 0x0007FF);
520 if (!isInt<21>(Value)) {
528 out |= (Value & 0x80000) << 7;
529 out |= (Value & 0x40000) >> 7;
530 out |= (Value & 0x20000) >> 4;
531 out |= (Value & 0x1F800) << 5;
532 out |= (Value & 0x007FF);
537 if (!isInt<25>(Value - 4) ||
541 !isInt<23>(Value - 4))) {
559 uint32_t signBit = (offset & 0x800000) >> 23;
560 uint32_t I1Bit = (offset & 0x400000) >> 22;
561 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
562 uint32_t I2Bit = (offset & 0x200000) >> 21;
563 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
564 uint32_t imm10Bits = (offset & 0x1FF800) >> 11;
565 uint32_t imm11Bits = (offset & 0x000007FF);
567 uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10Bits);
568 uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
569 (uint16_t)imm11Bits);
585 if (Value % 4 != 0) {
592 dyn_cast<MCSymbolRefExpr>(Fixup.
getValue()))
595 uint32_t signBit = (offset & 0x400000) >> 22;
596 uint32_t I1Bit = (offset & 0x200000) >> 21;
597 uint32_t J1Bit = (I1Bit ^ 0x1) ^ signBit;
598 uint32_t I2Bit = (offset & 0x100000) >> 20;
599 uint32_t J2Bit = (I2Bit ^ 0x1) ^ signBit;
600 uint32_t imm10HBits = (offset & 0xFFC00) >> 10;
601 uint32_t imm10LBits = (offset & 0x3FF);
603 uint32_t FirstHalf = (((uint16_t)signBit << 10) | (uint16_t)imm10HBits);
604 uint32_t SecondHalf = (((uint16_t)J1Bit << 13) | ((uint16_t)J2Bit << 11) |
605 ((uint16_t)imm10LBits) << 1);
614 const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
615 if (FixupDiagnostic) {
621 return ((Value - 4) >> 2) & 0xff;
633 return ((Binary & 0x20) << 4) | ((Binary & 0x1f) << 3);
640 const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
641 if (FixupDiagnostic) {
646 return ((Value - 4) >> 1) & 0x7ff;
651 const char *FixupDiagnostic = reasonForFixupRelaxation(Fixup, Value);
652 if (FixupDiagnostic) {
657 return ((Value - 4) >> 1) & 0xff;
662 if ((int64_t)Value < 0) {
671 Value = (Value & 0xf) | ((Value & 0xf0) << 4);
672 return Value | (isAdd << 23);
682 if ((int64_t)Value < 0) {
692 Value |= isAdd << 23;
709 if ((int64_t)Value < 0) {
723 Value |= isAdd << 23;
741 if ((int64_t)Value < 0) {
750 uint64_t EncValue = 0;
751 EncValue |= (Value & 0x800) << 15;
752 EncValue |= (Value & 0x700) << 4;
753 EncValue |= (Value & 0xff);
766 assert(Sym &&
"How did we resolve this?");
778 if (Sym && Sym->
isELF()) {
915 assert(Offset + NumBytes <= Data.
size() &&
"Invalid fixup offset!");
918 unsigned FullSizeBytes;
921 assert((Offset + FullSizeBytes) <= Data.
size() &&
"Invalid fixup size!");
922 assert(NumBytes <= FullSizeBytes &&
"Invalid fixup size!");
928 for (
unsigned i = 0; i != NumBytes; ++i) {
929 unsigned Idx = Endian ==
support::little ? i : (FullSizeBytes - 1 - i);
930 Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
976 int CFARegister = ARM::SP;
977 int CFARegisterOffset = 0;
980 int FloatRegCount = 0;
982 for (
size_t i = 0, e = Instrs.
size(); i != e; ++i) {
998 if (ARMMCRegisterClasses[ARM::GPRRegClassID].
contains(Reg))
1000 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].
contains(Reg)) {
1005 llvm::dbgs() <<
".cfi_offset on unknown register=" 1017 <<
"CFI directive not compatiable with comact " 1026 if ((CFARegister == ARM::SP) && (CFARegisterOffset == 0))
1030 if (CFARegister != ARM::R7) {
1033 <<
" instead of r7\n");
1036 int StackAdjust = CFARegisterOffset - 8;
1037 if (RegOffsets.
lookup(ARM::LR) != (-4 - StackAdjust)) {
1040 <<
"LR not saved as standard frame, StackAdjust=" 1042 <<
", CFARegisterOffset=" << CFARegisterOffset
1043 <<
", lr save at offset=" << RegOffsets[14] <<
"\n");
1046 if (RegOffsets.
lookup(ARM::R7) != (-8 - StackAdjust)) {
1048 llvm::dbgs() <<
"r7 not saved as standard frame\n");
1054 switch (StackAdjust) {
1058 CompactUnwindEncoding |= 0x00400000;
1061 CompactUnwindEncoding |= 0x00800000;
1064 CompactUnwindEncoding |= 0x00C00000;
1068 <<
".cfi_def_cfa stack adjust (" 1069 << StackAdjust <<
") out of range\n");
1086 int CurOffset = -8 - StackAdjust;
1087 for (
auto CSReg : GPRCSRegs) {
1092 int RegOffset =
Offset->second;
1093 if (RegOffset != CurOffset - 4) {
1096 << RegOffset <<
" but only supported at " 1097 << CurOffset <<
"\n");
1100 CompactUnwindEncoding |= CSReg.Encoding;
1105 if (FloatRegCount == 0)
1106 return CompactUnwindEncoding;
1114 if (FloatRegCount > 4) {
1116 llvm::dbgs() <<
"unsupported number of D registers saved (" 1117 << FloatRegCount <<
")\n");
1124 static unsigned FPRCSRegs[] = { ARM::D8, ARM::D10, ARM::D12, ARM::D14 };
1125 for (
int Idx = FloatRegCount - 1; Idx >= 0; --Idx) {
1126 auto Offset = RegOffsets.
find(FPRCSRegs[Idx]);
1129 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but " 1130 <<
MRI.getName(FPRCSRegs[Idx])
1133 }
else if (
Offset->second != CurOffset - 8) {
1135 llvm::dbgs() << FloatRegCount <<
" D-regs saved, but " 1136 <<
MRI.getName(FPRCSRegs[Idx])
1137 <<
" saved at " <<
Offset->second
1138 <<
", expected at " << CurOffset - 8
1145 return CompactUnwindEncoding | ((FloatRegCount - 1) << 8);
1153 case ARM::ArchKind::ARMV4T:
1155 case ARM::ArchKind::ARMV5T:
1156 case ARM::ArchKind::ARMV5TE:
1157 case ARM::ArchKind::ARMV5TEJ:
1159 case ARM::ArchKind::ARMV6:
1160 case ARM::ArchKind::ARMV6K:
1162 case ARM::ArchKind::ARMV7A:
1164 case ARM::ArchKind::ARMV7S:
1166 case ARM::ArchKind::ARMV7K:
1168 case ARM::ArchKind::ARMV6M:
1170 case ARM::ArchKind::ARMV7M:
1172 case ARM::ArchKind::ARMV7EM:
1192 return new ARMAsmBackendWinCOFF(T, STI);
1196 return new ARMAsmBackendELF(T, STI, OSABI, Endian);
MCAsmBackend * createARMLEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
unsigned getRelaxedOpcode(unsigned Op, const MCSubtargetInfo &STI) const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
This represents an "assembler immediate".
const char * reasonForFixupRelaxation(const MCFixup &Fixup, uint64_t Value) const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
OSType getOS() const
getOS - Get the parsed operating system type of this triple.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
void dump_pretty(raw_ostream &OS, const MCInstPrinter *Printer=nullptr, StringRef Separator=" ") const
Dump the MCInst as prettily as possible using the additional MC structures, if given.
A raw_ostream that writes to an SmallVector or SmallString.
static Lanai::Fixups FixupKind(const MCExpr *Expr)
static bool isThumb(const MCSubtargetInfo &STI)
return AArch64::GPR64RegClass contains(Reg)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
const Triple & getTargetTriple() const
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
MCContext & getContext() const
static MCOperand createReg(unsigned Reg)
const FeatureBitset & getFeatureBits() const
static MachO::CPUSubTypeARM getMachOSubTypeFromArch(StringRef Arch)
Encapsulates the layout of an assembly file at a particular point in time.
Represent a reference to a symbol from inside an expression.
A four-byte section relative fixup.
Context object for machine code objects.
A two-byte section relative fixup.
.code16 (X86) / .code 16 (ARM)
MCAsmBackend * createARMBEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Instances of this class represent a single low-level machine instruction.
static MCAsmBackend * createARMAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options, support::endianness Endian)
Flag
These should be considered private to the implementation of the MCInstrDesc class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
iterator find(const_arg_type_t< KeyT > Val)
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
bool isOSWindows() const
Tests whether the OS is Windows.
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
uint32_t generateCompactUnwindEncoding(ArrayRef< MCCFIInstruction > Instrs) const override
Generate compact unwind encoding for the function based on the CFI instructions.
unsigned const MachineRegisterInfo * MRI
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
The instances of the Type class are immutable: once they are created, they are never changed...
CompactUnwindEncodings
Compact unwind encoding values.
static uint32_t swapHalfWords(uint32_t Value, bool IsLittleEndian)
size_t size() const
size - Get the array size.
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.
MCFixupKind
Extensible enumeration to represent the type of a fixup.
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
const MCSymbolRefExpr * getSymA() const
OpType getOperation() const
const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const override
Get information on a fixup kind.
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
void reportError(SMLoc L, const Twine &Msg)
Should this fixup kind force a 4-byte aligned effective PC value?
uint32_t getOffset() 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 override
Write an (optimal) nop sequence of Count bytes to the given output.
static wasm::ValType getType(const TargetRegisterClass *RC)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
raw_ostream & write(unsigned char C)
unsigned getRegister() const
static unsigned getFixupKindContainerSizeBytes(unsigned Kind)
getFixupKindContainerSizeBytes - The number of bytes of the container involved in big endian...
StringRef getArchName() const
getArchName - Get the architecture (first) component of the triple.
void setOpcode(unsigned Op)
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
ArchKind parseArch(StringRef Arch)
const MCSymbol & getSymbol() const
void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, MCInst &Res) const override
Relax the instruction in the given fragment to the next wider instruction.
StringRef str()
Return a StringRef for the vector contents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Target - Wrapper for Target specific information.
bool isThumbFunc(const MCSymbol *Func) const
Check whether a given symbol has been flagged with .thumb_func.
.code32 (X86) / .code 32 (ARM)
void handleAssemblerFlag(MCAssemblerFlag Flag) override
Handle any target-specific assembler flags. By default, do nothing.
ObjectFormatType getObjectFormat() const
getFormat - Get the object format for this triple.
static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode)
Generic base class for all target subtargets.
Target independent information on a fixup kind.
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...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override
Check whether the given instruction may need relaxation.
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...
LLVM Value Representation.
Generic interface to target specific assembler backends.
This class implements an extremely fast bulk output stream that can only output to a stream...
const MCExpr * getValue() const
void addOperand(const MCOperand &Op)
StringRef - Represent a constant reference to a string, i.e.
unsigned getOpcode() const
static unsigned getFixupKindNumBytes(unsigned Kind)
getFixupKindNumBytes - The number of bytes the fixup may change.
static MCOperand createImm(int64_t Val)
static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, bool IsLittleEndian)
MCFixupKind getKind() const
bool empty() const
empty - Check if the array is empty.
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.