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