//===--- SIMDIntrinsicsCheck.cpp - clang-tidy------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "SIMDIntrinsicsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Regex.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace portability {

namespace {

// If the callee has parameter of VectorType or pointer to VectorType,
// or the return type is VectorType, we consider it a vector function
// and a candidate for checking.
AST_MATCHER(FunctionDecl, isVectorFunction) {
  bool IsVector = Node.getReturnType()->isVectorType();
  for (const ParmVarDecl *Parm : Node.parameters()) {
    QualType Type = Parm->getType();
    if (Type->isPointerType())
      Type = Type->getPointeeType();
    if (Type->isVectorType())
      IsVector = true;
  }
  return IsVector;
}

} // namespace

static StringRef TrySuggestPPC(StringRef Name) {
  if (!Name.consume_front("vec_"))
    return {};

  static const llvm::StringMap<StringRef> Mapping{
    // [simd.alg]
    {"max", "$std::max"},
    {"min", "$std::min"},

    // [simd.binary]
    {"add", "operator+ on $simd objects"},
    {"sub", "operator- on $simd objects"},
    {"mul", "operator* on $simd objects"},
  };

  auto It = Mapping.find(Name);
  if (It != Mapping.end())
    return It->second;
  return {};
}

static StringRef TrySuggestX86(StringRef Name) {
  if (!(Name.consume_front("_mm_") || Name.consume_front("_mm256_") ||
        Name.consume_front("_mm512_")))
    return {};

  // [simd.alg]
  if (Name.startswith("max_"))
    return "$simd::max";
  if (Name.startswith("min_"))
    return "$simd::min";

  // [simd.binary]
  if (Name.startswith("add_"))
    return "operator+ on $simd objects";
  if (Name.startswith("sub_"))
    return "operator- on $simd objects";
  if (Name.startswith("mul_"))
    return "operator* on $simd objects";

  return {};
}

SIMDIntrinsicsCheck::SIMDIntrinsicsCheck(StringRef Name,
                                         ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context), Std(Options.get("Std", "")),
      Suggest(Options.get("Suggest", 0) != 0) {}

void SIMDIntrinsicsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "Std", "");
  Options.store(Opts, "Suggest", 0);
}

void SIMDIntrinsicsCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus11)
    return;
  // If Std is not specified, infer it from the language options.
  // libcxx implementation backports it to C++11 std::experimental::simd.
  if (Std.empty())
    Std = getLangOpts().CPlusPlus2a ? "std" : "std::experimental";

  Finder->addMatcher(callExpr(callee(functionDecl(
                                  matchesName("^::(_mm_|_mm256_|_mm512_|vec_)"),
                                  isVectorFunction())),
                              unless(isExpansionInSystemHeader()))
                         .bind("call"),
                     this);
}

void SIMDIntrinsicsCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
  assert(Call != nullptr);
  const FunctionDecl *Callee = Call->getDirectCallee();
  if (!Callee)
    return;

  StringRef Old = Callee->getName();
  StringRef New;
  llvm::Triple::ArchType Arch =
      Result.Context->getTargetInfo().getTriple().getArch();

  // We warn or suggest if this SIMD intrinsic function has a std::simd
  // replacement.
  switch (Arch) {
  default:
    break;
  case llvm::Triple::ppc:
  case llvm::Triple::ppc64:
  case llvm::Triple::ppc64le:
    New = TrySuggestPPC(Old);
    break;
  case llvm::Triple::x86:
  case llvm::Triple::x86_64:
    New = TrySuggestX86(Old);
    break;
  }

  // We have found a std::simd replacement.
  if (!New.empty()) {
    std::string Message;
    // If Suggest is true, give a P0214 alternative, otherwise point it out it
    // is non-portable.
    if (Suggest) {
      Message = (Twine("'") + Old + "' can be replaced by " + New).str();
      Message = llvm::Regex("\\$std").sub(Std, Message);
      Message =
          llvm::Regex("\\$simd").sub((Std.str() + "::simd").str(), Message);
    } else {
      Message = (Twine("'") + Old + "' is a non-portable " +
                 llvm::Triple::getArchTypeName(Arch) + " intrinsic function")
                    .str();
    }
    diag(Call->getExprLoc(), Message);
  }
}

} // namespace portability
} // namespace tidy
} // namespace clang
