1 //===-- AArch64AsmBackend.cpp - AArch64 Assembler Backend -----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "AArch64.h" 11 #include "AArch64RegisterInfo.h" 12 #include "MCTargetDesc/AArch64FixupKinds.h" 13 #include "llvm/ADT/Triple.h" 14 #include "llvm/MC/MCAsmBackend.h" 15 #include "llvm/MC/MCContext.h" 16 #include "llvm/MC/MCDirectives.h" 17 #include "llvm/MC/MCELFObjectWriter.h" 18 #include "llvm/MC/MCFixupKindInfo.h" 19 #include "llvm/MC/MCObjectWriter.h" 20 #include "llvm/MC/MCSectionELF.h" 21 #include "llvm/MC/MCSectionMachO.h" 22 #include "llvm/MC/MCValue.h" 23 #include "llvm/Support/ErrorHandling.h" 24 #include "llvm/Support/MachO.h" 25 using namespace llvm; 26 27 namespace { 28 29 class AArch64AsmBackend : public MCAsmBackend { 30 static const unsigned PCRelFlagVal = 31 MCFixupKindInfo::FKF_IsAlignedDownTo32Bits | MCFixupKindInfo::FKF_IsPCRel; 32 public: 33 bool IsLittleEndian; 34 35 public: 36 AArch64AsmBackend(const Target &T, bool IsLittleEndian) 37 : MCAsmBackend(), IsLittleEndian(IsLittleEndian) {} 38 39 unsigned getNumFixupKinds() const override { 40 return AArch64::NumTargetFixupKinds; 41 } 42 43 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { 44 const static MCFixupKindInfo Infos[AArch64::NumTargetFixupKinds] = { 45 // This table *must* be in the order that the fixup_* kinds are defined in 46 // AArch64FixupKinds.h. 47 // 48 // Name Offset (bits) Size (bits) Flags 49 { "fixup_aarch64_pcrel_adr_imm21", 0, 32, PCRelFlagVal }, 50 { "fixup_aarch64_pcrel_adrp_imm21", 0, 32, PCRelFlagVal }, 51 { "fixup_aarch64_add_imm12", 10, 12, 0 }, 52 { "fixup_aarch64_ldst_imm12_scale1", 10, 12, 0 }, 53 { "fixup_aarch64_ldst_imm12_scale2", 10, 12, 0 }, 54 { "fixup_aarch64_ldst_imm12_scale4", 10, 12, 0 }, 55 { "fixup_aarch64_ldst_imm12_scale8", 10, 12, 0 }, 56 { "fixup_aarch64_ldst_imm12_scale16", 10, 12, 0 }, 57 { "fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal }, 58 { "fixup_aarch64_movw", 5, 16, 0 }, 59 { "fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal }, 60 { "fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal }, 61 { "fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal }, 62 { "fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal }, 63 { "fixup_aarch64_tlsdesc_call", 0, 0, 0 } 64 }; 65 66 if (Kind < FirstTargetFixupKind) 67 return MCAsmBackend::getFixupKindInfo(Kind); 68 69 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 70 "Invalid kind!"); 71 return Infos[Kind - FirstTargetFixupKind]; 72 } 73 74 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 75 uint64_t Value, bool IsPCRel) const override; 76 77 bool mayNeedRelaxation(const MCInst &Inst) const override; 78 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, 79 const MCRelaxableFragment *DF, 80 const MCAsmLayout &Layout) const override; 81 void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; 82 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; 83 84 void HandleAssemblerFlag(MCAssemblerFlag Flag) {} 85 86 unsigned getPointerSize() const { return 8; } 87 88 unsigned getFixupKindContainereSizeInBytes(unsigned Kind) const; 89 }; 90 91 } // end anonymous namespace 92 93 /// \brief The number of bytes the fixup may change. 94 static unsigned getFixupKindNumBytes(unsigned Kind) { 95 switch (Kind) { 96 default: 97 llvm_unreachable("Unknown fixup kind!"); 98 99 case AArch64::fixup_aarch64_tlsdesc_call: 100 return 0; 101 102 case FK_Data_1: 103 return 1; 104 105 case FK_Data_2: 106 case AArch64::fixup_aarch64_movw: 107 return 2; 108 109 case AArch64::fixup_aarch64_pcrel_branch14: 110 case AArch64::fixup_aarch64_add_imm12: 111 case AArch64::fixup_aarch64_ldst_imm12_scale1: 112 case AArch64::fixup_aarch64_ldst_imm12_scale2: 113 case AArch64::fixup_aarch64_ldst_imm12_scale4: 114 case AArch64::fixup_aarch64_ldst_imm12_scale8: 115 case AArch64::fixup_aarch64_ldst_imm12_scale16: 116 case AArch64::fixup_aarch64_ldr_pcrel_imm19: 117 case AArch64::fixup_aarch64_pcrel_branch19: 118 return 3; 119 120 case AArch64::fixup_aarch64_pcrel_adr_imm21: 121 case AArch64::fixup_aarch64_pcrel_adrp_imm21: 122 case AArch64::fixup_aarch64_pcrel_branch26: 123 case AArch64::fixup_aarch64_pcrel_call26: 124 case FK_Data_4: 125 return 4; 126 127 case FK_Data_8: 128 return 8; 129 } 130 } 131 132 static unsigned AdrImmBits(unsigned Value) { 133 unsigned lo2 = Value & 0x3; 134 unsigned hi19 = (Value & 0x1ffffc) >> 2; 135 return (hi19 << 5) | (lo2 << 29); 136 } 137 138 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, 139 MCContext *Ctx) { 140 unsigned Kind = Fixup.getKind(); 141 int64_t SignedValue = static_cast<int64_t>(Value); 142 switch (Kind) { 143 default: 144 llvm_unreachable("Unknown fixup kind!"); 145 case AArch64::fixup_aarch64_pcrel_adr_imm21: 146 if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152)) 147 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 148 return AdrImmBits(Value & 0x1fffffULL); 149 case AArch64::fixup_aarch64_pcrel_adrp_imm21: 150 return AdrImmBits((Value & 0x1fffff000ULL) >> 12); 151 case AArch64::fixup_aarch64_ldr_pcrel_imm19: 152 case AArch64::fixup_aarch64_pcrel_branch19: 153 // Signed 21-bit immediate 154 if (SignedValue > 2097151 || SignedValue < -2097152) 155 if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 156 if (Ctx && (Value & 0x3)) 157 Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); 158 // Low two bits are not encoded. 159 return (Value >> 2) & 0x7ffff; 160 case AArch64::fixup_aarch64_add_imm12: 161 case AArch64::fixup_aarch64_ldst_imm12_scale1: 162 // Unsigned 12-bit immediate 163 if (Ctx && Value >= 0x1000) 164 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 165 return Value; 166 case AArch64::fixup_aarch64_ldst_imm12_scale2: 167 // Unsigned 12-bit immediate which gets multiplied by 2 168 if (Ctx && (Value >= 0x2000)) 169 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 170 if (Ctx && (Value & 0x1)) 171 Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned"); 172 return Value >> 1; 173 case AArch64::fixup_aarch64_ldst_imm12_scale4: 174 // Unsigned 12-bit immediate which gets multiplied by 4 175 if (Ctx && (Value >= 0x4000)) 176 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 177 if (Ctx && (Value & 0x3)) 178 Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned"); 179 return Value >> 2; 180 case AArch64::fixup_aarch64_ldst_imm12_scale8: 181 // Unsigned 12-bit immediate which gets multiplied by 8 182 if (Ctx && (Value >= 0x8000)) 183 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 184 if (Ctx && (Value & 0x7)) 185 Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned"); 186 return Value >> 3; 187 case AArch64::fixup_aarch64_ldst_imm12_scale16: 188 // Unsigned 12-bit immediate which gets multiplied by 16 189 if (Ctx && (Value >= 0x10000)) 190 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 191 if (Ctx && (Value & 0xf)) 192 Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned"); 193 return Value >> 4; 194 case AArch64::fixup_aarch64_movw: 195 if (Ctx) 196 Ctx->reportError(Fixup.getLoc(), 197 "no resolvable MOVZ/MOVK fixups supported yet"); 198 return Value; 199 case AArch64::fixup_aarch64_pcrel_branch14: 200 // Signed 16-bit immediate 201 if (Ctx && (SignedValue > 32767 || SignedValue < -32768)) 202 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 203 // Low two bits are not encoded (4-byte alignment assumed). 204 if (Ctx && (Value & 0x3)) 205 Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); 206 return (Value >> 2) & 0x3fff; 207 case AArch64::fixup_aarch64_pcrel_branch26: 208 case AArch64::fixup_aarch64_pcrel_call26: 209 // Signed 28-bit immediate 210 if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728)) 211 Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); 212 // Low two bits are not encoded (4-byte alignment assumed). 213 if (Ctx && (Value & 0x3)) 214 Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); 215 return (Value >> 2) & 0x3ffffff; 216 case FK_Data_1: 217 case FK_Data_2: 218 case FK_Data_4: 219 case FK_Data_8: 220 return Value; 221 } 222 } 223 224 /// getFixupKindContainereSizeInBytes - The number of bytes of the 225 /// container involved in big endian or 0 if the item is little endian 226 unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) const { 227 if (IsLittleEndian) 228 return 0; 229 230 switch (Kind) { 231 default: 232 llvm_unreachable("Unknown fixup kind!"); 233 234 case FK_Data_1: 235 return 1; 236 case FK_Data_2: 237 return 2; 238 case FK_Data_4: 239 return 4; 240 case FK_Data_8: 241 return 8; 242 243 case AArch64::fixup_aarch64_tlsdesc_call: 244 case AArch64::fixup_aarch64_movw: 245 case AArch64::fixup_aarch64_pcrel_branch14: 246 case AArch64::fixup_aarch64_add_imm12: 247 case AArch64::fixup_aarch64_ldst_imm12_scale1: 248 case AArch64::fixup_aarch64_ldst_imm12_scale2: 249 case AArch64::fixup_aarch64_ldst_imm12_scale4: 250 case AArch64::fixup_aarch64_ldst_imm12_scale8: 251 case AArch64::fixup_aarch64_ldst_imm12_scale16: 252 case AArch64::fixup_aarch64_ldr_pcrel_imm19: 253 case AArch64::fixup_aarch64_pcrel_branch19: 254 case AArch64::fixup_aarch64_pcrel_adr_imm21: 255 case AArch64::fixup_aarch64_pcrel_adrp_imm21: 256 case AArch64::fixup_aarch64_pcrel_branch26: 257 case AArch64::fixup_aarch64_pcrel_call26: 258 // Instructions are always little endian 259 return 0; 260 } 261 } 262 263 void AArch64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data, 264 unsigned DataSize, uint64_t Value, 265 bool IsPCRel) const { 266 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); 267 if (!Value) 268 return; // Doesn't change encoding. 269 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 270 // Apply any target-specific value adjustments. 271 Value = adjustFixupValue(Fixup, Value, nullptr); 272 273 // Shift the value into position. 274 Value <<= Info.TargetOffset; 275 276 unsigned Offset = Fixup.getOffset(); 277 assert(Offset + NumBytes <= DataSize && "Invalid fixup offset!"); 278 279 // Used to point to big endian bytes. 280 unsigned FulleSizeInBytes = getFixupKindContainereSizeInBytes(Fixup.getKind()); 281 282 // For each byte of the fragment that the fixup touches, mask in the 283 // bits from the fixup value. 284 if (FulleSizeInBytes == 0) { 285 // Handle as little-endian 286 for (unsigned i = 0; i != NumBytes; ++i) { 287 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 288 } 289 } else { 290 // Handle as big-endian 291 assert((Offset + FulleSizeInBytes) <= DataSize && "Invalid fixup size!"); 292 assert(NumBytes <= FulleSizeInBytes && "Invalid fixup size!"); 293 for (unsigned i = 0; i != NumBytes; ++i) { 294 unsigned Idx = FulleSizeInBytes - 1 - i; 295 Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff); 296 } 297 } 298 } 299 300 bool AArch64AsmBackend::mayNeedRelaxation(const MCInst &Inst) const { 301 return false; 302 } 303 304 bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, 305 uint64_t Value, 306 const MCRelaxableFragment *DF, 307 const MCAsmLayout &Layout) const { 308 // FIXME: This isn't correct for AArch64. Just moving the "generic" logic 309 // into the targets for now. 310 // 311 // Relax if the value is too big for a (signed) i8. 312 return int64_t(Value) != int64_t(int8_t(Value)); 313 } 314 315 void AArch64AsmBackend::relaxInstruction(const MCInst &Inst, 316 MCInst &Res) const { 317 llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented"); 318 } 319 320 bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { 321 // If the count is not 4-byte aligned, we must be writing data into the text 322 // section (otherwise we have unaligned instructions, and thus have far 323 // bigger problems), so just write zeros instead. 324 OW->WriteZeros(Count % 4); 325 326 // We are properly aligned, so write NOPs as requested. 327 Count /= 4; 328 for (uint64_t i = 0; i != Count; ++i) 329 OW->write32(0xd503201f); 330 return true; 331 } 332 333 namespace { 334 335 namespace CU { 336 337 /// \brief Compact unwind encoding values. 338 enum CompactUnwindEncodings { 339 /// \brief A "frameless" leaf function, where no non-volatile registers are 340 /// saved. The return remains in LR throughout the function. 341 UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, 342 343 /// \brief No compact unwind encoding available. Instead the low 23-bits of 344 /// the compact unwind encoding is the offset of the DWARF FDE in the 345 /// __eh_frame section. This mode is never used in object files. It is only 346 /// generated by the linker in final linked images, which have only DWARF info 347 /// for a function. 348 UNWIND_ARM64_MODE_DWARF = 0x03000000, 349 350 /// \brief This is a standard arm64 prologue where FP/LR are immediately 351 /// pushed on the stack, then SP is copied to FP. If there are any 352 /// non-volatile register saved, they are copied into the stack fame in pairs 353 /// in a contiguous ranger right below the saved FP/LR pair. Any subset of the 354 /// five X pairs and four D pairs can be saved, but the memory layout must be 355 /// in register number order. 356 UNWIND_ARM64_MODE_FRAME = 0x04000000, 357 358 /// \brief Frame register pair encodings. 359 UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, 360 UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, 361 UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, 362 UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, 363 UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, 364 UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, 365 UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, 366 UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, 367 UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800 368 }; 369 370 } // end CU namespace 371 372 // FIXME: This should be in a separate file. 373 class DarwinAArch64AsmBackend : public AArch64AsmBackend { 374 const MCRegisterInfo &MRI; 375 376 /// \brief Encode compact unwind stack adjustment for frameless functions. 377 /// See UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK in compact_unwind_encoding.h. 378 /// The stack size always needs to be 16 byte aligned. 379 uint32_t encodeStackAdjustment(uint32_t StackSize) const { 380 return (StackSize / 16) << 12; 381 } 382 383 public: 384 DarwinAArch64AsmBackend(const Target &T, const MCRegisterInfo &MRI) 385 : AArch64AsmBackend(T, /*IsLittleEndian*/true), MRI(MRI) {} 386 387 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { 388 return createAArch64MachObjectWriter(OS, MachO::CPU_TYPE_ARM64, 389 MachO::CPU_SUBTYPE_ARM64_ALL); 390 } 391 392 /// \brief Generate the compact unwind encoding from the CFI directives. 393 uint32_t generateCompactUnwindEncoding( 394 ArrayRef<MCCFIInstruction> Instrs) const override { 395 if (Instrs.empty()) 396 return CU::UNWIND_ARM64_MODE_FRAMELESS; 397 398 bool HasFP = false; 399 unsigned StackSize = 0; 400 401 uint32_t CompactUnwindEncoding = 0; 402 for (size_t i = 0, e = Instrs.size(); i != e; ++i) { 403 const MCCFIInstruction &Inst = Instrs[i]; 404 405 switch (Inst.getOperation()) { 406 default: 407 // Cannot handle this directive: bail out. 408 return CU::UNWIND_ARM64_MODE_DWARF; 409 case MCCFIInstruction::OpDefCfa: { 410 // Defines a frame pointer. 411 assert(getXRegFromWReg(MRI.getLLVMRegNum(Inst.getRegister(), true)) == 412 AArch64::FP && 413 "Invalid frame pointer!"); 414 assert(i + 2 < e && "Insufficient CFI instructions to define a frame!"); 415 416 const MCCFIInstruction &LRPush = Instrs[++i]; 417 assert(LRPush.getOperation() == MCCFIInstruction::OpOffset && 418 "Link register not pushed!"); 419 const MCCFIInstruction &FPPush = Instrs[++i]; 420 assert(FPPush.getOperation() == MCCFIInstruction::OpOffset && 421 "Frame pointer not pushed!"); 422 423 unsigned LRReg = MRI.getLLVMRegNum(LRPush.getRegister(), true); 424 unsigned FPReg = MRI.getLLVMRegNum(FPPush.getRegister(), true); 425 426 LRReg = getXRegFromWReg(LRReg); 427 FPReg = getXRegFromWReg(FPReg); 428 429 assert(LRReg == AArch64::LR && FPReg == AArch64::FP && 430 "Pushing invalid registers for frame!"); 431 432 // Indicate that the function has a frame. 433 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAME; 434 HasFP = true; 435 break; 436 } 437 case MCCFIInstruction::OpDefCfaOffset: { 438 assert(StackSize == 0 && "We already have the CFA offset!"); 439 StackSize = std::abs(Inst.getOffset()); 440 break; 441 } 442 case MCCFIInstruction::OpOffset: { 443 // Registers are saved in pairs. We expect there to be two consecutive 444 // `.cfi_offset' instructions with the appropriate registers specified. 445 unsigned Reg1 = MRI.getLLVMRegNum(Inst.getRegister(), true); 446 if (i + 1 == e) 447 return CU::UNWIND_ARM64_MODE_DWARF; 448 449 const MCCFIInstruction &Inst2 = Instrs[++i]; 450 if (Inst2.getOperation() != MCCFIInstruction::OpOffset) 451 return CU::UNWIND_ARM64_MODE_DWARF; 452 unsigned Reg2 = MRI.getLLVMRegNum(Inst2.getRegister(), true); 453 454 // N.B. The encodings must be in register number order, and the X 455 // registers before the D registers. 456 457 // X19/X20 pair = 0x00000001, 458 // X21/X22 pair = 0x00000002, 459 // X23/X24 pair = 0x00000004, 460 // X25/X26 pair = 0x00000008, 461 // X27/X28 pair = 0x00000010 462 Reg1 = getXRegFromWReg(Reg1); 463 Reg2 = getXRegFromWReg(Reg2); 464 465 if (Reg1 == AArch64::X19 && Reg2 == AArch64::X20 && 466 (CompactUnwindEncoding & 0xF1E) == 0) 467 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X19_X20_PAIR; 468 else if (Reg1 == AArch64::X21 && Reg2 == AArch64::X22 && 469 (CompactUnwindEncoding & 0xF1C) == 0) 470 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X21_X22_PAIR; 471 else if (Reg1 == AArch64::X23 && Reg2 == AArch64::X24 && 472 (CompactUnwindEncoding & 0xF18) == 0) 473 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X23_X24_PAIR; 474 else if (Reg1 == AArch64::X25 && Reg2 == AArch64::X26 && 475 (CompactUnwindEncoding & 0xF10) == 0) 476 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X25_X26_PAIR; 477 else if (Reg1 == AArch64::X27 && Reg2 == AArch64::X28 && 478 (CompactUnwindEncoding & 0xF00) == 0) 479 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_X27_X28_PAIR; 480 else { 481 Reg1 = getDRegFromBReg(Reg1); 482 Reg2 = getDRegFromBReg(Reg2); 483 484 // D8/D9 pair = 0x00000100, 485 // D10/D11 pair = 0x00000200, 486 // D12/D13 pair = 0x00000400, 487 // D14/D15 pair = 0x00000800 488 if (Reg1 == AArch64::D8 && Reg2 == AArch64::D9 && 489 (CompactUnwindEncoding & 0xE00) == 0) 490 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D8_D9_PAIR; 491 else if (Reg1 == AArch64::D10 && Reg2 == AArch64::D11 && 492 (CompactUnwindEncoding & 0xC00) == 0) 493 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D10_D11_PAIR; 494 else if (Reg1 == AArch64::D12 && Reg2 == AArch64::D13 && 495 (CompactUnwindEncoding & 0x800) == 0) 496 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D12_D13_PAIR; 497 else if (Reg1 == AArch64::D14 && Reg2 == AArch64::D15) 498 CompactUnwindEncoding |= CU::UNWIND_ARM64_FRAME_D14_D15_PAIR; 499 else 500 // A pair was pushed which we cannot handle. 501 return CU::UNWIND_ARM64_MODE_DWARF; 502 } 503 504 break; 505 } 506 } 507 } 508 509 if (!HasFP) { 510 // With compact unwind info we can only represent stack adjustments of up 511 // to 65520 bytes. 512 if (StackSize > 65520) 513 return CU::UNWIND_ARM64_MODE_DWARF; 514 515 CompactUnwindEncoding |= CU::UNWIND_ARM64_MODE_FRAMELESS; 516 CompactUnwindEncoding |= encodeStackAdjustment(StackSize); 517 } 518 519 return CompactUnwindEncoding; 520 } 521 }; 522 523 } // end anonymous namespace 524 525 namespace { 526 527 class ELFAArch64AsmBackend : public AArch64AsmBackend { 528 public: 529 uint8_t OSABI; 530 531 ELFAArch64AsmBackend(const Target &T, uint8_t OSABI, bool IsLittleEndian) 532 : AArch64AsmBackend(T, IsLittleEndian), OSABI(OSABI) {} 533 534 MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { 535 return createAArch64ELFObjectWriter(OS, OSABI, IsLittleEndian); 536 } 537 538 void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, 539 const MCFixup &Fixup, const MCFragment *DF, 540 const MCValue &Target, uint64_t &Value, 541 bool &IsResolved) override; 542 }; 543 544 void ELFAArch64AsmBackend::processFixupValue( 545 const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, 546 const MCFragment *DF, const MCValue &Target, uint64_t &Value, 547 bool &IsResolved) { 548 // The ADRP instruction adds some multiple of 0x1000 to the current PC & 549 // ~0xfff. This means that the required offset to reach a symbol can vary by 550 // up to one step depending on where the ADRP is in memory. For example: 551 // 552 // ADRP x0, there 553 // there: 554 // 555 // If the ADRP occurs at address 0xffc then "there" will be at 0x1000 and 556 // we'll need that as an offset. At any other address "there" will be in the 557 // same page as the ADRP and the instruction should encode 0x0. Assuming the 558 // section isn't 0x1000-aligned, we therefore need to delegate this decision 559 // to the linker -- a relocation! 560 if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21) 561 IsResolved = false; 562 563 // Try to get the encoded value for the fixup as-if we're mapping it into 564 // the instruction. This allows adjustFixupValue() to issue a diagnostic 565 // if the value is invalid. 566 if (IsResolved) 567 (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); 568 } 569 570 } 571 572 MCAsmBackend *llvm::createAArch64leAsmBackend(const Target &T, 573 const MCRegisterInfo &MRI, 574 const Triple &TheTriple, 575 StringRef CPU) { 576 if (TheTriple.isOSBinFormatMachO()) 577 return new DarwinAArch64AsmBackend(T, MRI); 578 579 assert(TheTriple.isOSBinFormatELF() && "Expect either MachO or ELF target"); 580 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); 581 return new ELFAArch64AsmBackend(T, OSABI, /*IsLittleEndian=*/true); 582 } 583 584 MCAsmBackend *llvm::createAArch64beAsmBackend(const Target &T, 585 const MCRegisterInfo &MRI, 586 const Triple &TheTriple, 587 StringRef CPU) { 588 assert(TheTriple.isOSBinFormatELF() && 589 "Big endian is only supported for ELF targets!"); 590 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS()); 591 return new ELFAArch64AsmBackend(T, OSABI, 592 /*IsLittleEndian=*/false); 593 } 594