<commit_before>// 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 "iree/compiler/Dialect/HAL/Target/LLVM/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/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"

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

static llvm::CodeGenOpt::Level passBuilderOptLevelToCodeGenOptLevel(
    const llvm::OptimizationLevel &level) {
  switch (level.getSpeedupLevel()) {
    case 0:
      return llvm::CodeGenOpt::None;
    case 1:
      return llvm::CodeGenOpt::Less;
    case 2:
    default:
      return llvm::CodeGenOpt::Default;
    case 3:
      return llvm::CodeGenOpt::Aggressive;
  }
}

std::unique_ptr<llvm::TargetMachine> createTargetMachine(
    const LLVMTargetOptions &targetOptions) {
  std::string errorMessage;
  auto target = llvm::TargetRegistry::lookupTarget(targetOptions.targetTriple,
                                                   errorMessage);
  if (!target) return nullptr;
  std::unique_ptr<llvm::TargetMachine> machine(target->createTargetMachine(
      targetOptions.targetTriple, targetOptions.targetCPU /* cpu e.g k8*/,
      targetOptions.targetCPUFeatures /* cpu features e.g avx512fma*/,
      targetOptions.options, llvm::Reloc::Model::PIC_, {},
      passBuilderOptLevelToCodeGenOptLevel(targetOptions.optLevel),
      /*JIT=*/false));
  return machine;
}

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

  llvm::PassInstrumentationCallbacks passInstrumentationCallbacks;
  llvm::StandardInstrumentations standardInstrumentations(
      /*DebugLogging=*/false);
  standardInstrumentations.registerCallbacks(passInstrumentationCallbacks);

  llvm::PassBuilder passBuilder(machine, options.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 (options.sanitizerKind) {
    case SanitizerKind::kNone:
      break;
    case SanitizerKind::kAddress: {
      passBuilder.registerOptimizerLastEPCallback(
          [](llvm::ModulePassManager &modulePassManager,
             llvm::OptimizationLevel Level) {
            llvm::AddressSanitizerOptions Opts;
            bool moduleUseAfterScope = false;
            bool useOdrIndicator = false;
            modulePassManager.addPass(
                llvm::RequireAnalysisPass<llvm::ASanGlobalsMetadataAnalysis,
                                          llvm::Module>());
            modulePassManager.addPass(llvm::ModuleAddressSanitizerPass(
                Opts, moduleUseAfterScope, useOdrIndicator));
            modulePassManager.addPass(createModuleToFunctionPassAdaptor(
                llvm::AddressSanitizerPass(Opts)));
          });
    } break;
  }

  if (options.optLevel != llvm::OptimizationLevel::O0) {
    llvm::ModulePassManager modulePassManager;
    modulePassManager =
        passBuilder.buildPerModuleDefaultPipeline(options.optLevel);
    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;
  {
    // TODO(ataei): Use non legacy pass mamanger for this.
    llvm::legacy::PassManager passManager;
    passManager.add(
        new llvm::TargetLibraryInfoWrapperPass(machine->getTargetTriple()));
    llvm::raw_svector_ostream ostream(stream_buffer);
    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 HAL
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir
<commit_msg>Fix use-after-free of ostream in the passManager dtor (#7753)<commit_after>// 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 "iree/compiler/Dialect/HAL/Target/LLVM/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/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizer.h"

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

static llvm::CodeGenOpt::Level passBuilderOptLevelToCodeGenOptLevel(
    const llvm::OptimizationLevel &level) {
  switch (level.getSpeedupLevel()) {
    case 0:
      return llvm::CodeGenOpt::None;
    case 1:
      return llvm::CodeGenOpt::Less;
    case 2:
    default:
      return llvm::CodeGenOpt::Default;
    case 3:
      return llvm::CodeGenOpt::Aggressive;
  }
}

std::unique_ptr<llvm::TargetMachine> createTargetMachine(
    const LLVMTargetOptions &targetOptions) {
  std::string errorMessage;
  auto target = llvm::TargetRegistry::lookupTarget(targetOptions.targetTriple,
                                                   errorMessage);
  if (!target) return nullptr;
  std::unique_ptr<llvm::TargetMachine> machine(target->createTargetMachine(
      targetOptions.targetTriple, targetOptions.targetCPU /* cpu e.g k8*/,
      targetOptions.targetCPUFeatures /* cpu features e.g avx512fma*/,
      targetOptions.options, llvm::Reloc::Model::PIC_, {},
      passBuilderOptLevelToCodeGenOptLevel(targetOptions.optLevel),
      /*JIT=*/false));
  return machine;
}

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

  llvm::PassInstrumentationCallbacks passInstrumentationCallbacks;
  llvm::StandardInstrumentations standardInstrumentations(
      /*DebugLogging=*/false);
  standardInstrumentations.registerCallbacks(passInstrumentationCallbacks);

  llvm::PassBuilder passBuilder(machine, options.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 (options.sanitizerKind) {
    case SanitizerKind::kNone:
      break;
    case SanitizerKind::kAddress: {
      passBuilder.registerOptimizerLastEPCallback(
          [](llvm::ModulePassManager &modulePassManager,
             llvm::OptimizationLevel Level) {
            llvm::AddressSanitizerOptions Opts;
            bool moduleUseAfterScope = false;
            bool useOdrIndicator = false;
            modulePassManager.addPass(
                llvm::RequireAnalysisPass<llvm::ASanGlobalsMetadataAnalysis,
                                          llvm::Module>());
            modulePassManager.addPass(llvm::ModuleAddressSanitizerPass(
                Opts, moduleUseAfterScope, useOdrIndicator));
            modulePassManager.addPass(createModuleToFunctionPassAdaptor(
                llvm::AddressSanitizerPass(Opts)));
          });
    } break;
  }

  if (options.optLevel != llvm::OptimizationLevel::O0) {
    llvm::ModulePassManager modulePassManager;
    modulePassManager =
        passBuilder.buildPerModuleDefaultPipeline(options.optLevel);
    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 HAL
}  // namespace IREE
}  // namespace iree_compiler
}  // namespace mlir

{'fraction_non_alphanumeric': 0.10391131939437635, 'fraction_numerical': 0.003604902667627974, 'mean_word_length': 3.4872624342903356, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '412086', 'n_tokens_mistral': 3126, 'n_tokens_neox': 3081, 'n_words': 540}