|
|
|
@ -60,7 +60,6 @@
|
|
|
|
|
#include "llvm/Transforms/IPO.h"
|
|
|
|
|
#include "llvm/Transforms/IPO/AlwaysInliner.h"
|
|
|
|
|
#include "llvm/Transforms/IPO/LowerTypeTests.h"
|
|
|
|
|
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
|
|
|
|
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
|
|
|
|
|
#include "llvm/Transforms/InstCombine/InstCombine.h"
|
|
|
|
|
#include "llvm/Transforms/Instrumentation.h"
|
|
|
|
@ -127,8 +126,6 @@ class EmitAssemblyHelper {
|
|
|
|
|
return TargetIRAnalysis();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM);
|
|
|
|
|
|
|
|
|
|
/// Generates the TargetMachine.
|
|
|
|
|
/// Leaves TM unchanged if it is unable to create the target machine.
|
|
|
|
|
/// Some of our clang tests specify triples which are not built
|
|
|
|
@ -192,60 +189,10 @@ public:
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<TargetMachine> TM;
|
|
|
|
|
|
|
|
|
|
// Emit output using the legacy pass manager for the optimization pipeline.
|
|
|
|
|
// This will be removed soon when using the legacy pass manager for the
|
|
|
|
|
// optimization pipeline is no longer supported.
|
|
|
|
|
void EmitAssemblyWithLegacyPassManager(BackendAction Action,
|
|
|
|
|
std::unique_ptr<raw_pwrite_stream> OS);
|
|
|
|
|
|
|
|
|
|
// Emit output using the new pass manager for the optimization pipeline. This
|
|
|
|
|
// is the default.
|
|
|
|
|
// Emit output using the new pass manager for the optimization pipeline.
|
|
|
|
|
void EmitAssembly(BackendAction Action,
|
|
|
|
|
std::unique_ptr<raw_pwrite_stream> OS);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// We need this wrapper to access LangOpts and CGOpts from extension functions
|
|
|
|
|
// that we add to the PassManagerBuilder.
|
|
|
|
|
class PassManagerBuilderWrapper : public PassManagerBuilder {
|
|
|
|
|
public:
|
|
|
|
|
PassManagerBuilderWrapper(const Triple &TargetTriple,
|
|
|
|
|
const CodeGenOptions &CGOpts,
|
|
|
|
|
const LangOptions &LangOpts)
|
|
|
|
|
: TargetTriple(TargetTriple), CGOpts(CGOpts), LangOpts(LangOpts) {}
|
|
|
|
|
const Triple &getTargetTriple() const { return TargetTriple; }
|
|
|
|
|
const CodeGenOptions &getCGOpts() const { return CGOpts; }
|
|
|
|
|
const LangOptions &getLangOpts() const { return LangOpts; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const Triple &TargetTriple;
|
|
|
|
|
const CodeGenOptions &CGOpts;
|
|
|
|
|
const LangOptions &LangOpts;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addObjCARCAPElimPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
|
|
|
|
|
if (Builder.OptLevel > 0)
|
|
|
|
|
PM.add(createObjCARCAPElimPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addObjCARCExpandPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
|
|
|
|
|
if (Builder.OptLevel > 0)
|
|
|
|
|
PM.add(createObjCARCExpandPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addObjCARCOptPass(const PassManagerBuilder &Builder, PassManagerBase &PM) {
|
|
|
|
|
if (Builder.OptLevel > 0)
|
|
|
|
|
PM.add(createObjCARCOptPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addAddDiscriminatorsPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createAddDiscriminatorsPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addBoundsCheckingPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createBoundsCheckingLegacyPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static SanitizerCoverageOptions
|
|
|
|
@ -271,17 +218,6 @@ getSancovOptsFromCGOpts(const CodeGenOptions &CGOpts) {
|
|
|
|
|
return Opts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addSanitizerCoveragePass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
|
|
|
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
|
|
|
|
auto Opts = getSancovOptsFromCGOpts(CGOpts);
|
|
|
|
|
PM.add(createModuleSanitizerCoverageLegacyPassPass(
|
|
|
|
|
Opts, CGOpts.SanitizeCoverageAllowlistFiles,
|
|
|
|
|
CGOpts.SanitizeCoverageIgnorelistFiles));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check if ASan should use GC-friendly instrumentation for globals.
|
|
|
|
|
// First of all, there is no point if -fdata-sections is off (expect for MachO,
|
|
|
|
|
// where this is not a factor). Also, on ELF this feature requires an assembler
|
|
|
|
@ -307,122 +243,6 @@ static bool asanUseGlobalsGC(const Triple &T, const CodeGenOptions &CGOpts) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addMemProfilerPasses(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createMemProfilerFunctionPass());
|
|
|
|
|
PM.add(createModuleMemProfilerLegacyPassPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper&>(Builder);
|
|
|
|
|
const Triple &T = BuilderWrapper.getTargetTriple();
|
|
|
|
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
|
|
|
|
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Address);
|
|
|
|
|
bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope;
|
|
|
|
|
bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
|
|
|
|
|
bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
|
|
|
|
|
llvm::AsanDtorKind DestructorKind = CGOpts.getSanitizeAddressDtor();
|
|
|
|
|
llvm::AsanDetectStackUseAfterReturnMode UseAfterReturn =
|
|
|
|
|
CGOpts.getSanitizeAddressUseAfterReturn();
|
|
|
|
|
PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
|
|
|
|
|
UseAfterScope, UseAfterReturn));
|
|
|
|
|
PM.add(createModuleAddressSanitizerLegacyPassPass(
|
|
|
|
|
/*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator,
|
|
|
|
|
DestructorKind));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createAddressSanitizerFunctionPass(
|
|
|
|
|
/*CompileKernel*/ true, /*Recover*/ true, /*UseAfterScope*/ false,
|
|
|
|
|
/*UseAfterReturn*/ llvm::AsanDetectStackUseAfterReturnMode::Never));
|
|
|
|
|
PM.add(createModuleAddressSanitizerLegacyPassPass(
|
|
|
|
|
/*CompileKernel*/ true, /*Recover*/ true, /*UseGlobalsGC*/ true,
|
|
|
|
|
/*UseOdrIndicator*/ false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
|
|
|
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
|
|
|
|
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::HWAddress);
|
|
|
|
|
PM.add(createHWAddressSanitizerLegacyPassPass(
|
|
|
|
|
/*CompileKernel*/ false, Recover,
|
|
|
|
|
/*DisableOptimization*/ CGOpts.OptimizationLevel == 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addKernelHWAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper &>(Builder);
|
|
|
|
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
|
|
|
|
PM.add(createHWAddressSanitizerLegacyPassPass(
|
|
|
|
|
/*CompileKernel*/ true, /*Recover*/ true,
|
|
|
|
|
/*DisableOptimization*/ CGOpts.OptimizationLevel == 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addGeneralOptsForMemorySanitizer(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM,
|
|
|
|
|
bool CompileKernel) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper&>(Builder);
|
|
|
|
|
const CodeGenOptions &CGOpts = BuilderWrapper.getCGOpts();
|
|
|
|
|
int TrackOrigins = CGOpts.SanitizeMemoryTrackOrigins;
|
|
|
|
|
bool Recover = CGOpts.SanitizeRecover.has(SanitizerKind::Memory);
|
|
|
|
|
PM.add(createMemorySanitizerLegacyPassPass(
|
|
|
|
|
MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel,
|
|
|
|
|
CGOpts.SanitizeMemoryParamRetval != 0}));
|
|
|
|
|
|
|
|
|
|
// MemorySanitizer inserts complex instrumentation that mostly follows
|
|
|
|
|
// the logic of the original code, but operates on "shadow" values.
|
|
|
|
|
// It can benefit from re-running some general purpose optimization passes.
|
|
|
|
|
if (Builder.OptLevel > 0) {
|
|
|
|
|
PM.add(createEarlyCSEPass());
|
|
|
|
|
PM.add(createReassociatePass());
|
|
|
|
|
PM.add(createLICMPass());
|
|
|
|
|
PM.add(createGVNPass());
|
|
|
|
|
PM.add(createInstructionCombiningPass());
|
|
|
|
|
PM.add(createDeadStoreEliminationPass());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addKernelMemorySanitizerPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
addGeneralOptsForMemorySanitizer(Builder, PM, /*CompileKernel*/ true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addThreadSanitizerPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createThreadSanitizerLegacyPassPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addDataFlowSanitizerPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
const PassManagerBuilderWrapper &BuilderWrapper =
|
|
|
|
|
static_cast<const PassManagerBuilderWrapper&>(Builder);
|
|
|
|
|
const LangOptions &LangOpts = BuilderWrapper.getLangOpts();
|
|
|
|
|
PM.add(createDataFlowSanitizerLegacyPassPass(LangOpts.NoSanitizeFiles));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addEntryExitInstrumentationPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createEntryExitInstrumenterPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
addPostInlineEntryExitInstrumentationPass(const PassManagerBuilder &Builder,
|
|
|
|
|
legacy::PassManagerBase &PM) {
|
|
|
|
|
PM.add(createPostInlineEntryExitInstrumenterPass());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
|
|
|
|
|
const CodeGenOptions &CodeGenOpts) {
|
|
|
|
|
TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
|
|
|
|
@ -457,17 +277,6 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
|
|
|
|
|
return TLII;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void addSymbolRewriterPass(const CodeGenOptions &Opts,
|
|
|
|
|
legacy::PassManager *MPM) {
|
|
|
|
|
llvm::SymbolRewriter::RewriteDescriptorList DL;
|
|
|
|
|
|
|
|
|
|
llvm::SymbolRewriter::RewriteMapParser MapParser;
|
|
|
|
|
for (const auto &MapFile : Opts.RewriteMapFiles)
|
|
|
|
|
MapParser.parse(MapFile, &DL);
|
|
|
|
|
|
|
|
|
|
MPM->add(createRewriteSymbolsPass(DL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CodeGenOpt::Level getCGOptLevel(const CodeGenOptions &CodeGenOpts) {
|
|
|
|
|
switch (CodeGenOpts.OptimizationLevel) {
|
|
|
|
|
default:
|
|
|
|
@ -697,232 +506,6 @@ getInstrProfOptions(const CodeGenOptions &CodeGenOpts,
|
|
|
|
|
return Options;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
|
|
|
|
|
legacy::FunctionPassManager &FPM) {
|
|
|
|
|
// Handle disabling of all LLVM passes, where we want to preserve the
|
|
|
|
|
// internal module before any optimization.
|
|
|
|
|
if (CodeGenOpts.DisableLLVMPasses)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// Figure out TargetLibraryInfo. This needs to be added to MPM and FPM
|
|
|
|
|
// manually (and not via PMBuilder), since some passes (eg. InstrProfiling)
|
|
|
|
|
// are inserted before PMBuilder ones - they'd get the default-constructed
|
|
|
|
|
// TLI with an unknown target otherwise.
|
|
|
|
|
std::unique_ptr<TargetLibraryInfoImpl> TLII(
|
|
|
|
|
createTLII(TargetTriple, CodeGenOpts));
|
|
|
|
|
|
|
|
|
|
// If we reached here with a non-empty index file name, then the index file
|
|
|
|
|
// was empty and we are not performing ThinLTO backend compilation (used in
|
|
|
|
|
// testing in a distributed build environment). Drop any the type test
|
|
|
|
|
// assume sequences inserted for whole program vtables so that codegen doesn't
|
|
|
|
|
// complain.
|
|
|
|
|
if (!CodeGenOpts.ThinLTOIndexFile.empty())
|
|
|
|
|
MPM.add(createLowerTypeTestsPass(/*ExportSummary=*/nullptr,
|
|
|
|
|
/*ImportSummary=*/nullptr,
|
|
|
|
|
/*DropTypeTests=*/true));
|
|
|
|
|
|
|
|
|
|
PassManagerBuilderWrapper PMBuilder(TargetTriple, CodeGenOpts, LangOpts);
|
|
|
|
|
|
|
|
|
|
// At O0 and O1 we only run the always inliner which is more efficient. At
|
|
|
|
|
// higher optimization levels we run the normal inliner.
|
|
|
|
|
if (CodeGenOpts.OptimizationLevel <= 1) {
|
|
|
|
|
bool InsertLifetimeIntrinsics = ((CodeGenOpts.OptimizationLevel != 0 &&
|
|
|
|
|
!CodeGenOpts.DisableLifetimeMarkers) ||
|
|
|
|
|
LangOpts.Coroutines);
|
|
|
|
|
PMBuilder.Inliner = createAlwaysInlinerLegacyPass(InsertLifetimeIntrinsics);
|
|
|
|
|
} else {
|
|
|
|
|
// We do not want to inline hot callsites for SamplePGO module-summary build
|
|
|
|
|
// because profile annotation will happen again in ThinLTO backend, and we
|
|
|
|
|
// want the IR of the hot path to match the profile.
|
|
|
|
|
PMBuilder.Inliner = createFunctionInliningPass(
|
|
|
|
|
CodeGenOpts.OptimizationLevel, CodeGenOpts.OptimizeSize,
|
|
|
|
|
(!CodeGenOpts.SampleProfileFile.empty() &&
|
|
|
|
|
CodeGenOpts.PrepareForThinLTO));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PMBuilder.OptLevel = CodeGenOpts.OptimizationLevel;
|
|
|
|
|
PMBuilder.SizeLevel = CodeGenOpts.OptimizeSize;
|
|
|
|
|
PMBuilder.SLPVectorize = CodeGenOpts.VectorizeSLP;
|
|
|
|
|
PMBuilder.LoopVectorize = CodeGenOpts.VectorizeLoop;
|
|
|
|
|
// Only enable CGProfilePass when using integrated assembler, since
|
|
|
|
|
// non-integrated assemblers don't recognize .cgprofile section.
|
|
|
|
|
PMBuilder.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;
|
|
|
|
|
|
|
|
|
|
PMBuilder.DisableUnrollLoops = !CodeGenOpts.UnrollLoops;
|
|
|
|
|
// Loop interleaving in the loop vectorizer has historically been set to be
|
|
|
|
|
// enabled when loop unrolling is enabled.
|
|
|
|
|
PMBuilder.LoopsInterleaved = CodeGenOpts.UnrollLoops;
|
|
|
|
|
PMBuilder.MergeFunctions = CodeGenOpts.MergeFunctions;
|
|
|
|
|
PMBuilder.PrepareForThinLTO = CodeGenOpts.PrepareForThinLTO;
|
|
|
|
|
PMBuilder.PrepareForLTO = CodeGenOpts.PrepareForLTO;
|
|
|
|
|
PMBuilder.RerollLoops = CodeGenOpts.RerollLoops;
|
|
|
|
|
|
|
|
|
|
MPM.add(new TargetLibraryInfoWrapperPass(*TLII));
|
|
|
|
|
|
|
|
|
|
if (TM)
|
|
|
|
|
TM->adjustPassManager(PMBuilder);
|
|
|
|
|
|
|
|
|
|
if (CodeGenOpts.DebugInfoForProfiling ||
|
|
|
|
|
!CodeGenOpts.SampleProfileFile.empty())
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
|
|
|
|
|
addAddDiscriminatorsPass);
|
|
|
|
|
|
|
|
|
|
// In ObjC ARC mode, add the main ARC optimization passes.
|
|
|
|
|
if (LangOpts.ObjCAutoRefCount) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
|
|
|
|
|
addObjCARCExpandPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_ModuleOptimizerEarly,
|
|
|
|
|
addObjCARCAPElimPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
|
|
|
|
|
addObjCARCOptPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Coroutines)
|
|
|
|
|
addCoroutinePassesToExtensionPoints(PMBuilder);
|
|
|
|
|
|
|
|
|
|
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addMemProfilerPasses);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addMemProfilerPasses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::LocalBounds)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
|
|
|
|
|
addBoundsCheckingPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addBoundsCheckingPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CodeGenOpts.hasSanitizeCoverage()) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addSanitizerCoveragePass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addSanitizerCoveragePass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::Address)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addAddressSanitizerPasses);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addAddressSanitizerPasses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::KernelAddress)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addKernelAddressSanitizerPasses);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addKernelAddressSanitizerPasses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::HWAddress)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addHWAddressSanitizerPasses);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addHWAddressSanitizerPasses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::KernelHWAddress)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addKernelHWAddressSanitizerPasses);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addKernelHWAddressSanitizerPasses);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::Memory)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addMemorySanitizerPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addMemorySanitizerPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::KernelMemory)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addKernelMemorySanitizerPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addKernelMemorySanitizerPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::Thread)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addThreadSanitizerPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addThreadSanitizerPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LangOpts.Sanitize.has(SanitizerKind::DataFlow)) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addDataFlowSanitizerPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addDataFlowSanitizerPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CodeGenOpts.InstrumentFunctions ||
|
|
|
|
|
CodeGenOpts.InstrumentFunctionEntryBare ||
|
|
|
|
|
CodeGenOpts.InstrumentFunctionsAfterInlining ||
|
|
|
|
|
CodeGenOpts.InstrumentForProfiling) {
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
|
|
|
|
|
addEntryExitInstrumentationPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addEntryExitInstrumentationPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
|
|
|
|
addPostInlineEntryExitInstrumentationPass);
|
|
|
|
|
PMBuilder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
|
|
|
|
addPostInlineEntryExitInstrumentationPass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set up the per-function pass manager.
|
|
|
|
|
FPM.add(new TargetLibraryInfoWrapperPass(*TLII));
|
|
|
|
|
if (CodeGenOpts.VerifyModule)
|
|
|
|
|
FPM.add(createVerifierPass());
|
|
|
|
|
|
|
|
|
|
// Set up the per-module pass manager.
|
|
|
|
|
if (!CodeGenOpts.RewriteMapFiles.empty())
|
|
|
|
|
addSymbolRewriterPass(CodeGenOpts, &MPM);
|
|
|
|
|
|
|
|
|
|
if (Optional<GCOVOptions> Options = getGCOVOptions(CodeGenOpts, LangOpts)) {
|
|
|
|
|
MPM.add(createGCOVProfilerPass(*Options));
|
|
|
|
|
if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo)
|
|
|
|
|
MPM.add(createStripSymbolsPass(true));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Optional<InstrProfOptions> Options =
|
|
|
|
|
getInstrProfOptions(CodeGenOpts, LangOpts))
|
|
|
|
|
MPM.add(createInstrProfilingLegacyPass(*Options, false));
|
|
|
|
|
|
|
|
|
|
bool hasIRInstr = false;
|
|
|
|
|
if (CodeGenOpts.hasProfileIRInstr()) {
|
|
|
|
|
PMBuilder.EnablePGOInstrGen = true;
|
|
|
|
|
hasIRInstr = true;
|
|
|
|
|
}
|
|
|
|
|
if (CodeGenOpts.hasProfileCSIRInstr()) {
|
|
|
|
|
assert(!CodeGenOpts.hasProfileCSIRUse() &&
|
|
|
|
|
"Cannot have both CSProfileUse pass and CSProfileGen pass at the "
|
|
|
|
|
"same time");
|
|
|
|
|
assert(!hasIRInstr &&
|
|
|
|
|
"Cannot have both ProfileGen pass and CSProfileGen pass at the "
|
|
|
|
|
"same time");
|
|
|
|
|
PMBuilder.EnablePGOCSInstrGen = true;
|
|
|
|
|
hasIRInstr = true;
|
|
|
|
|
}
|
|
|
|
|
if (hasIRInstr) {
|
|
|
|
|
if (!CodeGenOpts.InstrProfileOutput.empty())
|
|
|
|
|
PMBuilder.PGOInstrGen = CodeGenOpts.InstrProfileOutput;
|
|
|
|
|
else
|
|
|
|
|
PMBuilder.PGOInstrGen = getDefaultProfileGenName();
|
|
|
|
|
}
|
|
|
|
|
if (CodeGenOpts.hasProfileIRUse()) {
|
|
|
|
|
PMBuilder.PGOInstrUse = CodeGenOpts.ProfileInstrumentUsePath;
|
|
|
|
|
PMBuilder.EnablePGOCSInstrUse = CodeGenOpts.hasProfileCSIRUse();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!CodeGenOpts.SampleProfileFile.empty())
|
|
|
|
|
PMBuilder.PGOSampleUse = CodeGenOpts.SampleProfileFile;
|
|
|
|
|
|
|
|
|
|
PMBuilder.populateFunctionPassManager(FPM);
|
|
|
|
|
PMBuilder.populateModulePassManager(MPM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
|
|
|
|
|
SmallVector<const char *, 16> BackendArgs;
|
|
|
|
|
BackendArgs.push_back("clang"); // Fake program name.
|
|
|
|
@ -1000,134 +583,6 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmitAssemblyHelper::EmitAssemblyWithLegacyPassManager(
|
|
|
|
|
BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) {
|
|
|
|
|
TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr);
|
|
|
|
|
|
|
|
|
|
setCommandLineOpts(CodeGenOpts);
|
|
|
|
|
|
|
|
|
|
bool UsesCodeGen = actionRequiresCodeGen(Action);
|
|
|
|
|
CreateTargetMachine(UsesCodeGen);
|
|
|
|
|
|
|
|
|
|
if (UsesCodeGen && !TM)
|
|
|
|
|
return;
|
|
|
|
|
if (TM)
|
|
|
|
|
TheModule->setDataLayout(TM->createDataLayout());
|
|
|
|
|
|
|
|
|
|
DebugifyCustomPassManager PerModulePasses;
|
|
|
|
|
DebugInfoPerPass DebugInfoBeforePass;
|
|
|
|
|
if (CodeGenOpts.EnableDIPreservationVerify) {
|
|
|
|
|
PerModulePasses.setDebugifyMode(DebugifyMode::OriginalDebugInfo);
|
|
|
|
|
PerModulePasses.setDebugInfoBeforePass(DebugInfoBeforePass);
|
|
|
|
|
|
|
|
|
|
if (!CodeGenOpts.DIBugsReportFilePath.empty())
|
|
|
|
|
PerModulePasses.setOrigDIVerifyBugsReportFilePath(
|
|
|
|
|
CodeGenOpts.DIBugsReportFilePath);
|
|
|
|
|
}
|
|
|
|
|
PerModulePasses.add(
|
|
|
|
|
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
|
|
|
|
|
|
|
|
|
|
legacy::FunctionPassManager PerFunctionPasses(TheModule);
|
|
|
|
|
PerFunctionPasses.add(
|
|
|
|
|
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
|
|
|
|
|
|
|
|
|
|
CreatePasses(PerModulePasses, PerFunctionPasses);
|
|
|
|
|
|
|
|
|
|
// Add a verifier pass if requested. We don't have to do this if the action
|
|
|
|
|
// requires code generation because there will already be a verifier pass in
|
|
|
|
|
// the code-generation pipeline.
|
|
|
|
|
if (!UsesCodeGen && CodeGenOpts.VerifyModule)
|
|
|
|
|
PerModulePasses.add(createVerifierPass());
|
|
|
|
|
|
|
|
|
|
legacy::PassManager CodeGenPasses;
|
|
|
|
|
CodeGenPasses.add(
|
|
|
|
|
createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<llvm::ToolOutputFile> ThinLinkOS, DwoOS;
|
|
|
|
|
|
|
|
|
|
switch (Action) {
|
|
|
|
|
case Backend_EmitNothing:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Backend_EmitBC:
|
|
|
|
|
if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
|
|
|
|
|
if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) {
|
|
|
|
|
ThinLinkOS = openOutputFile(CodeGenOpts.ThinLinkBitcodeFile);
|
|
|
|
|
if (!ThinLinkOS)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
|
|
|
|
|
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
|
|
|
|
CodeGenOpts.EnableSplitLTOUnit);
|
|
|
|
|
PerModulePasses.add(createWriteThinLTOBitcodePass(
|
|
|
|
|
*OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
|
|
|
|
|
} else {
|
|
|
|
|
// Emit a module summary by default for Regular LTO except for ld64
|
|
|
|
|
// targets
|
|
|
|
|
bool EmitLTOSummary = shouldEmitRegularLTOSummary();
|
|
|
|
|
if (EmitLTOSummary) {
|
|
|
|
|
if (!TheModule->getModuleFlag("ThinLTO"))
|
|
|
|
|
TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0));
|
|
|
|
|
if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
|
|
|
|
|
TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
|
|
|
|
|
uint32_t(1));
|
|
|
|
|
}
|
|
|
|
|
PerModulePasses.add(createBitcodeWriterPass(
|
|
|
|
|
*OS, CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Backend_EmitLL:
|
|
|
|
|
PerModulePasses.add(
|
|
|
|
|
createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if (!CodeGenOpts.SplitDwarfOutput.empty()) {
|
|
|
|
|
DwoOS = openOutputFile(CodeGenOpts.SplitDwarfOutput);
|
|
|
|
|
if (!DwoOS)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!AddEmitPasses(CodeGenPasses, Action, *OS,
|
|
|
|
|
DwoOS ? &DwoOS->os() : nullptr))
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Before executing passes, print the final values of the LLVM options.
|
|
|
|
|
cl::PrintOptionValues();
|
|
|
|
|
|
|
|
|
|
// Run passes. For now we do all passes at once, but eventually we
|
|
|
|
|
// would like to have the option of streaming code generation.
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
PrettyStackTraceString CrashInfo("Per-function optimization");
|
|
|
|
|
llvm::TimeTraceScope TimeScope("PerFunctionPasses");
|
|
|
|
|
|
|
|
|
|
PerFunctionPasses.doInitialization();
|
|
|
|
|
for (Function &F : *TheModule)
|
|
|
|
|
if (!F.isDeclaration())
|
|
|
|
|
PerFunctionPasses.run(F);
|
|
|
|
|
PerFunctionPasses.doFinalization();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
PrettyStackTraceString CrashInfo("Per-module optimization passes");
|
|
|
|
|
llvm::TimeTraceScope TimeScope("PerModulePasses");
|
|
|
|
|
PerModulePasses.run(*TheModule);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
PrettyStackTraceString CrashInfo("Code generation");
|
|
|
|
|
llvm::TimeTraceScope TimeScope("CodeGenPasses");
|
|
|
|
|
CodeGenPasses.run(*TheModule);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ThinLinkOS)
|
|
|
|
|
ThinLinkOS->keep();
|
|
|
|
|
if (DwoOS)
|
|
|
|
|
DwoOS->keep();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
|
|
|
|
|
switch (Opts.OptimizationLevel) {
|
|
|
|
|
default:
|
|
|
|
@ -1542,14 +997,6 @@ void EmitAssemblyHelper::RunCodegenPipeline(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A clean version of `EmitAssembly` that uses the new pass manager.
|
|
|
|
|
///
|
|
|
|
|
/// Not all features are currently supported in this system, but where
|
|
|
|
|
/// necessary it falls back to the legacy pass manager to at least provide
|
|
|
|
|
/// basic functionality.
|
|
|
|
|
///
|
|
|
|
|
/// This API is planned to have its functionality finished and then to replace
|
|
|
|
|
/// `EmitAssembly` at some point in the future when the default switches.
|
|
|
|
|
void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
|
|
|
|
|
std::unique_ptr<raw_pwrite_stream> OS) {
|
|
|
|
|
TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr);
|
|
|
|
@ -1637,7 +1084,6 @@ static void runThinLTOBackend(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Conf.ProfileRemapping = std::move(ProfileRemapping);
|
|
|
|
|
Conf.UseNewPM = !CGOpts.LegacyPassManager;
|
|
|
|
|
Conf.DebugPassManager = CGOpts.DebugPassManager;
|
|
|
|
|
Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
|
|
|
|
|
Conf.RemarksFilename = CGOpts.OptRecordFile;
|
|
|
|
@ -1727,11 +1173,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M);
|
|
|
|
|
|
|
|
|
|
if (CGOpts.LegacyPassManager)
|
|
|
|
|
AsmHelper.EmitAssemblyWithLegacyPassManager(Action, std::move(OS));
|
|
|
|
|
else
|
|
|
|
|
AsmHelper.EmitAssembly(Action, std::move(OS));
|
|
|
|
|
AsmHelper.EmitAssembly(Action, std::move(OS));
|
|
|
|
|
|
|
|
|
|
// Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's
|
|
|
|
|
// DataLayout.
|
|
|
|
|