// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Class for intrinsifying functions.
#define SHOULD_NOT_INCLUDE_RUNTIME

#include "vm/compiler/asm_intrinsifier.h"

namespace dart {
namespace compiler {

void AsmIntrinsifier::String_identityHash(Assembler* assembler,
                                          Label* normal_ir_body) {
  String_getHashCode(assembler, normal_ir_body);
}

#define __ assembler->

// TODO(srdjan): Add combinations (one-byte/two-byte/external strings).
void AsmIntrinsifier::StringEquality(Assembler* assembler,
                                     Register obj1,
                                     Register obj2,
                                     Register temp1,
                                     Register temp2,
                                     Register result,
                                     Label* normal_ir_body,
                                     intptr_t string_cid) {
  Label is_true, is_false, loop;

  __ CompareRegisters(obj1, obj2);
  __ BranchIf(EQUAL, &is_true, AssemblerBase::kNearJump);
  __ BranchIfSmi(obj2, &is_false, AssemblerBase::kNearJump);
  __ CompareClassId(obj2, string_cid, temp1);
  __ BranchIf(NOT_EQUAL, normal_ir_body, AssemblerBase::kNearJump);

  __ LoadFieldFromOffset(temp1, obj1, target::String::length_offset());
  __ CompareWithMemoryValue(
      temp1, FieldAddress(obj2, target::String::length_offset()));
  __ BranchIf(NOT_EQUAL, &is_false, AssemblerBase::kNearJump);

  // Ensure temp1 has length in bytes
  if (string_cid == kOneByteStringCid) {
    __ ArithmeticShiftRightImmediate(temp1, 1);
  }
  // Rounding up to word boundary
  __ AddImmediate(temp1, target::kWordSize - 1);
  __ ArithmeticShiftRightImmediate(temp1, target::kWordSizeLog2);
  __ CompareWords(obj1, obj2,
                  target::String::length_offset() + target::kWordSize, temp1,
                  temp2, &is_true);

  __ Bind(&is_false);
  __ LoadObject(result, CastHandle<Object>(FalseObject()));
  __ Ret();

  __ Bind(&is_true);
  __ LoadObject(result, CastHandle<Object>(TrueObject()));
  __ Ret();

  __ Bind(normal_ir_body);
}

}  // namespace compiler
}  // namespace dart
