mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 15:40:55 +03:00
Add basic clang-like support for XRay, through -fxray-instrument
and -fxray-instruction-threshold=
. (#2465)
Currently only fully working on Linux. See https://llvm.org/docs/XRay.html
This commit is contained in:
parent
43c02cecc0
commit
1da088330d
10 changed files with 148 additions and 0 deletions
|
@ -767,9 +767,13 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
|
||||||
copy_compilerrt_lib("darwin/libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan_osx_dynamic.dylib" TRUE)
|
copy_compilerrt_lib("darwin/libclang_rt.asan_osx_dynamic.dylib" "libldc_rt.asan_osx_dynamic.dylib" TRUE)
|
||||||
if(NOT (LDC_LLVM_VER LESS 600))
|
if(NOT (LDC_LLVM_VER LESS 600))
|
||||||
copy_compilerrt_lib("darwin/libclang_rt.fuzzer_osx.a" "libldc_rt.fuzzer_osx.a" FALSE)
|
copy_compilerrt_lib("darwin/libclang_rt.fuzzer_osx.a" "libldc_rt.fuzzer_osx.a" FALSE)
|
||||||
|
copy_compilerrt_lib("darwin/libclang_rt.xray_osx.a" "libldc_rt.xray_osx.a" FALSE)
|
||||||
endif()
|
endif()
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
copy_compilerrt_lib("linux/libclang_rt.asan-x86_64.a" "libldc_rt.asan-x86_64.a" FALSE)
|
copy_compilerrt_lib("linux/libclang_rt.asan-x86_64.a" "libldc_rt.asan-x86_64.a" FALSE)
|
||||||
|
if(NOT (LDC_LLVM_VER LESS 500))
|
||||||
|
copy_compilerrt_lib("linux/libclang_rt.xray-x86_64.a" "libldc_rt.xray-x86_64.a" FALSE)
|
||||||
|
endif()
|
||||||
if(NOT (LDC_LLVM_VER LESS 600))
|
if(NOT (LDC_LLVM_VER LESS 600))
|
||||||
copy_compilerrt_lib("linux/libclang_rt.fuzzer-x86_64.a" "libldc_rt.fuzzer-x86_64.a" FALSE)
|
copy_compilerrt_lib("linux/libclang_rt.fuzzer-x86_64.a" "libldc_rt.fuzzer-x86_64.a" FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
#include "gen/to_string.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -52,6 +53,15 @@ cl::opt<std::string> ASTPGOInstrUseFile(
|
||||||
cl::desc("Use instrumentation data for profile-guided optimization"),
|
cl::desc("Use instrumentation data for profile-guided optimization"),
|
||||||
cl::ValueRequired);
|
cl::ValueRequired);
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 500
|
||||||
|
cl::opt<int> fXRayInstructionThreshold(
|
||||||
|
"fxray-instruction-threshold", cl::value_desc("value"),
|
||||||
|
cl::desc("Sets the minimum function size to instrument with XRay"),
|
||||||
|
cl::init(200), cl::ZeroOrMore, cl::ValueRequired);
|
||||||
|
#else
|
||||||
|
constexpr int fXRayInstructionThreshold = 200;
|
||||||
|
#endif
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace opts {
|
namespace opts {
|
||||||
|
@ -68,6 +78,20 @@ static cl::opt<bool> dmdFunctionTrace(
|
||||||
"fdmd-trace-functions", cl::ZeroOrMore,
|
"fdmd-trace-functions", cl::ZeroOrMore,
|
||||||
cl::desc("DMD-style runtime performance profiling of generated code"));
|
cl::desc("DMD-style runtime performance profiling of generated code"));
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 500
|
||||||
|
cl::opt<bool> fXRayInstrument(
|
||||||
|
"fxray-instrument", cl::ZeroOrMore,
|
||||||
|
cl::desc("Generate XRay instrumentation sleds on function entry and exit"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
llvm::StringRef getXRayInstructionThresholdString() {
|
||||||
|
// The instruction threshold is constant during one compiler invoke, so we
|
||||||
|
// can cache the int->string conversion result.
|
||||||
|
static std::string thresholdString =
|
||||||
|
ldc::to_string(fXRayInstructionThreshold);
|
||||||
|
return thresholdString;
|
||||||
|
}
|
||||||
|
|
||||||
void initializeInstrumentationOptionsFromCmdline(const llvm::Triple &triple) {
|
void initializeInstrumentationOptionsFromCmdline(const llvm::Triple &triple) {
|
||||||
if (ASTPGOInstrGenFile.getNumOccurrences() > 0) {
|
if (ASTPGOInstrGenFile.getNumOccurrences() > 0) {
|
||||||
pgoMode = PGO_ASTBasedInstr;
|
pgoMode = PGO_ASTBasedInstr;
|
||||||
|
|
|
@ -27,6 +27,13 @@ namespace cl = llvm::cl;
|
||||||
|
|
||||||
extern cl::opt<bool> instrumentFunctions;
|
extern cl::opt<bool> instrumentFunctions;
|
||||||
|
|
||||||
|
#if LDC_LLVM_VER >= 500
|
||||||
|
extern cl::opt<bool> fXRayInstrument;
|
||||||
|
#else
|
||||||
|
constexpr bool fXRayInstrument = false;
|
||||||
|
#endif
|
||||||
|
llvm::StringRef getXRayInstructionThresholdString();
|
||||||
|
|
||||||
/// This initializes the instrumentation options, and checks the validity of the
|
/// This initializes the instrumentation options, and checks the validity of the
|
||||||
/// commandline flags. targetTriple should be initialized before calling this.
|
/// commandline flags. targetTriple should be initialized before calling this.
|
||||||
/// It should be called only once.
|
/// It should be called only once.
|
||||||
|
|
|
@ -53,6 +53,7 @@ private:
|
||||||
virtual void addASanLinkFlags(const llvm::Triple &triple);
|
virtual void addASanLinkFlags(const llvm::Triple &triple);
|
||||||
virtual void addFuzzLinkFlags(const llvm::Triple &triple);
|
virtual void addFuzzLinkFlags(const llvm::Triple &triple);
|
||||||
virtual void addCppStdlibLinkFlags(const llvm::Triple &triple);
|
virtual void addCppStdlibLinkFlags(const llvm::Triple &triple);
|
||||||
|
virtual void addXRayLinkFlags(const llvm::Triple &triple);
|
||||||
|
|
||||||
virtual void addLinker();
|
virtual void addLinker();
|
||||||
virtual void addUserSwitches();
|
virtual void addUserSwitches();
|
||||||
|
@ -312,6 +313,32 @@ void ArgsBuilder::addFuzzLinkFlags(const llvm::Triple &triple) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adds all required link flags for -fxray-instrument when the xray library is
|
||||||
|
// found.
|
||||||
|
void ArgsBuilder::addXRayLinkFlags(const llvm::Triple &triple) {
|
||||||
|
std::string searchPaths[] = {
|
||||||
|
getFullCompilerRTLibPath(triple, "libldc_rt.xray"),
|
||||||
|
getFullCompilerRTLibPath(triple, "libclang_rt.xray"),
|
||||||
|
getFullClangCompilerRTLibPath(triple, "libclang_rt.xray"),
|
||||||
|
};
|
||||||
|
|
||||||
|
bool linkerDarwin = triple.isOSDarwin();
|
||||||
|
if (!triple.isOSLinux())
|
||||||
|
warning(Loc(), "XRay is not (fully) supported on non-Linux target OS.");
|
||||||
|
|
||||||
|
for (const auto &filepath : searchPaths) {
|
||||||
|
if (!linkerDarwin)
|
||||||
|
addLdFlag("--whole-archive");
|
||||||
|
|
||||||
|
args.push_back(filepath);
|
||||||
|
|
||||||
|
if (!linkerDarwin)
|
||||||
|
addLdFlag("--no-whole-archive");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ArgsBuilder::addCppStdlibLinkFlags(const llvm::Triple &triple) {
|
void ArgsBuilder::addCppStdlibLinkFlags(const llvm::Triple &triple) {
|
||||||
if (linkNoCpp)
|
if (linkNoCpp)
|
||||||
return;
|
return;
|
||||||
|
@ -410,6 +437,10 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
|
||||||
|
|
||||||
addSanitizers(*global.params.targetTriple);
|
addSanitizers(*global.params.targetTriple);
|
||||||
|
|
||||||
|
if (opts::fXRayInstrument) {
|
||||||
|
addXRayLinkFlags(*global.params.targetTriple);
|
||||||
|
}
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 309
|
#if LDC_LLVM_VER >= 309
|
||||||
// Add LTO link flags before adding the user link switches, such that the user
|
// Add LTO link flags before adding the user link switches, such that the user
|
||||||
// can pass additional options to the LTO plugin.
|
// can pass additional options to the LTO plugin.
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "statement.h"
|
#include "statement.h"
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
#include "driver/cl_options.h"
|
#include "driver/cl_options.h"
|
||||||
|
#include "driver/cl_options_instrumentation.h"
|
||||||
#include "driver/cl_options_sanitizers.h"
|
#include "driver/cl_options_sanitizers.h"
|
||||||
#include "gen/abi.h"
|
#include "gen/abi.h"
|
||||||
#include "gen/arrays.h"
|
#include "gen/arrays.h"
|
||||||
|
@ -463,6 +464,18 @@ void applyTargetMachineAttributes(llvm::Function &func,
|
||||||
willEliminateFramePointer() ? "false" : "true");
|
willEliminateFramePointer() ? "false" : "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void applyXRayAttributes(FuncDeclaration &fdecl, llvm::Function &func) {
|
||||||
|
if (!opts::fXRayInstrument)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!fdecl.emitInstrumentation) {
|
||||||
|
func.addFnAttr("function-instrument", "xray-never");
|
||||||
|
} else {
|
||||||
|
func.addFnAttr("xray-instruction-threshold",
|
||||||
|
opts::getXRayInstructionThresholdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1010,6 +1023,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
||||||
func->addFnAttr(LLAttribute::SanitizeThread);
|
func->addFnAttr(LLAttribute::SanitizeThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
applyXRayAttributes(*fd, *func);
|
||||||
|
|
||||||
llvm::BasicBlock *beginbb =
|
llvm::BasicBlock *beginbb =
|
||||||
llvm::BasicBlock::Create(gIR->context(), "", func);
|
llvm::BasicBlock::Create(gIR->context(), "", func);
|
||||||
|
|
10
tests/instrument/lit.local.cfg
Normal file
10
tests/instrument/lit.local.cfg
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import os
|
||||||
|
import platform
|
||||||
|
import re
|
||||||
|
|
||||||
|
# Add "XRay_RT" feature if the runtime library is available
|
||||||
|
for file in os.listdir(config.ldc2_lib_dir):
|
||||||
|
m = re.match('.*xray.*', file)
|
||||||
|
if m is not None:
|
||||||
|
config.available_features.add('XRay')
|
||||||
|
continue
|
11
tests/instrument/xray_check_pipeline.d
Normal file
11
tests/instrument/xray_check_pipeline.d
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Check that the LLVM pipeline is set up correctly to generate XRay sleds.
|
||||||
|
|
||||||
|
// If we have the XRay runtime lib for this platform, then we can also do machinecodegen:
|
||||||
|
// REQUIRES: XRay_RT
|
||||||
|
|
||||||
|
// RUN: %ldc -c -output-s -betterC -fxray-instrument -fxray-instruction-threshold=1 -of=%t.s %s && FileCheck %s < %t.s
|
||||||
|
|
||||||
|
// CHECK: xray_sled
|
||||||
|
void instrument()
|
||||||
|
{
|
||||||
|
}
|
21
tests/instrument/xray_instrument.d
Normal file
21
tests/instrument/xray_instrument.d
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// REQUIRES: atleast_llvm500
|
||||||
|
|
||||||
|
// RUN: %ldc -c -output-ll -fxray-instrument -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
import ldc.attributes;
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{.*}} @{{.*}}10instrument
|
||||||
|
// CHECK-SAME: #[[INSTR:[0-9]+]]
|
||||||
|
void instrument()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{.*}} @{{.*}}15dont_instrument
|
||||||
|
// CHECK-SAME: #[[DONT_INSTR:[0-9]+]]
|
||||||
|
void dont_instrument()
|
||||||
|
{
|
||||||
|
pragma(LDC_profile_instr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-DAG: attributes #[[INSTR]] ={{.*}} "xray-instruction-threshold"=
|
||||||
|
// CHECK-DAG: attributes #[[DONT_INSTR]] ={{.*}} "function-instrument"="xray-never"
|
11
tests/instrument/xray_instrument_threshold.d
Normal file
11
tests/instrument/xray_instrument_threshold.d
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// REQUIRES: atleast_llvm500
|
||||||
|
|
||||||
|
// RUN: %ldc -c -output-ll -fxray-instrument -fxray-instruction-threshold=543 -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK-LABEL: define{{.*}} @{{.*}}10instrument
|
||||||
|
// CHECK-SAME: #[[INSTR:[0-9]+]]
|
||||||
|
void instrument()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-DAG: attributes #[[INSTR]] ={{.*}} "xray-instruction-threshold"="543"
|
15
tests/instrument/xray_link.d
Normal file
15
tests/instrument/xray_link.d
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// REQUIRES: XRay_RT
|
||||||
|
|
||||||
|
// RUN: %ldc -fxray-instrument -fxray-instruction-threshold=1 -of=%t%exe %s -vv | FileCheck %s
|
||||||
|
|
||||||
|
void foo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK: Linking with:
|
||||||
|
// CHECK-NEXT: rt.xray
|
Loading…
Add table
Add a link
Reference in a new issue