//===------ SemaWasm.cpp ---- WebAssembly target-specific routines --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis functions specific to WebAssembly.
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaWasm.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Sema/Attr.h"
#include "clang/Sema/Sema.h"

namespace clang {

SemaWasm::SemaWasm(Sema &S) : SemaBase(S) {}

/// Checks the argument at the given index is a WebAssembly table and if it
/// is, sets ElTy to the element type.
static bool CheckWasmBuiltinArgIsTable(Sema &S, CallExpr *E, unsigned ArgIndex,
                                       QualType &ElTy) {
  Expr *ArgExpr = E->getArg(ArgIndex);
  const auto *ATy = dyn_cast<ArrayType>(ArgExpr->getType());
  if (!ATy || !ATy->getElementType().isWebAssemblyReferenceType()) {
    return S.Diag(ArgExpr->getBeginLoc(),
                  diag::err_wasm_builtin_arg_must_be_table_type)
           << ArgIndex + 1 << ArgExpr->getSourceRange();
  }
  ElTy = ATy->getElementType();
  return false;
}

/// Checks the argument at the given index is an integer.
static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
                                         unsigned ArgIndex) {
  Expr *ArgExpr = E->getArg(ArgIndex);
  if (!ArgExpr->getType()->isIntegerType()) {
    return S.Diag(ArgExpr->getBeginLoc(),
                  diag::err_wasm_builtin_arg_must_be_integer_type)
           << ArgIndex + 1 << ArgExpr->getSourceRange();
  }
  return false;
}

bool SemaWasm::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, /*DesiredArgCount=*/0))
    return true;
  TheCall->setType(getASTContext().getWebAssemblyExternrefType());

  return false;
}

bool SemaWasm::BuiltinWasmRefIsNullExtern(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 1)) {
    return true;
  }

  Expr *ArgExpr = TheCall->getArg(0);
  if (!ArgExpr->getType().isWebAssemblyExternrefType()) {
    SemaRef.Diag(ArgExpr->getBeginLoc(),
                 diag::err_wasm_builtin_arg_must_be_externref_type)
        << 1 << ArgExpr->getSourceRange();
    return true;
  }

  return false;
}

bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
  ASTContext &Context = getASTContext();
  if (SemaRef.checkArgCount(TheCall, /*DesiredArgCount=*/0))
    return true;

  // This custom type checking code ensures that the nodes are as expected
  // in order to later on generate the necessary builtin.
  QualType Pointee = Context.getFunctionType(Context.VoidTy, {}, {});
  QualType Type = Context.getPointerType(Pointee);
  Pointee = Context.getAddrSpaceQualType(Pointee, LangAS::wasm_funcref);
  Type = Context.getAttributedType(attr::WebAssemblyFuncref, Type,
                                   Context.getPointerType(Pointee));
  TheCall->setType(Type);

  return false;
}

/// Check that the first argument is a WebAssembly table, and the second
/// is an index to use as index into the table.
bool SemaWasm::BuiltinWasmTableGet(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 2))
    return true;

  QualType ElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
    return true;

  if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
    return true;

  // If all is well, we set the type of TheCall to be the type of the
  // element of the table.
  // i.e. a table.get on an externref table has type externref,
  // or whatever the type of the table element is.
  TheCall->setType(ElTy);

  return false;
}

/// Check that the first argumnet is a WebAssembly table, the second is
/// an index to use as index into the table and the third is the reference
/// type to set into the table.
bool SemaWasm::BuiltinWasmTableSet(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 3))
    return true;

  QualType ElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
    return true;

  if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
    return true;

  if (!getASTContext().hasSameType(ElTy, TheCall->getArg(2)->getType()))
    return true;

  return false;
}

/// Check that the argument is a WebAssembly table.
bool SemaWasm::BuiltinWasmTableSize(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 1))
    return true;

  QualType ElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
    return true;

  return false;
}

/// Check that the first argument is a WebAssembly table, the second is the
/// value to use for new elements (of a type matching the table type), the
/// third value is an integer.
bool SemaWasm::BuiltinWasmTableGrow(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 3))
    return true;

  QualType ElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
    return true;

  Expr *NewElemArg = TheCall->getArg(1);
  if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
    return Diag(NewElemArg->getBeginLoc(),
                diag::err_wasm_builtin_arg_must_match_table_element_type)
           << 2 << 1 << NewElemArg->getSourceRange();
  }

  if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 2))
    return true;

  return false;
}

/// Check that the first argument is a WebAssembly table, the second is an
/// integer, the third is the value to use to fill the table (of a type
/// matching the table type), and the fourth is an integer.
bool SemaWasm::BuiltinWasmTableFill(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 4))
    return true;

  QualType ElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
    return true;

  if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
    return true;

  Expr *NewElemArg = TheCall->getArg(2);
  if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
    return Diag(NewElemArg->getBeginLoc(),
                diag::err_wasm_builtin_arg_must_match_table_element_type)
           << 3 << 1 << NewElemArg->getSourceRange();
  }

  if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 3))
    return true;

  return false;
}

/// Check that the first argument is a WebAssembly table, the second is also a
/// WebAssembly table (of the same element type), and the third to fifth
/// arguments are integers.
bool SemaWasm::BuiltinWasmTableCopy(CallExpr *TheCall) {
  if (SemaRef.checkArgCount(TheCall, 5))
    return true;

  QualType XElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, XElTy))
    return true;

  QualType YElTy;
  if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 1, YElTy))
    return true;

  Expr *TableYArg = TheCall->getArg(1);
  if (!getASTContext().hasSameType(XElTy, YElTy)) {
    return Diag(TableYArg->getBeginLoc(),
                diag::err_wasm_builtin_arg_must_match_table_element_type)
           << 2 << 1 << TableYArg->getSourceRange();
  }

  for (int I = 2; I <= 4; I++) {
    if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, I))
      return true;
  }

  return false;
}

bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
                                                   unsigned BuiltinID,
                                                   CallExpr *TheCall) {
  switch (BuiltinID) {
  case WebAssembly::BI__builtin_wasm_ref_null_extern:
    return BuiltinWasmRefNullExtern(TheCall);
  case WebAssembly::BI__builtin_wasm_ref_null_func:
    return BuiltinWasmRefNullFunc(TheCall);
  case WebAssembly::BI__builtin_wasm_ref_is_null_extern:
    return BuiltinWasmRefIsNullExtern(TheCall);
  case WebAssembly::BI__builtin_wasm_table_get:
    return BuiltinWasmTableGet(TheCall);
  case WebAssembly::BI__builtin_wasm_table_set:
    return BuiltinWasmTableSet(TheCall);
  case WebAssembly::BI__builtin_wasm_table_size:
    return BuiltinWasmTableSize(TheCall);
  case WebAssembly::BI__builtin_wasm_table_grow:
    return BuiltinWasmTableGrow(TheCall);
  case WebAssembly::BI__builtin_wasm_table_fill:
    return BuiltinWasmTableFill(TheCall);
  case WebAssembly::BI__builtin_wasm_table_copy:
    return BuiltinWasmTableCopy(TheCall);
  }

  return false;
}

WebAssemblyImportModuleAttr *
SemaWasm::mergeImportModuleAttr(Decl *D,
                                const WebAssemblyImportModuleAttr &AL) {
  auto *FD = cast<FunctionDecl>(D);

  if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
    if (ExistingAttr->getImportModule() == AL.getImportModule())
      return nullptr;
    Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
        << 0 << ExistingAttr->getImportModule() << AL.getImportModule();
    Diag(AL.getLoc(), diag::note_previous_attribute);
    return nullptr;
  }
  if (FD->hasBody()) {
    Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
    return nullptr;
  }
  return ::new (getASTContext())
      WebAssemblyImportModuleAttr(getASTContext(), AL, AL.getImportModule());
}

WebAssemblyImportNameAttr *
SemaWasm::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) {
  auto *FD = cast<FunctionDecl>(D);

  if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) {
    if (ExistingAttr->getImportName() == AL.getImportName())
      return nullptr;
    Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
        << 1 << ExistingAttr->getImportName() << AL.getImportName();
    Diag(AL.getLoc(), diag::note_previous_attribute);
    return nullptr;
  }
  if (FD->hasBody()) {
    Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
    return nullptr;
  }
  return ::new (getASTContext())
      WebAssemblyImportNameAttr(getASTContext(), AL, AL.getImportName());
}

void SemaWasm::handleWebAssemblyImportModuleAttr(Decl *D,
                                                 const ParsedAttr &AL) {
  auto *FD = cast<FunctionDecl>(D);

  StringRef Str;
  SourceLocation ArgLoc;
  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
    return;
  if (FD->hasBody()) {
    Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
    return;
  }

  FD->addAttr(::new (getASTContext())
                  WebAssemblyImportModuleAttr(getASTContext(), AL, Str));
}

void SemaWasm::handleWebAssemblyImportNameAttr(Decl *D, const ParsedAttr &AL) {
  auto *FD = cast<FunctionDecl>(D);

  StringRef Str;
  SourceLocation ArgLoc;
  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
    return;
  if (FD->hasBody()) {
    Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
    return;
  }

  FD->addAttr(::new (getASTContext())
                  WebAssemblyImportNameAttr(getASTContext(), AL, Str));
}

void SemaWasm::handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL) {
  ASTContext &Context = getASTContext();
  if (!isFuncOrMethodForAttrSubject(D)) {
    Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
        << AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
    return;
  }

  auto *FD = cast<FunctionDecl>(D);
  if (FD->isThisDeclarationADefinition()) {
    Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
    return;
  }

  StringRef Str;
  SourceLocation ArgLoc;
  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
    return;

  D->addAttr(::new (Context) WebAssemblyExportNameAttr(Context, AL, Str));
  D->addAttr(UsedAttr::CreateImplicit(Context));
}

} // namespace clang
