//===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "MCTargetDesc/PPCFixupKinds.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCMachObjectWriter.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MachO.h"

using namespace llvm;

namespace {
class PPCMachObjectWriter : public MCMachObjectTargetWriter {
  bool RecordScatteredRelocation(MachObjectWriter *Writer,
                                 const MCAssembler &Asm,
                                 const MCAsmLayout &Layout,
                                 const MCFragment *Fragment,
                                 const MCFixup &Fixup, MCValue Target,
                                 unsigned Log2Size, uint64_t &FixedValue);

  void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
                           const MCAsmLayout &Layout,
                           const MCFragment *Fragment, const MCFixup &Fixup,
                           MCValue Target, uint64_t &FixedValue);

public:
  PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
      : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype,
                                 /*UseAggressiveSymbolFolding=*/Is64Bit) {}

  void RecordRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
                        const MCAsmLayout &Layout, const MCFragment *Fragment,
                        const MCFixup &Fixup, MCValue Target,
                        uint64_t &FixedValue) override {
    if (Writer->is64Bit()) {
      report_fatal_error("Relocation emission for MachO/PPC64 unimplemented.");
    } else
      RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                          FixedValue);
  }
};
}

/// computes the log2 of the size of the relocation,
/// used for relocation_info::r_length.
static unsigned getFixupKindLog2Size(unsigned Kind) {
  switch (Kind) {
  default:
    report_fatal_error("log2size(FixupKind): Unhandled fixup kind!");
  case FK_PCRel_1:
  case FK_Data_1:
    return 0;
  case FK_PCRel_2:
  case FK_Data_2:
    return 1;
  case FK_PCRel_4:
  case PPC::fixup_ppc_brcond14:
  case PPC::fixup_ppc_half16:
  case PPC::fixup_ppc_br24:
  case FK_Data_4:
    return 2;
  case FK_PCRel_8:
  case FK_Data_8:
    return 3;
  }
  return 0;
}

/// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
/// Outline based on PPCELFObjectWriter::GetRelocType().
static unsigned getRelocType(const MCValue &Target,
                             const MCFixupKind FixupKind, // from
                                                          // Fixup.getKind()
                             const bool IsPCRel) {
  const MCSymbolRefExpr::VariantKind Modifier =
      Target.isAbsolute() ? MCSymbolRefExpr::VK_None
                          : Target.getSymA()->getKind();
  // determine the type of the relocation
  unsigned Type = MachO::GENERIC_RELOC_VANILLA;
  if (IsPCRel) { // relative to PC
    switch ((unsigned)FixupKind) {
    default:
      report_fatal_error("Unimplemented fixup kind (relative)");
    case PPC::fixup_ppc_br24:
      Type = MachO::PPC_RELOC_BR24; // R_PPC_REL24
      break;
    case PPC::fixup_ppc_brcond14:
      Type = MachO::PPC_RELOC_BR14;
      break;
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default:
        llvm_unreachable("Unsupported modifier for half16 fixup");
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = MachO::PPC_RELOC_HA16;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = MachO::PPC_RELOC_LO16;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = MachO::PPC_RELOC_HI16;
        break;
      }
      break;
    }
  } else {
    switch ((unsigned)FixupKind) {
    default:
      report_fatal_error("Unimplemented fixup kind (absolute)!");
    case PPC::fixup_ppc_half16:
      switch (Modifier) {
      default:
        llvm_unreachable("Unsupported modifier for half16 fixup");
      case MCSymbolRefExpr::VK_PPC_HA:
        Type = MachO::PPC_RELOC_HA16_SECTDIFF;
        break;
      case MCSymbolRefExpr::VK_PPC_LO:
        Type = MachO::PPC_RELOC_LO16_SECTDIFF;
        break;
      case MCSymbolRefExpr::VK_PPC_HI:
        Type = MachO::PPC_RELOC_HI16_SECTDIFF;
        break;
      }
      break;
    case FK_Data_4:
      break;
    case FK_Data_2:
      break;
    }
  }
  return Type;
}

static void makeRelocationInfo(MachO::any_relocation_info &MRE,
                               const uint32_t FixupOffset, const uint32_t Index,
                               const unsigned IsPCRel, const unsigned Log2Size,
                               const unsigned IsExtern, const unsigned Type) {
  MRE.r_word0 = FixupOffset;
  // The bitfield offsets that work (as determined by trial-and-error)
  // are different than what is documented in the mach-o manuals.
  // This appears to be an endianness issue; reversing the order of the
  // documented bitfields in <llvm/Support/MachO.h> fixes this (but
  // breaks x86/ARM assembly).
  MRE.r_word1 = ((Index << 8) |    // was << 0
                 (IsPCRel << 7) |  // was << 24
                 (Log2Size << 5) | // was << 25
                 (IsExtern << 4) | // was << 27
                 (Type << 0));     // was << 28
}

static void
makeScatteredRelocationInfo(MachO::any_relocation_info &MRE,
                            const uint32_t Addr, const unsigned Type,
                            const unsigned Log2Size, const unsigned IsPCRel,
                            const uint32_t Value2) {
  // For notes on bitfield positions and endianness, see:
  // https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry
  MRE.r_word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) |
                 (IsPCRel << 30) | MachO::R_SCATTERED);
  MRE.r_word1 = Value2;
}

/// Compute fixup offset (address).
static uint32_t getFixupOffset(const MCAsmLayout &Layout,
                               const MCFragment *Fragment,
                               const MCFixup &Fixup) {
  uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  // On Mach-O, ppc_fixup_half16 relocations must refer to the
  // start of the instruction, not the second halfword, as ELF does
  if (unsigned(Fixup.getKind()) == PPC::fixup_ppc_half16)
    FixupOffset &= ~uint32_t(3);
  return FixupOffset;
}

/// \return false if falling back to using non-scattered relocation,
/// otherwise true for normal scattered relocation.
/// based on X86MachObjectWriter::RecordScatteredRelocation
/// and ARMMachObjectWriter::RecordScatteredRelocation
bool PPCMachObjectWriter::RecordScatteredRelocation(
    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    unsigned Log2Size, uint64_t &FixedValue) {
  // caller already computes these, can we just pass and reuse?
  const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
  const MCFixupKind FK = Fixup.getKind();
  const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
  const unsigned Type = getRelocType(Target, FK, IsPCRel);

  // Is this a local or SECTDIFF relocation entry?
  // SECTDIFF relocation entries have symbol subtractions,
  // and require two entries, the first for the add-symbol value,
  // the second for the subtract-symbol value.

  // See <reloc.h>.
  const MCSymbol *A = &Target.getSymA()->getSymbol();
  const MCSymbolData *A_SD = &Asm.getSymbolData(*A);

  if (!A_SD->getFragment())
    report_fatal_error("symbol '" + A->getName() +
                       "' can not be undefined in a subtraction expression");

  uint32_t Value = Writer->getSymbolAddress(A_SD, Layout);
  uint64_t SecAddr =
      Writer->getSectionAddress(A_SD->getFragment()->getParent());
  FixedValue += SecAddr;
  uint32_t Value2 = 0;

  if (const MCSymbolRefExpr *B = Target.getSymB()) {
    const MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());

    if (!B_SD->getFragment())
      report_fatal_error("symbol '" + B->getSymbol().getName() +
                         "' can not be undefined in a subtraction expression");

    // FIXME: is Type correct? see include/llvm/Support/MachO.h
    Value2 = Writer->getSymbolAddress(B_SD, Layout);
    FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent());
  }
  // FIXME: does FixedValue get used??

  // Relocations are written out in reverse order, so the PAIR comes first.
  if (Type == MachO::PPC_RELOC_SECTDIFF ||
      Type == MachO::PPC_RELOC_HI16_SECTDIFF ||
      Type == MachO::PPC_RELOC_LO16_SECTDIFF ||
      Type == MachO::PPC_RELOC_HA16_SECTDIFF ||
      Type == MachO::PPC_RELOC_LO14_SECTDIFF ||
      Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) {
    // X86 had this piece, but ARM does not
    // If the offset is too large to fit in a scattered relocation,
    // we're hosed. It's an unfortunate limitation of the MachO format.
    if (FixupOffset > 0xffffff) {
      char Buffer[32];
      format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
      Asm.getContext().FatalError(Fixup.getLoc(),
                                  Twine("Section too large, can't encode "
                                        "r_address (") +
                                      Buffer + ") into 24 bits of scattered "
                                               "relocation entry.");
      llvm_unreachable("fatal error returned?!");
    }

    // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()?
    // see PPCMCExpr::EvaluateAsRelocatableImpl()
    uint32_t other_half = 0;
    switch (Type) {
    case MachO::PPC_RELOC_LO16_SECTDIFF:
      other_half = (FixedValue >> 16) & 0xffff;
      // applyFixupOffset longer extracts the high part because it now assumes
      // this was already done.
      // It looks like this is not true for the FixedValue needed with Mach-O
      // relocs.
      // So we need to adjust FixedValue again here.
      FixedValue &= 0xffff;
      break;
    case MachO::PPC_RELOC_HA16_SECTDIFF:
      other_half = FixedValue & 0xffff;
      FixedValue =
          ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff;
      break;
    case MachO::PPC_RELOC_HI16_SECTDIFF:
      other_half = FixedValue & 0xffff;
      FixedValue = (FixedValue >> 16) & 0xffff;
      break;
    default:
      llvm_unreachable("Invalid PPC scattered relocation type.");
      break;
    }

    MachO::any_relocation_info MRE;
    makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
                                Log2Size, IsPCRel, Value2);
    Writer->addRelocation(Fragment->getParent(), MRE);
  } else {
    // If the offset is more than 24-bits, it won't fit in a scattered
    // relocation offset field, so we fall back to using a non-scattered
    // relocation. This is a bit risky, as if the offset reaches out of
    // the block and the linker is doing scattered loading on this
    // symbol, things can go badly.
    //
    // Required for 'as' compatibility.
    if (FixupOffset > 0xffffff)
      return false;
  }
  MachO::any_relocation_info MRE;
  makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value);
  Writer->addRelocation(Fragment->getParent(), MRE);
  return true;
}

// see PPCELFObjectWriter for a general outline of cases
void PPCMachObjectWriter::RecordPPCRelocation(
    MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
    const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
    uint64_t &FixedValue) {
  const MCFixupKind FK = Fixup.getKind(); // unsigned
  const unsigned Log2Size = getFixupKindLog2Size(FK);
  const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
  const unsigned RelocType = getRelocType(Target, FK, IsPCRel);

  // If this is a difference or a defined symbol plus an offset, then we need a
  // scattered relocation entry. Differences always require scattered
  // relocations.
  if (Target.getSymB() &&
      // Q: are branch targets ever scattered?
      RelocType != MachO::PPC_RELOC_BR24 &&
      RelocType != MachO::PPC_RELOC_BR14) {
    RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
                              Log2Size, FixedValue);
    return;
  }

  // this doesn't seem right for RIT_PPC_BR24
  // Get the symbol data, if any.
  const MCSymbolData *SD = nullptr;
  if (Target.getSymA())
    SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());

  // See <reloc.h>.
  const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
  unsigned Index = 0;
  unsigned IsExtern = 0;
  unsigned Type = RelocType;

  if (Target.isAbsolute()) { // constant
                             // SymbolNum of 0 indicates the absolute section.
                             //
    // FIXME: Currently, these are never generated (see code below). I cannot
    // find a case where they are actually emitted.
    report_fatal_error("FIXME: relocations to absolute targets "
                       "not yet implemented");
    // the above line stolen from ARM, not sure
  } else {
    // Resolve constant variables.
    if (SD->getSymbol().isVariable()) {
      int64_t Res;
      if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
              Res, Layout, Writer->getSectionAddressMap())) {
        FixedValue = Res;
        return;
      }
    }

    // Check whether we need an external or internal relocation.
    if (Writer->doesSymbolRequireExternRelocation(SD)) {
      IsExtern = 1;
      Index = SD->getIndex();
      // For external relocations, make sure to offset the fixup value to
      // compensate for the addend of the symbol address, if it was
      // undefined. This occurs with weak definitions, for example.
      if (!SD->getSymbol().isUndefined())
        FixedValue -= Layout.getSymbolOffset(SD);
    } else {
      // The index is the section ordinal (1-based).
      const MCSectionData &SymSD =
          Asm.getSectionData(SD->getSymbol().getSection());
      Index = SymSD.getOrdinal() + 1;
      FixedValue += Writer->getSectionAddress(&SymSD);
    }
    if (IsPCRel)
      FixedValue -= Writer->getSectionAddress(Fragment->getParent());
  }

  // struct relocation_info (8 bytes)
  MachO::any_relocation_info MRE;
  makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, IsExtern,
                     Type);
  Writer->addRelocation(Fragment->getParent(), MRE);
}

MCObjectWriter *llvm::createPPCMachObjectWriter(raw_ostream &OS, bool Is64Bit,
                                                uint32_t CPUType,
                                                uint32_t CPUSubtype) {
  return createMachObjectWriter(
      new PPCMachObjectWriter(Is64Bit, CPUType, CPUSubtype), OS,
      /*IsLittleEndian=*/false);
}
