//===- CodeGenInstAlias.cpp - CodeGen InstAlias Class Wrapper -------------===//
//
// 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 the CodeGenInstAlias class.
//
//===----------------------------------------------------------------------===//

#include "CodeGenInstAlias.h"
#include "CodeGenInstruction.h"
#include "CodeGenRegisters.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Error.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"

using namespace llvm;

unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
  if (!isRecord())
    return 1;

  const Record *Rec = getRecord();
  if (!Rec->isSubClassOf("Operand"))
    return 1;

  const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
  if (MIOpInfo->getNumArgs() == 0) {
    // Unspecified, so it defaults to 1
    return 1;
  }

  return MIOpInfo->getNumArgs();
}

using ResultOperand = CodeGenInstAlias::ResultOperand;

static Expected<ResultOperand>
matchSimpleOperand(const Init *Arg, const StringInit *ArgName, const Record *Op,
                   const CodeGenTarget &T, ArrayRef<SMLoc> Loc) {
  if (const Record *OpRC = T.getAsRegClassLike(Op)) {
    if (const auto *ArgDef = dyn_cast<DefInit>(Arg)) {
      const Record *ArgRec = ArgDef->getDef();

      // Match 'RegClass:$name' or 'RegOp:$name'.
      if (const Record *ArgRC = T.getInitValueAsRegClassLike(Arg)) {
        if (ArgRC->isSubClassOf("RegisterClass")) {
          if (!OpRC->isSubClassOf("RegisterClass") ||
              !T.getRegisterClass(OpRC, Loc).hasSubClass(
                  &T.getRegisterClass(ArgRC, Loc)))
            return createStringError(
                "argument register class " + ArgRC->getName() +
                " is not a subclass of operand register class " +
                OpRC->getName());
          if (!ArgName)
            return createStringError(
                "register class argument must have a name");
        }

        // TODO: Verify RegClassByHwMode usage

        return ResultOperand::createRecord(ArgName->getAsUnquotedString(),
                                           ArgRec);
      }

      // Match 'Reg'.
      if (ArgRec->isSubClassOf("Register")) {
        if (!T.getRegisterClass(OpRC, Loc).contains(
                T.getRegBank().getReg(ArgRec)))
          return createStringError(
              "register argument " + ArgRec->getName() +
              " is not a member of operand register class " + OpRC->getName());
        if (ArgName)
          return createStringError("register argument must not have a name");
        return ResultOperand::createRegister(ArgRec);
      }

      // Match 'zero_reg'.
      if (ArgRec->getName() == "zero_reg") {
        if (ArgName)
          return createStringError("register argument must not have a name");
        return ResultOperand::createRegister(nullptr);
      }
    }

    return createStringError("argument must be a subclass of RegisterClass, "
                             "RegisterOperand, or zero_reg");
  }

  if (Op->isSubClassOf("Operand")) {
    // Match integer or bits.
    if (const auto *ArgInt = dyn_cast_or_null<IntInit>(
            Arg->convertInitializerTo(IntRecTy::get(Arg->getRecordKeeper())))) {
      if (ArgName)
        return createStringError("integer argument must not have a name");
      return ResultOperand::createImmediate(ArgInt->getValue());
    }

    // Match a subclass of Operand.
    if (const auto *ArgDef = dyn_cast<DefInit>(Arg);
        ArgDef && ArgDef->getDef()->isSubClassOf("Operand")) {
      if (!ArgName)
        return createStringError("argument must have a name");
      return ResultOperand::createRecord(ArgName->getAsUnquotedString(),
                                         ArgDef->getDef());
    }
  }
  return createStringError("argument must be a subclass of 'Operand' but got " +
                           Op->getName() + " instead");
}

static Expected<ResultOperand> matchComplexOperand(const Init *Arg,
                                                   const StringInit *ArgName,
                                                   const Record *Op) {
  assert(Op->isSubClassOf("Operand"));
  const auto *ArgDef = dyn_cast<DefInit>(Arg);
  if (!ArgDef || !ArgDef->getDef()->isSubClassOf("Operand"))
    return createStringError("argument must be a subclass of Operand");
  if (!ArgName)
    return createStringError("argument must have a name");
  return ResultOperand::createRecord(ArgName->getAsUnquotedString(),
                                     ArgDef->getDef());
}

CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T)
    : TheDef(R) {
  Result = R->getValueAsDag("ResultInst");
  AsmString = R->getValueAsString("AsmString");

  // Verify that the root of the result is an instruction.
  const DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
  if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
    PrintFatalError(R->getLoc(),
                    "result of inst alias should be an instruction");

  ResultInst = &T.getInstruction(DI->getDef());

  // NameClass - If argument names are repeated, we need to verify they have
  // the same class.
  StringMap<const Record *> NameClass;
  for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
    const DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
    if (!ADI || !Result->getArgName(i))
      continue;
    // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
    // $foo can exist multiple times in the result list, but it must have the
    // same type.
    const Record *&Entry = NameClass[Result->getArgNameStr(i)];
    if (Entry && Entry != ADI->getDef())
      PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
                                       " is both " + Entry->getName() +
                                       " and " + ADI->getDef()->getName() +
                                       "!");
    Entry = ADI->getDef();
  }

  // Decode and validate the arguments of the result.
  unsigned ArgIdx = 0;
  for (auto [OpIdx, OpInfo] : enumerate(ResultInst->Operands)) {
    // Tied registers don't have an entry in the result dag unless they're part
    // of a complex operand, in which case we include them anyways, as we
    // don't have any other way to specify the whole operand.
    if (OpInfo.MINumOperands == 1 && OpInfo.getTiedRegister() != -1) {
      // Tied operands of different RegisterClass should be explicit within an
      // instruction's syntax and so cannot be skipped.
      int TiedOpNum = OpInfo.getTiedRegister();
      if (OpInfo.Rec->getName() ==
          ResultInst->Operands[TiedOpNum].Rec->getName())
        continue;
    }

    if (ArgIdx >= Result->getNumArgs())
      PrintFatalError(R->getLoc(), "not enough arguments for instruction!");

    const Record *Op = OpInfo.Rec;
    if (Op->isSubClassOf("Operand") && !OpInfo.MIOperandInfo->arg_empty()) {
      // Complex operand (a subclass of Operand with non-empty MIOperandInfo).
      // The argument can be a DAG or a subclass of Operand.
      if (auto *ArgDag = dyn_cast<DagInit>(Result->getArg(ArgIdx))) {
        // The argument is a DAG. The operator must be the name of the operand.
        if (auto *Operator = dyn_cast<DefInit>(ArgDag->getOperator());
            !Operator || Operator->getDef()->getName() != Op->getName())
          PrintFatalError(R, "argument #" + Twine(ArgIdx) +
                                 " operator must be " + Op->getName());
        // The number of sub-arguments and the number of sub-operands
        // must match exactly.
        unsigned NumSubOps = OpInfo.MIOperandInfo->getNumArgs();
        unsigned NumSubArgs = ArgDag->getNumArgs();
        if (NumSubArgs != NumSubOps)
          PrintFatalError(R, "argument #" + Twine(ArgIdx) +
                                 " must have exactly " + Twine(NumSubOps) +
                                 " sub-arguments");
        // Match sub-operands individually.
        for (unsigned SubOpIdx = 0; SubOpIdx != NumSubOps; ++SubOpIdx) {
          const Record *SubOp =
              cast<DefInit>(OpInfo.MIOperandInfo->getArg(SubOpIdx))->getDef();
          Expected<ResultOperand> ResOpOrErr = matchSimpleOperand(
              ArgDag->getArg(SubOpIdx), ArgDag->getArgName(SubOpIdx), SubOp, T,
              R->getLoc());
          if (!ResOpOrErr)
            PrintFatalError(R, "in argument #" + Twine(ArgIdx) + "." +
                                   Twine(SubOpIdx) + ": " +
                                   toString(ResOpOrErr.takeError()));
          ResultOperands.push_back(*ResOpOrErr);
          ResultInstOperandIndex.emplace_back(OpIdx, SubOpIdx);
        }
      } else {
        // Match complex operand as a whole.
        Expected<ResultOperand> ResOpOrErr = matchComplexOperand(
            Result->getArg(ArgIdx), Result->getArgName(ArgIdx), Op);
        if (!ResOpOrErr)
          PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " +
                                 toString(ResOpOrErr.takeError()));
        ResultOperands.push_back(*ResOpOrErr);
        ResultInstOperandIndex.emplace_back(OpIdx, -1);
      }
    } else {
      // Simple operand (RegisterClass, RegisterOperand or Operand with empty
      // MIOperandInfo).
      Expected<ResultOperand> ResOpOrErr =
          matchSimpleOperand(Result->getArg(ArgIdx), Result->getArgName(ArgIdx),
                             Op, T, R->getLoc());
      if (!ResOpOrErr)
        PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " +
                               toString(ResOpOrErr.takeError()));
      ResultOperands.push_back(*ResOpOrErr);
      ResultInstOperandIndex.emplace_back(OpIdx, -1);
    }
    ArgIdx++;
  }

  if (ArgIdx != Result->getNumArgs())
    PrintFatalError(R->getLoc(), "too many operands for instruction!");
}
