/*
 * Copyright 2015, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "slang_rs_foreach_lowering.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "llvm/Support/raw_ostream.h"
#include "slang_rs_context.h"
#include "slang_rs_export_foreach.h"

namespace slang {

namespace {

const char KERNEL_LAUNCH_FUNCTION_NAME[] = "rsForEach";
const char KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS[] = "rsForEachWithOptions";
const char INTERNAL_LAUNCH_FUNCTION_NAME[] =
    "_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation";

}  // anonymous namespace

RSForEachLowering::RSForEachLowering(RSContext* ctxt)
    : mCtxt(ctxt), mASTCtxt(ctxt->getASTContext()) {}

// Check if the passed-in expr references a kernel function in the following
// pattern in the AST.
//
// ImplicitCastExpr 'void *' <BitCast>
//  `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
//    `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
const clang::FunctionDecl* RSForEachLowering::matchFunctionDesignator(
    clang::Expr* expr) {
  clang::ImplicitCastExpr* ToVoidPtr =
      clang::dyn_cast<clang::ImplicitCastExpr>(expr);
  if (ToVoidPtr == nullptr) {
    return nullptr;
  }

  clang::ImplicitCastExpr* Decay =
      clang::dyn_cast<clang::ImplicitCastExpr>(ToVoidPtr->getSubExpr());

  if (Decay == nullptr) {
    return nullptr;
  }

  clang::DeclRefExpr* DRE =
      clang::dyn_cast<clang::DeclRefExpr>(Decay->getSubExpr());

  if (DRE == nullptr) {
    return nullptr;
  }

  const clang::FunctionDecl* FD =
      clang::dyn_cast<clang::FunctionDecl>(DRE->getDecl());

  if (FD == nullptr) {
    return nullptr;
  }

  return FD;
}

// Checks if the call expression is a legal rsForEach call by looking for the
// following pattern in the AST. On success, returns the first argument that is
// a FunctionDecl of a kernel function.
//
// CallExpr 'void'
// |
// |-ImplicitCastExpr 'void (*)(void *, ...)' <FunctionToPointerDecay>
// | `-DeclRefExpr  'void (void *, ...)'  'rsForEach' 'void (void *, ...)'
// |
// |-ImplicitCastExpr 'void *' <BitCast>
// | `-ImplicitCastExpr 'int (*)(int)' <FunctionToPointerDecay>
// |   `-DeclRefExpr 'int (int)' Function 'foo' 'int (int)'
// |
// |-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
// | `-DeclRefExpr 'rs_allocation':'rs_allocation' lvalue ParmVar 'in' 'rs_allocation':'rs_allocation'
// |
// `-ImplicitCastExpr 'rs_allocation':'rs_allocation' <LValueToRValue>
//   `-DeclRefExpr  'rs_allocation':'rs_allocation' lvalue ParmVar 'out' 'rs_allocation':'rs_allocation'
const clang::FunctionDecl* RSForEachLowering::matchKernelLaunchCall(
    clang::CallExpr* CE, int* slot, bool* hasOptions) {
  const clang::Decl* D = CE->getCalleeDecl();
  const clang::FunctionDecl* FD = clang::dyn_cast<clang::FunctionDecl>(D);

  if (FD == nullptr) {
    return nullptr;
  }

  const clang::StringRef& funcName = FD->getName();

  if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME)) {
    *hasOptions = false;
  } else if (funcName.equals(KERNEL_LAUNCH_FUNCTION_NAME_WITH_OPTIONS)) {
    *hasOptions = true;
  } else {
    return nullptr;
  }

  if (mInsideKernel) {
    mCtxt->ReportError(CE->getExprLoc(),
        "Invalid kernel launch call made from inside another kernel.");
    return nullptr;
  }

  clang::Expr* arg0 = CE->getArg(0);
  const clang::FunctionDecl* kernel = matchFunctionDesignator(arg0);

  if (kernel == nullptr) {
    mCtxt->ReportError(arg0->getExprLoc(),
                       "Invalid kernel launch call. "
                       "Expects a function designator for the first argument.");
    return nullptr;
  }

  // Verifies that kernel is indeed a "kernel" function.
  *slot = mCtxt->getForEachSlotNumber(kernel);
  if (*slot == -1) {
    mCtxt->ReportError(CE->getExprLoc(),
         "%0 applied to function %1 defined without \"kernel\" attribute")
         << funcName << kernel->getName();
    return nullptr;
  }

  return kernel;
}

// Create an AST node for the declaration of rsForEachInternal
clang::FunctionDecl* RSForEachLowering::CreateForEachInternalFunctionDecl() {
  clang::DeclContext* DC = mASTCtxt.getTranslationUnitDecl();
  clang::SourceLocation Loc;

  llvm::StringRef SR(INTERNAL_LAUNCH_FUNCTION_NAME);
  clang::IdentifierInfo& II = mASTCtxt.Idents.get(SR);
  clang::DeclarationName N(&II);

  clang::FunctionProtoType::ExtProtoInfo EPI;

  const clang::QualType& AllocTy = mCtxt->getAllocationType();
  clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);

  clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
  const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);

  clang::QualType ParamTypes[] = {
    mASTCtxt.IntTy,   // int slot
    ScriptCallPtrTy,  // rs_script_call_t* launch_options
    mASTCtxt.IntTy,   // int numOutput
    mASTCtxt.IntTy,   // int numInputs
    AllocPtrTy        // rs_allocation* allocs
  };

  clang::QualType T = mASTCtxt.getFunctionType(
      mASTCtxt.VoidTy,  // Return type
      ParamTypes,       // Parameter types
      EPI);

  clang::FunctionDecl* FD = clang::FunctionDecl::Create(
      mASTCtxt, DC, Loc, Loc, N, T, nullptr, clang::SC_Extern);

  static constexpr unsigned kNumParams = sizeof(ParamTypes) / sizeof(ParamTypes[0]);
  clang::ParmVarDecl *ParamDecls[kNumParams];
  for (unsigned I = 0; I != kNumParams; ++I) {
    ParamDecls[I] = clang::ParmVarDecl::Create(mASTCtxt, FD, Loc,
        Loc, nullptr, ParamTypes[I], nullptr, clang::SC_None, nullptr);
    // Implicit means that this declaration was created by the compiler, and
    // not part of the actual source code.
    ParamDecls[I]->setImplicit();
  }
  FD->setParams(llvm::makeArrayRef(ParamDecls, kNumParams));

  // Implicit means that this declaration was created by the compiler, and
  // not part of the actual source code.
  FD->setImplicit();

  return FD;
}

// Create an expression like the following that references the rsForEachInternal to
// replace the callee in the original call expression that references rsForEach.
//
// ImplicitCastExpr 'void (*)(int, rs_script_call_t*, int, int, rs_allocation*)' <FunctionToPointerDecay>
// `-DeclRefExpr 'void' Function '_Z17rsForEachInternaliP14rs_script_calliiP13rs_allocation' 'void (int, rs_script_call_t*, int, int, rs_allocation*)'
clang::Expr* RSForEachLowering::CreateCalleeExprForInternalForEach() {
  clang::FunctionDecl* FDNew = CreateForEachInternalFunctionDecl();

  const clang::QualType FDNewType = FDNew->getType();

  clang::DeclRefExpr* refExpr = clang::DeclRefExpr::Create(
      mASTCtxt, clang::NestedNameSpecifierLoc(), clang::SourceLocation(), FDNew,
      false, clang::SourceLocation(), FDNewType, clang::VK_RValue);

  clang::Expr* calleeNew = clang::ImplicitCastExpr::Create(
      mASTCtxt, mASTCtxt.getPointerType(FDNewType),
      clang::CK_FunctionToPointerDecay, refExpr, nullptr, clang::VK_RValue);

  return calleeNew;
}

// This visit method checks (via pattern matching) if the call expression is to
// rsForEach, and the arguments satisfy the restrictions on the
// rsForEach API. If so, replace the call with a rsForEachInternal call
// with the first argument replaced by the slot number of the kernel function
// referenced in the original first argument.
//
// See comments to the helper methods defined above for details.
void RSForEachLowering::VisitCallExpr(clang::CallExpr* CE) {
  int slot;
  bool hasOptions;
  const clang::FunctionDecl* kernel = matchKernelLaunchCall(CE, &slot, &hasOptions);
  if (kernel == nullptr) {
    return;
  }

  slangAssert(slot >= 0);

  const unsigned numArgsOrig = CE->getNumArgs();

  clang::QualType resultType = kernel->getReturnType().getCanonicalType();
  const unsigned numOutputsExpected = resultType->isVoidType() ? 0 : 1;

  const unsigned numInputsExpected = RSExportForEach::getNumInputs(mCtxt->getTargetAPI(), kernel);

  // Verifies that rsForEach takes the right number of input and output allocations.
  // TODO: Check input/output allocation types match kernel function expectation.
  const unsigned numAllocations = numArgsOrig - (hasOptions ? 2 : 1);
  if (numInputsExpected + numOutputsExpected != numAllocations) {
    mCtxt->ReportError(
      CE->getExprLoc(),
      "Number of input and output allocations unexpected for kernel function %0")
    << kernel->getName();
    return;
  }

  clang::Expr* calleeNew = CreateCalleeExprForInternalForEach();
  CE->setCallee(calleeNew);

  const clang::CanQualType IntTy = mASTCtxt.IntTy;
  const unsigned IntTySize = mASTCtxt.getTypeSize(IntTy);
  const llvm::APInt APIntSlot(IntTySize, slot);
  const clang::Expr* arg0 = CE->getArg(0);
  const clang::SourceLocation Loc(arg0->getLocStart());
  clang::Expr* IntSlotNum =
      clang::IntegerLiteral::Create(mASTCtxt, APIntSlot, IntTy, Loc);
  CE->setArg(0, IntSlotNum);

  /*
    The last few arguments to rsForEach or rsForEachWithOptions are allocations.
    Creates a new compound literal of an array initialized with those values, and
    passes it to rsForEachInternal as the last (the 5th) argument.

    For example, rsForEach(foo, ain1, ain2, aout) would be translated into
    rsForEachInternal(
        1,                                   // Slot number for kernel
        NULL,                                // Launch options
        2,                                   // Number of input allocations
        1,                                   // Number of output allocations
        (rs_allocation[]){ain1, ain2, aout)  // Input and output allocations
    );

    The AST for the rs_allocation array looks like following:

    ImplicitCastExpr 0x99575670 'struct rs_allocation *' <ArrayToPointerDecay>
    `-CompoundLiteralExpr 0x99575648 'struct rs_allocation [3]' lvalue
      `-InitListExpr 0x99575590 'struct rs_allocation [3]'
      |-ImplicitCastExpr 0x99574b38 'rs_allocation':'struct rs_allocation' <LValueToRValue>
      | `-DeclRefExpr 0x99574a08 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c408 'ain1' 'rs_allocation':'struct rs_allocation'
      |-ImplicitCastExpr 0x99574b50 'rs_allocation':'struct rs_allocation' <LValueToRValue>
      | `-DeclRefExpr 0x99574a30 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'ain2' 'rs_allocation':'struct rs_allocation'
      `-ImplicitCastExpr 0x99574b68 'rs_allocation':'struct rs_allocation' <LValueToRValue>
        `-DeclRefExpr 0x99574a58 'rs_allocation':'struct rs_allocation' lvalue ParmVar 0x9942c478 'aout' 'rs_allocation':'struct rs_allocation'
  */

  const clang::QualType& AllocTy = mCtxt->getAllocationType();
  const llvm::APInt APIntNumAllocs(IntTySize, numAllocations);
  clang::QualType AllocArrayTy = mASTCtxt.getConstantArrayType(
      AllocTy,
      APIntNumAllocs,
      clang::ArrayType::ArraySizeModifier::Normal,
      0  // index type qualifiers
  );

  const int allocArgIndexEnd = numArgsOrig - 1;
  int allocArgIndexStart = allocArgIndexEnd;

  clang::Expr** args = CE->getArgs();

  clang::SourceLocation lparenloc;
  clang::SourceLocation rparenloc;

  if (numAllocations > 0) {
    allocArgIndexStart = hasOptions ? 2 : 1;
    lparenloc = args[allocArgIndexStart]->getExprLoc();
    rparenloc = args[allocArgIndexEnd]->getExprLoc();
  }

  clang::InitListExpr* init = new (mASTCtxt) clang::InitListExpr(
      mASTCtxt,
      lparenloc,
      llvm::ArrayRef<clang::Expr*>(args + allocArgIndexStart, numAllocations),
      rparenloc);
  init->setType(AllocArrayTy);

  clang::TypeSourceInfo* ti = mASTCtxt.getTrivialTypeSourceInfo(AllocArrayTy);
  clang::CompoundLiteralExpr* CLE = new (mASTCtxt) clang::CompoundLiteralExpr(
      lparenloc,
      ti,
      AllocArrayTy,
      clang::VK_LValue,  // A compound literal is an l-value in C.
      init,
      false  // Not file scope
  );

  const clang::QualType AllocPtrTy = mASTCtxt.getPointerType(AllocTy);

  clang::ImplicitCastExpr* Decay = clang::ImplicitCastExpr::Create(
      mASTCtxt,
      AllocPtrTy,
      clang::CK_ArrayToPointerDecay,
      CLE,
      nullptr,  // C++ cast path
      clang::VK_RValue
  );

  CE->setNumArgs(mASTCtxt, 5);

  CE->setArg(4, Decay);

  // Sets the new arguments for NULL launch option (if the user does not set one),
  // the number of outputs, and the number of inputs.

  if (!hasOptions) {
    const llvm::APInt APIntZero(IntTySize, 0);
    clang::Expr* IntNull =
        clang::IntegerLiteral::Create(mASTCtxt, APIntZero, IntTy, Loc);
    clang::QualType ScriptCallTy = mCtxt->getScriptCallType();
    const clang::QualType ScriptCallPtrTy = mASTCtxt.getPointerType(ScriptCallTy);
    clang::CStyleCastExpr* Cast =
        clang::CStyleCastExpr::Create(mASTCtxt,
                                      ScriptCallPtrTy,
                                      clang::VK_RValue,
                                      clang::CK_NullToPointer,
                                      IntNull,
                                      nullptr,
                                      mASTCtxt.getTrivialTypeSourceInfo(ScriptCallPtrTy),
                                      clang::SourceLocation(),
                                      clang::SourceLocation());
    CE->setArg(1, Cast);
  }

  const llvm::APInt APIntNumOutput(IntTySize, numOutputsExpected);
  clang::Expr* IntNumOutput =
      clang::IntegerLiteral::Create(mASTCtxt, APIntNumOutput, IntTy, Loc);
  CE->setArg(2, IntNumOutput);

  const llvm::APInt APIntNumInputs(IntTySize, numInputsExpected);
  clang::Expr* IntNumInputs =
      clang::IntegerLiteral::Create(mASTCtxt, APIntNumInputs, IntTy, Loc);
  CE->setArg(3, IntNumInputs);
}

void RSForEachLowering::VisitStmt(clang::Stmt* S) {
  for (clang::Stmt* Child : S->children()) {
    if (Child) {
      Visit(Child);
    }
  }
}

void RSForEachLowering::handleForEachCalls(clang::FunctionDecl* FD,
                                           unsigned int targetAPI) {
  slangAssert(FD && FD->hasBody());

  mInsideKernel = FD->hasAttr<clang::KernelAttr>();
  VisitStmt(FD->getBody());
}

}  // namespace slang
