//===-- HexagonTargetObjectFile.cpp ---------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the HexagonTargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "hexagon-sdata"

#include "HexagonTargetMachine.h"
#include "HexagonTargetObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ELF.h"

using namespace llvm;

static cl::opt<unsigned> SmallDataThreshold("hexagon-small-data-threshold",
  cl::init(8), cl::Hidden,
  cl::desc("The maximum size of an object in the sdata section"));

static cl::opt<bool> NoSmallDataSorting("mno-sort-sda", cl::init(false),
  cl::Hidden, cl::desc("Disable small data sections sorting"));

static cl::opt<bool> StaticsInSData("hexagon-statics-in-small-data",
  cl::init(false), cl::Hidden, cl::ZeroOrMore,
  cl::desc("Allow static variables in .sdata"));

static cl::opt<bool> TraceGVPlacement("trace-gv-placement",
  cl::Hidden, cl::init(false),
  cl::desc("Trace global value placement"));

// TraceGVPlacement controls messages for all builds. For builds with assertions
// (debug or release), messages are also controlled by the usual debug flags
// (e.g. -debug and -debug-only=globallayout)
#define TRACE_TO(s, X) s << X
#ifdef NDEBUG
#define TRACE(X) do { if (TraceGVPlacement) { TRACE_TO(errs(), X); } } while (0)
#else
#define TRACE(X) \
  do { \
    if (TraceGVPlacement) { TRACE_TO(errs(), X); } \
    else { DEBUG( TRACE_TO(dbgs(), X) ); } \
  } while (0)
#endif

// Returns true if the section name is such that the symbol will be put
// in a small data section.
// For instance, global variables with section attributes such as ".sdata"
// ".sdata.*", ".sbss", and ".sbss.*" will go into small data.
static bool isSmallDataSection(StringRef Sec) {
  // sectionName is either ".sdata" or ".sbss". Looking for an exact match
  // obviates the need for checks for section names such as ".sdatafoo".
  if (Sec.equals(".sdata") || Sec.equals(".sbss") || Sec.equals(".scommon"))
    return true;
  // If either ".sdata." or ".sbss." is a substring of the section name
  // then put the symbol in small data.
  return Sec.find(".sdata.") != StringRef::npos ||
         Sec.find(".sbss.") != StringRef::npos ||
         Sec.find(".scommon.") != StringRef::npos;
}


static const char *getSectionSuffixForSize(unsigned Size) {
  switch (Size) {
  default:
    return "";
  case 1:
    return ".1";
  case 2:
    return ".2";
  case 4:
    return ".4";
  case 8:
    return ".8";
  }
}

void HexagonTargetObjectFile::Initialize(MCContext &Ctx,
      const TargetMachine &TM) {
  TargetLoweringObjectFileELF::Initialize(Ctx, TM);
  InitializeELF(TM.Options.UseInitArray);

  SmallDataSection =
    getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,
                               ELF::SHF_WRITE | ELF::SHF_ALLOC |
                               ELF::SHF_HEX_GPREL);
  SmallBSSSection =
    getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
                               ELF::SHF_WRITE | ELF::SHF_ALLOC |
                               ELF::SHF_HEX_GPREL);
}


MCSection *HexagonTargetObjectFile::SelectSectionForGlobal(
      const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
      const TargetMachine &TM) const {
  TRACE("[SelectSectionForGlobal] GV(" << GV->getName() << ") ");
  TRACE("input section(" << GV->getSection() << ") ");

  TRACE((GV->hasPrivateLinkage() ? "private_linkage " : "")
         << (GV->hasLocalLinkage() ? "local_linkage " : "")
         << (GV->hasInternalLinkage() ? "internal " : "")
         << (GV->hasExternalLinkage() ? "external " : "")
         << (GV->hasCommonLinkage() ? "common_linkage " : "")
         << (GV->hasCommonLinkage() ? "common " : "" )
         << (Kind.isCommon() ? "kind_common " : "" )
         << (Kind.isBSS() ? "kind_bss " : "" )
         << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));

  if (isGlobalInSmallSection(GV, TM))
    return selectSmallSectionForGlobal(GV, Kind, Mang, TM);

  if (Kind.isCommon()) {
    // This is purely for LTO+Linker Script because commons don't really have a
    // section. However, the BitcodeSectionWriter pass will query for the
    // sections of commons (and the linker expects us to know their section) so
    // we'll return one here.
    return BSSSection;
  }

  TRACE("default_ELF_section\n");
  // Otherwise, we work the same as ELF.
  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind,
              Mang, TM);
}


MCSection *HexagonTargetObjectFile::getExplicitSectionGlobal(
      const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
      const TargetMachine &TM) const {
  TRACE("[getExplicitSectionGlobal] GV(" << GV->getName() << ") from("
        << GV->getSection() << ") ");
  TRACE((GV->hasPrivateLinkage() ? "private_linkage " : "")
         << (GV->hasLocalLinkage() ? "local_linkage " : "")
         << (GV->hasInternalLinkage() ? "internal " : "")
         << (GV->hasExternalLinkage() ? "external " : "")
         << (GV->hasCommonLinkage() ? "common_linkage " : "")
         << (GV->hasCommonLinkage() ? "common " : "" )
         << (Kind.isCommon() ? "kind_common " : "" )
         << (Kind.isBSS() ? "kind_bss " : "" )
         << (Kind.isBSSLocal() ? "kind_bss_local " : "" ));

  if (GV->hasSection()) {
    StringRef Section = GV->getSection();
    if (Section.find(".access.text.group") != StringRef::npos)
      return getContext().getELFSection(GV->getSection(), ELF::SHT_PROGBITS,
                                        ELF::SHF_ALLOC | ELF::SHF_EXECINSTR);
    if (Section.find(".access.data.group") != StringRef::npos)
      return getContext().getELFSection(GV->getSection(), ELF::SHT_PROGBITS,
                                        ELF::SHF_WRITE | ELF::SHF_ALLOC);
  }

  if (isGlobalInSmallSection(GV, TM))
    return selectSmallSectionForGlobal(GV, Kind, Mang, TM);

  // Otherwise, we work the same as ELF.
  TRACE("default_ELF_section\n");
  return TargetLoweringObjectFileELF::getExplicitSectionGlobal(GV, Kind,
            Mang, TM);
}


/// Return true if this global value should be placed into small data/bss
/// section.
bool HexagonTargetObjectFile::isGlobalInSmallSection(const GlobalValue *GV,
      const TargetMachine &TM) const {
  // Only global variables, not functions.
  DEBUG(dbgs() << "Checking if value is in small-data, -G"
               << SmallDataThreshold << ": \"" << GV->getName() << "\": ");
  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
  if (!GVar) {
    DEBUG(dbgs() << "no, not a global variable\n");
    return false;
  }

  // Globals with external linkage that have an original section set must be
  // emitted to that section, regardless of whether we would put them into
  // small data or not. This is how we can support mixing -G0/-G8 in LTO.
  if (GVar->hasSection()) {
    bool IsSmall = isSmallDataSection(GVar->getSection());
    DEBUG(dbgs() << (IsSmall ? "yes" : "no") << ", has section: "
                 << GVar->getSection() << '\n');
    return IsSmall;
  }

  if (GVar->isConstant()) {
    DEBUG(dbgs() << "no, is a constant\n");
    return false;
  }

  bool IsLocal = GVar->hasLocalLinkage();
  if (!StaticsInSData && IsLocal) {
    DEBUG(dbgs() << "no, is static\n");
    return false;
  }

  Type *GType = GVar->getType();
  if (PointerType *PT = dyn_cast<PointerType>(GType))
    GType = PT->getElementType();

  if (isa<ArrayType>(GType)) {
    DEBUG(dbgs() << "no, is an array\n");
    return false;
  }

  // If the type is a struct with no body provided, treat is conservatively.
  // There cannot be actual definitions of object of such a type in this CU
  // (only references), so assuming that they are not in sdata is safe. If
  // these objects end up in the sdata, the references will still be valid.
  if (StructType *ST = dyn_cast<StructType>(GType)) {
    if (ST->isOpaque()) {
      DEBUG(dbgs() << "no, has opaque type\n");
      return false;
    }
  }

  unsigned Size = GVar->getParent()->getDataLayout().getTypeAllocSize(GType);
  if (Size == 0) {
    DEBUG(dbgs() << "no, has size 0\n");
    return false;
  }
  if (Size > SmallDataThreshold) {
    DEBUG(dbgs() << "no, size exceeds sdata threshold: " << Size << '\n');
    return false;
  }

  DEBUG(dbgs() << "yes\n");
  return true;
}


bool HexagonTargetObjectFile::isSmallDataEnabled() const {
  return SmallDataThreshold > 0;
}


unsigned HexagonTargetObjectFile::getSmallDataSize() const {
  return SmallDataThreshold;
}


/// Descends any type down to "elementary" components,
/// discovering the smallest addressable one.
/// If zero is returned, declaration will not be modified.
unsigned HexagonTargetObjectFile::getSmallestAddressableSize(const Type *Ty,
      const GlobalValue *GV, const TargetMachine &TM) const {
  // Assign the smallest element access size to the highest
  // value which assembler can handle.
  unsigned SmallestElement = 8;

  if (!Ty)
    return 0;
  switch (Ty->getTypeID()) {
  case Type::StructTyID: {
    const StructType *STy = cast<const StructType>(Ty);
    for (auto &E : STy->elements()) {
      unsigned AtomicSize = getSmallestAddressableSize(E, GV, TM);
      if (AtomicSize < SmallestElement)
        SmallestElement = AtomicSize;
    }
    return (STy->getNumElements() == 0) ? 0 : SmallestElement;
  }
  case Type::ArrayTyID: {
    const ArrayType *ATy = cast<const ArrayType>(Ty);
    return getSmallestAddressableSize(ATy->getElementType(), GV, TM);
  }
  case Type::VectorTyID: {
    const VectorType *PTy = cast<const VectorType>(Ty);
    return getSmallestAddressableSize(PTy->getElementType(), GV, TM);
  }
  case Type::PointerTyID:
  case Type::HalfTyID:
  case Type::FloatTyID:
  case Type::DoubleTyID:
  case Type::IntegerTyID: {
    const DataLayout &DL = GV->getParent()->getDataLayout();
    // It is unfortunate that DL's function take non-const Type*.
    return DL.getTypeAllocSize(const_cast<Type*>(Ty));
  }
  case Type::FunctionTyID:
  case Type::VoidTyID:
  case Type::X86_FP80TyID:
  case Type::FP128TyID:
  case Type::PPC_FP128TyID:
  case Type::LabelTyID:
  case Type::MetadataTyID:
  case Type::X86_MMXTyID:
  case Type::TokenTyID:
    return 0;
  }

  return 0;
}


MCSection *HexagonTargetObjectFile::selectSmallSectionForGlobal(
      const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
      const TargetMachine &TM) const {
  const Type *GTy = GV->getType()->getElementType();
  unsigned Size = getSmallestAddressableSize(GTy, GV, TM);

  // If we have -ffunction-section or -fdata-section then we should emit the
  // global value to a unique section specifically for it... even for sdata.
  bool EmitUniquedSection = TM.getDataSections();

  TRACE("Small data. Size(" << Size << ")");
  // Handle Small Section classification here.
  if (Kind.isBSS() || Kind.isBSSLocal()) {
    // If -mno-sort-sda is not set, find out smallest accessible entity in
    // declaration and add it to the section name string.
    // Note. It does not track the actual usage of the value, only its de-
    // claration. Also, compiler adds explicit pad fields to some struct
    // declarations - they are currently counted towards smallest addres-
    // sable entity.
    if (NoSmallDataSorting) {
      TRACE(" default sbss\n");
      return SmallBSSSection;
    }

    StringRef Prefix(".sbss");
    SmallString<128> Name(Prefix);
    Name.append(getSectionSuffixForSize(Size));

    if (EmitUniquedSection) {
      Name.append(".");
      Name.append(GV->getName());
    }
    TRACE(" unique sbss(" << Name << ")\n");
    return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
                ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
  }

  if (Kind.isCommon()) {
    // This is purely for LTO+Linker Script because commons don't really have a
    // section. However, the BitcodeSectionWriter pass will query for the
    // sections of commons (and the linker expects us to know their section) so
    // we'll return one here.
    if (NoSmallDataSorting)
      return BSSSection;

    Twine Name = Twine(".scommon") + getSectionSuffixForSize(Size);
    TRACE(" small COMMON (" << Name << ")\n");

    return getContext().getELFSection(Name.str(), ELF::SHT_NOBITS,
                                      ELF::SHF_WRITE | ELF::SHF_ALLOC |
                                      ELF::SHF_HEX_GPREL);
  }

  // We could have changed sdata object to a constant... in this
  // case the Kind could be wrong for it.
  if (Kind.isMergeableConst()) {
    TRACE(" const_object_as_data ");
    const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
    if (GVar->hasSection() && isSmallDataSection(GVar->getSection()))
      Kind = SectionKind::getData();
  }

  if (Kind.isData()) {
    if (NoSmallDataSorting) {
      TRACE(" default sdata\n");
      return SmallDataSection;
    }

    StringRef Prefix(".sdata");
    SmallString<128> Name(Prefix);
    Name.append(getSectionSuffixForSize(Size));

    if (EmitUniquedSection) {
      Name.append(".");
      Name.append(GV->getName());
    }
    TRACE(" unique sdata(" << Name << ")\n");
    return getContext().getELFSection(Name.str(), ELF::SHT_PROGBITS,
                ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_HEX_GPREL);
  }

  TRACE("default ELF section\n");
  // Otherwise, we work the same as ELF.
  return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind,
              Mang, TM);
}
