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
|
||||
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
|
||||
for (unsigned i = 0; i < global.params.linkswitches->dim; i++)
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/PassNameParser.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
|
||||
|
@ -106,6 +107,17 @@ static cl::opt<bool>
|
|||
stripDebug("strip-debug",
|
||||
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() {
|
||||
// Use -O2 as a base for the size-optimization levels.
|
||||
return optimizeLevel >= 0 ? optimizeLevel : 2;
|
||||
|
@ -154,6 +166,36 @@ static void addGarbageCollect2StackPass(const PassManagerBuilder &builder, PassM
|
|||
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
|
||||
* 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.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 (!disableSimplifyDruntimeCalls)
|
||||
builder.addExtension(PassManagerBuilder::EP_LoopOptimizerEnd, addSimplifyDRuntimeCallsPass);
|
||||
|
|
|
@ -18,6 +18,17 @@
|
|||
// For llvm::CodeGenOpt::Level
|
||||
#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; }
|
||||
|
||||
bool ldc_optimize_module(llvm::Module* m);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue