//===- llvm/tools/gollvm/unittests/BackendCore/TestUtils.cpp ------------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//

#include "TestUtils.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/CFG.h"

namespace goBackendUnitTests {

std::string ccName(llvm::CallingConv::ID cc) {
  assert(cc == llvm::CallingConv::X86_64_SysV ||
         cc == llvm::CallingConv::ARM_AAPCS);
  switch (cc) {
  case llvm::CallingConv::X86_64_SysV:
    return "X8664SysV";
  case llvm::CallingConv::ARM_AAPCS:
    return "ARMAAPCS";
  default:
    return "";
  }
}

std::string repr(llvm::Value *val) {
  std::string res;
  llvm::raw_string_ostream os(res);
  if (!val)
    os << "<null_value>";
  else
    val->print(os);
  return trimsp(os.str());
}

std::string repr(llvm::Type *t) {
  std::string res;
  llvm::raw_string_ostream os(res);
  if (t == NULL) {
    os << "<null_type>";
  } else {
    t->print(os);
  }
  return trimsp(os.str());
}

Btype *mkBackendStruct(Backend *be, ...)
{
  va_list ap;
  va_start(ap, be);

  std::vector<Backend::Btyped_identifier> fields;
  Btype *ct = va_arg(ap, Btype *);
  while (ct != nullptr) {
    Location loc;
    const char *fieldName = va_arg(ap, const char *);
    assert(fieldName);
    fields.push_back(Backend::Btyped_identifier(fieldName, ct, loc));
    ct = va_arg(ap, Btype *);
  }
  return be->struct_type(fields);
}

Btype *mkBackendThreeFieldStruct(Backend *be) {
  return mkBackendStruct(be,
                         be->bool_type(), "f1",
                         be->pointer_type(be->float_type(32)), "f2",
                         be->integer_type(true, 64), "f3",
                         nullptr);
}

llvm::StructType *mkLlvmStruct(llvm::LLVMContext *context, ...)
{
  va_list ap;
  va_start(ap, context);

  llvm::SmallVector<llvm::Type *, 64> smv;
  llvm::Type *typ = va_arg(ap, llvm::Type *);
  assert(typ);
  while (typ != nullptr) {
    smv.push_back(typ);
    typ = va_arg(ap, llvm::Type *);
  }
  return llvm::StructType::get(*context, smv);
}

llvm::StructType *mkLlvmThreeFieldStruct(llvm::LLVMContext &context) {
  llvm::Type *flt = llvm::Type::getFloatTy(context);
  return mkLlvmStruct(&context,
                      llvm::Type::getInt8Ty(context),
                      llvm::PointerType::get(flt, 0),
                      llvm::IntegerType::get(context, 64),
                      nullptr);
}

Btype *mkTwoFieldStruct(Backend *be, Btype *t1, Btype *t2)
{
  return mkBackendStruct(be, t1, "f1", t2, "f2", nullptr);
}

llvm::Type *mkTwoFieldLLvmStruct(llvm::LLVMContext &context,
                                 llvm::Type *t1, llvm::Type *t2)
{
  return mkLlvmStruct(&context, t1, t2, nullptr);
}

Backend::Btyped_identifier mkid(Btype *t) {
  static unsigned ctr = 1;
  char buf[128];
  sprintf(buf, "id%u", ctr++);
  return Backend::Btyped_identifier(buf, t, Location());
}

BFunctionType *mkFuncTyp(Backend *be, ...) {
  va_list ap;

  va_start(ap, be);

  Backend::Btyped_identifier receiver("rec", NULL, Location());
  std::vector<Backend::Btyped_identifier> results;
  std::vector<Backend::Btyped_identifier> params;
  Btype *result_type = NULL;

  unsigned tok = va_arg(ap, unsigned);
  while (tok != L_END) {
    switch (tok) {
    case L_RCV:
      receiver.btype = va_arg(ap, Btype *);
      break;
    case L_PARM:
      params.push_back(mkid(va_arg(ap, Btype *)));
      break;
    case L_RES:
      results.push_back(mkid(va_arg(ap, Btype *)));
      break;
    case L_RES_ST:
      result_type = va_arg(ap, Btype *);
      break;
    default: {
      assert(false && "internal error");
      return NULL;
    }
    }
    tok = va_arg(ap, unsigned);
  }

  if (results.size() > 1)
    result_type = be->struct_type(results);

  Btype *ft = be->function_type(receiver, params, results,
                                result_type, Location());
  return ft->castToBFunctionType();
}

llvm::Type *mkLLFuncTyp(llvm::LLVMContext *context, ...) {
  va_list ap;

  llvm::SmallVector<llvm::Type *, 4> params(0);
  llvm::SmallVector<llvm::Type *, 4> results(0);
  llvm::Type *recv_typ = NULL;
  llvm::Type *res_styp = NULL;

  va_start(ap, context);
  unsigned tok = va_arg(ap, unsigned);
  while (tok != L_END) {
    switch (tok) {
    case L_RCV:
      recv_typ = va_arg(ap, llvm::Type *);
      break;
    case L_PARM:
      params.push_back(va_arg(ap, llvm::Type *));
      break;
    case L_RES:
      results.push_back(va_arg(ap, llvm::Type *));
      break;
    case L_RES_ST:
      res_styp = va_arg(ap, llvm::Type *);
      break;
    default: {
      assert(false && "internal error");
      return NULL;
    }
    }
    tok = va_arg(ap, unsigned);
  }

  llvm::SmallVector<llvm::Type *, 4> elems(0);
  llvm::Type *llit = llvm::IntegerType::get(*context, 8);
  elems.push_back(llvm::PointerType::get(llit, 0));
  if (recv_typ)
    elems.push_back(recv_typ);
  for (auto pt : params)
    elems.push_back(pt);

  llvm::Type *rtyp = NULL;
  if (results.empty())
    rtyp = llvm::Type::getVoidTy(*context);
  else if (results.size() == 1)
    rtyp = results[0];
  else {
    rtyp = res_styp;
  }
  return llvm::FunctionType::get(rtyp, elems, false);
}

bool llvmTypesEquiv(llvm::Type *t1, llvm::Type *t2)
{
  if (t1->getTypeID() != t2->getTypeID())
    return false;
  if (t1->getNumContainedTypes() != t2->getNumContainedTypes())
    return false;
  for (unsigned idx = 0; idx < t1->getNumContainedTypes(); ++idx)
    if (!llvmTypesEquiv(t1->getContainedType(idx),
                        t2->getContainedType(idx)))
      return false;
  return true;
}

Bfunction *mkFunci32o64(Backend *be, const char *fname, bool mkParams) {
  Btype *bi64t = be->integer_type(false, 64);
  Btype *bi32t = be->integer_type(false, 32);
  Btype *bpi64t = be->pointer_type(bi64t);
  Btype *befty = mkFuncTyp(be,
                           L_PARM, bi32t, L_PARM, bi32t, L_PARM, bpi64t,
                           L_RES, bi64t, L_END);
  unsigned fflags = (Backend::function_is_visible |
                     Backend::function_is_inlinable);
  Location loc;
  Bfunction *func = be->function(befty, fname, fname, fflags, loc);
  if (mkParams) {
    be->parameter_variable(func, "param1", bi32t, false, loc);
    be->parameter_variable(func, "param2", bi32t, false, loc);
    be->parameter_variable(func, "param3", bpi64t, false, loc);
  }
  return func;
}

Bfunction *mkFuncFromType(Backend *be, const char *fname,
                          BFunctionType *befty, Location loc)
{
  unsigned fflags = (Backend::function_is_visible |
                     Backend::function_is_inlinable);
  Bfunction *func = be->function(befty, fname, fname, fflags, loc);
  const std::vector<Btype *> &paramTypes = befty->paramTypes();
  for (unsigned idx = 0; idx < paramTypes.size(); ++idx) {
    std::stringstream ss;
    ss << "p" << idx;
    be->parameter_variable(func, ss.str(), paramTypes[idx], false, loc);
  }
  return func;
}

Bexpression *mkUIntConst(Backend *be, uint64_t val, unsigned bits) {
  mpz_t mpz_val;
  memset(&mpz_val, '0', sizeof(mpz_val));
  mpz_init_set_ui(mpz_val, val);
  Btype *but = be->integer_type(true, bits);
  Bexpression *rval = be->integer_constant_expression(but, mpz_val);
  mpz_clear(mpz_val);
  return rval;
}

Bexpression *mkIntConst(Backend *be, int64_t val, unsigned bits) {
  mpz_t mpz_val;
  memset(&mpz_val, '0', sizeof(mpz_val));
  mpz_init_set_si(mpz_val, val);
  Btype *bit = be->integer_type(false, bits);
  Bexpression *rval = be->integer_constant_expression(bit, mpz_val);
  mpz_clear(mpz_val);
  return rval;
}

Bexpression *mkInt64Const(Backend *be, int64_t val) {
  return mkIntConst(be, val, 64);
}

Bexpression *mkUint64Const(Backend *be, uint64_t val) {
  return mkUIntConst(be, val, 64);
}

Bexpression *mkInt32Const(Backend *be, int32_t val) {
  return mkIntConst(be, val, 32);
}

Bexpression *mkFloat64Const(Backend *be, double val) {
  mpfr_t mpfr_val;

  mpfr_init(mpfr_val);
  mpfr_set_d(mpfr_val, val, GMP_RNDN);
  Btype *bf64t = be->float_type(64);
  Bexpression *beval = be->float_constant_expression(bf64t, mpfr_val);
  mpfr_clear(mpfr_val);
  return beval;
}

// Return func desc type
Btype *mkFuncDescType(Backend *be)
{
  assert(be);
  Btype *bt = be->bool_type();
  Btype *pbt = be->pointer_type(bt);
  Btype *uintptrt = be->integer_type(true, be->type_size(pbt)*8);
  Btype *fdescst = mkBackendStruct(be, uintptrt, "f1", nullptr);
  return fdescst;
}

Bexpression *mkFuncDescExpr(Backend *be, Bfunction *fcn)
{
  assert(be);
  assert(fcn);
  Location loc;
  Btype *bt = be->bool_type();
  Btype *pbt = be->pointer_type(bt);
  Btype *uintptrt = be->integer_type(true, be->type_size(pbt)*8);
  Btype *fdescst = mkFuncDescType(be);
  Bexpression *fp = be->function_code_expression(fcn, loc);
  Bexpression *fpuint = be->convert_expression(uintptrt, fp, loc);
  std::vector<Bexpression *> vals;
  vals.push_back(fpuint);
  return be->constructor_expression(fdescst, vals, loc);
}

Bblock *mkBlockFromStmt(Backend *be, Bfunction *func, Bstatement *st) {
  const std::vector<Bvariable *> empty;
  Bblock *b = be->block(func, nullptr, empty, Location(), Location());
  std::vector<Bstatement *> stlist;
  stlist.push_back(st);
  be->block_add_statements(b, stlist);
  return b;
}

Bstatement *addStmtToBlock(Backend *be, Bblock *block, Bstatement *st) {
  std::vector<Bstatement *> stlist;
  stlist.push_back(st);
  be->block_add_statements(block, stlist);
  return st;
}

Bstatement *addExprToBlock(Backend *be, Bfunction *func,
                           Bblock *block, Bexpression *e) {
  Bstatement *es = be->expression_statement(func, e);
  std::vector<Bstatement *> stlist;
  stlist.push_back(es);
  be->block_add_statements(block, stlist);
  return es;
}

class NodeReprVisitor {
 public:
  NodeReprVisitor() : os_(str_) { }

  std::string result() { return os_.str(); }

  void visitNodePre(Bnode *node) { }

  void visitNodePost(Bnode *node) {
    assert(node);
    Bexpression *expr = node->castToBexpression();
    if (expr) {
      for (auto inst : expr->instructions()) {
        inst->print(os_);
        os_ << "\n";
      }
    }
    assert(node->flavor() != N_IfStmt &&
           node->flavor() != N_GotoStmt &&
           node->flavor() != N_LabelStmt &&
           node->flavor() != N_SwitchStmt);
  }

 private:
  std::string str_;
  llvm::raw_string_ostream os_;
};

std::string repr(Bnode *node) {
  if (!node)
    return "<null Bnode ptr>";

  NodeReprVisitor vis;
  simple_walk_nodes(node, vis);
  return trimsp(vis.result());
}

FcnTestHarness::FcnTestHarness(llvm::CallingConv::ID cconv, const char *fcnName)
    : context_()
    , be_(new Llvm_backend(context_, nullptr, nullptr, 0, llvm::Triple(), cconv))
    , func_(nullptr)
    , entryBlock_(nullptr)
    , curBlock_(nullptr)
    , nextLabel_(nullptr)
    , lineNum_(1)
    , finished_(false)
    , returnAdded_(false)
    , emitDumpFilesOnDiff_(false)
    , findOrphanBBs_(true)
{
  // establish initial file so as to make verifier happy
  be_->linemap()->start_file("unit_testing.go", 1);
  loc_ = be_->linemap()->get_location(lineNum_);

  // Eager function creation if name not specified
  if (fcnName) {
    func_ = mkFunci32o64(be(), fcnName);
    entryBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
    curBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
  }

  // debugging
  if (getenv("GOLLVM_UNITTESTS_BACKENDCORE_EMITDUMPFILES"))
    emitDumpFilesOnDiff_ = true;
  if (getenv("GOLLVM_UNITTESTS_EMIT_REMASTER_SCRIPT")) {
    emitRemasterScript_ = true;
    emitDumpFilesOnDiff_ = true;
  }
}

FcnTestHarness::~FcnTestHarness()
{
  assert(finished_);
}

Location FcnTestHarness::newloc()
{
  loc_ = be_->linemap()->get_location(++lineNum_);
  return loc_;
}

Location FcnTestHarness::newFileLineLoc(const char *file, unsigned line)
{
  lineNum_ = line;
  be_->linemap()->start_file(file, lineNum_);
  loc_ = be_->linemap()->get_location(lineNum_);
  return loc_;
}

Bfunction *FcnTestHarness::mkFunction(const char *fcnName, BFunctionType *befty)
{
  func_ = mkFuncFromType(be(), fcnName, befty, loc_);
  entryBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
  curBlock_ = be()->block(func_, nullptr, emptyVarList_, loc_, loc_);
  return func_;
}

Bvariable *FcnTestHarness::mkLocal(const char *name,
                                   Btype *typ,
                                   Bexpression *init)
{
  assert(func_);
  Bvariable *v = be()->local_variable(func_, name, typ, nullptr, false, loc_);
  if (!init)
    init = be()->zero_expression(typ);
  Bstatement *is = be()->init_statement(func_, v, init);
  addStmtToBlock(be(), curBlock_, is);
  return v;
}

void FcnTestHarness::mkAssign(Bexpression *lhs,
                              Bexpression *rhs,
                              AppendDisp disp)
{
  assert(func_);
  Bstatement *as = be()->assignment_statement(func_, lhs, rhs, loc_);
  if (disp == YesAppend)
    addStmtToBlock(be(), curBlock_, as);
}

Bstatement *FcnTestHarness::mkExprStmt(Bexpression *expr, AppendDisp disp)
{
  assert(func_);
  Bstatement *es = be()->expression_statement(func_, expr);
  if (disp == YesAppend)
    addStmtToBlock(be(), curBlock_, es);
  return es;
}

Bexpression *FcnTestHarness::mkCallExpr(Backend *be, Bfunction *fun, ...)
{
  va_list ap;

  va_start(ap, fun);
  Bexpression *fn = be->function_code_expression(fun, loc_);
  std::vector<Bexpression *> args;
  Bexpression *e = va_arg(ap, Bexpression *);
  while (e) {
    args.push_back(e);
    e = va_arg(ap, Bexpression *);
  }
  Bexpression *call = be->call_expression(func_, fn, args, nullptr, loc_);
  return call;
}

Bstatement *FcnTestHarness::mkReturn(Bexpression *expr, AppendDisp disp)
{
  std::vector<Bexpression *> vals;
  vals.push_back(expr);
  return mkReturn(vals, disp);
}

Bstatement *FcnTestHarness::mkReturn(const std::vector<Bexpression *> &vals,
                                     AppendDisp disp)
{
  assert(func_);
  Bstatement *ret = be()->return_statement(func_, vals, loc_);
  if (disp == YesAppend) {
    addStmtToBlock(be(), curBlock_, ret);
    returnAdded_ = true;
  }
  return ret;
}

Bstatement *FcnTestHarness::mkIf(Bexpression *cond,
                                 Bstatement *trueStmt,
                                 Bstatement *falseStmt,
                                 AppendDisp disp)
{
  assert(func_);
  Bblock *trueBlock = mkBlockFromStmt(be(), func_, trueStmt);
  Bblock *falseBlock = nullptr;
  if (falseStmt)
    falseBlock = mkBlockFromStmt(be(), func_, falseStmt);
  Bstatement *ifst = be()->if_statement(func_, cond,
                                        trueBlock, falseBlock, loc_);
  if (disp == YesAppend)
    addStmtToBlock(be(), curBlock_, ifst);
  return ifst;
}

Bstatement *FcnTestHarness::mkSwitch(Bexpression *swval,
                       const std::vector<std::vector<Bexpression *>> &cases,
                       const std::vector<Bstatement *> &statements,
                       AppendDisp disp)
{
  assert(func_);
  Bstatement *swst = be()->switch_statement(func_, swval,
                                            cases, statements, loc_);
  if (disp == YesAppend)
    addStmtToBlock(be(), curBlock_, swst);
  return swst;
}

void FcnTestHarness::addStmt(Bstatement *stmt)
{
  assert(func_);
  addStmtToBlock(be(), curBlock_, stmt);
}

void FcnTestHarness::newBlock(std::vector<Bvariable *> *varlist)
{
  assert(func_);

  if (!varlist)
    varlist = &emptyVarList_;

  // Create label for new block and append jump to current block
  std::string lab = be()->namegen("_lab");
  Blabel *blab = be()->label(func_, lab, loc_);
  Bstatement *gots = be()->goto_statement(blab, loc_);
  addStmtToBlock(be(), curBlock_, gots);

  // Turn current block into statement and tack onto entry block. Weird,
  // but this is the pardigm for gofrontend.
  Bstatement *bst = be()->block_statement(curBlock_);
  if (nextLabel_) {
    Bstatement *ldef = be()->label_definition_statement(nextLabel_);
    bst = be()->compound_statement(ldef, bst);
  }
  addStmtToBlock(be(), entryBlock_, bst);
  nextLabel_ = blab;
  returnAdded_ = false;

  // New block
  curBlock_ = be()->block(func_, nullptr, *varlist, loc_, loc_);
}

bool FcnTestHarness::expectStmt(Bstatement *st, const ExpectedDump &ed)
{
  const std::string &expected = ed.content;
  std::string reason;
  std::string actual(repr(st));
  bool equal = difftokens(expected, actual, reason);
  if (! equal)
    complainOnNequal(reason, ed, actual, emitDumpFilesOnDiff_, emitRemasterScript_);
  return equal;
}

bool FcnTestHarness::expectValue(llvm::Value *val, const ExpectedDump &ed)
{
  const std::string &expected = ed.content;
  std::string reason;
  std::string actual(repr(val));
  bool equal = difftokens(expected, actual, reason);
  if (! equal)
    complainOnNequal(reason, ed, actual, emitDumpFilesOnDiff_, emitRemasterScript_);
  return equal;
}

bool FcnTestHarness::expectBlock(const ExpectedDump &ed)
{
  const std::string &expected = ed.content;
  std::string reason;
  std::string actual(repr(curBlock_));
  bool equal = difftokens(expected, actual, reason);
  if (! equal)
    complainOnNequal(reason, ed, actual, emitDumpFilesOnDiff_, emitRemasterScript_);
  return equal;
}

bool FcnTestHarness::expectModuleDumpContains(const std::string &expected)
{
  std::string res;
  llvm::raw_string_ostream os(res);
  be()->module().print(os, nullptr);
  std::string actual(trimsp(os.str()));
  return containstokens(actual, expected);
}

unsigned FcnTestHarness::countInstancesInModuleDump(const std::string &expected)
{
  std::string res;
  llvm::raw_string_ostream os(res);
  be()->module().print(os, nullptr);
  std::string actual(trimsp(os.str()));
  return countinstances(actual, expected);
}

bool FcnTestHarness::expectRepr(Bnode *node, const ExpectedDump &ed)
{
  const std::string &expected = ed.content;
  std::string reason;
  std::string actual(repr(node));
  bool equal = difftokens(expected, actual, reason);
  if (! equal)
    complainOnNequal(reason, ed, actual, emitDumpFilesOnDiff_, emitRemasterScript_);
  return equal;
}

bool FcnTestHarness::finish(DebugDisposition whatToDoWithDebugInfo)
{
  if (func_) {

    // Emit a label def for the pending block if needed
    Bstatement *bst = be()->block_statement(curBlock_);
    if (nextLabel_) {
      Bstatement *ldef = be()->label_definition_statement(nextLabel_);
      bst = be()->compound_statement(ldef, bst);
    }

    // Add current block as stmt to entry block
    addStmtToBlock(be(), entryBlock_, bst);

    // Set function body
    be()->function_set_body(func_, entryBlock_);
  }
  // Finalize export data. This has the side effect of finalizing
  // debug meta-data, which we need to do before invoking the verifier.
  be()->finalizeExportData();

  // Strip debug info now if requested
  if (whatToDoWithDebugInfo == StripDebugInfo)
    llvm::StripDebugInfo(be()->module());

  // Look for non-entry blocks with no CFG preds, since they
  // are nearly always an indication that something is wrong.
  bool brokenBlock = false;
  if (func_ && findOrphanBBs_) {
    for (llvm::BasicBlock &bb : *func_->function()) {
      if (&bb == &func_->function()->getEntryBlock())
        continue;
      if (! bb.getParent()) {
        std::cerr << "** block with no parent:\n";
        llvm::Value *blockVal = &bb;
        std::cerr << repr(blockVal);
        brokenBlock = true;
      }
      if (llvm::pred_begin(&bb) == llvm::pred_end(&bb)) {
        std::cerr << "** block has no predecessors:\n";
        llvm::Value *blockVal = &bb;
        std::cerr << repr(blockVal);
        brokenBlock = true;
      }
    }
  }

  // Verify module
  bool broken = llvm::verifyModule(be()->module(), &llvm::dbgs());

  // Mark finished
  finished_ = true;
  curBlock_ = entryBlock_;

  return broken || brokenBlock;
}

} // namespace goBackendUnitTests
