//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
//
// 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 defines the WebAssembly-specific subclass of TargetMachine.
///
//===----------------------------------------------------------------------===//

#include "WebAssemblyTargetMachine.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "TargetInfo/WebAssemblyTargetInfo.h"
#include "WebAssembly.h"
#include "WebAssemblyISelLowering.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblyTargetObjectFile.h"
#include "WebAssemblyTargetTransformInfo.h"
#include "WebAssemblyUtilities.h"
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils.h"
#include <optional>
using namespace llvm;

#define DEBUG_TYPE "wasm"

// A command-line option to keep implicit locals
// for the purpose of testing with lit/llc ONLY.
// This produces output which is not valid WebAssembly, and is not supported
// by assemblers/disassemblers and other MC based tools.
cl::opt<bool> WebAssembly::WasmDisableExplicitLocals(
    "wasm-disable-explicit-locals", cl::Hidden,
    cl::desc("WebAssembly: output implicit locals in"
             " instruction output for test purposes only."),
    cl::init(false));

// Exception handling & setjmp-longjmp handling related options.

// Emscripten's asm.js-style setjmp/longjmp handling
cl::opt<bool> WebAssembly::WasmEnableEmSjLj(
    "enable-emscripten-sjlj",
    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
    cl::init(false));
// setjmp/longjmp handling using wasm EH instructions
cl::opt<bool> WebAssembly::WasmEnableSjLj(
    "wasm-enable-sjlj", cl::desc("WebAssembly setjmp/longjmp handling"));
// If true, use the legacy Wasm EH proposal:
// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
// And if false, use the standardized Wasm EH proposal:
// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
// Currently set to true by default because not all major web browsers turn on
// the new standard proposal by default, but will later change to false.
cl::opt<bool> WebAssembly::WasmUseLegacyEH(
    "wasm-use-legacy-eh", cl::desc("WebAssembly exception handling (legacy)"),
    cl::init(true));

extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
LLVMInitializeWebAssemblyTarget() {
  // Register the target.
  RegisterTargetMachine<WebAssemblyTargetMachine> X(
      getTheWebAssemblyTarget32());
  RegisterTargetMachine<WebAssemblyTargetMachine> Y(
      getTheWebAssemblyTarget64());

  // Register backend passes
  auto &PR = *PassRegistry::getPassRegistry();
  initializeGlobalISel(PR);
  initializeWebAssemblyPreLegalizerCombinerLegacyPass(PR);
  initializeWebAssemblyPostLegalizerCombinerLegacyPass(PR);
  initializeWebAssemblyAddMissingPrototypesLegacyPass(PR);
  initializeWebAssemblyLowerEmscriptenEHSjLjLegacyPass(PR);
  initializeLowerGlobalDtorsLegacyPassPass(PR);
  initializeWebAssemblyFixFunctionBitcastsLegacyPass(PR);
  initializeWebAssemblyOptimizeReturnedLegacyPass(PR);
  initializeWebAssemblyRefTypeMem2LocalLegacyPass(PR);
  initializeWebAssemblyArgumentMoveLegacyPass(PR);
  initializeWebAssemblyAsmPrinterPass(PR);
  initializeWebAssemblySetP2AlignOperandsLegacyPass(PR);
  initializeWebAssemblyReplacePhysRegsLegacyPass(PR);
  initializeWebAssemblyOptimizeLiveIntervalsLegacyPass(PR);
  initializeWebAssemblyMemIntrinsicResultsLegacyPass(PR);
  initializeWebAssemblyRegStackifyLegacyPass(PR);
  initializeWebAssemblyRegColoringLegacyPass(PR);
  initializeWebAssemblyNullifyDebugValueListsLegacyPass(PR);
  initializeWebAssemblyFixIrreducibleControlFlowLegacyPass(PR);
  initializeWebAssemblyLateEHPrepareLegacyPass(PR);
  initializeWebAssemblyExceptionInfoWrapperPassPass(PR);
  initializeWebAssemblyCFGSortLegacyPass(PR);
  initializeWebAssemblyCFGStackifyLegacyPass(PR);
  initializeWebAssemblyExplicitLocalsLegacyPass(PR);
  initializeWebAssemblyLowerBrUnlessLegacyPass(PR);
  initializeWebAssemblyRegNumberingLegacyPass(PR);
  initializeWebAssemblyDebugFixupLegacyPass(PR);
  initializeWebAssemblyPeepholeLegacyPass(PR);
  initializeWebAssemblyMCLowerPreLegacyPass(PR);
  initializeWebAssemblyFixBrTableDefaultsLegacyPass(PR);
  initializeWebAssemblyDAGToDAGISelLegacyPass(PR);
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering public interface.
//===----------------------------------------------------------------------===//

static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
  // Default to static relocation model.  This should always be more optimal
  // than PIC since the static linker can determine all global addresses and
  // assume direct function calls.
  return RM.value_or(Reloc::Static);
}

using WebAssembly::WasmDisableExplicitLocals;
using WebAssembly::WasmEnableEmSjLj;
using WebAssembly::WasmEnableSjLj;

static void basicCheckForEHAndSjLj(TargetMachine *TM) {

  bool EnableEmEH = TM->Options.ExceptionModel == ExceptionHandling::Emscripten;

  // You can't enable two modes of SjLj at the same time
  if (WasmEnableEmSjLj && WasmEnableSjLj)
    report_fatal_error(
        "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");
  // You can't mix Emscripten EH with Wasm SjLj.
  if (EnableEmEH && WasmEnableSjLj)
    report_fatal_error(
        "-exception-model=emscripten not allowed with -wasm-enable-sjlj");

  if (TM->Options.ExceptionModel == ExceptionHandling::Default) {
    // FIXME: This flag should be removed in favor of directly using the
    // generically configured ExceptionsType.
    if (WebAssembly::WasmEnableSjLj)
      TM->Options.ExceptionModel = ExceptionHandling::Wasm;
  }

  // Basic Correctness checking related to -exception-model
  if (TM->Options.ExceptionModel != ExceptionHandling::Default &&
      TM->Options.ExceptionModel != ExceptionHandling::None &&
      TM->Options.ExceptionModel != ExceptionHandling::Wasm &&
      TM->Options.ExceptionModel != ExceptionHandling::Emscripten)
    report_fatal_error(
        "-exception-model should be either 'none', 'wasm', or 'emscripten'");
  if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
    report_fatal_error(
        "-wasm-enable-sjlj only allowed with -exception-model=wasm");

  // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
  // measure, but some code will error out at compile time in this combination.
  // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
}

/// Create an WebAssembly architecture model.
///
WebAssemblyTargetMachine::WebAssemblyTargetMachine(
    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
    const TargetOptions &Options, std::optional<Reloc::Model> RM,
    std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)
    : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
                               getEffectiveRelocModel(RM),
                               getEffectiveCodeModel(CM, CodeModel::Large), OL),
      TLOF(new WebAssemblyTargetObjectFile()) {
  // WebAssembly type-checks instructions, but a noreturn function with a return
  // type that doesn't match the context will cause a check failure. So we lower
  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
  // 'unreachable' instructions which is meant for that case. Formerly, we also
  // needed to add checks to SP failure emission in the instruction selection
  // backends, but this has since been tied to TrapUnreachable and is no longer
  // necessary.
  this->Options.TrapUnreachable = true;
  this->Options.NoTrapAfterNoreturn = false;

  // WebAssembly treats each function as an independent unit. Force
  // -ffunction-sections, effectively, so that we can emit them independently.
  this->Options.FunctionSections = true;
  this->Options.DataSections = true;
  this->Options.UniqueSectionNames = true;

  basicCheckForEHAndSjLj(this);
  initAsmInfo();

  // WebAssembly does not run RegAllocFast; tied operands must be lowered by
  // TwoAddressInstructionPass.
  setEnableTiedFastRegAlloc(false);

  LLT::setUseExtended(true);

  // Note that we don't use setRequiresStructuredCFG(true). It disables
  // optimizations than we're ok with, and want, such as critical edge
  // splitting and tail merging.
}

WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(StringRef CPU, StringRef FS,
                                           StringRef ABIName) const {
  auto &I = SubtargetMap[CPU.str() + FS.str() + ABIName.str()];
  if (!I) {
    I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this,
                                               ABIName);
  }
  return I.get();
}

const WebAssemblySubtarget *
WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
  Attribute CPUAttr = F.getFnAttribute("target-cpu");
  Attribute FSAttr = F.getFnAttribute("target-features");

  StringRef CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString() : TargetCPU;
  StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS;

  return getSubtargetImpl(CPU, FS, getTargetABIName(*F.getParent()));
}

namespace {

/// WebAssembly Code Generator Pass Configuration Options.
class WebAssemblyPassConfig final : public TargetPassConfig {
public:
  WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
      : TargetPassConfig(TM, PM) {}

  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
    return getTM<WebAssemblyTargetMachine>();
  }

  FunctionPass *createTargetRegisterAllocator(bool) override;

  void addIRPasses() override;
  void addPassesToHandleExceptions() override;
  void addISelPrepare() override;
  bool addInstSelector() override;
  void addOptimizedRegAlloc() override;
  void addPostRegAlloc() override;
  bool addGCPasses() override { return false; }
  void addPreEmitPass() override;
  bool addPreISel() override;

  // No reg alloc
  bool addRegAssignAndRewriteFast() override { return false; }

  // No reg alloc
  bool addRegAssignAndRewriteOptimized() override { return false; }

  bool addIRTranslator() override;
  void addPreLegalizeMachineIR() override;
  bool addLegalizeMachineIR() override;
  void addPreRegBankSelect() override;
  bool addRegBankSelect() override;
  bool addGlobalInstructionSelect() override;
};
} // end anonymous namespace

MachineFunctionInfo *WebAssemblyTargetMachine::createMachineFunctionInfo(
    BumpPtrAllocator &Allocator, const Function &F,
    const TargetSubtargetInfo *STI) const {
  return WebAssemblyFunctionInfo::create<WebAssemblyFunctionInfo>(Allocator, F,
                                                                  STI);
}

TargetTransformInfo
WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) const {
  return TargetTransformInfo(std::make_unique<WebAssemblyTTIImpl>(this, F));
}

TargetPassConfig *
WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
  return new WebAssemblyPassConfig(*this, PM);
}

FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
  return nullptr; // No reg alloc
}

//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
//===----------------------------------------------------------------------===//

void WebAssemblyPassConfig::addIRPasses() {
  // Add signatures to prototype-less function declarations
  addPass(createWebAssemblyAddMissingPrototypesLegacyPass());

  // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
  addPass(createLowerGlobalDtorsLegacyPass());

  // Fix function bitcasts, as WebAssembly requires caller and callee signatures
  // to match.
  addPass(createWebAssemblyFixFunctionBitcastsLegacyPass());

  // Optimize "returned" function attributes.
  if (getOptLevel() != CodeGenOptLevel::None)
    addPass(createWebAssemblyOptimizeReturnedLegacyPass());

  // Wasm SjLj shares Emscripten SjLj's transformation, so it is handled here.
  // Without Wasm or Emscripten EH, this also lowers invokes.
  addPass(createWebAssemblyLowerEmscriptenEHSjLjLegacyPass());

  // Expand indirectbr instructions to switches.
  addPass(createIndirectBrExpandPass(getOptLevel()));

  // Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
  addPass(createWebAssemblyReduceToAnyAllTrueLegacyPass(
      getWebAssemblyTargetMachine()));

  TargetPassConfig::addIRPasses();
}

void WebAssemblyPassConfig::addPassesToHandleExceptions() {
  // Wasm EH needs WinEHPrepare to remove the catchswitch PHIs SelectionDAG
  // cannot lower.
  addPass(createWinEHPass());
  addPass(createWasmEHPass());
}

void WebAssemblyPassConfig::addISelPrepare() {
  // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
  // loads and stores are promoted to local.gets/local.sets.
  addPass(createWebAssemblyRefTypeMem2LocalLegacyPass());
  // Lower atomics and TLS if necessary
  addPass(createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
      getWebAssemblyTargetMachine()));

  // This is a no-op if atomics are not used in the module
  addPass(createAtomicExpandLegacyPass());

  TargetPassConfig::addISelPrepare();
}

bool WebAssemblyPassConfig::addInstSelector() {
  (void)TargetPassConfig::addInstSelector();
  addPass(createWebAssemblyISelDagLegacyPass(getWebAssemblyTargetMachine(),
                                             getOptLevel()));
  // Run the argument-move pass immediately after the ScheduleDAG scheduler
  // so that we can fix up the ARGUMENT instructions before anything else
  // sees them in the wrong place.
  addPass(createWebAssemblyArgumentMoveLegacyPass());
  // Set the p2align operands. This information is present during ISel, however
  // it's inconvenient to collect. Collect it now, and update the immediate
  // operands.
  addPass(createWebAssemblySetP2AlignOperandsLegacyPass());

  // Eliminate range checks and add default targets to br_table instructions.
  addPass(createWebAssemblyFixBrTableDefaultsLegacyPass());

  // unreachable is terminator, non-terminator instruction after it is not
  // allowed.
  addPass(createWebAssemblyCleanCodeAfterTrapLegacyPass());

  return false;
}

void WebAssemblyPassConfig::addOptimizedRegAlloc() {
  // Currently RegisterCoalesce degrades wasm debug info quality by a
  // significant margin. As a quick fix, disable this for -O1, which is often
  // used for debugging large applications. Disabling this increases code size
  // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is
  // usually not used for production builds.
  // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
  // it properly
  if (getOptLevel() == CodeGenOptLevel::Less)
    disablePass(&RegisterCoalescerID);
  TargetPassConfig::addOptimizedRegAlloc();
}

void WebAssemblyPassConfig::addPostRegAlloc() {
  // TODO: The following CodeGen passes don't currently support code containing
  // virtual registers. Consider removing their restrictions and re-enabling
  // them.

  // These functions all require the NoVRegs property.
  disablePass(&MachineLateInstrsCleanupID);
  disablePass(&MachineCopyPropagationID);
  disablePass(&PostRAMachineSinkingID);
  disablePass(&PostRASchedulerID);
  disablePass(&FuncletLayoutID);
  disablePass(&StackMapLivenessID);
  disablePass(&PatchableFunctionID);
  disablePass(&ShrinkWrapID);
  disablePass(&RemoveLoadsIntoFakeUsesID);

  // This pass hurts code size for wasm because it can generate irreducible
  // control flow.
  disablePass(&MachineBlockPlacementID);

  TargetPassConfig::addPostRegAlloc();
}

void WebAssemblyPassConfig::addPreEmitPass() {
  TargetPassConfig::addPreEmitPass();

  // Nullify DBG_VALUE_LISTs that we cannot handle.
  addPass(createWebAssemblyNullifyDebugValueListsLegacyPass());

  // Remove any unreachable blocks that may be left floating around.
  // Rare, but possible. Needed for WebAssemblyFixIrreducibleControlFlow.
  addPass(&UnreachableMachineBlockElimID);

  // Eliminate multiple-entry loops.
  addPass(createWebAssemblyFixIrreducibleControlFlowLegacyPass());

  // Do various transformations for exception handling.
  // Every CFG-changing optimizations should come before this.
  addPass(createWebAssemblyLateEHPrepareLegacyPass());

  // Now that we have a prologue and epilogue and all frame indices are
  // rewritten, eliminate SP and FP. This allows them to be stackified,
  // colored, and numbered with the rest of the registers.
  addPass(createWebAssemblyReplacePhysRegsLegacyPass());

  // Preparations and optimizations related to register stackification.
  if (getOptLevel() != CodeGenOptLevel::None) {
    // Depend on LiveIntervals and perform some optimizations on it.
    addPass(createWebAssemblyOptimizeLiveIntervalsLegacyPass());

    // Prepare memory intrinsic calls for register stackifying.
    addPass(createWebAssemblyMemIntrinsicResultsLegacyPass());
  }

  // Mark registers as representing wasm's value stack. This is a key
  // code-compression technique in WebAssembly. We run this pass (and
  // MemIntrinsicResults above) very late, so that it sees as much code as
  // possible, including code emitted by PEI and expanded by late tail
  // duplication.
  addPass(createWebAssemblyRegStackifyLegacyPass(getOptLevel()));

  if (getOptLevel() != CodeGenOptLevel::None) {
    // Run the register coloring pass to reduce the total number of registers.
    // This runs after stackification so that it doesn't consider registers
    // that become stackified.
    addPass(createWebAssemblyRegColoringLegacyPass());
  }

  // Sort the blocks of the CFG into topological order, a prerequisite for
  // BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGSortLegacyPass());

  // Insert BLOCK and LOOP markers.
  addPass(createWebAssemblyCFGStackifyLegacyPass());

  // Insert explicit local.get and local.set operators.
  if (!WasmDisableExplicitLocals)
    addPass(createWebAssemblyExplicitLocalsLegacyPass());

  // Lower br_unless into br_if.
  addPass(createWebAssemblyLowerBrUnlessLegacyPass());

  // Perform the very last peephole optimizations on the code.
  if (getOptLevel() != CodeGenOptLevel::None)
    addPass(createWebAssemblyPeepholeLegacyPass());

  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
  addPass(createWebAssemblyRegNumberingLegacyPass());

  // Fix debug_values whose defs have been stackified.
  if (!WasmDisableExplicitLocals)
    addPass(createWebAssemblyDebugFixupLegacyPass());

  // Collect information to prepare for MC lowering / asm printing.
  addPass(createWebAssemblyMCLowerPreLegacyPass());
}

bool WebAssemblyPassConfig::addPreISel() {
  TargetPassConfig::addPreISel();
  return false;
}

bool WebAssemblyPassConfig::addIRTranslator() {
  addPass(new IRTranslatorLegacy());
  return false;
}

void WebAssemblyPassConfig::addPreLegalizeMachineIR() {
  if (getOptLevel() != CodeGenOptLevel::None) {
    addPass(createWebAssemblyPreLegalizerCombinerLegacyPass());
  }
}
bool WebAssemblyPassConfig::addLegalizeMachineIR() {
  addPass(new LegalizerLegacy());
  return false;
}

void WebAssemblyPassConfig::addPreRegBankSelect() {
  if (getOptLevel() != CodeGenOptLevel::None) {
    addPass(createWebAssemblyPostLegalizerCombinerLegacyPass());
  }
}

bool WebAssemblyPassConfig::addRegBankSelect() {
  addPass(new RegBankSelectLegacy());
  return false;
}

bool WebAssemblyPassConfig::addGlobalInstructionSelect() {
  addPass(new InstructionSelectLegacy(getOptLevel()));

  // We insert only if ISelDAG won't insert these at a later point.
  if (isGlobalISelAbortEnabled()) {
    addPass(createWebAssemblyArgumentMoveLegacyPass());
    addPass(createWebAssemblySetP2AlignOperandsLegacyPass());
    addPass(createWebAssemblyFixBrTableDefaultsLegacyPass());
    addPass(createWebAssemblyCleanCodeAfterTrapLegacyPass());
  }

  return false;
}

yaml::MachineFunctionInfo *
WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
  return new yaml::WebAssemblyFunctionInfo();
}

yaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(
    const MachineFunction &MF) const {
  const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
  return new yaml::WebAssemblyFunctionInfo(MF, *MFI);
}

bool WebAssemblyTargetMachine::parseMachineFunctionInfo(
    const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
    SMDiagnostic &Error, SMRange &SourceRange) const {
  const auto &YamlMFI = static_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);
  MachineFunction &MF = PFS.MF;
  MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(MF, YamlMFI);
  return false;
}
