//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "WebAssemblyTargetMachine.h"
#include "llvm/IR/Analysis.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Scalar/LowerAtomicPass.h"

using namespace llvm;

#define DEBUG_TYPE "wasm-coalesce-features-and-strip-atomics"

namespace {
class WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy final
    : public ModulePass {
  // Take the union of all features used in the module and use it for each
  // function individually, since having multiple feature sets in one module
  // currently does not make sense for WebAssembly. If atomics are not enabled,
  // also strip atomic operations and thread local storage.
  WebAssemblyTargetMachine *WasmTM;

public:
  static char ID;

  WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy(
      WebAssemblyTargetMachine *WasmTM)
      : ModulePass(ID), WasmTM(WasmTM) {}

  bool runOnModule(Module &M) override;
};
} // namespace

char WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy::ID = 0;
INITIALIZE_PASS(WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy, DEBUG_TYPE,
                "Coalesce features and strip atomics", true, false)

ModulePass *llvm::createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
    WebAssemblyTargetMachine &TM) {
  return new WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy(&TM);
}

static std::string getFeatureString(const MCSubtargetInfo &STI,
                                    const FeatureBitset &Features) {
  std::string Ret;
  for (const SubtargetFeatureKV &KV : STI.getAllProcessorFeatures()) {
    if (Features[KV.Value])
      Ret += (StringRef("+") + KV.key() + ",").str();
    else
      Ret += (StringRef("-") + KV.key() + ",").str();
  }
  // remove trailing ','
  Ret.pop_back();
  return Ret;
}

static std::pair<FeatureBitset, std::string>
coalesceFeatures(const Module &M, WebAssemblyTargetMachine *WasmTM) {
  // Union the features of all defined functions. Start with an empty set, so
  // that if a feature is disabled in every function, we'll compute it as
  // disabled. If any function lacks a target-features attribute, it'll
  // default to the target CPU from the `TargetMachine`.
  FeatureBitset Features;
  bool AnyDefined = false;
  for (auto &F : M) {
    if (F.isDeclaration())
      continue;

    Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits();
    AnyDefined = true;
  }

  // If we have no defined functions, use the module-wide feature bits from the
  // `TargetMachine`.
  if (!AnyDefined)
    Features = WasmTM->getMCSubtargetInfo().getFeatureBits();

  return {Features, getFeatureString(WasmTM->getMCSubtargetInfo(), Features)};
}

static void replaceFeatures(Function &F, const std::string &Features) {
  F.removeFnAttr("target-features");
  F.removeFnAttr("target-cpu");
  F.addFnAttr("target-features", Features);
}

static bool stripAtomics(Module &M) {
  // Detect whether any atomics will be lowered, since there is no way to tell
  // whether the LowerAtomic pass lowers e.g. stores.
  bool Stripped = false;
  for (auto &F : M) {
    for (auto &B : F) {
      for (auto &I : B) {
        if (I.isAtomic()) {
          Stripped = true;
          goto done;
        }
      }
    }
  }

done:
  if (!Stripped)
    return false;

  LowerAtomicPass Lowerer;
  FunctionAnalysisManager FAM;
  for (auto &F : M)
    Lowerer.run(F, FAM);

  return true;
}

static bool stripThreadLocals(Module &M) {
  bool Stripped = false;
  for (auto &GV : M.globals()) {
    if (GV.isThreadLocal()) {
      // replace `@llvm.threadlocal.address.pX(GV)` with `GV`.
      for (Use &U : make_early_inc_range(GV.uses())) {
        if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) {
          if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&
              II->getArgOperand(0) == &GV) {
            II->replaceAllUsesWith(&GV);
            II->eraseFromParent();
          }
        }
      }

      Stripped = true;
      GV.setThreadLocal(false);
    }
  }
  return Stripped;
}

static void recordFeatures(Module &M, const WebAssemblySubtarget *ST,
                           const FeatureBitset &Features, bool Stripped) {
  for (const SubtargetFeatureKV &KV : ST->getAllProcessorFeatures()) {
    if (Features[KV.Value]) {
      // Mark features as used
      std::string MDKey = (StringRef("wasm-feature-") + KV.key()).str();
      M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
                      wasm::WASM_FEATURE_PREFIX_USED);
    }
  }
  // Code compiled without atomics or bulk-memory may have had its atomics or
  // thread-local data lowered to nonatomic operations or non-thread-local
  // data. In that case, we mark the pseudo-feature "shared-mem" as disallowed
  // to tell the linker that it would be unsafe to allow this code to be used
  // in a module with shared memory.
  if (Stripped) {
    M.addModuleFlag(Module::ModFlagBehavior::Error, "wasm-feature-shared-mem",
                    wasm::WASM_FEATURE_PREFIX_DISALLOWED);
  }
}

static bool coalesceFeaturesAndStripAtomics(Module &M,
                                            WebAssemblyTargetMachine *WasmTM) {
  auto [Features, FeatureStr] = coalesceFeatures(M, WasmTM);

  WasmTM->setTargetFeatureString(FeatureStr);
  for (auto &F : M)
    replaceFeatures(F, FeatureStr);

  bool StrippedAtomics = false;
  bool StrippedTLS = false;

  // In cooperative threading mode, thread locals are meaningful even without
  // atomics.
  const WebAssemblySubtarget *ST = WasmTM->getSubtargetImpl(
      WasmTM->getTargetCPU(), WasmTM->getTargetFeatureString());
  bool CooperativeThreading = ST->hasCooperativeMultithreading();

  if (!Features[WebAssembly::FeatureAtomics]) {
    StrippedAtomics = stripAtomics(M);
    if (!CooperativeThreading)
      StrippedTLS = stripThreadLocals(M);
  }
  if (!Features[WebAssembly::FeatureBulkMemory] && !StrippedTLS) {
    StrippedTLS = stripThreadLocals(M);
  }

  if (StrippedAtomics && !StrippedTLS && !CooperativeThreading)
    stripThreadLocals(M);
  else if (StrippedTLS && !StrippedAtomics)
    stripAtomics(M);

  bool Stripped = StrippedAtomics || StrippedTLS;
  if (!Stripped &&
      (Features[WebAssembly::FeatureAtomics] ||
       (CooperativeThreading && Features[WebAssembly::FeatureBulkMemory])) &&
      !M.getModuleFlag("thread-model")) {
    M.setThreadModel(ThreadModel::POSIX);
  }

  recordFeatures(M, ST, Features, Stripped);

  // Conservatively assume we have made some change
  return true;
}

bool WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy::runOnModule(Module &M) {
  return coalesceFeaturesAndStripAtomics(M, WasmTM);
}

PreservedAnalyses WebAssemblyCoalesceFeaturesAndStripAtomicsPass::run(
    Module &M, ModuleAnalysisManager &MAM) {
  return coalesceFeaturesAndStripAtomics(M, &TM) ? PreservedAnalyses::none()
                                                 : PreservedAnalyses::all();
}
