//===-- TargetMachine.cpp - General Target Information ---------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the general parts of a Target machine.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;

//---------------------------------------------------------------------------
// Command-line options that tend to be useful on more than one back-end.
//

namespace llvm {
  bool HasDivModLibcall;
  bool AsmVerbosityDefault(false);
}

static cl::opt<bool>
DataSections("fdata-sections",
  cl::desc("Emit data into separate sections"),
  cl::init(false));
static cl::opt<bool>
FunctionSections("ffunction-sections",
  cl::desc("Emit functions into separate sections"),
  cl::init(false));

//---------------------------------------------------------------------------
// TargetMachine Class
//

TargetMachine::TargetMachine(const Target &T,
                             StringRef TT, StringRef CPU, StringRef FS,
                             const TargetOptions &Options)
  : TheTarget(T), TargetTriple(TT), TargetCPU(CPU), TargetFS(FS),
    CodeGenInfo(0), AsmInfo(0),
    MCRelaxAll(false),
    MCNoExecStack(false),
    MCSaveTempLabels(false),
    MCUseCFI(true),
    MCUseDwarfDirectory(false),
    RequireStructuredCFG(false),
    Options(Options) {
}

TargetMachine::~TargetMachine() {
  delete CodeGenInfo;
  delete AsmInfo;
}

/// \brief Reset the target options based on the function's attributes.
void TargetMachine::resetTargetOptions(const MachineFunction *MF) const {
  const Function *F = MF->getFunction();
  TargetOptions &TO = MF->getTarget().Options;

#define RESET_OPTION(X, Y)                                              \
  do {                                                                  \
    if (F->hasFnAttribute(Y))                                           \
      TO.X =                                                            \
        (F->getAttributes().                                            \
           getAttribute(AttributeSet::FunctionIndex,                    \
                        Y).getValueAsString() == "true");               \
  } while (0)

  RESET_OPTION(NoFramePointerElim, "no-frame-pointer-elim");
  RESET_OPTION(LessPreciseFPMADOption, "less-precise-fpmad");
  RESET_OPTION(UnsafeFPMath, "unsafe-fp-math");
  RESET_OPTION(NoInfsFPMath, "no-infs-fp-math");
  RESET_OPTION(NoNaNsFPMath, "no-nans-fp-math");
  RESET_OPTION(UseSoftFloat, "use-soft-float");
  RESET_OPTION(DisableTailCalls, "disable-tail-calls");
}

/// getRelocationModel - Returns the code generation relocation model. The
/// choices are static, PIC, and dynamic-no-pic, and target default.
Reloc::Model TargetMachine::getRelocationModel() const {
  if (!CodeGenInfo)
    return Reloc::Default;
  return CodeGenInfo->getRelocationModel();
}

/// getCodeModel - Returns the code model. The choices are small, kernel,
/// medium, large, and target default.
CodeModel::Model TargetMachine::getCodeModel() const {
  if (!CodeGenInfo)
    return CodeModel::Default;
  return CodeGenInfo->getCodeModel();
}

/// Get the IR-specified TLS model for Var.
static TLSModel::Model getSelectedTLSModel(const GlobalVariable *Var) {
  switch (Var->getThreadLocalMode()) {
  case GlobalVariable::NotThreadLocal:
    llvm_unreachable("getSelectedTLSModel for non-TLS variable");
    break;
  case GlobalVariable::GeneralDynamicTLSModel:
    return TLSModel::GeneralDynamic;
  case GlobalVariable::LocalDynamicTLSModel:
    return TLSModel::LocalDynamic;
  case GlobalVariable::InitialExecTLSModel:
    return TLSModel::InitialExec;
  case GlobalVariable::LocalExecTLSModel:
    return TLSModel::LocalExec;
  }
  llvm_unreachable("invalid TLS model");
}

TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
  // If GV is an alias then use the aliasee for determining
  // thread-localness.
  if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
    GV = GA->resolveAliasedGlobal(false);
  const GlobalVariable *Var = cast<GlobalVariable>(GV);

  bool isLocal = Var->hasLocalLinkage();
  bool isDeclaration = Var->isDeclaration();
  bool isPIC = getRelocationModel() == Reloc::PIC_;
  bool isPIE = Options.PositionIndependentExecutable;
  // FIXME: what should we do for protected and internal visibility?
  // For variables, is internal different from hidden?
  bool isHidden = Var->hasHiddenVisibility();

  TLSModel::Model Model;
  if (isPIC && !isPIE) {
    if (isLocal || isHidden)
      Model = TLSModel::LocalDynamic;
    else
      Model = TLSModel::GeneralDynamic;
  } else {
    if (!isDeclaration || isHidden)
      Model = TLSModel::LocalExec;
    else
      Model = TLSModel::InitialExec;
  }

  // If the user specified a more specific model, use that.
  TLSModel::Model SelectedModel = getSelectedTLSModel(Var);
  if (SelectedModel > Model)
    return SelectedModel;

  return Model;
}

/// getOptLevel - Returns the optimization level: None, Less,
/// Default, or Aggressive.
CodeGenOpt::Level TargetMachine::getOptLevel() const {
  if (!CodeGenInfo)
    return CodeGenOpt::Default;
  return CodeGenInfo->getOptLevel();
}

void TargetMachine::setOptLevel(CodeGenOpt::Level Level) const {
  if (CodeGenInfo)
    CodeGenInfo->setOptLevel(Level);
}

bool TargetMachine::getAsmVerbosityDefault() {
  return AsmVerbosityDefault;
}

void TargetMachine::setAsmVerbosityDefault(bool V) {
  AsmVerbosityDefault = V;
}

bool TargetMachine::getFunctionSections() {
  return FunctionSections;
}

bool TargetMachine::getDataSections() {
  return DataSections;
}

void TargetMachine::setFunctionSections(bool V) {
  FunctionSections = V;
}

void TargetMachine::setDataSections(bool V) {
  DataSections = V;
}

void TargetMachine::getNameWithPrefix(SmallVectorImpl<char> &Name,
                                      const GlobalValue *GV, Mangler &Mang,
                                      bool MayAlwaysUsePrivate) const {
  if (MayAlwaysUsePrivate || !GV->hasPrivateLinkage()) {
    // Simple case: If GV is not private, it is not important to find out if
    // private labels are legal in this case or not.
    Mang.getNameWithPrefix(Name, GV, false);
    return;
  }
  SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, *this);
  const TargetLoweringObjectFile &TLOF =
      getTargetLowering()->getObjFileLowering();
  const MCSection *TheSection = TLOF.SectionForGlobal(GV, GVKind, Mang, *this);
  bool CannotUsePrivateLabel = TLOF.isSectionAtomizableBySymbols(*TheSection);
  Mang.getNameWithPrefix(Name, GV, CannotUsePrivateLabel);
}

MCSymbol *TargetMachine::getSymbol(const GlobalValue *GV, Mangler &Mang) const {
  SmallString<60> NameStr;
  getNameWithPrefix(NameStr, GV, Mang);
  const TargetLoweringObjectFile &TLOF =
      getTargetLowering()->getObjFileLowering();
  return TLOF.getContext().GetOrCreateSymbol(NameStr.str());
}
