//===- subzero/src/IceGlobalInits.h - Global declarations -------*- C++ -*-===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares the representation of function declarations, global variable
/// declarations, and the corresponding variable initializers in Subzero.
///
/// Global variable initializers are represented as a sequence of simple
/// initializers.
///
//===----------------------------------------------------------------------===//

#ifndef SUBZERO_SRC_ICEGLOBALINITS_H
#define SUBZERO_SRC_ICEGLOBALINITS_H

#include "IceDefs.h"
#include "IceFixups.h"
#include "IceGlobalContext.h"
#include "IceIntrinsics.h"
#include "IceOperand.h"
#include "IceTypes.h"

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wredundant-move"
#endif // __clang__

#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" // for NaClBitcodeRecord.
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/GlobalValue.h" // for GlobalValue::LinkageTypes.

#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__

#include <memory>
#include <utility>

// TODO(kschimpf): Remove ourselves from using LLVM representation for calling
// conventions and linkage types.

namespace Ice {

/// Base class for global variable and function declarations.
class GlobalDeclaration {
  GlobalDeclaration() = delete;
  GlobalDeclaration(const GlobalDeclaration &) = delete;
  GlobalDeclaration &operator=(const GlobalDeclaration &) = delete;

public:
  /// Discriminator for LLVM-style RTTI.
  enum GlobalDeclarationKind {
    FunctionDeclarationKind,
    VariableDeclarationKind
  };
  GlobalDeclarationKind getKind() const { return Kind; }
  const IceString &getName() const { return Name; }
  void setName(const IceString &NewName) { Name = NewName; }
  bool hasName() const { return !Name.empty(); }
  bool isInternal() const {
    return Linkage == llvm::GlobalValue::InternalLinkage;
  }
  llvm::GlobalValue::LinkageTypes getLinkage() const { return Linkage; }
  bool isExternal() const {
    return Linkage == llvm::GlobalValue::ExternalLinkage;
  }
  void setLinkage(llvm::GlobalValue::LinkageTypes NewLinkage) {
    Linkage = NewLinkage;
  }
  virtual ~GlobalDeclaration() = default;

  /// Prints out type of the global declaration.
  virtual void dumpType(Ostream &Stream) const = 0;

  /// Prints out the global declaration.
  virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
  void dump(Ostream &Stream) const {
    if (!BuildDefs::dump())
      return;
    GlobalContext *const Ctx = nullptr;
    dump(Ctx, Stream);
  }

  /// Returns true if when emitting names, we should suppress mangling.
  virtual bool getSuppressMangling() const = 0;

  /// Mangles name for cross tests, unless external and not defined locally (so
  /// that relocations across pnacl-sz and pnacl-llc will work).
  virtual IceString mangleName(GlobalContext *Ctx) const {
    return getSuppressMangling() ? Name : Ctx->mangleName(Name);
  }

  /// Returns textual name of linkage.
  const char *getLinkageName() const {
    return isInternal() ? "internal" : "external";
  }

protected:
  GlobalDeclaration(GlobalDeclarationKind Kind,
                    llvm::GlobalValue::LinkageTypes Linkage)
      : Kind(Kind), Linkage(Linkage) {}

  /// Returns true if linkage is defined correctly for the global declaration,
  /// based on default rules.
  bool verifyLinkageDefault(const GlobalContext *Ctx) const {
    switch (Linkage) {
    default:
      return false;
    case llvm::GlobalValue::InternalLinkage:
      return true;
    case llvm::GlobalValue::ExternalLinkage:
      return Ctx->getFlags().getAllowExternDefinedSymbols();
    }
  }

  const GlobalDeclarationKind Kind;
  IceString Name;
  llvm::GlobalValue::LinkageTypes Linkage;
};

/// Models a function declaration. This includes the type signature of the
/// function, its calling conventions, and its linkage.
class FunctionDeclaration : public GlobalDeclaration {
  FunctionDeclaration() = delete;
  FunctionDeclaration(const FunctionDeclaration &) = delete;
  FunctionDeclaration &operator=(const FunctionDeclaration &) = delete;

public:
  static FunctionDeclaration *create(GlobalContext *Context,
                                     const FuncSigType &Signature,
                                     llvm::CallingConv::ID CallingConv,
                                     llvm::GlobalValue::LinkageTypes Linkage,
                                     bool IsProto) {
    return new (Context->allocate<FunctionDeclaration>())
        FunctionDeclaration(Signature, CallingConv, Linkage, IsProto);
  }
  const FuncSigType &getSignature() const { return Signature; }
  llvm::CallingConv::ID getCallingConv() const { return CallingConv; }
  /// isProto implies that there isn't a (local) definition for the function.
  bool isProto() const { return IsProto; }
  static bool classof(const GlobalDeclaration *Addr) {
    return Addr->getKind() == FunctionDeclarationKind;
  }
  void dumpType(Ostream &Stream) const final;
  void dump(GlobalContext *Ctx, Ostream &Stream) const final;
  bool getSuppressMangling() const final { return isExternal() && IsProto; }

  /// Returns true if linkage is correct for the function declaration.
  bool verifyLinkageCorrect(const GlobalContext *Ctx) const {
    if (isPNaClABIExternalName() || isIntrinsicName(Ctx))
      return Linkage == llvm::GlobalValue::ExternalLinkage;
    return verifyLinkageDefault(Ctx);
  }

  /// Validates that the type signature of the function is correct. Returns true
  /// if valid.
  bool validateTypeSignature(const GlobalContext *Ctx) const {
    bool IsIntrinsic;
    if (const Intrinsics::FullIntrinsicInfo *Info =
            getIntrinsicInfo(Ctx, &IsIntrinsic))
      return validateIntrinsicTypeSignature(Info);
    return !IsIntrinsic && validateRegularTypeSignature();
  }

  /// Generates an error message describing why validateTypeSignature returns
  /// false.
  IceString getTypeSignatureError(const GlobalContext *Ctx);

  /// Returns corresponding PNaCl intrisic information.
  const Intrinsics::FullIntrinsicInfo *
  getIntrinsicInfo(const GlobalContext *Ctx) const {
    bool BadIntrinsic;
    return getIntrinsicInfo(Ctx, &BadIntrinsic);
  }

  /// Same as above, except IsIntrinsic is true if the function is intrinsic
  /// (even if not a PNaCl intrinsic).
  const Intrinsics::FullIntrinsicInfo *
  getIntrinsicInfo(const GlobalContext *Ctx, bool *IsIntrinsic) const;

private:
  const Ice::FuncSigType Signature;
  llvm::CallingConv::ID CallingConv;
  bool IsProto;

  FunctionDeclaration(const FuncSigType &Signature,
                      llvm::CallingConv::ID CallingConv,
                      llvm::GlobalValue::LinkageTypes Linkage, bool IsProto)
      : GlobalDeclaration(FunctionDeclarationKind, Linkage),
        Signature(Signature), CallingConv(CallingConv), IsProto(IsProto) {}

  bool isPNaClABIExternalName() const {
    const char *Name = getName().c_str();
    return strcmp(Name, "_start") == 0 || strcmp(Name, "__pnacl_pso_root") == 0;
  }

  bool isIntrinsicName(const GlobalContext *Ctx) const {
    bool IsIntrinsic;
    getIntrinsicInfo(Ctx, &IsIntrinsic);
    return IsIntrinsic;
  }

  bool validateRegularTypeSignature() const;

  bool validateIntrinsicTypeSignature(
      const Intrinsics::FullIntrinsicInfo *Info) const;
};

/// Models a global variable declaration, and its initializers.
class VariableDeclaration : public GlobalDeclaration {
  VariableDeclaration(const VariableDeclaration &) = delete;
  VariableDeclaration &operator=(const VariableDeclaration &) = delete;

public:
  /// Base class for a global variable initializer.
  class Initializer {
    Initializer(const Initializer &) = delete;
    Initializer &operator=(const Initializer &) = delete;

  public:
    /// Discriminator for LLVM-style RTTI.
    enum InitializerKind {
      DataInitializerKind,
      ZeroInitializerKind,
      RelocInitializerKind
    };
    InitializerKind getKind() const { return Kind; }
    virtual ~Initializer() = default;
    virtual SizeT getNumBytes() const = 0;
    virtual void dump(GlobalContext *Ctx, Ostream &Stream) const = 0;
    void dump(Ostream &Stream) const {
      if (BuildDefs::dump())
        dump(nullptr, Stream);
    }
    virtual void dumpType(Ostream &Stream) const;

  protected:
    explicit Initializer(InitializerKind Kind) : Kind(Kind) {}

  private:
    const InitializerKind Kind;
  };

  /// Models the data in a data initializer.
  using DataVecType = std::vector<char>;

  /// Defines a sequence of byte values as a data initializer.
  class DataInitializer : public Initializer {
    DataInitializer(const DataInitializer &) = delete;
    DataInitializer &operator=(const DataInitializer &) = delete;

  public:
    template <class... Args>
    static std::unique_ptr<DataInitializer> create(Args &&... TheArgs) {
      return makeUnique<DataInitializer>(std::forward<Args>(TheArgs)...);
    }

    const DataVecType &getContents() const { return Contents; }
    SizeT getNumBytes() const final { return Contents.size(); }
    void dump(GlobalContext *Ctx, Ostream &Stream) const final;
    static bool classof(const Initializer *D) {
      return D->getKind() == DataInitializerKind;
    }

  private:
    ENABLE_MAKE_UNIQUE;

    DataInitializer(const llvm::NaClBitcodeRecord::RecordVector &Values)
        : Initializer(DataInitializerKind), Contents(Values.size()) {
      for (SizeT I = 0; I < Values.size(); ++I)
        Contents[I] = static_cast<int8_t>(Values[I]);
    }

    DataInitializer(const char *Str, size_t StrLen)
        : Initializer(DataInitializerKind), Contents(StrLen) {
      for (size_t i = 0; i < StrLen; ++i)
        Contents[i] = Str[i];
    }

    /// The byte contents of the data initializer.
    DataVecType Contents;
  };

  /// Defines a sequence of bytes initialized to zero.
  class ZeroInitializer : public Initializer {
    ZeroInitializer(const ZeroInitializer &) = delete;
    ZeroInitializer &operator=(const ZeroInitializer &) = delete;

  public:
    static std::unique_ptr<ZeroInitializer> create(SizeT Size) {
      return makeUnique<ZeroInitializer>(Size);
    }
    SizeT getNumBytes() const final { return Size; }
    void dump(GlobalContext *Ctx, Ostream &Stream) const final;
    static bool classof(const Initializer *Z) {
      return Z->getKind() == ZeroInitializerKind;
    }

  private:
    ENABLE_MAKE_UNIQUE;

    explicit ZeroInitializer(SizeT Size)
        : Initializer(ZeroInitializerKind), Size(Size) {}

    /// The number of bytes to be zero initialized.
    SizeT Size;
  };

  /// Defines the relocation value of another global declaration.
  class RelocInitializer : public Initializer {
    RelocInitializer(const RelocInitializer &) = delete;
    RelocInitializer &operator=(const RelocInitializer &) = delete;

  public:
    static std::unique_ptr<RelocInitializer>
    create(const GlobalDeclaration *Declaration,
           const RelocOffsetArray &OffsetExpr) {
      constexpr bool NoFixup = false;
      return makeUnique<RelocInitializer>(Declaration, OffsetExpr, NoFixup);
    }

    static std::unique_ptr<RelocInitializer>
    create(const GlobalDeclaration *Declaration,
           const RelocOffsetArray &OffsetExpr, FixupKind Fixup) {
      constexpr bool HasFixup = true;
      return makeUnique<RelocInitializer>(Declaration, OffsetExpr, HasFixup,
                                          Fixup);
    }

    RelocOffsetT getOffset() const {
      RelocOffsetT Offset = 0;
      for (const auto *RelocOffset : OffsetExpr) {
        Offset += RelocOffset->getOffset();
      }
      return Offset;
    }

    bool hasFixup() const { return HasFixup; }
    FixupKind getFixup() const {
      assert(HasFixup);
      return Fixup;
    }

    const GlobalDeclaration *getDeclaration() const { return Declaration; }
    SizeT getNumBytes() const final { return RelocAddrSize; }
    void dump(GlobalContext *Ctx, Ostream &Stream) const final;
    void dumpType(Ostream &Stream) const final;
    static bool classof(const Initializer *R) {
      return R->getKind() == RelocInitializerKind;
    }

  private:
    ENABLE_MAKE_UNIQUE;

    RelocInitializer(const GlobalDeclaration *Declaration,
                     const RelocOffsetArray &OffsetExpr, bool HasFixup,
                     FixupKind Fixup = 0)
        : Initializer(RelocInitializerKind),
          Declaration(Declaration), // The global declaration used in the reloc.
          OffsetExpr(OffsetExpr), HasFixup(HasFixup), Fixup(Fixup) {}

    const GlobalDeclaration *Declaration;
    /// The offset to add to the relocation.
    const RelocOffsetArray OffsetExpr;
    const bool HasFixup = false;
    const FixupKind Fixup = 0;
  };

  /// Models the list of initializers.
  using InitializerListType = std::vector<std::unique_ptr<Initializer>>;

  static VariableDeclaration *create(GlobalContext *Context) {
    return new (Context->allocate<VariableDeclaration>()) VariableDeclaration();
  }

  const InitializerListType &getInitializers() const { return *Initializers; }
  bool getIsConstant() const { return IsConstant; }
  void setIsConstant(bool NewValue) { IsConstant = NewValue; }
  uint32_t getAlignment() const { return Alignment; }
  void setAlignment(uint32_t NewAlignment) { Alignment = NewAlignment; }
  bool hasInitializer() const { return HasInitializer; }
  bool hasNonzeroInitializer() const {
    return !(Initializers->size() == 1 &&
             llvm::isa<ZeroInitializer>((*Initializers)[0].get()));
  }

  /// Returns the number of bytes for the initializer of the global address.
  SizeT getNumBytes() const {
    SizeT Count = 0;
    for (const std::unique_ptr<Initializer> &Init : *Initializers) {
      Count += Init->getNumBytes();
    }
    return Count;
  }

  /// Adds Initializer to the list of initializers. Takes ownership of the
  /// initializer.
  void addInitializer(std::unique_ptr<Initializer> Initializer) {
    Initializers->emplace_back(std::move(Initializer));
    HasInitializer = true;
  }

  /// Prints out type for initializer associated with the declaration to Stream.
  void dumpType(Ostream &Stream) const final;

  /// Prints out the definition of the global variable declaration (including
  /// initialization).
  void dump(GlobalContext *Ctx, Ostream &Stream) const final;

  /// Returns true if linkage is correct for the variable declaration.
  bool verifyLinkageCorrect(const GlobalContext *Ctx) const {
    return verifyLinkageDefault(Ctx);
  }

  static bool classof(const GlobalDeclaration *Addr) {
    return Addr->getKind() == VariableDeclarationKind;
  }

  bool getSuppressMangling() const final {
    if (ForceSuppressMangling)
      return true;
    return isExternal() && !hasInitializer();
  }

  void setSuppressMangling() { ForceSuppressMangling = true; }

  void discardInitializers() { Initializers = nullptr; }

private:
  /// List of initializers for the declared variable.
  std::unique_ptr<InitializerListType> Initializers;
  bool HasInitializer;
  /// The alignment of the declared variable.
  uint32_t Alignment;
  /// True if a declared (global) constant.
  bool IsConstant;
  /// If set to true, force getSuppressMangling() to return true.
  bool ForceSuppressMangling;

  VariableDeclaration()
      : GlobalDeclaration(VariableDeclarationKind,
                          llvm::GlobalValue::InternalLinkage),
        Initializers(new InitializerListType), HasInitializer(false),
        Alignment(0), IsConstant(false), ForceSuppressMangling(false) {}
};

template <class StreamType>
inline StreamType &operator<<(StreamType &Stream,
                              const VariableDeclaration::Initializer &Init) {
  Init.dump(Stream);
  return Stream;
}

template <class StreamType>
inline StreamType &operator<<(StreamType &Stream,
                              const GlobalDeclaration &Addr) {
  Addr.dump(Stream);
  return Stream;
}

} // end of namespace Ice

#endif // SUBZERO_SRC_ICEGLOBALINITS_H
