mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-02 08:01:11 +03:00
[experimental] Add sanitizer options to LDC.
Add some of the sanitizer passes to LDC. This is not complete (linking must be done using clang and the right `-fsanitize=` option) and may not be useful at all. If it proves to be usefull then a lot of other options (e.g. blacklist) must be added.
This commit is contained in:
parent
6fe28e1660
commit
e6529cfd3d
3 changed files with 91 additions and 0 deletions
|
@ -137,6 +137,21 @@ static int linkObjToBinaryGcc(bool sharedLib)
|
||||||
// create path to exe
|
// create path to exe
|
||||||
CreateDirectoryOnDisk(gExePath);
|
CreateDirectoryOnDisk(gExePath);
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
// Pass sanitizer arguments to linker. Requires clang.
|
||||||
|
if (opts::sanitize == opts::AddressSanitizer) {
|
||||||
|
args.push_back("-fsanitize=address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts::sanitize == opts::MemorySanitizer) {
|
||||||
|
args.push_back("-fsanitize=memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||||
|
args.push_back("-fsanitize=thread");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// additional linker switches
|
// additional linker switches
|
||||||
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
|
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/PassNameParser.h"
|
#include "llvm/Support/PassNameParser.h"
|
||||||
|
#include "llvm/Transforms/Instrumentation.h"
|
||||||
#include "llvm/Transforms/IPO.h"
|
#include "llvm/Transforms/IPO.h"
|
||||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||||
|
|
||||||
|
@ -106,6 +107,17 @@ static cl::opt<bool>
|
||||||
stripDebug("strip-debug",
|
stripDebug("strip-debug",
|
||||||
cl::desc("Strip symbolic debug information before optimization"));
|
cl::desc("Strip symbolic debug information before optimization"));
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
cl::opt<opts::SanitizerCheck> opts::sanitize("sanitize",
|
||||||
|
cl::desc("Enable runtime instrumentation for bug detection"),
|
||||||
|
cl::init(opts::None),
|
||||||
|
cl::values(
|
||||||
|
clEnumValN(opts::AddressSanitizer, "address", "memory errors"),
|
||||||
|
clEnumValN(opts::MemorySanitizer, "memory", "memory errors"),
|
||||||
|
clEnumValN(opts::ThreadSanitizer, "thread", "race detection"),
|
||||||
|
clEnumValEnd));
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned optLevel() {
|
static unsigned optLevel() {
|
||||||
// Use -O2 as a base for the size-optimization levels.
|
// Use -O2 as a base for the size-optimization levels.
|
||||||
return optimizeLevel >= 0 ? optimizeLevel : 2;
|
return optimizeLevel >= 0 ? optimizeLevel : 2;
|
||||||
|
@ -154,6 +166,36 @@ static void addGarbageCollect2StackPass(const PassManagerBuilder &builder, PassM
|
||||||
addPass(pm, createGarbageCollect2Stack());
|
addPass(pm, createGarbageCollect2Stack());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
static void addAddressSanitizerPasses(const PassManagerBuilder &Builder,
|
||||||
|
PassManagerBase &PM) {
|
||||||
|
PM.add(createAddressSanitizerFunctionPass());
|
||||||
|
PM.add(createAddressSanitizerModulePass());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addMemorySanitizerPass(const PassManagerBuilder &Builder,
|
||||||
|
PassManagerBase &PM) {
|
||||||
|
PM.add(createMemorySanitizerPass());
|
||||||
|
|
||||||
|
// 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 addThreadSanitizerPass(const PassManagerBuilder &Builder,
|
||||||
|
PassManagerBase &PM) {
|
||||||
|
PM.add(createThreadSanitizerPass());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a set of optimization passes to the given module/function pass
|
* Adds a set of optimization passes to the given module/function pass
|
||||||
* managers based on the given optimization and size reduction levels.
|
* managers based on the given optimization and size reduction levels.
|
||||||
|
@ -188,6 +230,29 @@ static void addOptimizationPasses(PassManagerBase &mpm, FunctionPassManager &fpm
|
||||||
builder.DisableUnrollLoops = optLevel == 0;
|
builder.DisableUnrollLoops = optLevel == 0;
|
||||||
/* builder.Vectorize is set in ctor from command line switch */
|
/* builder.Vectorize is set in ctor from command line switch */
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
if (opts::sanitize == opts::AddressSanitizer) {
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||||
|
addAddressSanitizerPasses);
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||||
|
addAddressSanitizerPasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts::sanitize == opts::MemorySanitizer) {
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||||
|
addMemorySanitizerPass);
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||||
|
addMemorySanitizerPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts::sanitize == opts::ThreadSanitizer) {
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
|
||||||
|
addThreadSanitizerPass);
|
||||||
|
builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
|
||||||
|
addThreadSanitizerPass);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!disableLangSpecificPasses) {
|
if (!disableLangSpecificPasses) {
|
||||||
if (!disableSimplifyDruntimeCalls)
|
if (!disableSimplifyDruntimeCalls)
|
||||||
builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, addSimplifyDRuntimeCallsPass);
|
builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, addSimplifyDRuntimeCallsPass);
|
||||||
|
|
|
@ -18,6 +18,17 @@
|
||||||
// For llvm::CodeGenOpt::Level
|
// For llvm::CodeGenOpt::Level
|
||||||
#include "llvm/Support/CodeGen.h"
|
#include "llvm/Support/CodeGen.h"
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 303
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
|
||||||
|
namespace opts {
|
||||||
|
|
||||||
|
enum SanitizerCheck { None, AddressSanitizer, MemorySanitizer, ThreadSanitizer };
|
||||||
|
|
||||||
|
extern llvm::cl::opt<SanitizerCheck> sanitize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace llvm { class Module; }
|
namespace llvm { class Module; }
|
||||||
|
|
||||||
bool ldc_optimize_module(llvm::Module* m);
|
bool ldc_optimize_module(llvm::Module* m);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue