Repository: llvm/llvm-project
File: llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp (C++)

Code before:
unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
                                              const MCValue &Target,
                                              bool IsPCRel) const {
  auto Kind = Fixup.getKind();
  AArch64::Specifier RefKind =
      static_cast<AArch64::Specifier>(Target.getSpecifier());
  AArch64::Specifier SymLoc = AArch64::getSymbolLoc(RefKind);
  bool IsNC = AArch64::isNotChecked(RefKind);

  switch (SymLoc) {
  case AArch64::S_DTPREL:
  case AArch64::S_GOTTPREL:
  case AArch64::S_TPREL:
  case AArch64::S_TLSDESC:
  case AArch64::S_TLSDESC_AUTH:
    if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))
      static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);
    break;
  default:
    break;
  }

  switch (RefKind) {
  case AArch64::S_GOTPCREL:
  case AArch64::S_PLT:
    if (Kind == FK_Data_4)
      break;
    reportError(Fixup.getLoc(), AArch64::getSpecifierName(RefKind) +
                                    " can only be used in a .word directive");
    return ELF::R_AARCH64_NONE;
  default:
    break;
  }

  // Extract the relocation type from the fixup kind, after applying STT_TLS as
  // needed.
  if (mc::isRelocation(Fixup.getKind()))
    return Kind;

  if (IsPCRel) {
    switch (Kind) {
    case FK_Data_1:
      reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(PREL16);
    case FK_Data_4: {
      return R_CLS(PREL32);
    }
    case FK_Data_8:
      if (IsILP32) {

Review comment (suggestion):
Thinking of the interface here. We could have a fixed interface like this where `%pltpcrel` could only apply to .word and only produce a `ELF::R_AARCH64_PLT32` reloc. Or we could have an interface that changes the reloc when a different size directive is used. For example .xword could produce a theoretical `ELF::R_AARCH64_PLT64` reloc.

If it is the former I think we would be best putting 4 in the name of the expression such as `%pltpcrel4` so that we could introduce `%pltpcrel8` later.

Code after:
unsigned AArch64ELFObjectWriter::getRelocType(const MCFixup &Fixup,
                                              const MCValue &Target,
                                              bool IsPCRel) const {
  auto Kind = Fixup.getKind();
  AArch64::Specifier RefKind =
      static_cast<AArch64::Specifier>(Target.getSpecifier());
  AArch64::Specifier SymLoc = AArch64::getSymbolLoc(RefKind);
  bool IsNC = AArch64::isNotChecked(RefKind);

  switch (SymLoc) {
  case AArch64::S_DTPREL:
  case AArch64::S_GOTTPREL:
  case AArch64::S_TPREL:
  case AArch64::S_TLSDESC:
  case AArch64::S_TLSDESC_AUTH:
    if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))
      static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);
    break;
  default:
    break;
  }

  switch (RefKind) {
  case AArch64::S_GOTPCREL:
  case AArch64::S_PLT:
    if (Kind == FK_Data_4)
      break;
    // Only R_AARCH64_PLT32/R_AARCH64_GOTPCREL32 defined at present, but can
    // be extended to other sizes if additional relocations are defined.
    reportError(Fixup.getLoc(), AArch64::getSpecifierName(RefKind) +
                                    " can only be used in a .word directive");
    return ELF::R_AARCH64_NONE;
  default:
    break;
  }

  // Extract the relocation type from the fixup kind, after applying STT_TLS as
  // needed.
  if (mc::isRelocation(Fixup.getKind()))
    return Kind;

  if (IsPCRel) {
    switch (Kind) {
    case FK_Data_1:
      reportError(Fixup.getLoc(), "1-byte data relocations not supported");
      return ELF::R_AARCH64_NONE;
    case FK_Data_2:
      return R_CLS(PREL16);
    case FK_Data_4: {
      return R_CLS(PREL32);
    }