// Copyright 2020 The IREE Authors
//
// Licensed 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 "compiler/plugins/target/LLVMCPU/LLVMIRPasses.h"

#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"

namespace mlir::iree_compiler::IREE::HAL {

LogicalResult runLLVMIRPasses(const LLVMTarget &target,
                              llvm::TargetMachine *machine,
                              llvm::Module *module) {
  llvm::LoopAnalysisManager loopAnalysisManager;
  llvm::FunctionAnalysisManager functionAnalysisManager;
  llvm::CGSCCAnalysisManager cGSCCAnalysisManager;
  llvm::ModuleAnalysisManager moduleAnalysisManager;

  llvm::PassInstrumentationCallbacks passInstrumentationCallbacks;
  llvm::StandardInstrumentations standardInstrumentations(
      module->getContext(),
      /*DebugLogging=*/false);
  standardInstrumentations.registerCallbacks(passInstrumentationCallbacks);

  llvm::PassBuilder passBuilder(machine, target.pipelineTuningOptions, {},
                                &passInstrumentationCallbacks);
  llvm::AAManager aa = passBuilder.buildDefaultAAPipeline();
  functionAnalysisManager.registerPass([&] { return std::move(aa); });

  passBuilder.registerModuleAnalyses(moduleAnalysisManager);
  passBuilder.registerCGSCCAnalyses(cGSCCAnalysisManager);
  passBuilder.registerFunctionAnalyses(functionAnalysisManager);
  passBuilder.registerLoopAnalyses(loopAnalysisManager);
  passBuilder.crossRegisterProxies(loopAnalysisManager, functionAnalysisManager,
                                   cGSCCAnalysisManager, moduleAnalysisManager);

  switch (target.sanitizerKind) {
  case SanitizerKind::kNone:
    break;
  case SanitizerKind::kAddress: {
    passBuilder.registerOptimizerLastEPCallback(
        [](llvm::ModulePassManager &modulePassManager,
           llvm::OptimizationLevel Level, llvm::ThinOrFullLTOPhase) {
          llvm::AddressSanitizerOptions opts;
          // Can use Never or Always, just not the default Runtime, which
          // introduces a reference to
          // __asan_option_detect_stack_use_after_return, causing linker
          // errors, and anyway we wouldn't really want bother to with a
          // runtime switch for that.
          opts.UseAfterReturn = llvm::AsanDetectStackUseAfterReturnMode::Always;
          bool moduleUseAfterScope = false;
          bool useOdrIndicator = false;
          modulePassManager.addPass(llvm::AddressSanitizerPass(
              opts, moduleUseAfterScope, useOdrIndicator));
        });
  } break;
  case SanitizerKind::kThread: {
    passBuilder.registerOptimizerLastEPCallback(
        [](llvm::ModulePassManager &modulePassManager,
           llvm::OptimizationLevel Level, llvm::ThinOrFullLTOPhase) {
          modulePassManager.addPass(llvm::ModuleThreadSanitizerPass());
          modulePassManager.addPass(llvm::createModuleToFunctionPassAdaptor(
              llvm::ThreadSanitizerPass()));
        });
  } break;
  }

  if (target.optimizerOptLevel != llvm::OptimizationLevel::O0 ||
      target.sanitizerKind != SanitizerKind::kNone) {
    llvm::ModulePassManager modulePassManager;
    modulePassManager =
        passBuilder.buildPerModuleDefaultPipeline(target.optimizerOptLevel);
    modulePassManager.run(*module, moduleAnalysisManager);
  }

  if (llvm::verifyModule(*module))
    return failure();

  return success();
}

LogicalResult runEmitObjFilePasses(llvm::TargetMachine *machine,
                                   llvm::Module *module,
                                   llvm::CodeGenFileType fileType,
                                   std::string *objData) {
  llvm::SmallVector<char, 0> stream_buffer;
  {
    llvm::raw_svector_ostream ostream(stream_buffer);
    // TODO(ataei): Use non legacy pass mamanger for this.
    llvm::legacy::PassManager passManager;
    passManager.add(
        new llvm::TargetLibraryInfoWrapperPass(machine->getTargetTriple()));
    if (machine->addPassesToEmitFile(passManager, ostream,
                                     /*DwoOut=*/nullptr, fileType)) {
      return failure();
    }
    passManager.run(*module);
  }
  // TODO(ataei): This is a work around stream truncation when directly write to
  // string.
  *objData = std::string(stream_buffer.begin(), stream_buffer.end());
  return success();
}

} // namespace mlir::iree_compiler::IREE::HAL
