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)
|
||||
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.xray_osx.a" "libldc_rt.xray_osx.a" FALSE)
|
||||
endif()
|
||||
elseif(UNIX)
|
||||
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))
|
||||
copy_compilerrt_lib("linux/libclang_rt.fuzzer-x86_64.a" "libldc_rt.fuzzer-x86_64.a" FALSE)
|
||||
endif()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "errors.h"
|
||||
#include "globals.h"
|
||||
#include "gen/to_string.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
|
||||
namespace {
|
||||
|
@ -52,6 +53,15 @@ cl::opt<std::string> ASTPGOInstrUseFile(
|
|||
cl::desc("Use instrumentation data for profile-guided optimization"),
|
||||
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
|
||||
|
||||
namespace opts {
|
||||
|
@ -68,6 +78,20 @@ static cl::opt<bool> dmdFunctionTrace(
|
|||
"fdmd-trace-functions", cl::ZeroOrMore,
|
||||
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) {
|
||||
if (ASTPGOInstrGenFile.getNumOccurrences() > 0) {
|
||||
pgoMode = PGO_ASTBasedInstr;
|
||||
|
|
|
@ -27,6 +27,13 @@ namespace cl = llvm::cl;
|
|||
|
||||
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
|
||||
/// commandline flags. targetTriple should be initialized before calling this.
|
||||
/// It should be called only once.
|
||||
|
|
|
@ -53,6 +53,7 @@ private:
|
|||
virtual void addASanLinkFlags(const llvm::Triple &triple);
|
||||
virtual void addFuzzLinkFlags(const llvm::Triple &triple);
|
||||
virtual void addCppStdlibLinkFlags(const llvm::Triple &triple);
|
||||
virtual void addXRayLinkFlags(const llvm::Triple &triple);
|
||||
|
||||
virtual void addLinker();
|
||||
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) {
|
||||
if (linkNoCpp)
|
||||
return;
|
||||
|
@ -410,6 +437,10 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
|
|||
|
||||
addSanitizers(*global.params.targetTriple);
|
||||
|
||||
if (opts::fXRayInstrument) {
|
||||
addXRayLinkFlags(*global.params.targetTriple);
|
||||
}
|
||||
|
||||
#if LDC_LLVM_VER >= 309
|
||||
// Add LTO link flags before adding the user link switches, such that the user
|
||||
// can pass additional options to the LTO plugin.
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "statement.h"
|
||||
#include "template.h"
|
||||
#include "driver/cl_options.h"
|
||||
#include "driver/cl_options_instrumentation.h"
|
||||
#include "driver/cl_options_sanitizers.h"
|
||||
#include "gen/abi.h"
|
||||
#include "gen/arrays.h"
|
||||
|
@ -463,6 +464,18 @@ void applyTargetMachineAttributes(llvm::Function &func,
|
|||
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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1010,6 +1023,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
|
|||
func->addFnAttr(LLAttribute::SanitizeThread);
|
||||
}
|
||||
}
|
||||
applyXRayAttributes(*fd, *func);
|
||||
|
||||
llvm::BasicBlock *beginbb =
|
||||
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