//===-- WebAssemblyCallLowering.cpp - Call lowering for GlobalISel -*- C++ -*-//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the lowering of LLVM calls to machine code calls for
/// GlobalISel.
///
//===----------------------------------------------------------------------===//

#include "WebAssemblyCallLowering.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "Utils/WasmAddressSpaces.h"
#include "WebAssemblyISelLowering.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblyRegisterInfo.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyUtilities.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/LowLevelTypeUtils.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/ErrorHandling.h"

#define DEBUG_TYPE "wasm-call-lowering"

using namespace llvm;

// Test whether the given calling convention is supported.
static bool callingConvSupported(CallingConv::ID CallConv) {
  // We currently support the language-independent target-independent
  // conventions. We don't yet have a way to annotate calls with properties like
  // "cold", and we don't have any call-clobbered registers, so these are mostly
  // all handled the same.
  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
         CallConv == CallingConv::Cold ||
         CallConv == CallingConv::PreserveMost ||
         CallConv == CallingConv::PreserveAll ||
         CallConv == CallingConv::CXX_FAST_TLS ||
         CallConv == CallingConv::WASM_EmscriptenInvoke ||
         CallConv == CallingConv::Swift;
}

static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags) {
  if (Flags.isSExt())
    return TargetOpcode::G_SEXT;
  if (Flags.isZExt())
    return TargetOpcode::G_ZEXT;
  return TargetOpcode::G_ANYEXT;
}

static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL) {
  if (Ty == MVT::externref) {
    return LLT::pointer(
        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF,
        DL.getPointerSizeInBits(
            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF));
  }

  if (Ty == MVT::funcref) {
    return LLT::pointer(
        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF,
        DL.getPointerSizeInBits(
            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF));
  }

  return llvm::getLLTForMVT(Ty);
}

WebAssemblyCallLowering::WebAssemblyCallLowering(
    const WebAssemblyTargetLowering &TLI)
    : CallLowering(&TLI) {}

bool WebAssemblyCallLowering::canLowerReturn(MachineFunction &MF,
                                             CallingConv::ID CallConv,
                                             SmallVectorImpl<BaseArgInfo> &Outs,
                                             bool IsVarArg) const {
  return WebAssembly::canLowerReturn(Outs.size(),
                                     &MF.getSubtarget<WebAssemblySubtarget>());
}

bool WebAssemblyCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
                                          const Value *Val,
                                          ArrayRef<Register> VRegs,
                                          FunctionLoweringInfo &FLI,
                                          Register SwiftErrorVReg) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const WebAssemblySubtarget &Subtarget =
      MF.getSubtarget<WebAssemblySubtarget>();
  const RegisterBankInfo &RBI = *Subtarget.getRegBankInfo();
  const Function &F = MF.getFunction();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
  const DataLayout &DL = F.getDataLayout();

  MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(WebAssembly::RETURN);

  assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
         "Return value without a vreg or vice versa");

  if (Val) {
    LLVMContext &Ctx = Val->getType()->getContext();

    if (!FLI.CanLowerReturn) {
      insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);
    } else {
      SmallVector<EVT, 4> SplitEVTs;
      ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
      assert(VRegs.size() == SplitEVTs.size() &&
             "For each split Type there should be exactly one VReg.");

      SmallVector<ArgInfo, 8> SplitRets;
      CallingConv::ID CallConv = F.getCallingConv();

      unsigned RetIdx = 0;
      for (EVT SplitEVT : SplitEVTs) {
        Register CurVReg = VRegs[RetIdx];
        ArgInfo CurRetInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
        setArgFlags(CurRetInfo, AttributeList::ReturnIndex, DL, F);

        splitToValueTypes(CurRetInfo, SplitRets, DL, CallConv);
        ++RetIdx;
      }

      for (ArgInfo &Ret : SplitRets) {
        const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
        const MVT NewVT =
            TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
        const LLT OrigLLT =
            getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
        const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);

        const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);

        // If we need to split the type over multiple regs, check it's a
        // scenario we currently support.
        const unsigned NumParts =
            TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);

        const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
        Ret.Flags.clear();

        for (unsigned Part = 0; Part < NumParts; ++Part) {
          ISD::ArgFlagsTy Flags = OrigFlags;

          if (Part == 0) {
            Flags.setSplit();
          } else {
            Flags.setOrigAlign(Align(1));
            if (Part == NumParts - 1)
              Flags.setSplitEnd();
          }

          Ret.Flags.push_back(Flags);
        }

        Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
        if (NumParts != 1 || OrigLLT != NewLLT) {
          // If we can't directly assign the register, we need one or more
          // intermediate values.
          Ret.Regs.resize(NumParts);

          // For each split register, create and assign a vreg that will store
          // the incoming component of the larger value. These will later be
          // merged to form the final vreg.
          for (unsigned Part = 0; Part < NumParts; ++Part) {
            Register NewOutReg = MRI.createGenericVirtualRegister(NewLLT);

            if (!RBI.constrainGenericRegister(NewOutReg, NewRegClass, MRI))
              reportFatalInternalError(
                  "Couldn't constrain brand-new register?");

            MIB.addUse(NewOutReg);

            Ret.Regs[Part] = NewOutReg;
          }

          buildCopyToRegs(MIRBuilder, Ret.Regs, Ret.OrigRegs[0], OrigLLT,
                          NewLLT, extendOpFromFlags(Ret.Flags[0]));
        } else {
          MIB.addUse(Ret.Regs[0]);
        }
      }
    }
  }

  if (SwiftErrorVReg) {
    reportFatalInternalError(
        "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
        "improperly valid.");
  }

  MIRBuilder.insertInstr(MIB);
  return true;
}

static unsigned getWasmArgumentOpcode(MVT ArgType) {
  switch (ArgType.SimpleTy) {
  case MVT::i32:
    return WebAssembly::ARGUMENT_i32;
  case MVT::i64:
    return WebAssembly::ARGUMENT_i64;
  case MVT::f32:
    return WebAssembly::ARGUMENT_f32;
  case MVT::f64:
    return WebAssembly::ARGUMENT_f64;

  case MVT::funcref:
    return WebAssembly::ARGUMENT_funcref;
  case MVT::externref:
    return WebAssembly::ARGUMENT_externref;
  case MVT::exnref:
    return WebAssembly::ARGUMENT_exnref;

  case MVT::v16i8:
    return WebAssembly::ARGUMENT_v16i8;
  case MVT::v8i16:
    return WebAssembly::ARGUMENT_v8i16;
  case MVT::v4i32:
    return WebAssembly::ARGUMENT_v4i32;
  case MVT::v2i64:
    return WebAssembly::ARGUMENT_v2i64;
  case MVT::v8f16:
    return WebAssembly::ARGUMENT_v8f16;
  case MVT::v4f32:
    return WebAssembly::ARGUMENT_v4f32;
  case MVT::v2f64:
    return WebAssembly::ARGUMENT_v2f64;
  default:
    break;
  }
  llvm_unreachable("Found unexpected type for Wasm argument");
}

bool WebAssemblyCallLowering::lowerFormalArguments(
    MachineIRBuilder &MIRBuilder, const Function &F,
    ArrayRef<ArrayRef<Register>> VRegs, FunctionLoweringInfo &FLI) const {
  MachineFunction &MF = MIRBuilder.getMF();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  WebAssemblyFunctionInfo *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
  const DataLayout &DL = F.getDataLayout();
  const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
  const WebAssemblySubtarget &Subtarget =
      MF.getSubtarget<WebAssemblySubtarget>();
  const WebAssemblyRegisterInfo &TRI = *Subtarget.getRegisterInfo();
  const WebAssemblyInstrInfo &TII = *Subtarget.getInstrInfo();
  const RegisterBankInfo &RBI = *Subtarget.getRegBankInfo();

  LLVMContext &Ctx = MIRBuilder.getContext();
  const CallingConv::ID CallConv = F.getCallingConv();

  if (!callingConvSupported(CallConv)) {
    return false;
  }

  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
  MF.front().addLiveIn(WebAssembly::ARGUMENTS);

  SmallVector<ArgInfo, 8> SplitArgs;

  if (!FLI.CanLowerReturn) {
    insertSRetIncomingArgument(F, SplitArgs, FLI.DemoteRegister, MRI, DL);
  }

  unsigned ArgIdx = 0;
  bool HasSwiftErrorArg = false;
  bool HasSwiftSelfArg = false;
  for (const Argument &Arg : F.args()) {
    ArgInfo OrigArg{VRegs[ArgIdx], Arg.getType(), ArgIdx};
    setArgFlags(OrigArg, ArgIdx + AttributeList::FirstArgIndex, DL, F);

    HasSwiftSelfArg |= Arg.hasSwiftSelfAttr();
    HasSwiftErrorArg |= Arg.hasSwiftErrorAttr();
    if (Arg.hasInAllocaAttr()) {
      return false;
    }
    if (Arg.hasNestAttr()) {
      return false;
    }
    splitToValueTypes(OrigArg, SplitArgs, DL, F.getCallingConv());
    ++ArgIdx;
  }

  unsigned FinalArgIdx = 0;
  for (ArgInfo &Arg : SplitArgs) {
    const EVT OrigVT = TLI.getValueType(DL, Arg.Ty);
    const MVT NewVT = TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
    const LLT OrigLLT =
        getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
    const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);

    // If we need to split the type over multiple regs, check it's a scenario
    // we currently support.
    const unsigned NumParts =
        TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);

    const ISD::ArgFlagsTy OrigFlags = Arg.Flags[0];
    Arg.Flags.clear();

    for (unsigned Part = 0; Part < NumParts; ++Part) {
      ISD::ArgFlagsTy Flags = OrigFlags;
      if (Part == 0) {
        Flags.setSplit();
      } else {
        Flags.setOrigAlign(Align(1));
        if (Part == NumParts - 1)
          Flags.setSplitEnd();
      }

      Arg.Flags.push_back(Flags);
    }

    Arg.OrigRegs.assign(Arg.Regs.begin(), Arg.Regs.end());
    if (NumParts != 1 || OrigLLT != NewLLT) {
      // If we can't directly assign the register, we need one or more
      // intermediate values.
      Arg.Regs.resize(NumParts);

      // For each split register, create and assign a vreg that will store
      // the incoming component of the larger value. These will later be
      // merged to form the final vreg.
      for (unsigned Part = 0; Part < NumParts; ++Part) {
        Arg.Regs[Part] = MRI.createGenericVirtualRegister(NewLLT);
      }
    }

    for (unsigned Part = 0; Part < NumParts; ++Part) {
      MachineInstrBuilder ArgInst =
          MIRBuilder.buildInstr(getWasmArgumentOpcode(NewVT))
              .addDef(Arg.Regs[Part])
              .addImm(FinalArgIdx);

      constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *ArgInst,
                               ArgInst->getDesc(), ArgInst->getOperand(0), 0);
      MFI->addParam(NewVT);
      ++FinalArgIdx;
    }

    if (OrigVT != NewVT) {
      buildCopyFromRegs(MIRBuilder, Arg.OrigRegs, Arg.Regs, OrigLLT, NewLLT,
                        Arg.Flags[0]);
    }
  }

  // For swiftcc, emit additional swiftself and swifterror arguments
  // if there aren't. These additional arguments are also added for callee
  // signature They are necessary to match callee and caller signature for
  // indirect call.
  if (CallConv == CallingConv::Swift) {
    const MVT PtrVT = TLI.getPointerTy(DL);

    if (!HasSwiftSelfArg) {
      MFI->addParam(PtrVT);
    }
    if (!HasSwiftErrorArg) {
      MFI->addParam(PtrVT);
    }
  }

  // Varargs are copied into a buffer allocated by the caller, and a pointer to
  // the buffer is passed as an argument.
  if (F.isVarArg()) {
    const MVT PtrVT = TLI.getPointerTy(DL, 0);
    const LLT PtrLLT = LLT::pointer(0, DL.getPointerSizeInBits(0));
    Register VarargVreg = MF.getRegInfo().createGenericVirtualRegister(PtrLLT);

    MFI->setVarargBufferVreg(VarargVreg);

    MachineInstrBuilder ArgInst =
        MIRBuilder.buildInstr(getWasmArgumentOpcode(PtrVT))
            .addDef(VarargVreg)
            .addImm(FinalArgIdx);

    constrainOperandRegClass(MF, TRI, MRI, TII, RBI, *ArgInst,
                             ArgInst->getDesc(), ArgInst->getOperand(0), 0);

    MFI->addParam(PtrVT);
    ++FinalArgIdx;
  }

  // Record the number and types of arguments and results.
  SmallVector<MVT, 4> Params;
  SmallVector<MVT, 4> Results;
  computeSignatureVTs(MF.getFunction().getFunctionType(), &MF.getFunction(),
                      MF.getFunction(), MF.getTarget(), Params, Results);
  for (MVT VT : Results)
    MFI->addResult(VT);

  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
  // the param logic here with ComputeSignatureVTs
  assert(MFI->getParams().size() == Params.size() &&
         std::equal(MFI->getParams().begin(), MFI->getParams().end(),
                    Params.begin()));
  return true;
}

bool WebAssemblyCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
                                        CallLoweringInfo &Info) const {
  return false;
}
