// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 "util/tuple-row-compare.h"

#include <gutil/strings/substitute.h>

#include "codegen/codegen-anyval.h"
#include "codegen/llvm-codegen.h"
#include "exprs/scalar-expr.h"
#include "exprs/scalar-expr-evaluator.h"
#include "runtime/runtime-state.h"
#include "util/runtime-profile-counters.h"

using namespace impala;
using namespace strings;

Status TupleRowComparator::Open(ObjectPool* pool, RuntimeState* state,
    MemPool* expr_perm_pool, MemPool* expr_results_pool) {
  if (ordering_expr_evals_lhs_.empty()) {
    RETURN_IF_ERROR(ScalarExprEvaluator::Create(ordering_exprs_, state, pool,
        expr_perm_pool, expr_results_pool, &ordering_expr_evals_lhs_));
    RETURN_IF_ERROR(ScalarExprEvaluator::Open(ordering_expr_evals_lhs_, state));
  }
  DCHECK_EQ(ordering_exprs_.size(), ordering_expr_evals_lhs_.size());
  if (ordering_expr_evals_rhs_.empty()) {
    RETURN_IF_ERROR(ScalarExprEvaluator::Clone(pool, state, expr_perm_pool,
        expr_results_pool, ordering_expr_evals_lhs_, &ordering_expr_evals_rhs_));
  }
  DCHECK_EQ(ordering_expr_evals_lhs_.size(), ordering_expr_evals_rhs_.size());
  return Status::OK();
}

void TupleRowComparator::Close(RuntimeState* state) {
  ScalarExprEvaluator::Close(ordering_expr_evals_rhs_, state);
  ScalarExprEvaluator::Close(ordering_expr_evals_lhs_, state);
}

int TupleRowComparator::CompareInterpreted(
    const TupleRow* lhs, const TupleRow* rhs) const {
  DCHECK_EQ(ordering_exprs_.size(), ordering_expr_evals_lhs_.size());
  DCHECK_EQ(ordering_expr_evals_lhs_.size(), ordering_expr_evals_rhs_.size());
  for (int i = 0; i < ordering_expr_evals_lhs_.size(); ++i) {
    void* lhs_value = ordering_expr_evals_lhs_[i]->GetValue(lhs);
    void* rhs_value = ordering_expr_evals_rhs_[i]->GetValue(rhs);

    // The sort order of NULLs is independent of asc/desc.
    if (lhs_value == NULL && rhs_value == NULL) continue;
    if (lhs_value == NULL && rhs_value != NULL) return nulls_first_[i];
    if (lhs_value != NULL && rhs_value == NULL) return -nulls_first_[i];

    int result = RawValue::Compare(lhs_value, rhs_value, ordering_exprs_[i]->type());
    if (!is_asc_[i]) result = -result;
    if (result != 0) return result;
    // Otherwise, try the next Expr
  }
  return 0; // fully equivalent key
}

Status TupleRowComparator::Codegen(RuntimeState* state) {
  llvm::Function* fn;
  LlvmCodeGen* codegen = state->codegen();
  DCHECK(codegen != NULL);
  RETURN_IF_ERROR(CodegenCompare(codegen, &fn));
  codegend_compare_fn_ = state->obj_pool()->Add(new CompareFn);
  codegen->AddFunctionToJit(fn, reinterpret_cast<void**>(codegend_compare_fn_));
  return Status::OK();
}

// Codegens an unrolled version of Compare(). Uses codegen'd key exprs and injects
// nulls_first_ and is_asc_ values.
//
// Example IR for comparing an int column then a float column:
//
// ; Function Attrs: alwaysinline
// define i32 @Compare(%"class.impala::ScalarExprEvaluator"**
//                         %ordering_expr_evals_lhs,
//                     %"class.impala::ScalarExprEvaluator"**
//                         %ordering_expr_evals_rhs,
//                     %"class.impala::TupleRow"* %lhs,
//                     %"class.impala::TupleRow"* %rhs) #20 {
// entry:
//   %type13 = alloca %"struct.impala::ColumnType"
//   %0 = alloca float
//   %1 = alloca float
//   %type = alloca %"struct.impala::ColumnType"
//   %2 = alloca i32
//   %3 = alloca i32
//   %4 = getelementptr %"class.impala::ScalarExprEvaluator"**
//            %ordering_expr_evals_lhs, i32 0
//   %5 = load %"class.impala::ScalarExprEvaluator"** %4
//   %lhs_value = call i64 @GetSlotRef(
//       %"class.impala::ScalarExprEvaluator"* %5, %"class.impala::TupleRow"* %lhs)
//   %6 = getelementptr %"class.impala::ScalarExprEvaluator"**
//            %ordering_expr_evals_rhs, i32 0
//   %7 = load %"class.impala::ScalarExprEvaluator"** %6
//   %rhs_value = call i64 @GetSlotRef(
//       %"class.impala::ScalarExprEvaluator"* %7, %"class.impala::TupleRow"* %rhs)
//   %is_null = trunc i64 %lhs_value to i1
//   %is_null1 = trunc i64 %rhs_value to i1
//   %both_null = and i1 %is_null, %is_null1
//   br i1 %both_null, label %next_key, label %non_null
//
// non_null:                                         ; preds = %entry
//   br i1 %is_null, label %lhs_null, label %lhs_non_null
//
// lhs_null:                                         ; preds = %non_null
//   ret i32 1
//
// lhs_non_null:                                     ; preds = %non_null
//   br i1 %is_null1, label %rhs_null, label %rhs_non_null
//
// rhs_null:                                         ; preds = %lhs_non_null
//   ret i32 -1
//
// rhs_non_null:                                     ; preds = %lhs_non_null
//   %8 = ashr i64 %lhs_value, 32
//   %9 = trunc i64 %8 to i32
//   store i32 %9, i32* %3
//   %10 = bitcast i32* %3 to i8*
//   %11 = ashr i64 %rhs_value, 32
//   %12 = trunc i64 %11 to i32
//   store i32 %12, i32* %2
//   %13 = bitcast i32* %2 to i8*
//   store %"struct.impala::ColumnType" { i32 5, i32 -1, i32 -1, i32 -1,
//                                        %"class.std::vector.44" zeroinitializer,
//                                        %"class.std::vector.49" zeroinitializer },
//         %"struct.impala::ColumnType"* %type
//   %result = call i32 @_ZN6impala8RawValue7CompareEPKvS2_RKNS_10ColumnTypeE(
//       i8* %10, i8* %13, %"struct.impala::ColumnType"* %type)
//   %14 = icmp ne i32 %result, 0
//   br i1 %14, label %result_nonzero, label %next_key
//
// result_nonzero:                                   ; preds = %rhs_non_null
//   ret i32 %result
//
// next_key:                                         ; preds = %rhs_non_null, %entry
//   %15 = getelementptr %"class.impala::ScalarExprEvaluator"**
//             %ordering_expr_evals_lhs, i32 1
//   %16 = load %"class.impala::ScalarExprEvaluator"** %15
//   %lhs_value3 = call i64 @GetSlotRef1(
//       %"class.impala::ScalarExprEvaluator"* %16, %"class.impala::TupleRow"* %lhs)
//   %17 = getelementptr %"class.impala::ScalarExprEvaluator"**
//            %ordering_expr_evals_rhs, i32 1
//   %18 = load %"class.impala::ScalarExprEvaluator"** %17
//   %rhs_value4 = call i64 @GetSlotRef1(
//       %"class.impala::ScalarExprEvaluator"* %18, %"class.impala::TupleRow"* %rhs)
//   %is_null5 = trunc i64 %lhs_value3 to i1
//   %is_null6 = trunc i64 %rhs_value4 to i1
//   %both_null8 = and i1 %is_null5, %is_null6
//   br i1 %both_null8, label %next_key2, label %non_null7
//
// non_null7:                                        ; preds = %next_key
//   br i1 %is_null5, label %lhs_null9, label %lhs_non_null10
//
// lhs_null9:                                        ; preds = %non_null7
//   ret i32 1
//
// lhs_non_null10:                                   ; preds = %non_null7
//   br i1 %is_null6, label %rhs_null11, label %rhs_non_null12
//
// rhs_null11:                                       ; preds = %lhs_non_null10
//   ret i32 -1
//
// rhs_non_null12:                                   ; preds = %lhs_non_null10
//   %19 = ashr i64 %lhs_value3, 32
//   %20 = trunc i64 %19 to i32
//   %21 = bitcast i32 %20 to float
//   store float %21, float* %1
//   %22 = bitcast float* %1 to i8*
//   %23 = ashr i64 %rhs_value4, 32
//   %24 = trunc i64 %23 to i32
//   %25 = bitcast i32 %24 to float
//   store float %25, float* %0
//   %26 = bitcast float* %0 to i8*
//   store %"struct.impala::ColumnType" { i32 7, i32 -1, i32 -1, i32 -1,
//                                        %"class.std::vector.44" zeroinitializer,
//                                        %"class.std::vector.49" zeroinitializer },
//         %"struct.impala::ColumnType"* %type13
//   %result14 = call i32 @_ZN6impala8RawValue7CompareEPKvS2_RKNS_10ColumnTypeE(
//       i8* %22, i8* %26, %"struct.impala::ColumnType"* %type13)
//   %27 = icmp ne i32 %result14, 0
//   br i1 %27, label %result_nonzero15, label %next_key2
//
// result_nonzero15:                                 ; preds = %rhs_non_null12
//   ret i32 %result14
//
// next_key2:                                        ; preds = %rhs_non_null12, %next_key
//   ret i32 0
// }
Status TupleRowComparator::CodegenCompare(LlvmCodeGen* codegen, llvm::Function** fn) {
  llvm::LLVMContext& context = codegen->context();
  const vector<ScalarExpr*>& ordering_exprs = ordering_exprs_;
  llvm::Function* key_fns[ordering_exprs.size()];
  for (int i = 0; i < ordering_exprs.size(); ++i) {
    Status status = ordering_exprs[i]->GetCodegendComputeFn(codegen, false, &key_fns[i]);
    if (!status.ok()) {
      return Status::Expected(Substitute(
            "Could not codegen TupleRowComparator::Compare(): $0", status.GetDetail()));
    }
  }

  // Construct function signature (note that this is different than the interpreted
  // Compare() function signature):
  // int Compare(ScalarExprEvaluator** ordering_expr_evals_lhs,
  //     ScalarExprEvaluator** ordering_expr_evals_rhs,
  //     TupleRow* lhs, TupleRow* rhs)
  llvm::PointerType* expr_evals_type =
      codegen->GetStructPtrPtrType<ScalarExprEvaluator>();
  llvm::PointerType* tuple_row_type = codegen->GetStructPtrType<TupleRow>();
  LlvmCodeGen::FnPrototype prototype(codegen, "Compare", codegen->i32_type());
  prototype.AddArgument("ordering_expr_evals_lhs", expr_evals_type);
  prototype.AddArgument("ordering_expr_evals_rhs", expr_evals_type);
  prototype.AddArgument("lhs", tuple_row_type);
  prototype.AddArgument("rhs", tuple_row_type);

  LlvmBuilder builder(context);
  llvm::Value* args[4];
  *fn = prototype.GeneratePrototype(&builder, args);
  llvm::Value* lhs_evals_arg = args[0];
  llvm::Value* rhs_evals_arg = args[1];
  llvm::Value* lhs_arg = args[2];
  llvm::Value* rhs_arg = args[3];

  // Unrolled loop over each key expr
  for (int i = 0; i < ordering_exprs.size(); ++i) {
    // The start of the next key expr after this one. Used to implement "continue" logic
    // in the unrolled loop.
    llvm::BasicBlock* next_key_block = llvm::BasicBlock::Create(context, "next_key", *fn);

    // Call key_fns[i](ordering_expr_evals_lhs[i], lhs_arg)
    llvm::Value* lhs_eval = codegen->CodegenArrayAt(&builder, lhs_evals_arg, i);
    llvm::Value* lhs_args[] = {lhs_eval, lhs_arg};
    CodegenAnyVal lhs_value = CodegenAnyVal::CreateCallWrapped(codegen, &builder,
        ordering_exprs[i]->type(), key_fns[i], lhs_args, "lhs_value");

    // Call key_fns[i](ordering_expr_evals_rhs[i], rhs_arg)
    llvm::Value* rhs_eval = codegen->CodegenArrayAt(&builder, rhs_evals_arg, i);
    llvm::Value* rhs_args[] = {rhs_eval, rhs_arg};
    CodegenAnyVal rhs_value = CodegenAnyVal::CreateCallWrapped(codegen, &builder,
        ordering_exprs[i]->type(), key_fns[i], rhs_args, "rhs_value");

    // Handle NULLs if necessary
    llvm::Value* lhs_null = lhs_value.GetIsNull();
    llvm::Value* rhs_null = rhs_value.GetIsNull();
    // if (lhs_value == NULL && rhs_value == NULL) continue;
    llvm::Value* both_null = builder.CreateAnd(lhs_null, rhs_null, "both_null");
    llvm::BasicBlock* non_null_block =
        llvm::BasicBlock::Create(context, "non_null", *fn, next_key_block);
    builder.CreateCondBr(both_null, next_key_block, non_null_block);
    // if (lhs_value == NULL && rhs_value != NULL) return nulls_first_[i];
    builder.SetInsertPoint(non_null_block);
    llvm::BasicBlock* lhs_null_block =
        llvm::BasicBlock::Create(context, "lhs_null", *fn, next_key_block);
    llvm::BasicBlock* lhs_non_null_block =
        llvm::BasicBlock::Create(context, "lhs_non_null", *fn, next_key_block);
    builder.CreateCondBr(lhs_null, lhs_null_block, lhs_non_null_block);
    builder.SetInsertPoint(lhs_null_block);
    builder.CreateRet(builder.getInt32(nulls_first_[i]));
    // if (lhs_value != NULL && rhs_value == NULL) return -nulls_first_[i];
    builder.SetInsertPoint(lhs_non_null_block);
    llvm::BasicBlock* rhs_null_block =
        llvm::BasicBlock::Create(context, "rhs_null", *fn, next_key_block);
    llvm::BasicBlock* rhs_non_null_block =
        llvm::BasicBlock::Create(context, "rhs_non_null", *fn, next_key_block);
    builder.CreateCondBr(rhs_null, rhs_null_block, rhs_non_null_block);
    builder.SetInsertPoint(rhs_null_block);
    builder.CreateRet(builder.getInt32(-nulls_first_[i]));

    // int result = RawValue::Compare(lhs_value, rhs_value, <type>)
    builder.SetInsertPoint(rhs_non_null_block);
    llvm::Value* result = lhs_value.Compare(&rhs_value, "result");

    // if (!is_asc_[i]) result = -result;
    if (!is_asc_[i]) result = builder.CreateSub(builder.getInt32(0), result, "result");
    // if (result != 0) return result;
    // Otherwise, try the next Expr
    llvm::Value* result_nonzero = builder.CreateICmpNE(result, builder.getInt32(0));
    llvm::BasicBlock* result_nonzero_block =
        llvm::BasicBlock::Create(context, "result_nonzero", *fn, next_key_block);
    builder.CreateCondBr(result_nonzero, result_nonzero_block, next_key_block);
    builder.SetInsertPoint(result_nonzero_block);
    builder.CreateRet(result);

    // Get builder ready for next iteration or final return
    builder.SetInsertPoint(next_key_block);
  }
  builder.CreateRet(builder.getInt32(0));
  *fn = codegen->FinalizeFunction(*fn);
  if (*fn == NULL) {
    return Status("Codegen'd TupleRowComparator::Compare() function failed verification, "
        "see log");
  }
  return Status::OK();
}
