Compare commits
1 Commits
main
...
users/arse
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ae56b6712d |
@ -280,7 +280,6 @@ set(TARGET_LIBC_ENTRYPOINTS
|
||||
|
||||
set(TARGET_LIBM_ENTRYPOINTS
|
||||
# math.h entrypoints
|
||||
libc.src.math.acos
|
||||
libc.src.math.acosf
|
||||
libc.src.math.acoshf
|
||||
libc.src.math.asin
|
||||
|
@ -2432,6 +2432,14 @@ functions:
|
||||
return_type: double
|
||||
arguments:
|
||||
- type: double
|
||||
- name: sincosf
|
||||
standards:
|
||||
- gnu
|
||||
return_type: void
|
||||
arguments:
|
||||
- type: float
|
||||
- type: float *
|
||||
- type: float *
|
||||
- name: sinf
|
||||
standards:
|
||||
- stdc
|
||||
@ -2445,22 +2453,6 @@ functions:
|
||||
arguments:
|
||||
- type: _Float16
|
||||
guard: LIBC_TYPES_HAS_FLOAT16
|
||||
- name: sincos
|
||||
standards:
|
||||
- gnu
|
||||
return_type: void
|
||||
arguments:
|
||||
- type: double
|
||||
- type: double *
|
||||
- type: double *
|
||||
- name: sincosf
|
||||
standards:
|
||||
- gnu
|
||||
return_type: void
|
||||
arguments:
|
||||
- type: float
|
||||
- type: float *
|
||||
- type: float *
|
||||
- name: sinhf
|
||||
standards:
|
||||
- stdc
|
||||
|
@ -21,6 +21,7 @@ def isOSOpenBSD : RuntimeLibcallPredicate<"TT.isOSOpenBSD()">;
|
||||
def isNotOSOpenBSD : RuntimeLibcallPredicate<"!TT.isOSOpenBSD()">;
|
||||
def isOSWindows : RuntimeLibcallPredicate<"TT.isOSWindows()">;
|
||||
def isNotOSWindows : RuntimeLibcallPredicate<"!TT.isOSWindows()">;
|
||||
def isNotOSLinux : RuntimeLibcallPredicate<[{!TT.isOSLinux()}]>;
|
||||
def isNotOSMSVCRT : RuntimeLibcallPredicate<"!TT.isOSMSVCRT()">;
|
||||
def isPS : RuntimeLibcallPredicate<"TT.isPS()">;
|
||||
def isNotOSWindowsOrIsCygwinMinGW
|
||||
@ -28,6 +29,12 @@ def isNotOSWindowsOrIsCygwinMinGW
|
||||
def isWindowsMSVCEnvironment : RuntimeLibcallPredicate<
|
||||
[{TT.isWindowsMSVCEnvironment()}]>;
|
||||
|
||||
def isNotOSLinuxAndNotOSOpenBSD : RuntimeLibcallPredicate<
|
||||
[{!TT.isOSLinux() && !TT.isOSOpenBSD()}]>;
|
||||
|
||||
def isWindowsMSVCOrItaniumEnvironment : RuntimeLibcallPredicate<
|
||||
[{TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment()}]>;
|
||||
|
||||
def isGNUEnvironment : RuntimeLibcallPredicate<"TT.isGNUEnvironment()">;
|
||||
def darwinHasSinCosStret : RuntimeLibcallPredicate<"darwinHasSinCosStret(TT)">;
|
||||
def darwinHasExp10 : RuntimeLibcallPredicate<"darwinHasExp10(TT)">;
|
||||
@ -471,6 +478,16 @@ def OBJC_RETAIN_AUTORELEASE : RuntimeLibcall;
|
||||
def OBJC_SYNC_ENTER : RuntimeLibcall;
|
||||
def OBJC_SYNC_EXIT : RuntimeLibcall;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Global variable references
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// TODO: These are not libcalls and probably should be distinguished
|
||||
// in some way from callable functions.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
def STACK_CHECK_GUARD : RuntimeLibcall;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Define implementation default libcalls
|
||||
//--------------------------------------------------------------------
|
||||
@ -1103,6 +1120,21 @@ defset list<RuntimeLibcallImpl> LibmF128FiniteLibcalls = {
|
||||
def __powf128_finite : RuntimeLibcallImpl<POW_FINITE_F128>;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Global variable references
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
def __stack_chk_guard : RuntimeLibcallImpl<STACK_CHECK_GUARD>;
|
||||
|
||||
// Name used on OpenBSD
|
||||
def __guard_local : RuntimeLibcallImpl<STACK_CHECK_GUARD>;
|
||||
|
||||
// Name used with Windows MSVC
|
||||
def __security_cookie : RuntimeLibcallImpl<STACK_CHECK_GUARD>;
|
||||
|
||||
// Name used on AIX
|
||||
def __ssp_canary_word : RuntimeLibcallImpl<STACK_CHECK_GUARD>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Common Libcall Sets
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1159,7 +1191,8 @@ defvar DarwinSinCosStret = LibcallImpls<(add __sincosf_stret, __sincos_stret),
|
||||
defvar DarwinExp10 = LibcallImpls<(add __exp10f, __exp10), darwinHasExp10>;
|
||||
|
||||
defvar SecurityCheckCookieIfWinMSVC =
|
||||
LibcallImpls<(add __security_check_cookie), isWindowsMSVCEnvironment>;
|
||||
LibcallImpls<(add __security_check_cookie, __security_cookie),
|
||||
isWindowsMSVCOrItaniumEnvironment>;
|
||||
|
||||
defvar LibmHasSinCosF32 = LibcallImpls<(add sincosf), hasSinCos>;
|
||||
defvar LibmHasSinCosF64 = LibcallImpls<(add sincos), hasSinCos>;
|
||||
@ -1205,10 +1238,13 @@ defvar LibmHasFrexpF128 = LibcallImpls<(add frexp_f128), isNotOSWindowsOrIsCygwi
|
||||
defvar LibmHasLdexpF128 = LibcallImpls<(add ldexp_f128), isNotOSWindowsOrIsCygwinMinGW>;
|
||||
|
||||
defvar has__stack_chk_fail = LibcallImpls<(add __stack_chk_fail), isNotOSOpenBSD>;
|
||||
defvar has__stack_chk_guard =
|
||||
LibcallImpls<(add __stack_chk_guard), isNotOSOpenBSD>;
|
||||
defvar has__stack_smash_handler = LibcallImpls<(add __stack_smash_handler), isOSOpenBSD>;
|
||||
defvar has___guard_local = LibcallImpls<(add __guard_local), isOSOpenBSD>;
|
||||
|
||||
defvar DefaultStackProtector = (add has__stack_chk_fail,
|
||||
has__stack_smash_handler);
|
||||
defvar DefaultStackProtector = (add has__stack_chk_fail, has__stack_chk_guard,
|
||||
has__stack_smash_handler, has___guard_local);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Objective-C Runtime Libcalls
|
||||
@ -1357,7 +1393,9 @@ def WindowsARM64ECSystemLibrary
|
||||
: SystemRuntimeLibrary<isWindowsArm64EC,
|
||||
(add WinArm64ECDefaultRuntimeLibcallImpls,
|
||||
arm64ec___stack_chk_fail,
|
||||
LibcallImpls<(add __security_check_cookie_arm64ec),
|
||||
__stack_chk_guard,
|
||||
LibcallImpls<(add __security_check_cookie_arm64ec,
|
||||
__security_cookie),
|
||||
isWindowsMSVCEnvironment>,
|
||||
ExceptionModelCallsArm64EC)>;
|
||||
|
||||
@ -1848,7 +1886,7 @@ def HexagonSystemLibrary
|
||||
__umoddi3, __divdf3, __muldf3, __divsi3, __subdf3, sqrtf,
|
||||
__divdi3, __umodsi3, __moddi3, __modsi3), HexagonLibcalls,
|
||||
LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128,
|
||||
exp10f, exp10, exp10l_f128, __stack_chk_fail)>;
|
||||
exp10f, exp10, exp10l_f128, __stack_chk_fail, __stack_chk_guard)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Lanai Runtime Libcalls
|
||||
@ -1859,7 +1897,7 @@ def isLanai : RuntimeLibcallPredicate<"TT.getArch() == Triple::lanai">;
|
||||
// Use fast calling convention for library functions.
|
||||
def LanaiSystemLibrary
|
||||
: SystemRuntimeLibrary<isLanai, (add DefaultRuntimeLibcallImpls,
|
||||
__stack_chk_fail)> {
|
||||
__stack_chk_fail, __stack_chk_guard)> {
|
||||
let DefaultLibcallCallingConv = FASTCC;
|
||||
}
|
||||
|
||||
@ -2157,7 +2195,8 @@ def MSP430SystemLibrary
|
||||
__mspabi_slll,
|
||||
// __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc
|
||||
|
||||
__stack_chk_fail
|
||||
__stack_chk_fail,
|
||||
__stack_chk_guard
|
||||
)
|
||||
>;
|
||||
|
||||
@ -2251,7 +2290,11 @@ def PPCSystemLibrary
|
||||
LibmHasSinCosPPCF128,
|
||||
AvailableIf<memcpy, isNotAIX>,
|
||||
LibcallImpls<(add Int128RTLibcalls), isPPC64>,
|
||||
DefaultStackProtector)>;
|
||||
has__stack_chk_fail,
|
||||
has__stack_smash_handler,
|
||||
has___guard_local,
|
||||
AvailableIf<__ssp_canary_word, isAIX>,
|
||||
AvailableIf<__stack_chk_guard, isNotAIX>)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RISCV Runtime Libcalls
|
||||
@ -2334,7 +2377,10 @@ def SPARCSystemLibrary
|
||||
LibcallImpls<(add _Q_qtoll, _Q_qtoull, _Q_lltoq, _Q_ulltoq), isSPARC32>,
|
||||
LibcallImpls<(add SPARC64_MulDivCalls, Int128RTLibcalls), isSPARC64>,
|
||||
LibmHasSinCosF32, LibmHasSinCosF64, LibmHasSinCosF128,
|
||||
DefaultStackProtector)
|
||||
has__stack_chk_fail,
|
||||
has__stack_smash_handler,
|
||||
has___guard_local,
|
||||
AvailableIf<__stack_chk_guard, isNotOSLinuxAndNotOSOpenBSD>)
|
||||
>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -2544,7 +2590,7 @@ def WasmSystemLibrary
|
||||
exp10f, exp10,
|
||||
_Unwind_CallPersonality,
|
||||
emscripten_return_address,
|
||||
__stack_chk_fail)>;
|
||||
__stack_chk_fail, __stack_chk_guard)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Legacy Default Runtime Libcalls
|
||||
|
@ -18983,9 +18983,7 @@ SDValue DAGCombiner::visitFP_ROUND(SDNode *N) {
|
||||
// single-step fp_round we want to fold to.
|
||||
// In other words, double rounding isn't the same as rounding.
|
||||
// Also, this is a value preserving truncation iff both fp_round's are.
|
||||
if ((N->getFlags().hasAllowContract() &&
|
||||
N0->getFlags().hasAllowContract()) ||
|
||||
N0IsTrunc)
|
||||
if (DAG.getTarget().Options.UnsafeFPMath || N0IsTrunc)
|
||||
return DAG.getNode(
|
||||
ISD::FP_ROUND, DL, VT, N0.getOperand(0),
|
||||
DAG.getIntPtrConstant(NIsTrunc && N0IsTrunc, DL, /*isTarget=*/true));
|
||||
|
@ -2059,10 +2059,16 @@ Value *TargetLoweringBase::getIRStackGuard(IRBuilderBase &IRB) const {
|
||||
// Currently only support "standard" __stack_chk_guard.
|
||||
// TODO: add LOAD_STACK_GUARD support.
|
||||
void TargetLoweringBase::insertSSPDeclarations(Module &M) const {
|
||||
if (!M.getNamedValue("__stack_chk_guard")) {
|
||||
RTLIB::LibcallImpl StackGuardImpl = getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
|
||||
if (StackGuardImpl == RTLIB::Unsupported)
|
||||
return;
|
||||
|
||||
StringRef StackGuardVarName = getLibcallImplName(StackGuardImpl);
|
||||
M.getOrInsertGlobal(
|
||||
StackGuardVarName, PointerType::getUnqual(M.getContext()), [=, &M]() {
|
||||
auto *GV = new GlobalVariable(M, PointerType::getUnqual(M.getContext()),
|
||||
false, GlobalVariable::ExternalLinkage,
|
||||
nullptr, "__stack_chk_guard");
|
||||
nullptr, StackGuardVarName);
|
||||
|
||||
// FreeBSD has "__stack_chk_guard" defined externally on libc.so
|
||||
if (M.getDirectAccessExternalData() &&
|
||||
@ -2072,16 +2078,18 @@ void TargetLoweringBase::insertSSPDeclarations(Module &M) const {
|
||||
(!TM.getTargetTriple().isOSDarwin() ||
|
||||
TM.getRelocationModel() == Reloc::Static))
|
||||
GV->setDSOLocal(true);
|
||||
}
|
||||
|
||||
return GV;
|
||||
});
|
||||
}
|
||||
|
||||
// Currently only support "standard" __stack_chk_guard.
|
||||
// TODO: add LOAD_STACK_GUARD support.
|
||||
Value *TargetLoweringBase::getSDagStackGuard(const Module &M) const {
|
||||
if (getTargetMachine().getTargetTriple().isOSOpenBSD()) {
|
||||
return M.getNamedValue("__guard_local");
|
||||
}
|
||||
return M.getNamedValue("__stack_chk_guard");
|
||||
RTLIB::LibcallImpl GuardVarImpl = getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
|
||||
if (GuardVarImpl == RTLIB::Unsupported)
|
||||
return nullptr;
|
||||
return M.getNamedValue(getLibcallImplName(GuardVarImpl));
|
||||
}
|
||||
|
||||
Function *TargetLoweringBase::getSSPStackGuardCheck(const Module &M) const {
|
||||
|
@ -46,18 +46,6 @@ static cl::opt<bool> DisableBitcodeVersionUpgrade(
|
||||
"disable-bitcode-version-upgrade", cl::Hidden,
|
||||
cl::desc("Disable automatic bitcode upgrade for version mismatch"));
|
||||
|
||||
static constexpr StringLiteral PreservedSymbols[] = {
|
||||
// There are global variables, so put it here instead of in
|
||||
// RuntimeLibcalls.td.
|
||||
// TODO: Are there similar such variables?
|
||||
"__ssp_canary_word",
|
||||
"__stack_chk_guard",
|
||||
};
|
||||
|
||||
static bool isPreservedGlobalVarName(StringRef Name) {
|
||||
return PreservedSymbols[0] == Name || PreservedSymbols[1] == Name;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const char *getExpectedProducerName() {
|
||||
@ -106,7 +94,7 @@ struct Builder {
|
||||
|
||||
std::vector<storage::Str> DependentLibraries;
|
||||
|
||||
bool isPreservedLibFuncName(StringRef Name) {
|
||||
bool isPreservedName(StringRef Name) {
|
||||
return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
|
||||
}
|
||||
|
||||
@ -281,8 +269,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
|
||||
StringRef GVName = GV->getName();
|
||||
setStr(Sym.IRName, GVName);
|
||||
|
||||
if (Used.count(GV) || isPreservedLibFuncName(GVName) ||
|
||||
isPreservedGlobalVarName(GVName))
|
||||
if (Used.count(GV) || isPreservedName(GVName))
|
||||
Sym.Flags |= 1 << storage::Symbol::FB_used;
|
||||
if (GV->isThreadLocal())
|
||||
Sym.Flags |= 1 << storage::Symbol::FB_tls;
|
||||
|
@ -28686,9 +28686,13 @@ void AArch64TargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
// MSVC CRT provides functionalities for stack protection.
|
||||
RTLIB::LibcallImpl SecurityCheckCookieLibcall =
|
||||
getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
|
||||
if (SecurityCheckCookieLibcall != RTLIB::Unsupported) {
|
||||
|
||||
RTLIB::LibcallImpl SecurityCookieVar =
|
||||
getLibcallImpl(RTLIB::STACK_CHECK_GUARD);
|
||||
if (SecurityCheckCookieLibcall != RTLIB::Unsupported &&
|
||||
SecurityCookieVar != RTLIB::Unsupported) {
|
||||
// MSVC CRT has a global variable holding security cookie.
|
||||
M.getOrInsertGlobal("__security_cookie",
|
||||
M.getOrInsertGlobal(getLibcallImplName(SecurityCookieVar),
|
||||
PointerType::getUnqual(M.getContext()));
|
||||
|
||||
// MSVC CRT has a function to validate security cookie.
|
||||
@ -28705,13 +28709,6 @@ void AArch64TargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
TargetLowering::insertSSPDeclarations(M);
|
||||
}
|
||||
|
||||
Value *AArch64TargetLowering::getSDagStackGuard(const Module &M) const {
|
||||
// MSVC CRT has a global variable holding security cookie.
|
||||
if (Subtarget->getTargetTriple().isWindowsMSVCEnvironment())
|
||||
return M.getGlobalVariable("__security_cookie");
|
||||
return TargetLowering::getSDagStackGuard(M);
|
||||
}
|
||||
|
||||
Function *AArch64TargetLowering::getSSPStackGuardCheck(const Module &M) const {
|
||||
// MSVC CRT has a function to validate security cookie.
|
||||
RTLIB::LibcallImpl SecurityCheckCookieLibcall =
|
||||
|
@ -354,7 +354,6 @@ public:
|
||||
Value *getIRStackGuard(IRBuilderBase &IRB) const override;
|
||||
|
||||
void insertSSPDeclarations(Module &M) const override;
|
||||
Value *getSDagStackGuard(const Module &M) const override;
|
||||
Function *getSSPStackGuardCheck(const Module &M) const override;
|
||||
|
||||
/// If the target has a standard location for the unsafe stack pointer,
|
||||
|
@ -6135,19 +6135,6 @@ unsigned AMDGPUTargetLowering::computeNumSignBitsForTargetInstr(
|
||||
}
|
||||
}
|
||||
|
||||
bool AMDGPUTargetLowering::canCreateUndefOrPoisonForTargetNode(
|
||||
SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG,
|
||||
bool PoisonOnly, bool ConsiderFlags, unsigned Depth) const {
|
||||
unsigned Opcode = Op.getOpcode();
|
||||
switch (Opcode) {
|
||||
case AMDGPUISD::BFE_I32:
|
||||
case AMDGPUISD::BFE_U32:
|
||||
return false;
|
||||
}
|
||||
return TargetLowering::canCreateUndefOrPoisonForTargetNode(
|
||||
Op, DemandedElts, DAG, PoisonOnly, ConsiderFlags, Depth);
|
||||
}
|
||||
|
||||
bool AMDGPUTargetLowering::isKnownNeverNaNForTargetNode(
|
||||
SDValue Op, const APInt &DemandedElts, const SelectionDAG &DAG, bool SNaN,
|
||||
unsigned Depth) const {
|
||||
|
@ -323,12 +323,6 @@ public:
|
||||
const MachineRegisterInfo &MRI,
|
||||
unsigned Depth = 0) const override;
|
||||
|
||||
bool canCreateUndefOrPoisonForTargetNode(SDValue Op,
|
||||
const APInt &DemandedElts,
|
||||
const SelectionDAG &DAG,
|
||||
bool PoisonOnly, bool ConsiderFlags,
|
||||
unsigned Depth) const override;
|
||||
|
||||
bool isKnownNeverNaNForTargetNode(SDValue Op, const APInt &DemandedElts,
|
||||
const SelectionDAG &DAG, bool SNaN = false,
|
||||
unsigned Depth = 0) const override;
|
||||
|
@ -21341,20 +21341,6 @@ void ARMTargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
F->addParamAttr(0, Attribute::AttrKind::InReg);
|
||||
}
|
||||
|
||||
Value *ARMTargetLowering::getSDagStackGuard(const Module &M) const {
|
||||
RTLIB::LibcallImpl SecurityCheckCookieLibcall =
|
||||
getLibcallImpl(RTLIB::SECURITY_CHECK_COOKIE);
|
||||
if (SecurityCheckCookieLibcall != RTLIB::Unsupported) {
|
||||
// MSVC CRT has a global variable holding security cookie.
|
||||
//
|
||||
// FIXME: We have a libcall entry for the correlated check function, but not
|
||||
// the global name.
|
||||
return M.getGlobalVariable("__security_cookie");
|
||||
}
|
||||
|
||||
return TargetLowering::getSDagStackGuard(M);
|
||||
}
|
||||
|
||||
Function *ARMTargetLowering::getSSPStackGuardCheck(const Module &M) const {
|
||||
// MSVC CRT has a function to validate security cookie.
|
||||
RTLIB::LibcallImpl SecurityCheckCookie =
|
||||
|
@ -704,7 +704,6 @@ class VectorType;
|
||||
bool useLoadStackGuardNode(const Module &M) const override;
|
||||
|
||||
void insertSSPDeclarations(Module &M) const override;
|
||||
Value *getSDagStackGuard(const Module &M) const override;
|
||||
Function *getSSPStackGuardCheck(const Module &M) const override;
|
||||
|
||||
bool canCombineStoreAndExtract(Type *VectorTy, Value *Idx,
|
||||
|
@ -158,8 +158,6 @@ static bool isNByteElemShuffleMask(ShuffleVectorSDNode *, unsigned, int);
|
||||
|
||||
static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl);
|
||||
|
||||
static const char AIXSSPCanaryWordName[] = "__ssp_canary_word";
|
||||
|
||||
// A faster local-[exec|dynamic] TLS access sequence (enabled with the
|
||||
// -maix-small-local-[exec|dynamic]-tls option) can be produced for TLS
|
||||
// variables; consistent with the IBM XL compiler, we apply a max size of
|
||||
@ -18656,24 +18654,6 @@ bool PPCTargetLowering::useLoadStackGuardNode(const Module &M) const {
|
||||
return TargetLowering::useLoadStackGuardNode(M);
|
||||
}
|
||||
|
||||
// Override to disable global variable loading on Linux and insert AIX canary
|
||||
// word declaration.
|
||||
void PPCTargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
if (Subtarget.isAIXABI()) {
|
||||
M.getOrInsertGlobal(AIXSSPCanaryWordName,
|
||||
PointerType::getUnqual(M.getContext()));
|
||||
return;
|
||||
}
|
||||
if (!Subtarget.isTargetLinux())
|
||||
return TargetLowering::insertSSPDeclarations(M);
|
||||
}
|
||||
|
||||
Value *PPCTargetLowering::getSDagStackGuard(const Module &M) const {
|
||||
if (Subtarget.isAIXABI())
|
||||
return M.getGlobalVariable(AIXSSPCanaryWordName);
|
||||
return TargetLowering::getSDagStackGuard(M);
|
||||
}
|
||||
|
||||
bool PPCTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
|
||||
bool ForCodeSize) const {
|
||||
if (!VT.isSimple() || !Subtarget.hasVSX())
|
||||
|
@ -1141,8 +1141,6 @@ namespace llvm {
|
||||
|
||||
/// Override to support customized stack guard loading.
|
||||
bool useLoadStackGuardNode(const Module &M) const override;
|
||||
void insertSSPDeclarations(Module &M) const override;
|
||||
Value *getSDagStackGuard(const Module &M) const override;
|
||||
|
||||
bool isFPImmLegal(const APFloat &Imm, EVT VT,
|
||||
bool ForCodeSize) const override;
|
||||
|
@ -3549,12 +3549,6 @@ bool SparcTargetLowering::isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
|
||||
return Subtarget->isUA2007() && !Subtarget->useSoftFloat();
|
||||
}
|
||||
|
||||
// Override to disable global variable loading on Linux.
|
||||
void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
if (!Subtarget->isTargetLinux())
|
||||
return TargetLowering::insertSSPDeclarations(M);
|
||||
}
|
||||
|
||||
void SparcTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
|
||||
SDNode *Node) const {
|
||||
assert(MI.getOpcode() == SP::SUBCCrr || MI.getOpcode() == SP::SUBCCri);
|
||||
|
@ -79,7 +79,6 @@ namespace llvm {
|
||||
|
||||
/// Override to support customized stack guard loading.
|
||||
bool useLoadStackGuardNode(const Module &M) const override;
|
||||
void insertSSPDeclarations(Module &M) const override;
|
||||
|
||||
/// getSetCCResultType - Return the ISD::SETCC ValueType
|
||||
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
|
||||
|
@ -1591,7 +1591,6 @@ namespace llvm {
|
||||
bool useLoadStackGuardNode(const Module &M) const override;
|
||||
bool useStackGuardXorFP() const override;
|
||||
void insertSSPDeclarations(Module &M) const override;
|
||||
Value *getSDagStackGuard(const Module &M) const override;
|
||||
Function *getSSPStackGuardCheck(const Module &M) const override;
|
||||
SDValue emitStackGuardXorFP(SelectionDAG &DAG, SDValue Val,
|
||||
const SDLoc &DL) const override;
|
||||
|
@ -632,15 +632,6 @@ void X86TargetLowering::insertSSPDeclarations(Module &M) const {
|
||||
TargetLowering::insertSSPDeclarations(M);
|
||||
}
|
||||
|
||||
Value *X86TargetLowering::getSDagStackGuard(const Module &M) const {
|
||||
// MSVC CRT has a global variable holding security cookie.
|
||||
if (Subtarget.getTargetTriple().isWindowsMSVCEnvironment() ||
|
||||
Subtarget.getTargetTriple().isWindowsItaniumEnvironment()) {
|
||||
return M.getGlobalVariable("__security_cookie");
|
||||
}
|
||||
return TargetLowering::getSDagStackGuard(M);
|
||||
}
|
||||
|
||||
Function *X86TargetLowering::getSSPStackGuardCheck(const Module &M) const {
|
||||
// MSVC CRT has a function to validate security cookie.
|
||||
if (Subtarget.getTargetTriple().isWindowsMSVCEnvironment() ||
|
||||
|
@ -344,7 +344,7 @@ define amdgpu_ps void @fptrunc_f32_to_bf16(float %a, ptr %out) {
|
||||
; GFX1250: ; %bb.0: ; %entry
|
||||
; GFX1250-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v2, v1
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.cvt = fptrunc float %a to bfloat
|
||||
@ -380,7 +380,7 @@ define amdgpu_ps void @fptrunc_f32_to_bf16_abs(float %a, ptr %out) {
|
||||
; GFX1250: ; %bb.0: ; %entry
|
||||
; GFX1250-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v2, v1
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, |v0|, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.abs = call float @llvm.fabs.f32(float %a)
|
||||
@ -417,7 +417,7 @@ define amdgpu_ps void @fptrunc_f32_to_bf16_neg(float %a, ptr %out) {
|
||||
; GFX1250: ; %bb.0: ; %entry
|
||||
; GFX1250-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v2, v1
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, -v0, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.neg = fneg float %a
|
||||
@ -480,7 +480,7 @@ define amdgpu_ps void @fptrunc_f64_to_bf16(double %a, ptr %out) {
|
||||
; GFX1250-NEXT: s_or_b32 vcc_lo, vcc_lo, s0
|
||||
; GFX1250-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc_lo
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.cvt = fptrunc double %a to bfloat
|
||||
@ -543,7 +543,7 @@ define amdgpu_ps void @fptrunc_f64_to_bf16_neg(double %a, ptr %out) {
|
||||
; GFX1250-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc_lo
|
||||
; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1)
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.neg = fneg double %a
|
||||
@ -607,7 +607,7 @@ define amdgpu_ps void @fptrunc_f64_to_bf16_abs(double %a, ptr %out) {
|
||||
; GFX1250-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc_lo
|
||||
; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1)
|
||||
; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0 scope:SCOPE_SE
|
||||
; GFX1250-NEXT: flat_store_b16 v[2:3], v0
|
||||
; GFX1250-NEXT: s_endpgm
|
||||
entry:
|
||||
%a.abs = call double @llvm.fabs.f64(double %a)
|
||||
|
@ -1582,22 +1582,28 @@ define amdgpu_kernel void @frem_f64(ptr addrspace(1) %out, ptr addrspace(1) %in1
|
||||
; SI-NEXT: s_nop 1
|
||||
; SI-NEXT: v_div_fmas_f64 v[4:5], v[12:13], v[6:7], v[10:11]
|
||||
; SI-NEXT: v_div_fixup_f64 v[4:5], v[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s0, v4
|
||||
; SI-NEXT: v_readfirstlane_b32 s1, v5
|
||||
; SI-NEXT: s_bfe_u32 s2, s1, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s8, s2, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s3, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s2, s6
|
||||
; SI-NEXT: s_lshr_b64 s[2:3], s[2:3], s8
|
||||
; SI-NEXT: s_andn2_b64 s[2:3], s[0:1], s[2:3]
|
||||
; SI-NEXT: s_and_b32 s9, s1, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s8, 0
|
||||
; SI-NEXT: s_cselect_b32 s2, 0, s2
|
||||
; SI-NEXT: s_cselect_b32 s3, s9, s3
|
||||
; SI-NEXT: s_cmp_gt_i32 s8, 51
|
||||
; SI-NEXT: s_cselect_b32 s1, s1, s3
|
||||
; SI-NEXT: s_cselect_b32 s0, s0, s2
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -s[0:1], v[2:3], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s2, v5
|
||||
; SI-NEXT: s_bfe_u32 s0, s2, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s3, s0, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s1, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s0, s6
|
||||
; SI-NEXT: s_lshr_b64 s[0:1], s[0:1], s3
|
||||
; SI-NEXT: v_not_b32_e32 v6, s0
|
||||
; SI-NEXT: v_and_b32_e32 v6, v4, v6
|
||||
; SI-NEXT: v_not_b32_e32 v7, s1
|
||||
; SI-NEXT: v_and_b32_e32 v5, v5, v7
|
||||
; SI-NEXT: s_and_b32 s0, s2, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s3, 0
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s0
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: s_cmp_gt_i32 s3, 51
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s2
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -v[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: buffer_store_dwordx2 v[0:1], off, s[4:7], 0
|
||||
; SI-NEXT: s_endpgm
|
||||
;
|
||||
@ -1853,22 +1859,28 @@ define amdgpu_kernel void @fast_frem_f64(ptr addrspace(1) %out, ptr addrspace(1)
|
||||
; SI-NEXT: v_mul_f64 v[6:7], v[0:1], v[4:5]
|
||||
; SI-NEXT: v_fma_f64 v[8:9], -v[2:3], v[6:7], v[0:1]
|
||||
; SI-NEXT: v_fma_f64 v[4:5], v[8:9], v[4:5], v[6:7]
|
||||
; SI-NEXT: v_readfirstlane_b32 s4, v4
|
||||
; SI-NEXT: v_readfirstlane_b32 s5, v5
|
||||
; SI-NEXT: s_bfe_u32 s6, s5, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s8, s6, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s7, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s6, s2
|
||||
; SI-NEXT: s_lshr_b64 s[6:7], s[6:7], s8
|
||||
; SI-NEXT: s_andn2_b64 s[6:7], s[4:5], s[6:7]
|
||||
; SI-NEXT: s_and_b32 s9, s5, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s8, 0
|
||||
; SI-NEXT: s_cselect_b32 s6, 0, s6
|
||||
; SI-NEXT: s_cselect_b32 s7, s9, s7
|
||||
; SI-NEXT: s_cmp_gt_i32 s8, 51
|
||||
; SI-NEXT: s_cselect_b32 s5, s5, s7
|
||||
; SI-NEXT: s_cselect_b32 s4, s4, s6
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -s[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s6, v5
|
||||
; SI-NEXT: s_bfe_u32 s4, s6, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s7, s4, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s5, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s4, s2
|
||||
; SI-NEXT: s_lshr_b64 s[4:5], s[4:5], s7
|
||||
; SI-NEXT: v_not_b32_e32 v6, s4
|
||||
; SI-NEXT: v_and_b32_e32 v6, v4, v6
|
||||
; SI-NEXT: v_not_b32_e32 v7, s5
|
||||
; SI-NEXT: v_and_b32_e32 v5, v5, v7
|
||||
; SI-NEXT: s_and_b32 s4, s6, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s7, 0
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s4
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: s_cmp_gt_i32 s7, 51
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s6
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -v[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0
|
||||
; SI-NEXT: s_endpgm
|
||||
;
|
||||
@ -2097,22 +2109,28 @@ define amdgpu_kernel void @unsafe_frem_f64(ptr addrspace(1) %out, ptr addrspace(
|
||||
; SI-NEXT: v_mul_f64 v[6:7], v[0:1], v[4:5]
|
||||
; SI-NEXT: v_fma_f64 v[8:9], -v[2:3], v[6:7], v[0:1]
|
||||
; SI-NEXT: v_fma_f64 v[4:5], v[8:9], v[4:5], v[6:7]
|
||||
; SI-NEXT: v_readfirstlane_b32 s4, v4
|
||||
; SI-NEXT: v_readfirstlane_b32 s5, v5
|
||||
; SI-NEXT: s_bfe_u32 s6, s5, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s8, s6, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s7, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s6, s2
|
||||
; SI-NEXT: s_lshr_b64 s[6:7], s[6:7], s8
|
||||
; SI-NEXT: s_andn2_b64 s[6:7], s[4:5], s[6:7]
|
||||
; SI-NEXT: s_and_b32 s9, s5, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s8, 0
|
||||
; SI-NEXT: s_cselect_b32 s6, 0, s6
|
||||
; SI-NEXT: s_cselect_b32 s7, s9, s7
|
||||
; SI-NEXT: s_cmp_gt_i32 s8, 51
|
||||
; SI-NEXT: s_cselect_b32 s5, s5, s7
|
||||
; SI-NEXT: s_cselect_b32 s4, s4, s6
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -s[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s6, v5
|
||||
; SI-NEXT: s_bfe_u32 s4, s6, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s7, s4, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s5, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s4, s2
|
||||
; SI-NEXT: s_lshr_b64 s[4:5], s[4:5], s7
|
||||
; SI-NEXT: v_not_b32_e32 v6, s4
|
||||
; SI-NEXT: v_and_b32_e32 v6, v4, v6
|
||||
; SI-NEXT: v_not_b32_e32 v7, s5
|
||||
; SI-NEXT: v_and_b32_e32 v5, v5, v7
|
||||
; SI-NEXT: s_and_b32 s4, s6, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s7, 0
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_cndmask_b32_e64 v6, v6, 0, vcc
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s4
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: s_cmp_gt_i32 s7, 51
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_mov_b32_e32 v7, s6
|
||||
; SI-NEXT: v_cndmask_b32_e32 v5, v5, v7, vcc
|
||||
; SI-NEXT: v_cndmask_b32_e32 v4, v6, v4, vcc
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -v[4:5], v[2:3], v[0:1]
|
||||
; SI-NEXT: buffer_store_dwordx2 v[0:1], off, s[0:3], 0
|
||||
; SI-NEXT: s_endpgm
|
||||
;
|
||||
@ -5233,22 +5251,27 @@ define amdgpu_kernel void @frem_v2f64(ptr addrspace(1) %out, ptr addrspace(1) %i
|
||||
; SI-NEXT: s_nop 1
|
||||
; SI-NEXT: v_div_fmas_f64 v[8:9], v[16:17], v[10:11], v[14:15]
|
||||
; SI-NEXT: v_div_fixup_f64 v[8:9], v[8:9], v[6:7], v[2:3]
|
||||
; SI-NEXT: v_readfirstlane_b32 s0, v8
|
||||
; SI-NEXT: v_readfirstlane_b32 s1, v9
|
||||
; SI-NEXT: s_bfe_u32 s2, s1, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s10, s2, 0xfffffc01
|
||||
; SI-NEXT: v_readfirstlane_b32 s8, v9
|
||||
; SI-NEXT: s_bfe_u32 s0, s8, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s9, s0, 0xfffffc01
|
||||
; SI-NEXT: s_mov_b32 s3, 0xfffff
|
||||
; SI-NEXT: s_mov_b32 s2, s6
|
||||
; SI-NEXT: s_lshr_b64 s[8:9], s[2:3], s10
|
||||
; SI-NEXT: s_andn2_b64 s[8:9], s[0:1], s[8:9]
|
||||
; SI-NEXT: s_and_b32 s11, s1, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s10, 0
|
||||
; SI-NEXT: s_cselect_b32 s8, 0, s8
|
||||
; SI-NEXT: s_cselect_b32 s9, s11, s9
|
||||
; SI-NEXT: s_cmp_gt_i32 s10, 51
|
||||
; SI-NEXT: s_cselect_b32 s1, s1, s9
|
||||
; SI-NEXT: s_cselect_b32 s0, s0, s8
|
||||
; SI-NEXT: v_fma_f64 v[2:3], -s[0:1], v[6:7], v[2:3]
|
||||
; SI-NEXT: s_lshr_b64 s[0:1], s[2:3], s9
|
||||
; SI-NEXT: v_not_b32_e32 v10, s0
|
||||
; SI-NEXT: v_and_b32_e32 v10, v8, v10
|
||||
; SI-NEXT: v_not_b32_e32 v11, s1
|
||||
; SI-NEXT: v_and_b32_e32 v9, v9, v11
|
||||
; SI-NEXT: s_and_b32 s0, s8, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s9, 0
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_cndmask_b32_e64 v10, v10, 0, vcc
|
||||
; SI-NEXT: v_mov_b32_e32 v11, s0
|
||||
; SI-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc
|
||||
; SI-NEXT: s_cmp_gt_i32 s9, 51
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_mov_b32_e32 v11, s8
|
||||
; SI-NEXT: v_cndmask_b32_e32 v9, v9, v11, vcc
|
||||
; SI-NEXT: v_cndmask_b32_e32 v8, v10, v8, vcc
|
||||
; SI-NEXT: v_fma_f64 v[2:3], -v[8:9], v[6:7], v[2:3]
|
||||
; SI-NEXT: v_div_scale_f64 v[6:7], s[0:1], v[4:5], v[4:5], v[0:1]
|
||||
; SI-NEXT: v_rcp_f64_e32 v[8:9], v[6:7]
|
||||
; SI-NEXT: v_fma_f64 v[10:11], -v[6:7], v[8:9], 1.0
|
||||
@ -5264,20 +5287,26 @@ define amdgpu_kernel void @frem_v2f64(ptr addrspace(1) %out, ptr addrspace(1) %i
|
||||
; SI-NEXT: s_nop 1
|
||||
; SI-NEXT: v_div_fmas_f64 v[6:7], v[14:15], v[8:9], v[12:13]
|
||||
; SI-NEXT: v_div_fixup_f64 v[6:7], v[6:7], v[4:5], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s0, v6
|
||||
; SI-NEXT: v_readfirstlane_b32 s1, v7
|
||||
; SI-NEXT: s_bfe_u32 s8, s1, 0xb0014
|
||||
; SI-NEXT: s_addk_i32 s8, 0xfc01
|
||||
; SI-NEXT: s_lshr_b64 s[2:3], s[2:3], s8
|
||||
; SI-NEXT: s_andn2_b64 s[2:3], s[0:1], s[2:3]
|
||||
; SI-NEXT: s_and_b32 s9, s1, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s8, 0
|
||||
; SI-NEXT: s_cselect_b32 s2, 0, s2
|
||||
; SI-NEXT: s_cselect_b32 s3, s9, s3
|
||||
; SI-NEXT: s_cmp_gt_i32 s8, 51
|
||||
; SI-NEXT: s_cselect_b32 s1, s1, s3
|
||||
; SI-NEXT: s_cselect_b32 s0, s0, s2
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -s[0:1], v[4:5], v[0:1]
|
||||
; SI-NEXT: v_readfirstlane_b32 s8, v7
|
||||
; SI-NEXT: s_bfe_u32 s0, s8, 0xb0014
|
||||
; SI-NEXT: s_add_i32 s9, s0, 0xfffffc01
|
||||
; SI-NEXT: s_lshr_b64 s[0:1], s[2:3], s9
|
||||
; SI-NEXT: v_not_b32_e32 v8, s0
|
||||
; SI-NEXT: v_and_b32_e32 v8, v6, v8
|
||||
; SI-NEXT: v_not_b32_e32 v9, s1
|
||||
; SI-NEXT: v_and_b32_e32 v7, v7, v9
|
||||
; SI-NEXT: s_and_b32 s0, s8, 0x80000000
|
||||
; SI-NEXT: s_cmp_lt_i32 s9, 0
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_cndmask_b32_e64 v8, v8, 0, vcc
|
||||
; SI-NEXT: v_mov_b32_e32 v9, s0
|
||||
; SI-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc
|
||||
; SI-NEXT: s_cmp_gt_i32 s9, 51
|
||||
; SI-NEXT: s_cselect_b64 vcc, -1, 0
|
||||
; SI-NEXT: v_mov_b32_e32 v9, s8
|
||||
; SI-NEXT: v_cndmask_b32_e32 v7, v7, v9, vcc
|
||||
; SI-NEXT: v_cndmask_b32_e32 v6, v8, v6, vcc
|
||||
; SI-NEXT: v_fma_f64 v[0:1], -v[6:7], v[4:5], v[0:1]
|
||||
; SI-NEXT: buffer_store_dwordx4 v[0:3], off, s[4:7], 0
|
||||
; SI-NEXT: s_endpgm
|
||||
;
|
||||
|
@ -76,13 +76,12 @@ define amdgpu_kernel void @v_round_f64(ptr addrspace(1) %out, ptr addrspace(1) %
|
||||
; SI-NEXT: s_waitcnt lgkmcnt(0)
|
||||
; SI-NEXT: s_mov_b64 s[4:5], s[2:3]
|
||||
; SI-NEXT: buffer_load_dwordx2 v[2:3], v[0:1], s[4:7], 0 addr64
|
||||
; SI-NEXT: s_movk_i32 s4, 0xfc01
|
||||
; SI-NEXT: s_mov_b32 s2, -1
|
||||
; SI-NEXT: s_mov_b32 s3, 0xfffff
|
||||
; SI-NEXT: v_mov_b32_e32 v8, 0x3ff00000
|
||||
; SI-NEXT: s_waitcnt vmcnt(0)
|
||||
; SI-NEXT: v_bfe_u32 v4, v3, 20, 11
|
||||
; SI-NEXT: v_add_i32_e32 v6, vcc, s4, v4
|
||||
; SI-NEXT: v_add_i32_e32 v6, vcc, 0xfffffc01, v4
|
||||
; SI-NEXT: v_lshr_b64 v[4:5], s[2:3], v6
|
||||
; SI-NEXT: v_and_b32_e32 v7, 0x80000000, v3
|
||||
; SI-NEXT: v_not_b32_e32 v5, v5
|
||||
|
@ -65,8 +65,8 @@ define void @func() sspreq nounwind {
|
||||
; LINUX32: # %bb.0:
|
||||
; LINUX32-NEXT: mflr 0
|
||||
; LINUX32-NEXT: stwu 1, -16(1)
|
||||
; LINUX32-NEXT: stw 0, 20(1)
|
||||
; LINUX32-NEXT: lwz 3, -28680(2)
|
||||
; LINUX32-NEXT: stw 0, 20(1)
|
||||
; LINUX32-NEXT: stw 3, 12(1)
|
||||
; LINUX32-NEXT: addi 3, 1, 8
|
||||
; LINUX32-NEXT: bl capture
|
||||
@ -86,8 +86,8 @@ define void @func() sspreq nounwind {
|
||||
; LINUX64: # %bb.0:
|
||||
; LINUX64-NEXT: mflr 0
|
||||
; LINUX64-NEXT: stdu 1, -128(1)
|
||||
; LINUX64-NEXT: std 0, 144(1)
|
||||
; LINUX64-NEXT: ld 3, -28688(13)
|
||||
; LINUX64-NEXT: std 0, 144(1)
|
||||
; LINUX64-NEXT: std 3, 120(1)
|
||||
; LINUX64-NEXT: addi 3, 1, 116
|
||||
; LINUX64-NEXT: bl capture
|
||||
|
@ -1,53 +1,20 @@
|
||||
; RUN: llc < %s | FileCheck %s
|
||||
; RUN: llc < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SAFE
|
||||
; RUN: llc < %s -enable-unsafe-fp-math | FileCheck %s --check-prefix=CHECK --check-prefix=UNSAFE
|
||||
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64--"
|
||||
|
||||
; CHECK-LABEL: double_rounding_safe:
|
||||
; CHECK: callq __trunctfdf2
|
||||
; CHECK-NEXT: cvtsd2ss %xmm0
|
||||
define void @double_rounding_safe(ptr %x, ptr %f) {
|
||||
entry:
|
||||
%x.fp128 = load fp128, ptr %x, align 16
|
||||
%x.double = fptrunc fp128 %x.fp128 to double
|
||||
%x.float = fptrunc double %x.double to float
|
||||
store float %x.float, ptr %f, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: double_rounding_contract_fst:
|
||||
; CHECK: callq __trunctfdf2
|
||||
; CHECK-NEXT: cvtsd2ss %xmm0
|
||||
define void @double_rounding_contract_fst(ptr %x, ptr %f) {
|
||||
entry:
|
||||
%x.fp128 = load fp128, ptr %x, align 16
|
||||
%x.double = fptrunc contract fp128 %x.fp128 to double
|
||||
%x.float = fptrunc double %x.double to float
|
||||
store float %x.float, ptr %f, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: double_rounding_contract_snd:
|
||||
; CHECK: callq __trunctfdf2
|
||||
; CHECK-NEXT: cvtsd2ss %xmm0
|
||||
define void @double_rounding_contract_snd(ptr %x, ptr %f) {
|
||||
entry:
|
||||
%x.fp128 = load fp128, ptr %x, align 16
|
||||
%x.double = fptrunc fp128 %x.fp128 to double
|
||||
%x.float = fptrunc contract double %x.double to float
|
||||
store float %x.float, ptr %f, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: double_rounding:
|
||||
; CHECK: callq __trunctfsf2
|
||||
; CHECK-NOT: cvt
|
||||
; SAFE: callq __trunctfdf2
|
||||
; SAFE-NEXT: cvtsd2ss %xmm0
|
||||
; UNSAFE: callq __trunctfsf2
|
||||
; UNSAFE-NOT: cvt
|
||||
define void @double_rounding(ptr %x, ptr %f) {
|
||||
entry:
|
||||
%x.fp128 = load fp128, ptr %x, align 16
|
||||
%x.double = fptrunc contract fp128 %x.fp128 to double
|
||||
%x.float = fptrunc contract double %x.double to float
|
||||
store float %x.float, ptr %f, align 4
|
||||
%0 = load fp128, ptr %x, align 16
|
||||
%1 = fptrunc fp128 %0 to double
|
||||
%2 = fptrunc double %1 to float
|
||||
store float %2, ptr %f, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,8 @@ void ExecuteRegionOp::print(OpAsmPrinter &p) {
|
||||
p.printRegion(getRegion(),
|
||||
/*printEntryBlockArgs=*/false,
|
||||
/*printBlockTerminators=*/true);
|
||||
p.printOptionalAttrDict((*this)->getAttrs(), /*elidedAttrs=*/{"no_inline"});
|
||||
|
||||
p.printOptionalAttrDict((*this)->getAttrs());
|
||||
}
|
||||
|
||||
LogicalResult ExecuteRegionOp::verify() {
|
||||
|
@ -1479,7 +1479,7 @@ func.func @execute_region_no_inline() {
|
||||
// CHECK-NEXT: scf.execute_region
|
||||
// CHECK-NEXT: %[[VAL:.*]] = "test.val"() : () -> i64
|
||||
// CHECK-NEXT: scf.yield %[[VAL]] : i64
|
||||
// CHECK-NOT: no_inline
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// -----
|
||||
|
||||
|
@ -369,7 +369,6 @@ There are following check-* make targets for tests.
|
||||
|
||||
- ``check-ompt`` (ompt tests under runtime/test/ompt)
|
||||
- ``check-ompt-multiplex`` (ompt multiplex tests under tools/multiplex/tests)
|
||||
- ``check-ompt-omptest`` (ompt omptest tests under tools/omptest/tests)
|
||||
- ``check-libarcher`` (libarcher tests under tools/archer/tests)
|
||||
- ``check-libomp`` (libomp tests under runtime/test. This includes check-ompt tests too)
|
||||
- ``check-libomptarget-*`` (libomptarget tests for specific target under libomptarget/test)
|
||||
|
@ -15,21 +15,6 @@ if(LIBOMP_OMPT_SUPPORT AND LIBOMP_ARCHER_SUPPORT)
|
||||
target_link_libraries(archer ${CMAKE_DL_LIBS})
|
||||
add_library(archer_static STATIC ompt-tsan.cpp)
|
||||
|
||||
if(TARGET cxx-headers)
|
||||
add_dependencies(archer cxx-headers)
|
||||
add_dependencies(archer_static cxx-headers)
|
||||
endif()
|
||||
|
||||
if(TARGET cxx_shared)
|
||||
add_dependencies(archer cxx_shared)
|
||||
add_dependencies(archer_static cxx_shared)
|
||||
endif()
|
||||
|
||||
if(TARGET cxxabi_shared)
|
||||
add_dependencies(archer cxxabi_shared)
|
||||
add_dependencies(archer_static cxxabi_shared)
|
||||
endif()
|
||||
|
||||
install(TARGETS archer archer_static
|
||||
LIBRARY DESTINATION ${OPENMP_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${OPENMP_INSTALL_LIBDIR})
|
||||
|
@ -1,154 +0,0 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# Build OMPT unit testing library: ompTest
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(omptest LANGUAGES CXX)
|
||||
|
||||
option(LIBOMPTEST_BUILD_STANDALONE
|
||||
"Build ompTest 'standalone', i.e. w/o GoogleTest."
|
||||
${OPENMP_STANDALONE_BUILD})
|
||||
option(LIBOMPTEST_BUILD_UNITTESTS
|
||||
"Build ompTest's unit tests, requires GoogleTest." OFF)
|
||||
|
||||
# In absence of corresponding OMPT support: exit early
|
||||
if(NOT ${LIBOMP_OMPT_SUPPORT})
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
set(OMPTEST_HEADERS
|
||||
./include/AssertMacros.h
|
||||
./include/InternalEvent.h
|
||||
./include/InternalEventCommon.h
|
||||
./include/Logging.h
|
||||
./include/OmptAliases.h
|
||||
./include/OmptAsserter.h
|
||||
./include/OmptAssertEvent.h
|
||||
./include/OmptCallbackHandler.h
|
||||
./include/OmptTester.h
|
||||
./include/OmptTesterGlobals.h
|
||||
)
|
||||
|
||||
add_library(omptest
|
||||
SHARED
|
||||
|
||||
${OMPTEST_HEADERS}
|
||||
./src/InternalEvent.cpp
|
||||
./src/InternalEventOperators.cpp
|
||||
./src/Logging.cpp
|
||||
./src/OmptAsserter.cpp
|
||||
./src/OmptAssertEvent.cpp
|
||||
./src/OmptCallbackHandler.cpp
|
||||
./src/OmptTester.cpp
|
||||
)
|
||||
|
||||
# Target: ompTest library
|
||||
# On (implicit) request of GoogleTest, link against the one provided with LLVM.
|
||||
if ((NOT LIBOMPTEST_BUILD_STANDALONE) OR LIBOMPTEST_BUILD_UNITTESTS)
|
||||
# Check if standalone build was requested together with unittests
|
||||
if (LIBOMPTEST_BUILD_STANDALONE)
|
||||
# Emit warning: this build actually depends on LLVM's GoogleTest
|
||||
message(WARNING "LIBOMPTEST_BUILD_STANDALONE and LIBOMPTEST_BUILD_UNITTESTS"
|
||||
" requested simultaneously.\n"
|
||||
"Linking against LLVM's GoogleTest library archives.\n"
|
||||
"Disable LIBOMPTEST_BUILD_UNITTESTS to perform an actual"
|
||||
" standalone build.")
|
||||
# Explicitly disable LIBOMPTEST_BUILD_STANDALONE
|
||||
set(LIBOMPTEST_BUILD_STANDALONE OFF)
|
||||
endif()
|
||||
|
||||
# Make sure target llvm_gtest is available
|
||||
if (NOT TARGET llvm_gtest)
|
||||
message(FATAL_ERROR "Required target not found: llvm_gtest")
|
||||
endif()
|
||||
|
||||
# Add llvm_gtest as dependency
|
||||
add_dependencies(omptest llvm_gtest)
|
||||
|
||||
# Link llvm_gtest as whole-archive to expose required symbols
|
||||
set(GTEST_LINK_CMD "-Wl,--whole-archive" llvm_gtest
|
||||
"-Wl,--no-whole-archive" LLVMSupport)
|
||||
|
||||
# Add GoogleTest-based header
|
||||
target_sources(omptest PRIVATE ./include/OmptTesterGoogleTest.h)
|
||||
|
||||
# Add LLVM-provided GoogleTest include directories.
|
||||
target_include_directories(omptest PRIVATE
|
||||
${LLVM_THIRD_PARTY_DIR}/unittest/googletest/include)
|
||||
|
||||
# TODO: Re-visit ABI breaking checks, disable for now.
|
||||
target_compile_definitions(omptest PUBLIC
|
||||
-DLLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING)
|
||||
|
||||
# Link against gtest and gtest_main
|
||||
target_link_libraries(omptest PRIVATE ${GTEST_LINK_CMD})
|
||||
else()
|
||||
# Add 'standalone' compile definitions
|
||||
target_compile_definitions(omptest PRIVATE
|
||||
-DOPENMP_LIBOMPTEST_BUILD_STANDALONE)
|
||||
|
||||
# Add 'standalone' source files
|
||||
target_sources(omptest PRIVATE
|
||||
./include/OmptTesterStandalone.h
|
||||
./src/OmptTesterStandalone.cpp)
|
||||
endif()
|
||||
|
||||
if(TARGET cxx-headers)
|
||||
add_dependencies(omptest cxx-headers)
|
||||
endif()
|
||||
|
||||
if(TARGET cxx_shared)
|
||||
add_dependencies(omptest cxx_shared)
|
||||
endif()
|
||||
|
||||
if(TARGET cxxabi_shared)
|
||||
add_dependencies(omptest cxxabi_shared)
|
||||
endif()
|
||||
|
||||
# Add common include directories.
|
||||
target_include_directories(omptest PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/${LIBOMP_HEADERS_INSTALL_PATH}/omptest>
|
||||
)
|
||||
|
||||
target_compile_features(omptest PRIVATE cxx_std_17)
|
||||
|
||||
# Create and install package configuration files.
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/omptest-config.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/cmake/omptest-config.cmake
|
||||
INSTALL_DESTINATION "${OPENMP_INSTALL_LIBDIR}/cmake/openmp/omptest"
|
||||
)
|
||||
|
||||
install(FILES ${omptest_BINARY_DIR}/cmake/omptest-config.cmake
|
||||
DESTINATION "${OPENMP_INSTALL_LIBDIR}/cmake/openmp/omptest")
|
||||
|
||||
# Install libomptest header files: Copy header-files from include dir
|
||||
install(DIRECTORY ./include/
|
||||
DESTINATION "${LIBOMP_HEADERS_INSTALL_PATH}/omptest"
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
|
||||
# Install library and export targets.
|
||||
# Note: find_package(omptest) may require setting of PATH_SUFFIXES
|
||||
# Example: "lib/cmake/openmp/omptest", this is due to the install location
|
||||
install(TARGETS omptest
|
||||
EXPORT OPENMPomptest
|
||||
LIBRARY COMPONENT omptest
|
||||
DESTINATION "${OPENMP_INSTALL_LIBDIR}"
|
||||
INCLUDES DESTINATION "${LIBOMP_HEADERS_INSTALL_PATH}/omptest")
|
||||
|
||||
# Allow to link omptest by using: target_link_libraries( ... omptest::omptest)
|
||||
# Additionally, it automatically propagates the include directory.
|
||||
install(EXPORT OPENMPomptest
|
||||
DESTINATION "${OPENMP_INSTALL_LIBDIR}/cmake/openmp/omptest"
|
||||
NAMESPACE omptest::
|
||||
FILE omptest-targets.cmake)
|
||||
|
||||
# Discover unit tests (added to check-openmp)
|
||||
if(LIBOMPTEST_BUILD_UNITTESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
@ -1,279 +0,0 @@
|
||||
|
||||
README for the OpenMP Tooling Interface Testing Library (ompTest)
|
||||
=================================================================
|
||||
|
||||
# Introduction
|
||||
OpenMP Tooling Interface Testing Library (ompTest)
|
||||
ompTest is a unit testing framework for testing OpenMP implementations.
|
||||
It offers a simple-to-use framework that allows a tester to check for OMPT
|
||||
events in addition to regular unit testing code, supported by linking against
|
||||
GoogleTest by default. It also facilitates writing concise tests while bridging
|
||||
the semantic gap between the unit under test and the OMPT-event testing.
|
||||
|
||||
# Testing macros
|
||||
|
||||
Corresponding macro definitions are located in: `./include/AssertMacros.h`
|
||||
|
||||
## OMPT_GENERATE_EVENTS(NumberOfCopies, EventMacro)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_EVENT(Name, Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET(EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_GROUPED(Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_NAMED(Name, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_EVENT_NOT(Name, Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_NOT(EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_GROUPED_NOT(Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_NAMED_NOT(Name, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_EVENT(Name, Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE(EventTy, ...)
|
||||
This macro checks for the occurrence of the provided event, which also
|
||||
entails the exact sequence of events. When only using this assertion macro one
|
||||
has to provide every single event in the exact order of occurrence.
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_GROUPED(Group, EventTy, ...)
|
||||
This macro acts like `OMPT_ASSERT_SEQUENCE` with the addition of grouping.
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_NAMED(Name, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_EVENT_NOT(Name, Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_NOT(EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_GROUPED_NOT(Group, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_NAMED_NOT(Name, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_SUSPEND()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_ONLY(EventTy, ...)
|
||||
This macro acts like `OMPT_ASSERT_SEQUENCE`, while actually being preceded
|
||||
-AND- succeeded by commands to suspend sequenced assertion until the next match.
|
||||
As a result, one may omit all other "unnecessary" events from the sequence.
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_GROUPED_ONLY(Group, EventTy, ...)
|
||||
This macro acts like `OMPT_ASSERT_SEQUENCE_ONLY`, plus grouping.
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_NAMED_ONLY(Name, EventTy, ...)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_MODE_STRICT(Asserter)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_MODE_RELAXED(Asserter)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_MODE_STRICT()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_MODE_RELAXED()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_MODE_STRICT()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_MODE_RELAXED()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_DISABLE(Asserter)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_ENABLE(Asserter)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_DISABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SET_ENABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_DISABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SEQUENCE_ENABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_REPORT_EVENT_DISABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_REPORT_EVENT_ENABLE()
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_PERMIT_EVENT(Asserter, EventTy)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_SUPPRESS_EVENT(Asserter, EventTy)
|
||||
`TODO`
|
||||
|
||||
## OMPT_PERMIT_EVENT(EventTy)
|
||||
`TODO`
|
||||
|
||||
## OMPT_SUPPRESS_EVENT(EventTy)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_LOG_LEVEL(Asserter, LogLevel)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERTER_LOG_FORMATTED(Asserter, FormatLog)
|
||||
`TODO`
|
||||
|
||||
## OMPT_ASSERT_SYNC_POINT(SyncPointName)
|
||||
`TODO`
|
||||
|
||||
### Grouping Asserts
|
||||
|
||||
This allows to generate and verify data during runtime of a test.
|
||||
Currently, we only use target region information which manifests into groups.
|
||||
This allows to correlate multiple events to a certain target region without
|
||||
manual interaction just by specifying a groupname for these events.
|
||||
|
||||
When a target region is encountered and we are about to enter it, we gather the
|
||||
`target_id` (non-EMI) -OR- `target_data->value` (EMI). This value is stored
|
||||
along the groupname for future reference. Upon target region end, the
|
||||
corresponding group is erased. (Note: The groupname is available again.)
|
||||
|
||||
Other asserted callbacks which may occur within target regions query their
|
||||
groupname: retrieving and comparing the value of the group against the observed
|
||||
event's value.
|
||||
|
||||
### Suspending Sequenced Asserts
|
||||
|
||||
When a sequence of events is not of interest while testing, these additional
|
||||
events may be ignored by suspending the assertion until the next match. This
|
||||
can be done by using `OMPT_ASSERT_SEQUENCE_SUSPEND` manually or the `_ONLY`
|
||||
macro variants, like `OMPT_ASSERT_GROUPED_SEQUENCE_ONLY`.
|
||||
|
||||
The former adds a special event to the queue of expected events and signal
|
||||
that any non-matching event should be ignored rather than failing the test.
|
||||
`_ONLY` macros embed their corresponding macro between two calls to
|
||||
`OMPT_ASSERT_SEQUENCE_SUSPEND`. As a consequence, we enter passive assertion
|
||||
until a match occurs, then enter passive assertion again. This enables us to
|
||||
"only" assert a certain, single event in arbitrary circumstances.
|
||||
|
||||
### Asserter Modes
|
||||
`TODO`
|
||||
|
||||
## Aliases (shorthands)
|
||||
To allow for easier writing of tests and enhanced readability, the following set
|
||||
of aliases is introduced. The left hand side represents the original value,
|
||||
while the right hand side depicts the shorthand version.
|
||||
|
||||
| Type | Enum Value | Shorthand |
|
||||
|---------------------------|---------------------------------------------|---------------------------|
|
||||
| **ompt_scope_endpoint_t** | | |
|
||||
| | ompt_scope_begin | BEGIN |
|
||||
| | ompt_scope_end | END |
|
||||
| | ompt_scope_beginend | BEGINEND |
|
||||
| **ompt_target_t** | | |
|
||||
| | ompt_target | TARGET |
|
||||
| | ompt_target_enter_data | ENTER_DATA |
|
||||
| | ompt_target_exit_data | EXIT_DATA |
|
||||
| | ompt_target_update | UPDATE |
|
||||
| | ompt_target_nowait | TARGET_NOWAIT |
|
||||
| | ompt_target_enter_data_nowait | ENTER_DATA_NOWAIT |
|
||||
| | ompt_target_exit_data_nowait | EXIT_DATA_NOWAIT |
|
||||
| | ompt_target_update_nowait | UPDATE_NOWAIT |
|
||||
| **ompt_target_data_op_t** | | |
|
||||
| | ompt_target_data_alloc | ALLOC |
|
||||
| | ompt_target_data_transfer_to_device | H2D |
|
||||
| | ompt_target_data_transfer_from_device | D2H |
|
||||
| | ompt_target_data_delete | DELETE |
|
||||
| | ompt_target_data_associate | ASSOCIATE |
|
||||
| | ompt_target_data_disassociate | DISASSOCIATE |
|
||||
| | ompt_target_data_alloc_async | ALLOC_ASYNC |
|
||||
| | ompt_target_data_transfer_to_device_async | H2D_ASYNC |
|
||||
| | ompt_target_data_transfer_from_device_async | D2H_ASYNC |
|
||||
| | ompt_target_data_delete_async | DELETE_ASYNC |
|
||||
| **ompt_callbacks_t** | | |
|
||||
| | ompt_callback_target | CB_TARGET |
|
||||
| | ompt_callback_target_data_op | CB_DATAOP |
|
||||
| | ompt_callback_target_submit | CB_KERNEL |
|
||||
| **ompt_work_t** | | |
|
||||
| | ompt_work_loop | WORK_LOOP |
|
||||
| | ompt_work_sections | WORK_SECT |
|
||||
| | ompt_work_single_executor | WORK_EXEC |
|
||||
| | ompt_work_single_other | WORK_SINGLE |
|
||||
| | ompt_work_workshare | WORK_SHARE |
|
||||
| | ompt_work_distribute | WORK_DIST |
|
||||
| | ompt_work_taskloop | WORK_TASK |
|
||||
| | ompt_work_scope | WORK_SCOPE |
|
||||
| | ompt_work_loop_static | WORK_LOOP_STA |
|
||||
| | ompt_work_loop_dynamic | WORK_LOOP_DYN |
|
||||
| | ompt_work_loop_guided | WORK_LOOP_GUI |
|
||||
| | ompt_work_loop_other | WORK_LOOP_OTH |
|
||||
| **ompt_sync_region_t** | | |
|
||||
| | ompt_sync_region_barrier | SR_BARRIER |
|
||||
| | ompt_sync_region_barrier_implicit | SR_BARRIER_IMPL |
|
||||
| | ompt_sync_region_barrier_explicit | SR_BARRIER_EXPL |
|
||||
| | ompt_sync_region_barrier_implementation | SR_BARRIER_IMPLEMENTATION |
|
||||
| | ompt_sync_region_taskwait | SR_TASKWAIT |
|
||||
| | ompt_sync_region_taskgroup | SR_TASKGROUP |
|
||||
| | ompt_sync_region_reduction | SR_REDUCTION |
|
||||
| | ompt_sync_region_barrier_implicit_workshare | SR_BARRIER_IMPL_WORKSHARE |
|
||||
| | ompt_sync_region_barrier_implicit_parallel | SR_BARRIER_IMPL_PARALLEL |
|
||||
| | ompt_sync_region_barrier_teams | SR_BARRIER_TEAMS |
|
||||
|
||||
|
||||
Limitations
|
||||
===========
|
||||
Currently, there are some peculiarities which have to be kept in mind when using
|
||||
this library:
|
||||
|
||||
## Callbacks
|
||||
* It is not possible to e.g. test non-EMI -AND- EMI callbacks within the same
|
||||
test file. Reason: all testsuites share the initialization and therefore the
|
||||
registered callbacks.
|
||||
* It is not possible to check for device initialization and/or load callbacks
|
||||
more than once per test file. The first testcase being run, triggers these
|
||||
callbacks and is therefore the only testcase that is able to check for them.
|
||||
This is because, after that, the device remains initialized.
|
||||
* It is not possible to check for device finalization callbacks, as libomptest
|
||||
is un-loaded before this callback occurs. Same holds true for the final
|
||||
ThreadEnd event(s).
|
||||
|
||||
Miscellaneous
|
||||
=============
|
||||
|
||||
## Default values
|
||||
|
||||
To allow for easier writing of tests, many OMPT events may be created using less
|
||||
parameters than actually requested by the spec -- by using default values. These
|
||||
defaults are currently set to the corresponding data type's minimum as follows,
|
||||
for example integers use: `std::numeric_limits<int>::min()`.
|
||||
|
||||
When an expected / user-specified event has certain values set to the
|
||||
corresponding default, these values are ignored. That is, when compared to an
|
||||
observed event, this property is considered as 'equal' regardless of their
|
||||
actual equality relation.
|
||||
|
||||
References
|
||||
==========
|
||||
[0]: ompTest – Unit Testing with OMPT
|
||||
https://doi.org/10.1109/SCW63240.2024.00031
|
||||
|
||||
[1]: OMPTBench – OpenMP Tool Interface Conformance Testing
|
||||
https://doi.org/10.1109/SCW63240.2024.00036
|
@ -1,32 +0,0 @@
|
||||
################################################################################
|
||||
##
|
||||
## omptest cmake configuration file.
|
||||
## Enable support for find_package(omptest).
|
||||
##
|
||||
################################################################################
|
||||
|
||||
# Initialize package.
|
||||
@PACKAGE_INIT@
|
||||
|
||||
# Include exported targets.
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/omptest-targets.cmake")
|
||||
|
||||
# Provide information, if ompTest has been built 'standalone'.
|
||||
set(LIBOMPTEST_BUILD_STANDALONE "@LIBOMPTEST_BUILD_STANDALONE@")
|
||||
|
||||
# Note: The following variables are meant as a fallback.
|
||||
# But eventually we may remove them in favor of linking via namespace.
|
||||
|
||||
# Set LLVM installation root directory by using exported package information.
|
||||
set(LLVM_ROOT "${PACKAGE_PREFIX_DIR}")
|
||||
|
||||
# Provide header and library paths.
|
||||
set(LIBOMP_HEADERS_INSTALL_PATH "${LLVM_ROOT}/@LIBOMP_HEADERS_INSTALL_PATH@")
|
||||
set(LIBOMP_LIBRARY_INSTALL_PATH "${LLVM_ROOT}/@OPENMP_INSTALL_LIBDIR@")
|
||||
set(omptest_INCLUDE_DIR "${LIBOMP_HEADERS_INSTALL_PATH}/omptest")
|
||||
set(omptest_LIBRARY_DIR "${LIBOMP_LIBRARY_INSTALL_PATH}")
|
||||
|
||||
# Provide compiler default values.
|
||||
set(LLVM_BIN_INSTALL_DIR "${LLVM_ROOT}/bin")
|
||||
set(omptest_C_COMPILER "${LLVM_BIN_INSTALL_DIR}/clang")
|
||||
set(omptest_CXX_COMPILER "${LLVM_BIN_INSTALL_DIR}/clang++")
|
@ -1,138 +0,0 @@
|
||||
//===- AssertMacros.h - Macro aliases for ease-of-use -----------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Provides macros to be used in unit tests for OMPT events.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_ASSERTMACROS_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_ASSERTMACROS_H
|
||||
|
||||
#define OMPTEST_EXCLUDED_EVENT omptest::ObserveState::Never
|
||||
#define OMPTEST_REQUIRED_EVENT omptest::ObserveState::Always
|
||||
|
||||
/// ASSERT MACROS TO BE USED BY THE USER
|
||||
|
||||
#define OMPT_GENERATE_EVENTS(NumberOfCopies, EventMacro) \
|
||||
for (size_t i = 0; i < NumberOfCopies; ++i) { \
|
||||
EventMacro \
|
||||
}
|
||||
|
||||
// Handle a minimum unordered set of events
|
||||
// Required events
|
||||
#define OMPT_ASSERT_SET_EVENT(Name, Group, EventTy, ...) \
|
||||
SetAsserter->insert(OmptAssertEvent::EventTy( \
|
||||
Name, Group, OMPTEST_REQUIRED_EVENT, __VA_ARGS__));
|
||||
#define OMPT_ASSERT_SET(EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT("", "", EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SET_GROUPED(Group, EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT("", Group, EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SET_NAMED(Name, EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT(Name, "", EventTy, __VA_ARGS__)
|
||||
// Excluded ("NOT") events
|
||||
#define OMPT_ASSERT_SET_EVENT_NOT(Name, Group, EventTy, ...) \
|
||||
SetAsserter->insert(OmptAssertEvent::EventTy( \
|
||||
Name, Group, OMPTEST_EXCLUDED_EVENT, __VA_ARGS__));
|
||||
#define OMPT_ASSERT_SET_NOT(EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT_NOT("", "", EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SET_GROUPED_NOT(Group, EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT_NOT("", Group, EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SET_NAMED_NOT(Name, EventTy, ...) \
|
||||
OMPT_ASSERT_SET_EVENT_NOT(Name, "", EventTy, __VA_ARGS__)
|
||||
|
||||
// Handle an exact sequence of events
|
||||
// Required events
|
||||
#define OMPT_ASSERT_SEQUENCE_EVENT(Name, Group, EventTy, ...) \
|
||||
SequenceAsserter->insert(OmptAssertEvent::EventTy( \
|
||||
Name, Group, OMPTEST_REQUIRED_EVENT, __VA_ARGS__));
|
||||
#define OMPT_ASSERT_SEQUENCE(EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT("", "", EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SEQUENCE_GROUPED(Group, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT("", Group, EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SEQUENCE_NAMED(Name, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT(Name, "", EventTy, __VA_ARGS__)
|
||||
// Excluded ("NOT") events
|
||||
#define OMPT_ASSERT_SEQUENCE_EVENT_NOT(Name, Group, EventTy, ...) \
|
||||
SequenceAsserter->insert(OmptAssertEvent::EventTy( \
|
||||
Name, Group, OMPTEST_EXCLUDED_EVENT, __VA_ARGS__));
|
||||
#define OMPT_ASSERT_SEQUENCE_NOT(EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT_NOT("", "", EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SEQUENCE_GROUPED_NOT(Group, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT_NOT("", Group, EventTy, __VA_ARGS__)
|
||||
#define OMPT_ASSERT_SEQUENCE_NAMED_NOT(Name, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT_NOT(Name, "", EventTy, __VA_ARGS__)
|
||||
// Special command: suspend active assertion
|
||||
// The created event is not correlated to any observed event
|
||||
#define OMPT_ASSERT_SEQUENCE_SUSPEND() \
|
||||
SequenceAsserter->insert( \
|
||||
OmptAssertEvent::AssertionSuspend("", "", OMPTEST_EXCLUDED_EVENT));
|
||||
#define OMPT_ASSERT_SEQUENCE_ONLY(EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND() \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT("", "", EventTy, __VA_ARGS__) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND()
|
||||
#define OMPT_ASSERT_SEQUENCE_GROUPED_ONLY(Group, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND() \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT("", Group, EventTy, __VA_ARGS__) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND()
|
||||
#define OMPT_ASSERT_SEQUENCE_NAMED_ONLY(Name, EventTy, ...) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND() \
|
||||
OMPT_ASSERT_SEQUENCE_EVENT(Name, "", EventTy, __VA_ARGS__) \
|
||||
OMPT_ASSERT_SEQUENCE_SUSPEND()
|
||||
|
||||
#define OMPT_ASSERTER_MODE_STRICT(Asserter) \
|
||||
Asserter->setOperationMode(AssertMode::Strict);
|
||||
#define OMPT_ASSERTER_MODE_RELAXED(Asserter) \
|
||||
Asserter->setOperationMode(AssertMode::Relaxed);
|
||||
#define OMPT_ASSERT_SEQUENCE_MODE_STRICT() \
|
||||
OMPT_ASSERTER_MODE_STRICT(SequenceAsserter)
|
||||
#define OMPT_ASSERT_SEQUENCE_MODE_RELAXED() \
|
||||
OMPT_ASSERTER_MODE_RELAXED(SequenceAsserter)
|
||||
#define OMPT_ASSERT_SET_MODE_STRICT() OMPT_ASSERTER_MODE_STRICT(SetAsserter)
|
||||
#define OMPT_ASSERT_SET_MODE_RELAXED() OMPT_ASSERTER_MODE_RELAXED(SetAsserter)
|
||||
|
||||
// Enable / disable asserters entirely
|
||||
#define OMPT_ASSERTER_DISABLE(Asserter) Asserter->setActive(false);
|
||||
#define OMPT_ASSERTER_ENABLE(Asserter) Asserter->setActive(true);
|
||||
#define OMPT_ASSERT_SET_DISABLE() OMPT_ASSERTER_DISABLE(SetAsserter)
|
||||
#define OMPT_ASSERT_SET_ENABLE() OMPT_ASSERTER_ENABLE(SetAsserter)
|
||||
#define OMPT_ASSERT_SEQUENCE_DISABLE() OMPT_ASSERTER_DISABLE(SequenceAsserter)
|
||||
#define OMPT_ASSERT_SEQUENCE_ENABLE() OMPT_ASSERTER_ENABLE(SequenceAsserter)
|
||||
#define OMPT_REPORT_EVENT_DISABLE() OMPT_ASSERTER_DISABLE(EventReporter)
|
||||
#define OMPT_REPORT_EVENT_ENABLE() OMPT_ASSERTER_ENABLE(EventReporter)
|
||||
|
||||
// Enable / disable certain event types for asserters
|
||||
#define OMPT_ASSERTER_PERMIT_EVENT(Asserter, EventTy) \
|
||||
Asserter->permitEvent(EventTy);
|
||||
#define OMPT_ASSERTER_SUPPRESS_EVENT(Asserter, EventTy) \
|
||||
Asserter->suppressEvent(EventTy);
|
||||
#define OMPT_PERMIT_EVENT(EventTy) \
|
||||
OMPT_ASSERTER_PERMIT_EVENT(SetAsserter, EventTy); \
|
||||
OMPT_ASSERTER_PERMIT_EVENT(EventReporter, EventTy); \
|
||||
OMPT_ASSERTER_PERMIT_EVENT(SequenceAsserter, EventTy);
|
||||
#define OMPT_SUPPRESS_EVENT(EventTy) \
|
||||
OMPT_ASSERTER_SUPPRESS_EVENT(SetAsserter, EventTy); \
|
||||
OMPT_ASSERTER_SUPPRESS_EVENT(EventReporter, EventTy); \
|
||||
OMPT_ASSERTER_SUPPRESS_EVENT(SequenceAsserter, EventTy);
|
||||
|
||||
// Set logging level for asserters
|
||||
// Note: Logger is a singleton, hence this will affect all asserter instances
|
||||
#define OMPT_ASSERTER_LOG_LEVEL(Asserter, LogLevel) \
|
||||
Asserter->getLog()->setLoggingLevel(LogLevel);
|
||||
|
||||
// Set log formatting (esp. coloring) for asserters
|
||||
// Note: Logger is a singleton, hence this will affect all asserter instances
|
||||
#define OMPT_ASSERTER_LOG_FORMATTED(Asserter, FormatLog) \
|
||||
Asserter->getLog()->setFormatOutput(FormatLog);
|
||||
|
||||
// SyncPoint handling
|
||||
#define OMPT_ASSERT_SYNC_POINT(SyncPointName) \
|
||||
flush_traced_devices(); \
|
||||
OmptCallbackHandler::get().handleAssertionSyncPoint(SyncPointName);
|
||||
|
||||
#endif
|
@ -1,436 +0,0 @@
|
||||
//===- InternalEvent.h - Internal event representation ----------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Declares internal event representations along the default CTOR definition.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_INTERNALEVENT_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_INTERNALEVENT_H
|
||||
|
||||
#include "InternalEventCommon.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <omp-tools.h>
|
||||
|
||||
#define expectedDefault(TypeName) std::numeric_limits<TypeName>::min()
|
||||
|
||||
namespace omptest {
|
||||
|
||||
namespace util {
|
||||
|
||||
/// String manipulation helper function. Takes up to 8 bytes of data and returns
|
||||
/// their hexadecimal representation as string. The data can be expanded to the
|
||||
/// given size in bytes and will by default be prefixed with '0x'.
|
||||
std::string makeHexString(uint64_t Data, bool IsPointer = true,
|
||||
size_t DataBytes = 0, bool ShowHexBase = true);
|
||||
|
||||
} // namespace util
|
||||
|
||||
namespace internal {
|
||||
struct AssertionSyncPoint : public EventBase<AssertionSyncPoint> {
|
||||
std::string toString() const override;
|
||||
AssertionSyncPoint(const std::string &Name) : Name(Name) {}
|
||||
const std::string Name;
|
||||
};
|
||||
|
||||
struct AssertionSuspend : public EventBase<AssertionSuspend> {
|
||||
AssertionSuspend() = default;
|
||||
};
|
||||
|
||||
struct ThreadBegin : public EventBase<ThreadBegin> {
|
||||
std::string toString() const override;
|
||||
ThreadBegin(ompt_thread_t ThreadType) : ThreadType(ThreadType) {}
|
||||
ompt_thread_t ThreadType;
|
||||
};
|
||||
|
||||
struct ThreadEnd : public EventBase<ThreadEnd> {
|
||||
std::string toString() const override;
|
||||
ThreadEnd() = default;
|
||||
};
|
||||
|
||||
struct ParallelBegin : public EventBase<ParallelBegin> {
|
||||
std::string toString() const override;
|
||||
ParallelBegin(int NumThreads) : NumThreads(NumThreads) {}
|
||||
unsigned int NumThreads;
|
||||
};
|
||||
|
||||
struct ParallelEnd : public EventBase<ParallelEnd> {
|
||||
std::string toString() const override;
|
||||
ParallelEnd(ompt_data_t *ParallelData, ompt_data_t *EncounteringTaskData,
|
||||
int Flags, const void *CodeptrRA)
|
||||
: ParallelData(ParallelData), EncounteringTaskData(EncounteringTaskData),
|
||||
Flags(Flags), CodeptrRA(CodeptrRA) {}
|
||||
ompt_data_t *ParallelData;
|
||||
ompt_data_t *EncounteringTaskData;
|
||||
int Flags;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct Work : public EventBase<Work> {
|
||||
std::string toString() const override;
|
||||
Work(ompt_work_t WorkType, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData, uint64_t Count,
|
||||
const void *CodeptrRA)
|
||||
: WorkType(WorkType), Endpoint(Endpoint), ParallelData(ParallelData),
|
||||
TaskData(TaskData), Count(Count), CodeptrRA(CodeptrRA) {}
|
||||
ompt_work_t WorkType;
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
ompt_data_t *ParallelData;
|
||||
ompt_data_t *TaskData;
|
||||
uint64_t Count;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct Dispatch : public EventBase<Dispatch> {
|
||||
std::string toString() const override;
|
||||
Dispatch(ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
ompt_dispatch_t Kind, ompt_data_t Instance)
|
||||
: ParallelData(ParallelData), TaskData(TaskData), Kind(Kind),
|
||||
Instance(Instance) {}
|
||||
ompt_data_t *ParallelData;
|
||||
ompt_data_t *TaskData;
|
||||
ompt_dispatch_t Kind;
|
||||
ompt_data_t Instance;
|
||||
};
|
||||
|
||||
struct TaskCreate : public EventBase<TaskCreate> {
|
||||
std::string toString() const override;
|
||||
TaskCreate(ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame,
|
||||
ompt_data_t *NewTaskData, int Flags, int HasDependences,
|
||||
const void *CodeptrRA)
|
||||
: EncounteringTaskData(EncounteringTaskData),
|
||||
EncounteringTaskFrame(EncounteringTaskFrame), NewTaskData(NewTaskData),
|
||||
Flags(Flags), HasDependences(HasDependences), CodeptrRA(CodeptrRA) {}
|
||||
ompt_data_t *EncounteringTaskData;
|
||||
const ompt_frame_t *EncounteringTaskFrame;
|
||||
ompt_data_t *NewTaskData;
|
||||
int Flags;
|
||||
int HasDependences;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct Dependences : public EventBase<Dependences> {
|
||||
Dependences() = default;
|
||||
};
|
||||
|
||||
struct TaskDependence : public EventBase<TaskDependence> {
|
||||
TaskDependence() = default;
|
||||
};
|
||||
|
||||
struct TaskSchedule : public EventBase<TaskSchedule> {
|
||||
TaskSchedule() = default;
|
||||
};
|
||||
|
||||
struct ImplicitTask : public EventBase<ImplicitTask> {
|
||||
std::string toString() const override;
|
||||
ImplicitTask(ompt_scope_endpoint_t Endpoint, ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData, unsigned int ActualParallelism,
|
||||
unsigned int Index, int Flags)
|
||||
: Endpoint(Endpoint), ParallelData(ParallelData), TaskData(TaskData),
|
||||
ActualParallelism(ActualParallelism), Index(Index), Flags(Flags) {}
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
ompt_data_t *ParallelData;
|
||||
ompt_data_t *TaskData;
|
||||
unsigned int ActualParallelism;
|
||||
unsigned int Index;
|
||||
int Flags;
|
||||
};
|
||||
|
||||
struct Masked : public EventBase<Masked> {
|
||||
Masked() = default;
|
||||
};
|
||||
|
||||
struct SyncRegion : public EventBase<SyncRegion> {
|
||||
std::string toString() const override;
|
||||
SyncRegion(ompt_sync_region_t Kind, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
const void *CodeptrRA)
|
||||
: Kind(Kind), Endpoint(Endpoint), ParallelData(ParallelData),
|
||||
TaskData(TaskData), CodeptrRA(CodeptrRA) {}
|
||||
ompt_sync_region_t Kind;
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
ompt_data_t *ParallelData;
|
||||
ompt_data_t *TaskData;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct MutexAcquire : public EventBase<MutexAcquire> {
|
||||
MutexAcquire() = default;
|
||||
};
|
||||
|
||||
struct Mutex : public EventBase<Mutex> {
|
||||
Mutex() = default;
|
||||
};
|
||||
|
||||
struct NestLock : public EventBase<NestLock> {
|
||||
NestLock() = default;
|
||||
};
|
||||
|
||||
struct Flush : public EventBase<Flush> {
|
||||
Flush() = default;
|
||||
};
|
||||
|
||||
struct Cancel : public EventBase<Cancel> {
|
||||
Cancel() = default;
|
||||
};
|
||||
|
||||
struct Target : public EventBase<Target> {
|
||||
std::string toString() const override;
|
||||
Target(ompt_target_t Kind, ompt_scope_endpoint_t Endpoint, int DeviceNum,
|
||||
ompt_data_t *TaskData, ompt_id_t TargetId, const void *CodeptrRA)
|
||||
: Kind(Kind), Endpoint(Endpoint), DeviceNum(DeviceNum),
|
||||
TaskData(TaskData), TargetId(TargetId), CodeptrRA(CodeptrRA) {}
|
||||
ompt_target_t Kind;
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
int DeviceNum;
|
||||
ompt_data_t *TaskData;
|
||||
ompt_id_t TargetId;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct TargetEmi : public EventBase<TargetEmi> {
|
||||
std::string toString() const override;
|
||||
TargetEmi(ompt_target_t Kind, ompt_scope_endpoint_t Endpoint, int DeviceNum,
|
||||
ompt_data_t *TaskData, ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, const void *CodeptrRA)
|
||||
: Kind(Kind), Endpoint(Endpoint), DeviceNum(DeviceNum),
|
||||
TaskData(TaskData), TargetTaskData(TargetTaskData),
|
||||
TargetData(TargetData), CodeptrRA(CodeptrRA) {}
|
||||
ompt_target_t Kind;
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
int DeviceNum;
|
||||
ompt_data_t *TaskData;
|
||||
ompt_data_t *TargetTaskData;
|
||||
ompt_data_t *TargetData;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct TargetDataOp : public EventBase<TargetDataOp> {
|
||||
std::string toString() const override;
|
||||
TargetDataOp(ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr, int SrcDeviceNum,
|
||||
void *DstAddr, int DstDeviceNum, size_t Bytes,
|
||||
const void *CodeptrRA)
|
||||
: TargetId(TargetId), HostOpId(HostOpId), OpType(OpType),
|
||||
SrcAddr(SrcAddr), SrcDeviceNum(SrcDeviceNum), DstAddr(DstAddr),
|
||||
DstDeviceNum(DstDeviceNum), Bytes(Bytes), CodeptrRA(CodeptrRA) {}
|
||||
ompt_id_t TargetId;
|
||||
ompt_id_t HostOpId;
|
||||
ompt_target_data_op_t OpType;
|
||||
void *SrcAddr;
|
||||
int SrcDeviceNum;
|
||||
void *DstAddr;
|
||||
int DstDeviceNum;
|
||||
size_t Bytes;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct TargetDataOpEmi : public EventBase<TargetDataOpEmi> {
|
||||
std::string toString() const override;
|
||||
TargetDataOpEmi(ompt_scope_endpoint_t Endpoint, ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr, int SrcDeviceNum,
|
||||
void *DstAddr, int DstDeviceNum, size_t Bytes,
|
||||
const void *CodeptrRA)
|
||||
: Endpoint(Endpoint), TargetTaskData(TargetTaskData),
|
||||
TargetData(TargetData), HostOpId(HostOpId), OpType(OpType),
|
||||
SrcAddr(SrcAddr), SrcDeviceNum(SrcDeviceNum), DstAddr(DstAddr),
|
||||
DstDeviceNum(DstDeviceNum), Bytes(Bytes), CodeptrRA(CodeptrRA) {}
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
ompt_data_t *TargetTaskData;
|
||||
ompt_data_t *TargetData;
|
||||
ompt_id_t *HostOpId;
|
||||
ompt_target_data_op_t OpType;
|
||||
void *SrcAddr;
|
||||
int SrcDeviceNum;
|
||||
void *DstAddr;
|
||||
int DstDeviceNum;
|
||||
size_t Bytes;
|
||||
const void *CodeptrRA;
|
||||
};
|
||||
|
||||
struct TargetSubmit : public EventBase<TargetSubmit> {
|
||||
std::string toString() const override;
|
||||
TargetSubmit(ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
unsigned int RequestedNumTeams)
|
||||
: TargetId(TargetId), HostOpId(HostOpId),
|
||||
RequestedNumTeams(RequestedNumTeams) {}
|
||||
ompt_id_t TargetId;
|
||||
ompt_id_t HostOpId;
|
||||
unsigned int RequestedNumTeams;
|
||||
};
|
||||
|
||||
struct TargetSubmitEmi : public EventBase<TargetSubmitEmi> {
|
||||
std::string toString() const override;
|
||||
TargetSubmitEmi(ompt_scope_endpoint_t Endpoint, ompt_data_t *TargetData,
|
||||
ompt_id_t *HostOpId, unsigned int RequestedNumTeams)
|
||||
: Endpoint(Endpoint), TargetData(TargetData), HostOpId(HostOpId),
|
||||
RequestedNumTeams(RequestedNumTeams) {}
|
||||
ompt_scope_endpoint_t Endpoint;
|
||||
ompt_data_t *TargetData;
|
||||
ompt_id_t *HostOpId;
|
||||
unsigned int RequestedNumTeams;
|
||||
};
|
||||
|
||||
struct ControlTool : public EventBase<ControlTool> {
|
||||
ControlTool() = default;
|
||||
};
|
||||
|
||||
struct DeviceInitialize : public EventBase<DeviceInitialize> {
|
||||
std::string toString() const override;
|
||||
DeviceInitialize(int DeviceNum, const char *Type, ompt_device_t *Device,
|
||||
ompt_function_lookup_t LookupFn, const char *DocStr)
|
||||
: DeviceNum(DeviceNum), Type(Type), Device(Device), LookupFn(LookupFn),
|
||||
DocStr(DocStr) {}
|
||||
int DeviceNum;
|
||||
const char *Type;
|
||||
ompt_device_t *Device;
|
||||
ompt_function_lookup_t LookupFn;
|
||||
const char *DocStr;
|
||||
};
|
||||
|
||||
struct DeviceFinalize : public EventBase<DeviceFinalize> {
|
||||
std::string toString() const override;
|
||||
DeviceFinalize(int DeviceNum) : DeviceNum(DeviceNum) {}
|
||||
int DeviceNum;
|
||||
};
|
||||
|
||||
struct DeviceLoad : public EventBase<DeviceLoad> {
|
||||
std::string toString() const override;
|
||||
DeviceLoad(int DeviceNum, const char *Filename, int64_t OffsetInFile,
|
||||
void *VmaInFile, size_t Bytes, void *HostAddr, void *DeviceAddr,
|
||||
uint64_t ModuleId)
|
||||
: DeviceNum(DeviceNum), Filename(Filename), OffsetInFile(OffsetInFile),
|
||||
VmaInFile(VmaInFile), Bytes(Bytes), HostAddr(HostAddr),
|
||||
DeviceAddr(DeviceAddr), ModuleId(ModuleId) {}
|
||||
int DeviceNum;
|
||||
const char *Filename;
|
||||
int64_t OffsetInFile;
|
||||
void *VmaInFile;
|
||||
size_t Bytes;
|
||||
void *HostAddr;
|
||||
void *DeviceAddr;
|
||||
uint64_t ModuleId;
|
||||
};
|
||||
|
||||
struct DeviceUnload : public EventBase<DeviceUnload> {
|
||||
DeviceUnload() = default;
|
||||
};
|
||||
|
||||
struct BufferRequest : public EventBase<BufferRequest> {
|
||||
std::string toString() const override;
|
||||
BufferRequest(int DeviceNum, ompt_buffer_t **Buffer, size_t *Bytes)
|
||||
: DeviceNum(DeviceNum), Buffer(Buffer), Bytes(Bytes) {}
|
||||
int DeviceNum;
|
||||
ompt_buffer_t **Buffer;
|
||||
size_t *Bytes;
|
||||
};
|
||||
|
||||
struct BufferComplete : public EventBase<BufferComplete> {
|
||||
std::string toString() const override;
|
||||
BufferComplete(int DeviceNum, ompt_buffer_t *Buffer, size_t Bytes,
|
||||
ompt_buffer_cursor_t Begin, int BufferOwned)
|
||||
: DeviceNum(DeviceNum), Buffer(Buffer), Bytes(Bytes), Begin(Begin),
|
||||
BufferOwned(BufferOwned) {}
|
||||
int DeviceNum;
|
||||
ompt_buffer_t *Buffer;
|
||||
size_t Bytes;
|
||||
ompt_buffer_cursor_t Begin;
|
||||
int BufferOwned;
|
||||
};
|
||||
|
||||
struct BufferRecord : public EventBase<BufferRecord> {
|
||||
std::string toString() const override;
|
||||
BufferRecord(ompt_record_ompt_t *RecordPtr) : RecordPtr(RecordPtr) {
|
||||
if (RecordPtr != nullptr)
|
||||
Record = *RecordPtr;
|
||||
else
|
||||
memset(&Record, 0, sizeof(ompt_record_ompt_t));
|
||||
}
|
||||
ompt_record_ompt_t Record;
|
||||
ompt_record_ompt_t *RecordPtr;
|
||||
};
|
||||
|
||||
struct BufferRecordDeallocation : public EventBase<BufferRecordDeallocation> {
|
||||
std::string toString() const override;
|
||||
BufferRecordDeallocation(ompt_buffer_t *Buffer) : Buffer(Buffer) {}
|
||||
ompt_buffer_t *Buffer;
|
||||
};
|
||||
|
||||
// Add specialized event equality operators here.
|
||||
// Note: Placement of these forward declarations is important as they need to
|
||||
// take precedence over the following default equality operator definition.
|
||||
bool operator==(const ParallelBegin &, const ParallelBegin &);
|
||||
bool operator==(const Work &, const Work &);
|
||||
bool operator==(const ImplicitTask &, const ImplicitTask &);
|
||||
bool operator==(const SyncRegion &, const SyncRegion &);
|
||||
bool operator==(const Target &, const Target &);
|
||||
bool operator==(const TargetEmi &, const TargetEmi &);
|
||||
bool operator==(const TargetDataOp &, const TargetDataOp &);
|
||||
bool operator==(const TargetDataOpEmi &, const TargetDataOpEmi &);
|
||||
bool operator==(const TargetSubmit &, const TargetSubmit &);
|
||||
bool operator==(const TargetSubmitEmi &, const TargetSubmitEmi &);
|
||||
bool operator==(const DeviceInitialize &, const DeviceInitialize &);
|
||||
bool operator==(const DeviceFinalize &, const DeviceFinalize &);
|
||||
bool operator==(const DeviceLoad &, const DeviceLoad &);
|
||||
bool operator==(const BufferRequest &, const BufferRequest &);
|
||||
bool operator==(const BufferComplete &, const BufferComplete &);
|
||||
bool operator==(const BufferRecord &, const BufferRecord &);
|
||||
|
||||
/// Default (fallback) event equality operator definition.
|
||||
template <typename Event> bool operator==(const Event &, const Event &) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
event_type_trait(AssertionSyncPoint)
|
||||
event_type_trait(AssertionSuspend)
|
||||
event_type_trait(ThreadBegin)
|
||||
event_type_trait(ThreadEnd)
|
||||
event_type_trait(ParallelBegin)
|
||||
event_type_trait(ParallelEnd)
|
||||
event_type_trait(Work)
|
||||
event_type_trait(Dispatch)
|
||||
event_type_trait(TaskCreate)
|
||||
event_type_trait(Dependences)
|
||||
event_type_trait(TaskDependence)
|
||||
event_type_trait(TaskSchedule)
|
||||
event_type_trait(ImplicitTask)
|
||||
event_type_trait(Masked)
|
||||
event_type_trait(SyncRegion)
|
||||
event_type_trait(MutexAcquire)
|
||||
event_type_trait(Mutex)
|
||||
event_type_trait(NestLock)
|
||||
event_type_trait(Flush)
|
||||
event_type_trait(Cancel)
|
||||
event_type_trait(Target)
|
||||
event_type_trait(TargetEmi)
|
||||
event_type_trait(TargetDataOp)
|
||||
event_type_trait(TargetDataOpEmi)
|
||||
event_type_trait(TargetSubmit)
|
||||
event_type_trait(TargetSubmitEmi)
|
||||
event_type_trait(ControlTool)
|
||||
event_type_trait(DeviceInitialize)
|
||||
event_type_trait(DeviceFinalize)
|
||||
event_type_trait(DeviceLoad)
|
||||
event_type_trait(DeviceUnload)
|
||||
event_type_trait(BufferRequest)
|
||||
event_type_trait(BufferComplete)
|
||||
event_type_trait(BufferRecord)
|
||||
event_type_trait(BufferRecordDeallocation)
|
||||
// clang-format on
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace omptest
|
||||
|
||||
#endif
|
@ -1,130 +0,0 @@
|
||||
//===- InternalEventCommon.h - Common internal event basics -----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Provides event types, and class/operator declaration macros.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_INTERNALEVENTCOMMON_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_INTERNALEVENTCOMMON_H
|
||||
|
||||
#include "omp-tools.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace omptest {
|
||||
|
||||
namespace internal {
|
||||
/// Enum values are used for comparison of observed and asserted events
|
||||
/// List is based on OpenMP 5.2 specification, table 19.2 (page 447)
|
||||
enum class EventTy {
|
||||
None, // not part of OpenMP spec, used for implementation
|
||||
AssertionSyncPoint, // not part of OpenMP spec, used for implementation
|
||||
AssertionSuspend, // not part of OpenMP spec, used for implementation
|
||||
BufferRecord, // not part of OpenMP spec, used for implementation
|
||||
BufferRecordDeallocation, // not part of OpenMP spec, used for implementation
|
||||
ThreadBegin,
|
||||
ThreadEnd,
|
||||
ParallelBegin,
|
||||
ParallelEnd,
|
||||
Work,
|
||||
Dispatch,
|
||||
TaskCreate, // TODO: Implement
|
||||
Dependences, // TODO: Implement
|
||||
TaskDependence, // TODO: Implement
|
||||
TaskSchedule, // TODO: Implement
|
||||
ImplicitTask, // TODO: Implement
|
||||
Masked, // TODO: Implement
|
||||
SyncRegion,
|
||||
MutexAcquire, // TODO: Implement
|
||||
Mutex, // TODO: Implement
|
||||
NestLock, // TODO: Implement
|
||||
Flush, // TODO: Implement
|
||||
Cancel, // TODO: Implement
|
||||
DeviceInitialize,
|
||||
DeviceFinalize,
|
||||
DeviceLoad,
|
||||
DeviceUnload,
|
||||
BufferRequest,
|
||||
BufferComplete,
|
||||
TargetDataOp,
|
||||
TargetDataOpEmi,
|
||||
Target,
|
||||
TargetEmi,
|
||||
TargetSubmit,
|
||||
TargetSubmitEmi,
|
||||
ControlTool
|
||||
};
|
||||
|
||||
/// Base event class
|
||||
/// Offers default CTOR, DTOR and CTOR which assigns the actual event type.
|
||||
struct InternalEvent {
|
||||
InternalEvent() : Type(EventTy::None) {}
|
||||
InternalEvent(EventTy T) : Type(T) {}
|
||||
virtual ~InternalEvent() = default;
|
||||
|
||||
virtual bool equals(const InternalEvent *o) const {
|
||||
assert(false && "Base class implementation");
|
||||
return false;
|
||||
};
|
||||
|
||||
virtual std::string toString() const {
|
||||
std::string S{"InternalEvent: Type="};
|
||||
S.append(std::to_string((uint32_t)Type));
|
||||
return S;
|
||||
}
|
||||
|
||||
/// Identifying event type
|
||||
EventTy Type;
|
||||
};
|
||||
|
||||
/// Specialize EventType member for each derived internal event type.
|
||||
/// Effectively selecting an event type as initialization value.
|
||||
template <typename EventType> struct EventTypeOf;
|
||||
|
||||
/// Actual definition macro for EventTypeOf.
|
||||
#define event_type_trait(EvTy) \
|
||||
template <> struct EventTypeOf<EvTy> { \
|
||||
static constexpr EventTy Value = EventTy::EvTy; \
|
||||
};
|
||||
|
||||
/// CRTP (Curiously Recurring Template Pattern) intermediate class
|
||||
/// Adding a new event type can be achieved by inheriting from an EventBase
|
||||
/// template instantiation of the new class' name, like this:
|
||||
/// struct NewEventType : public EventBase<NewEventType>
|
||||
template <typename Derived> class EventBase : public InternalEvent {
|
||||
public:
|
||||
static constexpr EventTy EventType = EventTypeOf<Derived>::Value;
|
||||
EventBase() : InternalEvent(EventType) {}
|
||||
virtual ~EventBase() = default;
|
||||
|
||||
/// Equals method to cast and dispatch to the specific class operator==
|
||||
virtual bool equals(const InternalEvent *o) const override {
|
||||
// Note: When the if-condition evaluates to true, the event types are
|
||||
// trivially identical. Otherwise, a cast to the Derived pointer would have
|
||||
// been impossible.
|
||||
if (const auto Other = dynamic_cast<const Derived *>(o))
|
||||
return operator==(*static_cast<const Derived *>(this), *Other);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Basic toString method, which may be overridden with own implementations.
|
||||
virtual std::string toString() const override {
|
||||
std::string S{"EventBase: Type="};
|
||||
S.append(std::to_string((uint32_t)Type));
|
||||
return S;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace omptest
|
||||
|
||||
#endif
|
@ -1,155 +0,0 @@
|
||||
//===- Logging.h - General logging class ------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Provides ompTest-tailored logging, with log-levels and formatting/coloring.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_LOGGING_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_LOGGING_H
|
||||
|
||||
#include "OmptAssertEvent.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace omptest {
|
||||
namespace logging {
|
||||
|
||||
enum class Level : uint32_t {
|
||||
// Levels (Note: DEBUG may already be reserved)
|
||||
Diagnostic = 10,
|
||||
Info = 20,
|
||||
Warning = 30,
|
||||
Error = 40,
|
||||
Critical = 50,
|
||||
|
||||
// Types used for formatting options
|
||||
Default,
|
||||
ExpectedEvent,
|
||||
ObservedEvent,
|
||||
OffendingEvent,
|
||||
|
||||
// Suppress all prints
|
||||
Silent = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
enum class FormatOption : uint32_t {
|
||||
// General options
|
||||
// Note: Bold is actually "BRIGHT" -- But it will be perceived as 'bold' font
|
||||
// It is implicitly switching colors to the 'Light' variant
|
||||
// Thus, it has -NO EFFECT- when already using a Light* color
|
||||
None = 0,
|
||||
Bold = 1,
|
||||
Dim = 2,
|
||||
Underlined = 4,
|
||||
Blink = 5,
|
||||
Inverted = 7,
|
||||
Hidden = 8,
|
||||
// Foreground colors
|
||||
ColorDefault = 39,
|
||||
ColorBlack = 30,
|
||||
ColorRed = 31,
|
||||
ColorGreen = 32,
|
||||
ColorYellow = 33,
|
||||
ColorBlue = 34,
|
||||
ColorMagenta = 35,
|
||||
ColorCyan = 36,
|
||||
ColorLightGray = 37,
|
||||
ColorDarkGray = 90,
|
||||
ColorLightRed = 91,
|
||||
ColorLightGreen = 92,
|
||||
ColorLightYellow = 93,
|
||||
ColorLightBlue = 94,
|
||||
ColorLightMagenta = 95,
|
||||
ColorLightCyan = 96,
|
||||
ColorWhite = 97,
|
||||
// Background colors
|
||||
ColorBackgroundDefault = 49,
|
||||
ColorBackgroundBlack = 40,
|
||||
ColorBackgroundRed = 41,
|
||||
ColorBackgroundGreen = 42,
|
||||
ColorBackgroundYellow = 43,
|
||||
ColorBackgroundBlue = 44,
|
||||
ColorBackgroundMagenta = 45,
|
||||
ColorBackgroundCyan = 46,
|
||||
ColorBackgroundLightGray = 47,
|
||||
ColorBackgroundDarkGray = 100,
|
||||
ColorBackgroundLightRed = 101,
|
||||
ColorBackgroundLightGreen = 102,
|
||||
ColorBackgroundLightYellow = 103,
|
||||
ColorBackgroundLightBlue = 104,
|
||||
ColorBackgroundLightMagenta = 105,
|
||||
ColorBackgroundLightCyan = 106,
|
||||
ColorBackgroundWhite = 107
|
||||
};
|
||||
|
||||
/// Returns a string representation of the given logging level.
|
||||
const char *to_string(Level LogLevel);
|
||||
|
||||
/// Returns the format options as escaped sequence, for the given logging level
|
||||
std::string getFormatSequence(Level LogLevel = Level::Default);
|
||||
|
||||
/// Format the given message with the provided option(s) and return it.
|
||||
/// Here formatting is only concerning control sequences using <Esc> character
|
||||
/// which can be obtained using '\e' (on console), '\033' or '\x1B'.
|
||||
std::string format(const std::string &Message, FormatOption Option);
|
||||
std::string format(const std::string &Message, std::set<FormatOption> Options);
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger(Level LogLevel = Level::Warning, std::ostream &OutStream = std::cerr,
|
||||
bool FormatOutput = true);
|
||||
~Logger();
|
||||
|
||||
/// Log the given message to the output.
|
||||
void log(const std::string &Message, Level LogLevel) const;
|
||||
|
||||
/// Log a single event mismatch.
|
||||
void logEventMismatch(const std::string &Message,
|
||||
const omptest::OmptAssertEvent &OffendingEvent,
|
||||
Level LogLevel = Level::Error) const;
|
||||
|
||||
/// Log an event-pair mismatch.
|
||||
void logEventMismatch(const std::string &Message,
|
||||
const omptest::OmptAssertEvent &ExpectedEvent,
|
||||
const omptest::OmptAssertEvent &ObservedEvent,
|
||||
Level LogLevel = Level::Error) const;
|
||||
|
||||
/// Set if output is being formatted (e.g. colored).
|
||||
void setFormatOutput(bool Enabled);
|
||||
|
||||
/// Return the current (minimum) Logging Level.
|
||||
Level getLoggingLevel() const;
|
||||
|
||||
/// Set the (minimum) Logging Level.
|
||||
void setLoggingLevel(Level LogLevel);
|
||||
|
||||
private:
|
||||
/// The minimum logging level that is considered by the logger instance.
|
||||
Level LoggingLevel;
|
||||
|
||||
/// The output stream used by the logger instance.
|
||||
std::ostream &OutStream;
|
||||
|
||||
/// Determine if log messages are formatted using control sequences.
|
||||
bool FormatOutput;
|
||||
|
||||
/// Mutex to ensure serialized logging
|
||||
mutable std::mutex LogMutex;
|
||||
};
|
||||
|
||||
} // namespace logging
|
||||
} // namespace omptest
|
||||
|
||||
#endif
|
@ -1,85 +0,0 @@
|
||||
//===- OmptAliases.h - Shorthand aliases for OMPT enum values ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Defines shorthand aliases for OMPT enum values, providing improved
|
||||
/// ease-of-use and readability.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTALIASES_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTALIASES_H
|
||||
|
||||
#include <omp-tools.h>
|
||||
|
||||
/// Aliases for enum: ompt_scope_endpoint_t
|
||||
constexpr ompt_scope_endpoint_t BEGIN = ompt_scope_begin;
|
||||
constexpr ompt_scope_endpoint_t END = ompt_scope_end;
|
||||
constexpr ompt_scope_endpoint_t BEGINEND = ompt_scope_beginend;
|
||||
|
||||
/// Aliases for enum: ompt_target_t
|
||||
constexpr ompt_target_t TARGET = ompt_target;
|
||||
constexpr ompt_target_t ENTER_DATA = ompt_target_enter_data;
|
||||
constexpr ompt_target_t EXIT_DATA = ompt_target_exit_data;
|
||||
constexpr ompt_target_t UPDATE = ompt_target_update;
|
||||
constexpr ompt_target_t TARGET_NOWAIT = ompt_target_nowait;
|
||||
constexpr ompt_target_t ENTER_DATA_NOWAIT = ompt_target_enter_data_nowait;
|
||||
constexpr ompt_target_t EXIT_DATA_NOWAIT = ompt_target_exit_data_nowait;
|
||||
constexpr ompt_target_t UPDATE_NOWAIT = ompt_target_update_nowait;
|
||||
|
||||
/// Aliases for enum: ompt_target_data_op_t
|
||||
constexpr ompt_target_data_op_t ALLOC = ompt_target_data_alloc;
|
||||
constexpr ompt_target_data_op_t H2D = ompt_target_data_transfer_to_device;
|
||||
constexpr ompt_target_data_op_t D2H = ompt_target_data_transfer_from_device;
|
||||
constexpr ompt_target_data_op_t DELETE = ompt_target_data_delete;
|
||||
constexpr ompt_target_data_op_t ASSOCIATE = ompt_target_data_associate;
|
||||
constexpr ompt_target_data_op_t DISASSOCIATE = ompt_target_data_disassociate;
|
||||
constexpr ompt_target_data_op_t ALLOC_ASYNC = ompt_target_data_alloc_async;
|
||||
constexpr ompt_target_data_op_t H2D_ASYNC =
|
||||
ompt_target_data_transfer_to_device_async;
|
||||
constexpr ompt_target_data_op_t D2H_ASYNC =
|
||||
ompt_target_data_transfer_from_device_async;
|
||||
constexpr ompt_target_data_op_t DELETE_ASYNC = ompt_target_data_delete_async;
|
||||
|
||||
/// Aliases for enum: ompt_callbacks_t (partial)
|
||||
constexpr ompt_callbacks_t CB_TARGET = ompt_callback_target;
|
||||
constexpr ompt_callbacks_t CB_DATAOP = ompt_callback_target_data_op;
|
||||
constexpr ompt_callbacks_t CB_KERNEL = ompt_callback_target_submit;
|
||||
|
||||
/// Aliases for enum: ompt_work_t
|
||||
constexpr ompt_work_t WORK_LOOP = ompt_work_loop;
|
||||
constexpr ompt_work_t WORK_SECT = ompt_work_sections;
|
||||
constexpr ompt_work_t WORK_EXEC = ompt_work_single_executor;
|
||||
constexpr ompt_work_t WORK_SINGLE = ompt_work_single_other;
|
||||
constexpr ompt_work_t WORK_SHARE = ompt_work_workshare;
|
||||
constexpr ompt_work_t WORK_DIST = ompt_work_distribute;
|
||||
constexpr ompt_work_t WORK_TASK = ompt_work_taskloop;
|
||||
constexpr ompt_work_t WORK_SCOPE = ompt_work_scope;
|
||||
constexpr ompt_work_t WORK_LOOP_STA = ompt_work_loop_static;
|
||||
constexpr ompt_work_t WORK_LOOP_DYN = ompt_work_loop_dynamic;
|
||||
constexpr ompt_work_t WORK_LOOP_GUI = ompt_work_loop_guided;
|
||||
constexpr ompt_work_t WORK_LOOP_OTH = ompt_work_loop_other;
|
||||
|
||||
/// Aliases for enum: ompt_sync_region_t
|
||||
constexpr ompt_sync_region_t SR_BARRIER = ompt_sync_region_barrier;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_IMPL =
|
||||
ompt_sync_region_barrier_implicit;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_EXPL =
|
||||
ompt_sync_region_barrier_explicit;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_IMPLEMENTATION =
|
||||
ompt_sync_region_barrier_implementation;
|
||||
constexpr ompt_sync_region_t SR_TASKWAIT = ompt_sync_region_taskwait;
|
||||
constexpr ompt_sync_region_t SR_TASKGROUP = ompt_sync_region_taskgroup;
|
||||
constexpr ompt_sync_region_t SR_REDUCTION = ompt_sync_region_reduction;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_IMPL_WORKSHARE =
|
||||
ompt_sync_region_barrier_implicit_workshare;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_IMPL_PARALLEL =
|
||||
ompt_sync_region_barrier_implicit_parallel;
|
||||
constexpr ompt_sync_region_t SR_BARRIER_TEAMS = ompt_sync_region_barrier_teams;
|
||||
|
||||
#endif
|
@ -1,377 +0,0 @@
|
||||
//===- OmptAssertEvent.h - Assertion event declarations ---------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Contains assertion event constructors, for generally all observable events.
|
||||
/// This includes user-generated events, like synchronization.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTEVENT_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTEVENT_H
|
||||
|
||||
#include "InternalEvent.h"
|
||||
#include "omp-tools.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace omptest {
|
||||
|
||||
enum class ObserveState { Generated, Always, Never };
|
||||
|
||||
/// Helper function, returning an ObserveState string representation
|
||||
const char *to_string(ObserveState State);
|
||||
|
||||
/// Assertion event struct, provides statically callable CTORs.
|
||||
struct OmptAssertEvent {
|
||||
static OmptAssertEvent AssertionSyncPoint(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
const std::string &SyncPointName);
|
||||
|
||||
static OmptAssertEvent AssertionSuspend(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected);
|
||||
|
||||
static OmptAssertEvent ThreadBegin(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_thread_t ThreadType);
|
||||
|
||||
static OmptAssertEvent ThreadEnd(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected);
|
||||
|
||||
static OmptAssertEvent ParallelBegin(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int NumThreads);
|
||||
|
||||
static OmptAssertEvent ParallelEnd(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_data_t *ParallelData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *EncounteringTaskData = expectedDefault(ompt_data_t *),
|
||||
int Flags = expectedDefault(int),
|
||||
const void *CodeptrRA = expectedDefault(const void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
Work(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_work_t WorkType,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
uint64_t Count = expectedDefault(uint64_t),
|
||||
const void *CodeptrRA = expectedDefault(const void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
Dispatch(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_data_t *ParallelData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
ompt_dispatch_t Kind = expectedDefault(ompt_dispatch_t),
|
||||
ompt_data_t Instance = expectedDefault(ompt_data_t));
|
||||
|
||||
static OmptAssertEvent
|
||||
TaskCreate(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_data_t *EncounteringTaskData = expectedDefault(ompt_data_t *),
|
||||
const ompt_frame_t *EncounteringTaskFrame =
|
||||
expectedDefault(ompt_frame_t *),
|
||||
ompt_data_t *NewTaskData = expectedDefault(ompt_data_t *),
|
||||
int Flags = expectedDefault(int),
|
||||
int HasDependences = expectedDefault(int),
|
||||
const void *CodeptrRA = expectedDefault(const void *));
|
||||
|
||||
static OmptAssertEvent TaskSchedule(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected);
|
||||
|
||||
static OmptAssertEvent
|
||||
ImplicitTask(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
unsigned int ActualParallelism = expectedDefault(unsigned int),
|
||||
unsigned int Index = expectedDefault(unsigned int),
|
||||
int Flags = expectedDefault(int));
|
||||
|
||||
static OmptAssertEvent
|
||||
SyncRegion(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_sync_region_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
const void *CodeptrRA = expectedDefault(const void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
Target(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint, int DeviceNum = expectedDefault(int),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum = expectedDefault(int),
|
||||
ompt_data_t *TaskData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TargetTaskData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TargetData = expectedDefault(ompt_data_t *),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetDataOp(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_id_t TargetId,
|
||||
ompt_id_t HostOpId, ompt_target_data_op_t OpType, void *SrcAddr,
|
||||
int SrcDeviceNum, void *DstAddr, int DstDeviceNum, size_t Bytes,
|
||||
const void *CodeptrRA);
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetDataOp(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_data_op_t OpType,
|
||||
size_t Bytes = expectedDefault(size_t),
|
||||
void *SrcAddr = expectedDefault(void *),
|
||||
void *DstAddr = expectedDefault(void *),
|
||||
int SrcDeviceNum = expectedDefault(int),
|
||||
int DstDeviceNum = expectedDefault(int),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetDataOpEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetTaskData, ompt_data_t *TargetData,
|
||||
ompt_id_t *HostOpId, ompt_target_data_op_t OpType,
|
||||
void *SrcAddr, int SrcDeviceNum, void *DstAddr,
|
||||
int DstDeviceNum, size_t Bytes, const void *CodeptrRA);
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetDataOpEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_data_op_t OpType,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
size_t Bytes = expectedDefault(size_t),
|
||||
void *SrcAddr = expectedDefault(void *),
|
||||
void *DstAddr = expectedDefault(void *),
|
||||
int SrcDeviceNum = expectedDefault(int),
|
||||
int DstDeviceNum = expectedDefault(int),
|
||||
ompt_data_t *TargetTaskData = expectedDefault(ompt_data_t *),
|
||||
ompt_data_t *TargetData = expectedDefault(ompt_data_t *),
|
||||
ompt_id_t *HostOpId = expectedDefault(ompt_id_t *),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
static OmptAssertEvent TargetSubmit(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
unsigned int RequestedNumTeams);
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetSubmit(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, unsigned int RequestedNumTeams,
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t));
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetSubmitEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
unsigned int RequestedNumTeams);
|
||||
|
||||
static OmptAssertEvent
|
||||
TargetSubmitEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, unsigned int RequestedNumTeams,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetData = expectedDefault(ompt_data_t *),
|
||||
ompt_id_t *HostOpId = expectedDefault(ompt_id_t *));
|
||||
|
||||
static OmptAssertEvent ControlTool(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected);
|
||||
|
||||
static OmptAssertEvent DeviceInitialize(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum,
|
||||
const char *Type = expectedDefault(const char *),
|
||||
ompt_device_t *Device = expectedDefault(ompt_device_t *),
|
||||
ompt_function_lookup_t LookupFn = expectedDefault(ompt_function_lookup_t),
|
||||
const char *DocumentationStr = expectedDefault(const char *));
|
||||
|
||||
static OmptAssertEvent DeviceFinalize(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int DeviceNum);
|
||||
|
||||
static OmptAssertEvent
|
||||
DeviceLoad(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum,
|
||||
const char *Filename = expectedDefault(const char *),
|
||||
int64_t OffsetInFile = expectedDefault(int64_t),
|
||||
void *VmaInFile = expectedDefault(void *),
|
||||
size_t Bytes = expectedDefault(size_t),
|
||||
void *HostAddr = expectedDefault(void *),
|
||||
void *DeviceAddr = expectedDefault(void *),
|
||||
uint64_t ModuleId = expectedDefault(int64_t));
|
||||
|
||||
static OmptAssertEvent DeviceUnload(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected);
|
||||
|
||||
static OmptAssertEvent BufferRequest(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int DeviceNum, ompt_buffer_t **Buffer,
|
||||
size_t *Bytes);
|
||||
|
||||
static OmptAssertEvent
|
||||
BufferComplete(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum,
|
||||
ompt_buffer_t *Buffer, size_t Bytes,
|
||||
ompt_buffer_cursor_t Begin, int BufferOwned);
|
||||
|
||||
static OmptAssertEvent BufferRecord(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_record_ompt_t *Record);
|
||||
|
||||
/// Handle type = ompt_record_target_t
|
||||
static OmptAssertEvent
|
||||
BufferRecord(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_target_t Kind, ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum = expectedDefault(int),
|
||||
ompt_id_t TaskId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
/// Handle type = ompt_callback_target_data_op
|
||||
static OmptAssertEvent
|
||||
BufferRecord(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_target_data_op_t OpType, size_t Bytes,
|
||||
std::pair<ompt_device_time_t, ompt_device_time_t> Timeframe,
|
||||
void *SrcAddr = expectedDefault(void *),
|
||||
void *DstAddr = expectedDefault(void *),
|
||||
int SrcDeviceNum = expectedDefault(int),
|
||||
int DstDeviceNum = expectedDefault(int),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
/// Handle type = ompt_callback_target_data_op
|
||||
static OmptAssertEvent BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_target_data_op_t OpType, size_t Bytes = expectedDefault(size_t),
|
||||
ompt_device_time_t MinimumTimeDelta = expectedDefault(ompt_device_time_t),
|
||||
void *SrcAddr = expectedDefault(void *),
|
||||
void *DstAddr = expectedDefault(void *),
|
||||
int SrcDeviceNum = expectedDefault(int),
|
||||
int DstDeviceNum = expectedDefault(int),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t),
|
||||
const void *CodeptrRA = expectedDefault(void *));
|
||||
|
||||
/// Handle type = ompt_callback_target_submit
|
||||
static OmptAssertEvent
|
||||
BufferRecord(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
std::pair<ompt_device_time_t, ompt_device_time_t> Timeframe,
|
||||
unsigned int RequestedNumTeams = expectedDefault(unsigned int),
|
||||
unsigned int GrantedNumTeams = expectedDefault(unsigned int),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t));
|
||||
|
||||
/// Handle type = ompt_callback_target_submit
|
||||
/// Note: This will also act as the simplest default CTOR
|
||||
static OmptAssertEvent BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_device_time_t MinimumTimeDelta = expectedDefault(ompt_device_time_t),
|
||||
unsigned int RequestedNumTeams = expectedDefault(unsigned int),
|
||||
unsigned int GrantedNumTeams = expectedDefault(unsigned int),
|
||||
ompt_id_t TargetId = expectedDefault(ompt_id_t),
|
||||
ompt_id_t HostOpId = expectedDefault(ompt_id_t));
|
||||
|
||||
static OmptAssertEvent BufferRecordDeallocation(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_buffer_t *Buffer);
|
||||
|
||||
/// Allow move construction (due to std::unique_ptr)
|
||||
OmptAssertEvent(OmptAssertEvent &&o) = default;
|
||||
OmptAssertEvent &operator=(OmptAssertEvent &&o) = default;
|
||||
|
||||
/// Get the event's name
|
||||
std::string getEventName() const;
|
||||
|
||||
/// Get the event's group name
|
||||
std::string getEventGroup() const;
|
||||
|
||||
/// Get the event's expected observation state
|
||||
ObserveState getEventExpectedState() const;
|
||||
|
||||
/// Return the actual event type enum value
|
||||
internal::EventTy getEventType() const;
|
||||
|
||||
/// Get a pointer to the internal event
|
||||
internal::InternalEvent *getEvent() const;
|
||||
|
||||
/// Make events comparable
|
||||
friend bool operator==(const OmptAssertEvent &A, const OmptAssertEvent &B);
|
||||
|
||||
/// Returns the string representation of the event
|
||||
std::string toString(bool PrefixEventName = false) const;
|
||||
|
||||
private:
|
||||
OmptAssertEvent(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, internal::InternalEvent *IE);
|
||||
OmptAssertEvent(const OmptAssertEvent &o) = delete;
|
||||
|
||||
/// Determine the event name. Either it is provided directly or determined
|
||||
/// from the calling function's name.
|
||||
static std::string getName(const std::string &Name,
|
||||
const char *Caller = __builtin_FUNCTION()) {
|
||||
std::string EName = Name;
|
||||
if (EName.empty())
|
||||
EName.append(Caller).append(" (auto generated)");
|
||||
|
||||
return EName;
|
||||
}
|
||||
|
||||
/// Determine the event name. Either it is provided directly or "default".
|
||||
static std::string getGroup(const std::string &Group) {
|
||||
if (Group.empty())
|
||||
return "default";
|
||||
|
||||
return Group;
|
||||
}
|
||||
|
||||
std::string Name;
|
||||
std::string Group;
|
||||
ObserveState ExpectedState;
|
||||
std::unique_ptr<internal::InternalEvent> TheEvent;
|
||||
};
|
||||
|
||||
/// POD type, which holds the target region id, corresponding to an event group.
|
||||
struct AssertEventGroup {
|
||||
AssertEventGroup(uint64_t TargetRegion) : TargetRegion(TargetRegion) {}
|
||||
uint64_t TargetRegion;
|
||||
};
|
||||
|
||||
bool operator==(const OmptAssertEvent &A, const OmptAssertEvent &B);
|
||||
|
||||
} // namespace omptest
|
||||
|
||||
#endif
|
@ -1,291 +0,0 @@
|
||||
//===- OmptAsserter.h - Asserter-related classes, enums, etc. ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Contains all asserter-related class declarations and important enums.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTER_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTER_H
|
||||
|
||||
#include "Logging.h"
|
||||
#include "OmptAssertEvent.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace omptest {
|
||||
|
||||
// Forward declaration.
|
||||
class OmptEventGroupInterface;
|
||||
|
||||
enum class AssertMode { Strict, Relaxed };
|
||||
enum class AssertState { Pass, Fail };
|
||||
|
||||
/// General base class for the subscriber/notification pattern in
|
||||
/// OmptCallbackHandler. Derived classes need to implement the notify method.
|
||||
class OmptListener {
|
||||
public:
|
||||
virtual ~OmptListener() = default;
|
||||
|
||||
/// Called for each registered OMPT event of the OmptCallbackHandler
|
||||
virtual void notify(omptest::OmptAssertEvent &&AE) = 0;
|
||||
|
||||
/// Control whether this asserter should be considered 'active'.
|
||||
void setActive(bool Enabled);
|
||||
|
||||
/// Check if this asserter is considered 'active'.
|
||||
bool isActive();
|
||||
|
||||
/// Check if the given event type is from the set of suppressed event types.
|
||||
bool isSuppressedEventType(omptest::internal::EventTy EvTy);
|
||||
|
||||
/// Remove the given event type to the set of suppressed events.
|
||||
void permitEvent(omptest::internal::EventTy EvTy);
|
||||
|
||||
/// Add the given event type to the set of suppressed events.
|
||||
void suppressEvent(omptest::internal::EventTy EvTy);
|
||||
|
||||
private:
|
||||
bool Active{true};
|
||||
|
||||
// Add event types to the set of suppressed events by default.
|
||||
std::set<omptest::internal::EventTy> SuppressedEvents{
|
||||
omptest::internal::EventTy::ThreadBegin,
|
||||
omptest::internal::EventTy::ThreadEnd,
|
||||
omptest::internal::EventTy::ParallelBegin,
|
||||
omptest::internal::EventTy::ParallelEnd,
|
||||
omptest::internal::EventTy::Work,
|
||||
omptest::internal::EventTy::Dispatch,
|
||||
omptest::internal::EventTy::TaskCreate,
|
||||
omptest::internal::EventTy::Dependences,
|
||||
omptest::internal::EventTy::TaskDependence,
|
||||
omptest::internal::EventTy::TaskSchedule,
|
||||
omptest::internal::EventTy::ImplicitTask,
|
||||
omptest::internal::EventTy::Masked,
|
||||
omptest::internal::EventTy::SyncRegion,
|
||||
omptest::internal::EventTy::MutexAcquire,
|
||||
omptest::internal::EventTy::Mutex,
|
||||
omptest::internal::EventTy::NestLock,
|
||||
omptest::internal::EventTy::Flush,
|
||||
omptest::internal::EventTy::Cancel};
|
||||
};
|
||||
|
||||
/// Base class for asserting on OMPT events
|
||||
class OmptAsserter : public OmptListener {
|
||||
public:
|
||||
OmptAsserter();
|
||||
virtual ~OmptAsserter() = default;
|
||||
|
||||
/// Add an event to the asserter's internal data structure.
|
||||
virtual void insert(omptest::OmptAssertEvent &&AE);
|
||||
|
||||
/// Called from the CallbackHandler with a corresponding AssertEvent to which
|
||||
/// callback was handled.
|
||||
void notify(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
/// Implemented in subclasses to implement what should actually be done with
|
||||
/// the notification.
|
||||
virtual void notifyImpl(omptest::OmptAssertEvent &&AE) = 0;
|
||||
|
||||
/// Get the number of currently remaining events, with: ObserveState::Always.
|
||||
virtual size_t getRemainingEventCount() = 0;
|
||||
|
||||
/// Get the total number of received, effective notifications.
|
||||
int getNotificationCount() { return NumNotifications; }
|
||||
|
||||
/// Get the total number of successful assertion checks.
|
||||
int getSuccessfulAssertionCount() { return NumSuccessfulAsserts; }
|
||||
|
||||
/// Get the asserter's current operationmode: e.g.: Strict or Relaxed.
|
||||
AssertMode getOperationMode() { return OperationMode; }
|
||||
|
||||
/// Return the asserter's current state.
|
||||
omptest::AssertState getState() { return State; }
|
||||
|
||||
/// Determine and return the asserter's state.
|
||||
virtual omptest::AssertState checkState();
|
||||
|
||||
/// Accessor for the event group interface.
|
||||
std::shared_ptr<OmptEventGroupInterface> getEventGroups() const {
|
||||
return EventGroups;
|
||||
}
|
||||
|
||||
/// Accessor for the event group interface.
|
||||
std::shared_ptr<logging::Logger> getLog() const { return Log; }
|
||||
|
||||
/// Check the observed events' group association. If the event indicates the
|
||||
/// begin/end of an OpenMP target region, we will create/deprecate the
|
||||
/// expected event's group. Return true if the expected event group exists
|
||||
/// (and is active), otherwise: false. Note: BufferRecords may also match with
|
||||
/// deprecated groups as they may be delivered asynchronously.
|
||||
bool verifyEventGroups(const omptest::OmptAssertEvent &ExpectedEvent,
|
||||
const omptest::OmptAssertEvent &ObservedEvent);
|
||||
|
||||
/// Set the asserter's mode of operation w.r.t. assertion.
|
||||
void setOperationMode(AssertMode Mode);
|
||||
|
||||
protected:
|
||||
/// The asserter's current state.
|
||||
omptest::AssertState State{omptest::AssertState::Pass};
|
||||
|
||||
/// Mutex to avoid data races w.r.t. event notifications and/or insertions.
|
||||
std::mutex AssertMutex;
|
||||
|
||||
/// Pointer to the OmptEventGroupInterface.
|
||||
std::shared_ptr<OmptEventGroupInterface> EventGroups{nullptr};
|
||||
|
||||
/// Pointer to the logging instance.
|
||||
std::shared_ptr<logging::Logger> Log{nullptr};
|
||||
|
||||
/// Operation mode during assertion / notification.
|
||||
AssertMode OperationMode{AssertMode::Strict};
|
||||
|
||||
/// The total number of effective notifications. For example, if specific
|
||||
/// notifications are to be ignored, they will not count towards this total.
|
||||
int NumNotifications{0};
|
||||
|
||||
/// The number of successful assertion checks.
|
||||
int NumSuccessfulAsserts{0};
|
||||
|
||||
private:
|
||||
/// Mutex for creating/accessing the singleton members
|
||||
static std::mutex StaticMemberAccessMutex;
|
||||
|
||||
/// Static member to manage the singleton event group interface instance
|
||||
static std::weak_ptr<OmptEventGroupInterface> EventGroupInterfaceInstance;
|
||||
|
||||
/// Static member to manage the singleton logging instance
|
||||
static std::weak_ptr<logging::Logger> LoggingInstance;
|
||||
};
|
||||
|
||||
/// Class that can assert in a sequenced fashion, i.e., events have to occur in
|
||||
/// the order they were registered
|
||||
class OmptSequencedAsserter : public OmptAsserter {
|
||||
public:
|
||||
OmptSequencedAsserter() : OmptAsserter(), NextEvent(0) {}
|
||||
|
||||
/// Add the event to the in-sequence set of events that the asserter should
|
||||
/// check for.
|
||||
void insert(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
/// Implements the asserter's actual logic
|
||||
virtual void notifyImpl(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
size_t getRemainingEventCount() override;
|
||||
|
||||
omptest::AssertState checkState() override;
|
||||
|
||||
bool AssertionSuspended{false};
|
||||
|
||||
protected:
|
||||
/// Notification helper function, implementing SyncPoint logic. Returns true
|
||||
/// in case of consumed event, indicating early exit of notification.
|
||||
bool consumeSyncPoint(const omptest::OmptAssertEvent &AE);
|
||||
|
||||
/// Notification helper function, implementing excess event notification
|
||||
/// logic. Returns true when no more events were expected, indicating early
|
||||
/// exit of notification.
|
||||
bool checkExcessNotify(const omptest::OmptAssertEvent &AE);
|
||||
|
||||
/// Notification helper function, implementing Suspend logic. Returns true
|
||||
/// in case of consumed event, indicating early exit of notification.
|
||||
bool consumeSuspend();
|
||||
|
||||
/// Notification helper function, implementing regular event notification
|
||||
/// logic. Returns true when a matching event was encountered, indicating
|
||||
/// early exit of notification.
|
||||
bool consumeRegularEvent(const omptest::OmptAssertEvent &AE);
|
||||
|
||||
public:
|
||||
/// Index of the next, expected event.
|
||||
size_t NextEvent{0};
|
||||
std::vector<omptest::OmptAssertEvent> Events{};
|
||||
};
|
||||
|
||||
/// Class that asserts with set semantics, i.e., unordered
|
||||
struct OmptEventAsserter : public OmptAsserter {
|
||||
OmptEventAsserter() : OmptAsserter(), NumEvents(0), Events() {}
|
||||
|
||||
/// Add the event to the set of events that the asserter should check for.
|
||||
void insert(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
/// Implements the asserter's logic
|
||||
virtual void notifyImpl(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
size_t getRemainingEventCount() override;
|
||||
|
||||
omptest::AssertState checkState() override;
|
||||
|
||||
size_t NumEvents{0};
|
||||
|
||||
/// For now use vector (but do set semantics)
|
||||
// TODO std::unordered_set?
|
||||
std::vector<omptest::OmptAssertEvent> Events{};
|
||||
};
|
||||
|
||||
/// Class that reports the occurred events
|
||||
class OmptEventReporter : public OmptListener {
|
||||
public:
|
||||
OmptEventReporter(std::ostream &OutStream = std::cout)
|
||||
: OutStream(OutStream) {}
|
||||
|
||||
/// Called from the CallbackHandler with a corresponding AssertEvent to which
|
||||
/// callback was handled.
|
||||
void notify(omptest::OmptAssertEvent &&AE) override;
|
||||
|
||||
private:
|
||||
std::ostream &OutStream;
|
||||
};
|
||||
|
||||
/// This class provides the members and methods to manage event groups and
|
||||
/// SyncPoints in conjunction with asserters. Most importantly it maintains a
|
||||
/// coherent view of active and past events or SyncPoints.
|
||||
class OmptEventGroupInterface {
|
||||
public:
|
||||
OmptEventGroupInterface() = default;
|
||||
~OmptEventGroupInterface() = default;
|
||||
|
||||
/// Non-copyable and non-movable
|
||||
OmptEventGroupInterface(const OmptEventGroupInterface &) = delete;
|
||||
OmptEventGroupInterface &operator=(const OmptEventGroupInterface &) = delete;
|
||||
OmptEventGroupInterface(OmptEventGroupInterface &&) = delete;
|
||||
OmptEventGroupInterface &operator=(OmptEventGroupInterface &&) = delete;
|
||||
|
||||
/// Add given group to the set of active event groups. Effectively connecting
|
||||
/// the given groupname (expected) with a target region id (observed).
|
||||
bool addActiveEventGroup(const std::string &GroupName,
|
||||
omptest::AssertEventGroup Group);
|
||||
|
||||
/// Move given group from the set of active event groups to the set of
|
||||
/// previously active event groups.
|
||||
bool deprecateActiveEventGroup(const std::string &GroupName);
|
||||
|
||||
/// Check if given group is currently part of the active event groups.
|
||||
bool checkActiveEventGroups(const std::string &GroupName,
|
||||
omptest::AssertEventGroup Group);
|
||||
|
||||
/// Check if given group is currently part of the deprecated event groups.
|
||||
bool checkDeprecatedEventGroups(const std::string &GroupName,
|
||||
omptest::AssertEventGroup Group);
|
||||
|
||||
private:
|
||||
mutable std::mutex GroupMutex;
|
||||
std::map<std::string, omptest::AssertEventGroup> ActiveEventGroups{};
|
||||
std::map<std::string, omptest::AssertEventGroup> DeprecatedEventGroups{};
|
||||
std::set<std::string> EncounteredSyncPoints{};
|
||||
};
|
||||
|
||||
} // namespace omptest
|
||||
|
||||
#endif
|
@ -1,165 +0,0 @@
|
||||
//===- OmptCallbackHandler.h - Callback reception and handling --*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file provides the OMPT callback handling declarations.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTCALLBACKHANDLER_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTCALLBACKHANDLER_H
|
||||
|
||||
#include "OmptAssertEvent.h"
|
||||
#include "OmptAsserter.h"
|
||||
|
||||
#include "omp-tools.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace omptest {
|
||||
|
||||
/// Handler class to do whatever is needed to be done when a callback is invoked
|
||||
/// by the OMP runtime
|
||||
/// Supports a RecordAndReplay mechanism in which all OMPT events are recorded
|
||||
/// and then replayed. This is so that a test can assert on, e.g., a device
|
||||
/// initialize event, even though this would occur before a unit test is
|
||||
/// actually executed.
|
||||
class OmptCallbackHandler {
|
||||
public:
|
||||
~OmptCallbackHandler() = default;
|
||||
|
||||
/// Singleton handler
|
||||
static OmptCallbackHandler &get();
|
||||
|
||||
/// Subscribe a listener to be notified for OMPT events
|
||||
void subscribe(OmptListener *Listener);
|
||||
|
||||
/// Remove all subscribers
|
||||
void clearSubscribers();
|
||||
|
||||
/// When the record and replay mechanism is enabled this replays all OMPT
|
||||
/// events
|
||||
void replay();
|
||||
|
||||
/// Special asserter callback which checks that upon encountering the
|
||||
/// synchronization point, all expected events have been processed. That is:
|
||||
/// there are currently no remaining expected events for any asserter.
|
||||
void handleAssertionSyncPoint(const std::string &SyncPointName);
|
||||
|
||||
void handleThreadBegin(ompt_thread_t ThreadType, ompt_data_t *ThreadData);
|
||||
|
||||
void handleThreadEnd(ompt_data_t *ThreadData);
|
||||
|
||||
void handleTaskCreate(ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame,
|
||||
ompt_data_t *NewTaskData, int Flags, int HasDependences,
|
||||
const void *CodeptrRA);
|
||||
|
||||
void handleTaskSchedule(ompt_data_t *PriorTaskData,
|
||||
ompt_task_status_t PriorTaskStatus,
|
||||
ompt_data_t *NextTaskData);
|
||||
|
||||
void handleImplicitTask(ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
unsigned int ActualParallelism, unsigned int Index,
|
||||
int Flags);
|
||||
|
||||
void handleParallelBegin(ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame,
|
||||
ompt_data_t *ParallelData,
|
||||
unsigned int RequestedParallelism, int Flags,
|
||||
const void *CodeptrRA);
|
||||
|
||||
void handleParallelEnd(ompt_data_t *ParallelData,
|
||||
ompt_data_t *EncounteringTaskData, int Flags,
|
||||
const void *CodeptrRA);
|
||||
|
||||
void handleDeviceInitialize(int DeviceNum, const char *Type,
|
||||
ompt_device_t *Device,
|
||||
ompt_function_lookup_t LookupFn,
|
||||
const char *DocumentationStr);
|
||||
|
||||
void handleDeviceFinalize(int DeviceNum);
|
||||
|
||||
void handleTarget(ompt_target_t Kind, ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum, ompt_data_t *TaskData, ompt_id_t TargetId,
|
||||
const void *CodeptrRA);
|
||||
|
||||
void handleTargetEmi(ompt_target_t Kind, ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum, ompt_data_t *TaskData,
|
||||
ompt_data_t *TargetTaskData, ompt_data_t *TargetData,
|
||||
const void *CodeptrRA);
|
||||
|
||||
void handleTargetSubmit(ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
unsigned int RequestedNumTeams);
|
||||
|
||||
void handleTargetSubmitEmi(ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
unsigned int RequestedNumTeams);
|
||||
|
||||
void handleTargetDataOp(ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr,
|
||||
int SrcDeviceNum, void *DstAddr, int DstDeviceNum,
|
||||
size_t Bytes, const void *CodeptrRA);
|
||||
|
||||
void handleTargetDataOpEmi(ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr,
|
||||
int SrcDeviceNum, void *DstAddr, int DstDeviceNum,
|
||||
size_t Bytes, const void *CodeptrRA);
|
||||
|
||||
void handleDeviceLoad(int DeviceNum, const char *Filename,
|
||||
int64_t OffsetInFile, void *VmaInFile, size_t Bytes,
|
||||
void *HostAddr, void *DeviceAddr, uint64_t ModuleId);
|
||||
|
||||
void handleDeviceUnload(int DeviceNum, uint64_t ModuleId);
|
||||
|
||||
void handleBufferRequest(int DeviceNum, ompt_buffer_t **Buffer,
|
||||
size_t *Bytes);
|
||||
|
||||
void handleBufferComplete(int DeviceNum, ompt_buffer_t *Buffer, size_t Bytes,
|
||||
ompt_buffer_cursor_t Begin, int BufferOwned);
|
||||
|
||||
void handleBufferRecord(ompt_record_ompt_t *Record);
|
||||
|
||||
void handleBufferRecordDeallocation(ompt_buffer_t *Buffer);
|
||||
|
||||
/// Not needed for a conforming minimal OMPT implementation
|
||||
void handleWork(ompt_work_t WorkType, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
uint64_t Count, const void *CodeptrRA);
|
||||
|
||||
void handleDispatch(ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
ompt_dispatch_t Kind, ompt_data_t Instance);
|
||||
|
||||
void handleSyncRegion(ompt_sync_region_t Kind, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
const void *CodeptrRA);
|
||||
|
||||
private:
|
||||
/// Wrapper around emplace_back for potential additional logging / checking or
|
||||
/// so
|
||||
void recordEvent(OmptAssertEvent &&Event);
|
||||
|
||||
/// Listeners to be notified
|
||||
std::vector<OmptListener *> Subscribers;
|
||||
|
||||
/// Toggle if OMPT events should notify subscribers immediately or not
|
||||
bool RecordAndReplay{false};
|
||||
|
||||
/// Recorded events in Record and Replay mode
|
||||
std::vector<OmptAssertEvent> RecordedEvents;
|
||||
};
|
||||
|
||||
} // namespace omptest
|
||||
|
||||
// Pointer to global callback handler
|
||||
extern omptest::OmptCallbackHandler *Handler;
|
||||
|
||||
#endif
|
@ -1,60 +0,0 @@
|
||||
//===- OmptTester.h - Main header for ompTest usage -------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file represents the main header file for usage of the ompTest library.
|
||||
/// Depending on the build either 'standalone' or GoogleTest headers are
|
||||
/// included and corresponding main-function macros are defined.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTER_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTER_H
|
||||
|
||||
#include "AssertMacros.h"
|
||||
#include "Logging.h"
|
||||
#include "OmptAliases.h"
|
||||
#include "OmptAssertEvent.h"
|
||||
#include "OmptAsserter.h"
|
||||
#include "OmptCallbackHandler.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
// Standalone header section
|
||||
#ifdef OPENMP_LIBOMPTEST_BUILD_STANDALONE
|
||||
|
||||
#include "OmptTesterStandalone.h"
|
||||
|
||||
// Define standalone main function (place once at the bottom of a testsuite)
|
||||
#define OMPTEST_TESTSUITE_MAIN() \
|
||||
int main(int argc, char **argv) { \
|
||||
Runner R; \
|
||||
return R.run(); \
|
||||
}
|
||||
|
||||
// GoogleTest header section
|
||||
#else
|
||||
|
||||
#include "OmptTesterGoogleTest.h"
|
||||
|
||||
// Define GoogleTest main function (place once at the bottom of a testsuite)
|
||||
#define OMPTEST_TESTSUITE_MAIN() \
|
||||
int main(int argc, char **argv) { \
|
||||
testing::InitGoogleTest(&argc, argv); \
|
||||
return RUN_ALL_TESTS(); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,36 +0,0 @@
|
||||
//===- OmptTesterGlobals.h - Global function declarations -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Contains global function declarations, esp. for OMPT symbols.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERGLOBALS_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERGLOBALS_H
|
||||
|
||||
#include <omp-tools.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version,
|
||||
const char *runtime_version);
|
||||
int start_trace(ompt_device_t *Device);
|
||||
int flush_trace(ompt_device_t *Device);
|
||||
// Function which calls flush_trace(ompt_device_t *) on all traced devices.
|
||||
int flush_traced_devices();
|
||||
int stop_trace(ompt_device_t *Device);
|
||||
// Function which calls stop_trace(ompt_device_t *) on all traced devices.
|
||||
int stop_trace_devices();
|
||||
void libomptest_global_eventreporter_set_active(bool State);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,86 +0,0 @@
|
||||
//===- OmptTesterGoogleTest.h - GoogleTest header variant -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file represents the GoogleTest-based header variant, defining the
|
||||
/// actual test classes and their behavior.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERGOOGLETEST_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERGOOGLETEST_H
|
||||
|
||||
#include "AssertMacros.h"
|
||||
#include "OmptAliases.h"
|
||||
#include "OmptAssertEvent.h"
|
||||
#include "OmptAsserter.h"
|
||||
#include "OmptCallbackHandler.h"
|
||||
#include "OmptTesterGlobals.h"
|
||||
|
||||
// This will allow us to override the "TEST" macro of gtest
|
||||
#define GTEST_DONT_DEFINE_TEST 1
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace testing {
|
||||
class GTEST_API_ OmptTestCase : public testing::Test,
|
||||
public omptest::OmptEventGroupInterface {
|
||||
public:
|
||||
std::unique_ptr<omptest::OmptSequencedAsserter> SequenceAsserter =
|
||||
std::make_unique<omptest::OmptSequencedAsserter>();
|
||||
std::unique_ptr<omptest::OmptEventAsserter> SetAsserter =
|
||||
std::make_unique<omptest::OmptEventAsserter>();
|
||||
std::unique_ptr<omptest::OmptEventReporter> EventReporter =
|
||||
std::make_unique<omptest::OmptEventReporter>();
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
omptest::OmptCallbackHandler::get().subscribe(SequenceAsserter.get());
|
||||
omptest::OmptCallbackHandler::get().subscribe(SetAsserter.get());
|
||||
omptest::OmptCallbackHandler::get().subscribe(EventReporter.get());
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// Actively flush potential in-flight trace records
|
||||
flush_traced_devices();
|
||||
|
||||
// Remove subscribers to not be notified of events after test execution.
|
||||
omptest::OmptCallbackHandler::get().clearSubscribers();
|
||||
|
||||
// This common testcase must not encounter any failures.
|
||||
if (SequenceAsserter->checkState() == omptest::AssertState::Fail ||
|
||||
SetAsserter->checkState() == omptest::AssertState::Fail)
|
||||
ADD_FAILURE();
|
||||
}
|
||||
};
|
||||
|
||||
class GTEST_API_ OmptTestCaseXFail : public testing::OmptTestCase {
|
||||
protected:
|
||||
void TearDown() override {
|
||||
// Actively flush potential in-flight trace records
|
||||
flush_traced_devices();
|
||||
|
||||
// Remove subscribers to not be notified of events after test execution.
|
||||
omptest::OmptCallbackHandler::get().clearSubscribers();
|
||||
|
||||
// This eXpectedly failing testcase has to encounter at least one failure.
|
||||
if (SequenceAsserter->checkState() == omptest::AssertState::Pass &&
|
||||
SetAsserter->checkState() == omptest::AssertState::Pass)
|
||||
ADD_FAILURE();
|
||||
}
|
||||
};
|
||||
} // namespace testing
|
||||
|
||||
#define TEST(test_suite_name, test_name) \
|
||||
GTEST_TEST_(test_suite_name, test_name, ::testing::OmptTestCase, \
|
||||
::testing::internal::GetTypeId<::testing::OmptTestCase>())
|
||||
|
||||
#define TEST_XFAIL(test_suite_name, test_name) \
|
||||
GTEST_TEST_(test_suite_name, test_name, ::testing::OmptTestCaseXFail, \
|
||||
::testing::internal::GetTypeId<::testing::OmptTestCaseXFail>())
|
||||
|
||||
#endif // include guard
|
@ -1,123 +0,0 @@
|
||||
//===- OmptTesterStandalone.h - Standalone header variant -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file represents the 'standalone' header variant, defining the actual
|
||||
/// test classes and their behavior (it does not have external dependencies).
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERSTANDALONE_H
|
||||
#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTTESTERSTANDALONE_H
|
||||
|
||||
#include "OmptAssertEvent.h"
|
||||
#include "OmptAsserter.h"
|
||||
#include "OmptTesterGlobals.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
// Forward declarations.
|
||||
namespace omptest {
|
||||
struct OmptEventAsserter;
|
||||
class OmptEventReporter;
|
||||
class OmptSequencedAsserter;
|
||||
} // namespace omptest
|
||||
|
||||
struct Error {
|
||||
operator bool() { return Fail; }
|
||||
bool Fail;
|
||||
};
|
||||
|
||||
/// A pretty crude test case abstraction
|
||||
struct TestCase {
|
||||
TestCase(const std::string &name)
|
||||
: IsDisabled(name.rfind("DISABLED_", 0) == 0), Name(name) {}
|
||||
TestCase(const std::string &name, const omptest::AssertState &expected)
|
||||
: IsDisabled(name.rfind("DISABLED_", 0) == 0), Name(name),
|
||||
ExpectedState(expected) {}
|
||||
virtual ~TestCase() = default;
|
||||
Error exec();
|
||||
virtual void execImpl() { assert(false && "Allocating base class"); }
|
||||
|
||||
bool IsDisabled{false};
|
||||
std::string Name;
|
||||
omptest::AssertState ExpectedState{omptest::AssertState::Pass};
|
||||
omptest::AssertState ResultState{omptest::AssertState::Pass};
|
||||
|
||||
std::unique_ptr<omptest::OmptSequencedAsserter> SequenceAsserter =
|
||||
std::make_unique<omptest::OmptSequencedAsserter>();
|
||||
std::unique_ptr<omptest::OmptEventAsserter> SetAsserter =
|
||||
std::make_unique<omptest::OmptEventAsserter>();
|
||||
std::unique_ptr<omptest::OmptEventReporter> EventReporter =
|
||||
std::make_unique<omptest::OmptEventReporter>();
|
||||
};
|
||||
/// A pretty crude test suite abstraction
|
||||
struct TestSuite {
|
||||
using TestCaseVec = std::vector<std::unique_ptr<TestCase>>;
|
||||
std::string Name;
|
||||
TestSuite() = default;
|
||||
TestSuite(const TestSuite &O) = delete;
|
||||
TestSuite(TestSuite &&O);
|
||||
void setup();
|
||||
void teardown();
|
||||
TestCaseVec::iterator begin();
|
||||
TestCaseVec::iterator end();
|
||||
TestCaseVec TestCases;
|
||||
};
|
||||
/// Static class used to register all test cases and provide them to the driver
|
||||
class TestRegistrar {
|
||||
public:
|
||||
static TestRegistrar &get();
|
||||
static std::vector<TestSuite> getTestSuites();
|
||||
static void addCaseToSuite(TestCase *TC, std::string TSName);
|
||||
|
||||
private:
|
||||
TestRegistrar() = default;
|
||||
TestRegistrar(const TestRegistrar &o) = delete;
|
||||
TestRegistrar operator=(const TestRegistrar &o) = delete;
|
||||
// Keep tests in order 'of appearance' (top -> bottom), avoid unordered_map
|
||||
static std::map<std::string, TestSuite> Tests;
|
||||
};
|
||||
/// Hack to register test cases
|
||||
struct Registerer {
|
||||
Registerer(TestCase *TC, const std::string SuiteName);
|
||||
};
|
||||
/// Eventually executes all test suites and cases, should contain logic to skip
|
||||
/// stuff if needed
|
||||
struct Runner {
|
||||
Runner() : TestSuites(TestRegistrar::get().getTestSuites()) {}
|
||||
int run();
|
||||
void reportError(const Error &Err);
|
||||
void abortOrKeepGoing();
|
||||
// Print an execution summary of all testsuites and their corresponding
|
||||
// testcases.
|
||||
void printSummary();
|
||||
std::vector<TestSuite> TestSuites;
|
||||
};
|
||||
|
||||
/// MACROS TO DEFINE A TESTSUITE + TESTCASE (like GoogleTest does)
|
||||
#define XQUOTE(str) QUOTE(str)
|
||||
#define QUOTE(str) #str
|
||||
|
||||
#define TEST_TEMPLATE(SuiteName, CaseName, ExpectedState) \
|
||||
struct SuiteName##_##CaseName : public TestCase { \
|
||||
SuiteName##_##CaseName() \
|
||||
: TestCase(XQUOTE(CaseName), omptest::AssertState::ExpectedState) {} \
|
||||
virtual void execImpl() override; \
|
||||
}; \
|
||||
static Registerer R_##SuiteName##CaseName(new SuiteName##_##CaseName(), \
|
||||
#SuiteName); \
|
||||
void SuiteName##_##CaseName::execImpl()
|
||||
|
||||
#define TEST(SuiteName, CaseName) \
|
||||
TEST_TEMPLATE(SuiteName, CaseName, /*ExpectedState=*/Pass)
|
||||
#define TEST_XFAIL(SuiteName, CaseName) \
|
||||
TEST_TEMPLATE(SuiteName, CaseName, /*ExpectedState=*/Fail)
|
||||
|
||||
#endif
|
@ -1,367 +0,0 @@
|
||||
//===- InternalEvent.cpp - Internal event implementation --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implements internal event representation methods and helper functions.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InternalEvent.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
using namespace omptest;
|
||||
using namespace util;
|
||||
|
||||
std::string util::makeHexString(uint64_t Data, bool IsPointer, size_t MinBytes,
|
||||
bool ShowHexBase) {
|
||||
if (Data == 0 && IsPointer)
|
||||
return "(nil)";
|
||||
|
||||
thread_local std::ostringstream os;
|
||||
// Clear the content of the stream
|
||||
os.str(std::string());
|
||||
|
||||
// Manually prefixing "0x" will make the use of std::setfill more easy
|
||||
if (ShowHexBase)
|
||||
os << "0x";
|
||||
|
||||
// Default to 32bit (8 hex digits) width, if exceeding 64bit or zero value
|
||||
size_t NumDigits = (MinBytes > 0 && MinBytes < 9) ? (MinBytes << 1) : 8;
|
||||
|
||||
if (MinBytes > 0)
|
||||
os << std::setfill('0') << std::setw(NumDigits);
|
||||
|
||||
os << std::hex << Data;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string internal::AssertionSyncPoint::toString() const {
|
||||
std::string S{"Assertion SyncPoint: '"};
|
||||
S.append(Name).append(1, '\'');
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::ThreadBegin::toString() const {
|
||||
std::string S{"OMPT Callback ThreadBegin: "};
|
||||
S.append("ThreadType=").append(std::to_string(ThreadType));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::ThreadEnd::toString() const {
|
||||
std::string S{"OMPT Callback ThreadEnd"};
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::ParallelBegin::toString() const {
|
||||
std::string S{"OMPT Callback ParallelBegin: "};
|
||||
S.append("NumThreads=").append(std::to_string(NumThreads));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::ParallelEnd::toString() const {
|
||||
// TODO: Should we expose more detailed info here?
|
||||
std::string S{"OMPT Callback ParallelEnd"};
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::Work::toString() const {
|
||||
std::string S{"OMPT Callback Work: "};
|
||||
S.append("work_type=").append(std::to_string(WorkType));
|
||||
S.append(" endpoint=").append(std::to_string(Endpoint));
|
||||
S.append(" parallel_data=").append(makeHexString((uint64_t)ParallelData));
|
||||
S.append(" task_data=").append(makeHexString((uint64_t)TaskData));
|
||||
S.append(" count=").append(std::to_string(Count));
|
||||
S.append(" codeptr=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::Dispatch::toString() const {
|
||||
std::string S{"OMPT Callback Dispatch: "};
|
||||
S.append("parallel_data=").append(makeHexString((uint64_t)ParallelData));
|
||||
S.append(" task_data=").append(makeHexString((uint64_t)TaskData));
|
||||
S.append(" kind=").append(std::to_string(Kind));
|
||||
// TODO Check what to print for instance in all different cases
|
||||
if (Kind == ompt_dispatch_iteration) {
|
||||
S.append(" instance=[it=")
|
||||
.append(std::to_string(Instance.value))
|
||||
.append(1, ']');
|
||||
} else if (Kind == ompt_dispatch_section) {
|
||||
S.append(" instance=[ptr=")
|
||||
.append(makeHexString((uint64_t)Instance.ptr))
|
||||
.append(1, ']');
|
||||
} else if ((Kind == ompt_dispatch_ws_loop_chunk ||
|
||||
Kind == ompt_dispatch_taskloop_chunk ||
|
||||
Kind == ompt_dispatch_distribute_chunk) &&
|
||||
Instance.ptr != nullptr) {
|
||||
auto Chunk = static_cast<ompt_dispatch_chunk_t *>(Instance.ptr);
|
||||
S.append(" instance=[chunk=(start=")
|
||||
.append(std::to_string(Chunk->start))
|
||||
.append(", iterations=")
|
||||
.append(std::to_string(Chunk->iterations))
|
||||
.append(")]");
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TaskCreate::toString() const {
|
||||
std::string S{"OMPT Callback TaskCreate: "};
|
||||
S.append("encountering_task_data=")
|
||||
.append(makeHexString((uint64_t)EncounteringTaskData));
|
||||
S.append(" encountering_task_frame=")
|
||||
.append(makeHexString((uint64_t)EncounteringTaskFrame));
|
||||
S.append(" new_task_data=").append(makeHexString((uint64_t)NewTaskData));
|
||||
S.append(" flags=").append(std::to_string(Flags));
|
||||
S.append(" has_dependences=").append(std::to_string(HasDependences));
|
||||
S.append(" codeptr=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::ImplicitTask::toString() const {
|
||||
std::string S{"OMPT Callback ImplicitTask: "};
|
||||
S.append("endpoint=").append(std::to_string(Endpoint));
|
||||
S.append(" parallel_data=").append(makeHexString((uint64_t)ParallelData));
|
||||
S.append(" task_data=").append(makeHexString((uint64_t)TaskData));
|
||||
S.append(" actual_parallelism=").append(std::to_string(ActualParallelism));
|
||||
S.append(" index=").append(std::to_string(Index));
|
||||
S.append(" flags=").append(std::to_string(Flags));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::SyncRegion::toString() const {
|
||||
std::string S{"OMPT Callback SyncRegion: "};
|
||||
S.append("kind=").append(std::to_string(Kind));
|
||||
S.append(" endpoint=").append(std::to_string(Endpoint));
|
||||
S.append(" parallel_data=").append(makeHexString((uint64_t)ParallelData));
|
||||
S.append(" task_data=").append(makeHexString((uint64_t)TaskData));
|
||||
S.append(" codeptr=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::Target::toString() const {
|
||||
// TODO Should we canonicalize the string prefix (use "OMPT ..." everywhere)?
|
||||
std::string S{"Callback Target: target_id="};
|
||||
S.append(std::to_string(TargetId));
|
||||
S.append(" kind=").append(std::to_string(Kind));
|
||||
S.append(" endpoint=").append(std::to_string(Endpoint));
|
||||
S.append(" device_num=").append(std::to_string(DeviceNum));
|
||||
S.append(" code=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TargetEmi::toString() const {
|
||||
// TODO Should we canonicalize the string prefix (use "OMPT ..." everywhere)?
|
||||
std::string S{"Callback Target EMI: kind="};
|
||||
S.append(std::to_string(Kind));
|
||||
S.append(" endpoint=").append(std::to_string(Endpoint));
|
||||
S.append(" device_num=").append(std::to_string(DeviceNum));
|
||||
S.append(" task_data=").append(makeHexString((uint64_t)TaskData));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(TaskData) ? TaskData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" target_task_data=")
|
||||
.append(makeHexString((uint64_t)TargetTaskData));
|
||||
S.append(" (")
|
||||
.append(
|
||||
makeHexString((uint64_t)(TargetTaskData) ? TargetTaskData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" target_data=").append(makeHexString((uint64_t)TargetData));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(TargetData) ? TargetData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" code=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TargetDataOp::toString() const {
|
||||
std::string S{" Callback DataOp: target_id="};
|
||||
S.append(std::to_string(TargetId));
|
||||
S.append(" host_op_id=").append(std::to_string(HostOpId));
|
||||
S.append(" optype=").append(std::to_string(OpType));
|
||||
S.append(" src=").append(makeHexString((uint64_t)SrcAddr));
|
||||
S.append(" src_device_num=").append(std::to_string(SrcDeviceNum));
|
||||
S.append(" dest=").append(makeHexString((uint64_t)DstAddr));
|
||||
S.append(" dest_device_num=").append(std::to_string(DstDeviceNum));
|
||||
S.append(" bytes=").append(std::to_string(Bytes));
|
||||
S.append(" code=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TargetDataOpEmi::toString() const {
|
||||
std::string S{" Callback DataOp EMI: endpoint="};
|
||||
S.append(std::to_string(Endpoint));
|
||||
S.append(" optype=").append(std::to_string(OpType));
|
||||
S.append(" target_task_data=")
|
||||
.append(makeHexString((uint64_t)TargetTaskData));
|
||||
S.append(" (")
|
||||
.append(
|
||||
makeHexString((uint64_t)(TargetTaskData) ? TargetTaskData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" target_data=").append(makeHexString((uint64_t)TargetData));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(TargetData) ? TargetData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" host_op_id=").append(makeHexString((uint64_t)HostOpId));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(HostOpId) ? (*HostOpId) : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" src=").append(makeHexString((uint64_t)SrcAddr));
|
||||
S.append(" src_device_num=").append(std::to_string(SrcDeviceNum));
|
||||
S.append(" dest=").append(makeHexString((uint64_t)DstAddr));
|
||||
S.append(" dest_device_num=").append(std::to_string(DstDeviceNum));
|
||||
S.append(" bytes=").append(std::to_string(Bytes));
|
||||
S.append(" code=").append(makeHexString((uint64_t)CodeptrRA));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TargetSubmit::toString() const {
|
||||
std::string S{" Callback Submit: target_id="};
|
||||
S.append(std::to_string(TargetId));
|
||||
S.append(" host_op_id=").append(std::to_string(HostOpId));
|
||||
S.append(" req_num_teams=").append(std::to_string(RequestedNumTeams));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::TargetSubmitEmi::toString() const {
|
||||
std::string S{" Callback Submit EMI: endpoint="};
|
||||
S.append(std::to_string(Endpoint));
|
||||
S.append(" req_num_teams=").append(std::to_string(RequestedNumTeams));
|
||||
S.append(" target_data=").append(makeHexString((uint64_t)TargetData));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(TargetData) ? TargetData->value : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
S.append(" host_op_id=").append(makeHexString((uint64_t)HostOpId));
|
||||
S.append(" (")
|
||||
.append(makeHexString((uint64_t)(HostOpId) ? (*HostOpId) : 0,
|
||||
/*IsPointer=*/false))
|
||||
.append(1, ')');
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::DeviceInitialize::toString() const {
|
||||
std::string S{"Callback Init: device_num="};
|
||||
S.append(std::to_string(DeviceNum));
|
||||
S.append(" type=").append((Type) ? Type : "(null)");
|
||||
S.append(" device=").append(makeHexString((uint64_t)Device));
|
||||
S.append(" lookup=").append(makeHexString((uint64_t)LookupFn));
|
||||
S.append(" doc=").append(makeHexString((uint64_t)DocStr));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::DeviceFinalize::toString() const {
|
||||
std::string S{"Callback Fini: device_num="};
|
||||
S.append(std::to_string(DeviceNum));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::DeviceLoad::toString() const {
|
||||
std::string S{"Callback Load: device_num:"};
|
||||
S.append(std::to_string(DeviceNum));
|
||||
S.append(" module_id:").append(std::to_string(ModuleId));
|
||||
S.append(" filename:").append((Filename == nullptr) ? "(null)" : Filename);
|
||||
S.append(" host_addr:").append(makeHexString((uint64_t)HostAddr));
|
||||
S.append(" device_addr:").append(makeHexString((uint64_t)DeviceAddr));
|
||||
S.append(" bytes:").append(std::to_string(Bytes));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::BufferRequest::toString() const {
|
||||
std::string S{"Allocated "};
|
||||
S.append(std::to_string((Bytes != nullptr) ? *Bytes : 0))
|
||||
.append(" bytes at ");
|
||||
S.append(makeHexString((Buffer != nullptr) ? (uint64_t)*Buffer : 0));
|
||||
S.append(" in buffer request callback");
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::BufferComplete::toString() const {
|
||||
std::string S{"Executing buffer complete callback: "};
|
||||
S.append(std::to_string(DeviceNum)).append(1, ' ');
|
||||
S.append(makeHexString((uint64_t)Buffer)).append(1, ' ');
|
||||
S.append(std::to_string(Bytes)).append(1, ' ');
|
||||
S.append(makeHexString((uint64_t)Begin)).append(1, ' ');
|
||||
S.append(std::to_string(BufferOwned));
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::BufferRecord::toString() const {
|
||||
std::string S{""};
|
||||
std::string T{""};
|
||||
S.append("rec=").append(makeHexString((uint64_t)RecordPtr));
|
||||
S.append(" type=").append(std::to_string(Record.type));
|
||||
|
||||
T.append("time=").append(std::to_string(Record.time));
|
||||
T.append(" thread_id=").append(std::to_string(Record.thread_id));
|
||||
T.append(" target_id=").append(std::to_string(Record.target_id));
|
||||
|
||||
switch (Record.type) {
|
||||
case ompt_callback_target:
|
||||
case ompt_callback_target_emi: {
|
||||
// Handle Target Record
|
||||
ompt_record_target_t TR = Record.record.target;
|
||||
S.append(" (Target task) ").append(T);
|
||||
S.append(" kind=").append(std::to_string(TR.kind));
|
||||
S.append(" endpoint=").append(std::to_string(TR.endpoint));
|
||||
S.append(" device=").append(std::to_string(TR.device_num));
|
||||
S.append(" task_id=").append(std::to_string(TR.task_id));
|
||||
S.append(" codeptr=").append(makeHexString((uint64_t)TR.codeptr_ra));
|
||||
break;
|
||||
}
|
||||
case ompt_callback_target_data_op:
|
||||
case ompt_callback_target_data_op_emi: {
|
||||
// Handle Target DataOp Record
|
||||
ompt_record_target_data_op_t TDR = Record.record.target_data_op;
|
||||
S.append(" (Target data op) ").append(T);
|
||||
S.append(" host_op_id=").append(std::to_string(TDR.host_op_id));
|
||||
S.append(" optype=").append(std::to_string(TDR.optype));
|
||||
S.append(" src_addr=").append(makeHexString((uint64_t)TDR.src_addr));
|
||||
S.append(" src_device=").append(std::to_string(TDR.src_device_num));
|
||||
S.append(" dest_addr=").append(makeHexString((uint64_t)TDR.dest_addr));
|
||||
S.append(" dest_device=").append(std::to_string(TDR.dest_device_num));
|
||||
S.append(" bytes=").append(std::to_string(TDR.bytes));
|
||||
S.append(" end_time=").append(std::to_string(TDR.end_time));
|
||||
S.append(" duration=").append(std::to_string(TDR.end_time - Record.time));
|
||||
S.append(" ns codeptr=").append(makeHexString((uint64_t)TDR.codeptr_ra));
|
||||
break;
|
||||
}
|
||||
case ompt_callback_target_submit:
|
||||
case ompt_callback_target_submit_emi: {
|
||||
// Handle Target Kernel Record
|
||||
ompt_record_target_kernel_t TKR = Record.record.target_kernel;
|
||||
S.append(" (Target kernel) ").append(T);
|
||||
S.append(" host_op_id=").append(std::to_string(TKR.host_op_id));
|
||||
S.append(" requested_num_teams=")
|
||||
.append(std::to_string(TKR.requested_num_teams));
|
||||
S.append(" granted_num_teams=")
|
||||
.append(std::to_string(TKR.granted_num_teams));
|
||||
S.append(" end_time=").append(std::to_string(TKR.end_time));
|
||||
S.append(" duration=").append(std::to_string(TKR.end_time - Record.time));
|
||||
S.append(" ns");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
S.append(" (unsupported record type)");
|
||||
break;
|
||||
}
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
std::string internal::BufferRecordDeallocation::toString() const {
|
||||
std::string S{"Deallocated "};
|
||||
S.append(makeHexString((uint64_t)Buffer));
|
||||
return S;
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
//===- InternalEventOperators.cpp - Operator implementations ----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Defines the internal event operators, like comparators.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InternalEvent.h"
|
||||
|
||||
namespace omptest {
|
||||
|
||||
namespace internal {
|
||||
|
||||
bool operator==(const ParallelBegin &Expected, const ParallelBegin &Observed) {
|
||||
return Expected.NumThreads == Observed.NumThreads;
|
||||
}
|
||||
|
||||
bool operator==(const Work &Expected, const Work &Observed) {
|
||||
bool isSameWorkType = (Expected.WorkType == Observed.WorkType);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameParallelData =
|
||||
(Expected.ParallelData == std::numeric_limits<ompt_data_t *>::min()) ||
|
||||
(Expected.ParallelData == Observed.ParallelData);
|
||||
bool isSameTaskData =
|
||||
(Expected.TaskData == std::numeric_limits<ompt_data_t *>::min()) ||
|
||||
(Expected.TaskData == Observed.TaskData);
|
||||
bool isSameCount = (Expected.Count == std::numeric_limits<uint64_t>::min()) ||
|
||||
(Expected.Count == Observed.Count);
|
||||
return isSameWorkType && isSameEndpoint && isSameParallelData &&
|
||||
isSameTaskData && isSameCount;
|
||||
}
|
||||
|
||||
bool operator==(const ImplicitTask &Expected, const ImplicitTask &Observed) {
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameActualParallelism =
|
||||
(Expected.ActualParallelism ==
|
||||
std::numeric_limits<unsigned int>::min()) ||
|
||||
(Expected.ActualParallelism == Observed.ActualParallelism);
|
||||
bool isSameIndex =
|
||||
(Expected.Index == std::numeric_limits<unsigned int>::min()) ||
|
||||
(Expected.Index == Observed.Index);
|
||||
return isSameEndpoint && isSameActualParallelism && isSameIndex;
|
||||
}
|
||||
|
||||
bool operator==(const SyncRegion &Expected, const SyncRegion &Observed) {
|
||||
bool isSameKind = (Expected.Kind == Observed.Kind);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameParallelData =
|
||||
(Expected.ParallelData == std::numeric_limits<ompt_data_t *>::min()) ||
|
||||
(Expected.ParallelData == Observed.ParallelData);
|
||||
bool isSameTaskData =
|
||||
(Expected.TaskData == std::numeric_limits<ompt_data_t *>::min()) ||
|
||||
(Expected.TaskData == Observed.TaskData);
|
||||
return isSameKind && isSameEndpoint && isSameParallelData && isSameTaskData;
|
||||
}
|
||||
|
||||
bool operator==(const Target &Expected, const Target &Observed) {
|
||||
bool isSameKind = (Expected.Kind == Observed.Kind);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
return isSameKind && isSameEndpoint && isSameDeviceNum;
|
||||
}
|
||||
|
||||
bool operator==(const TargetEmi &Expected, const TargetEmi &Observed) {
|
||||
bool isSameKind = (Expected.Kind == Observed.Kind);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
return isSameKind && isSameEndpoint && isSameDeviceNum;
|
||||
}
|
||||
|
||||
bool operator==(const TargetDataOp &Expected, const TargetDataOp &Observed) {
|
||||
bool isSameOpType = (Expected.OpType == Observed.OpType);
|
||||
bool isSameSize = (Expected.Bytes == std::numeric_limits<size_t>::min()) ||
|
||||
(Expected.Bytes == Observed.Bytes);
|
||||
bool isSameSrcAddr =
|
||||
(Expected.SrcAddr == std::numeric_limits<void *>::min()) ||
|
||||
(Expected.SrcAddr == Observed.SrcAddr);
|
||||
bool isSameDstAddr =
|
||||
(Expected.DstAddr == std::numeric_limits<void *>::min()) ||
|
||||
(Expected.DstAddr == Observed.DstAddr);
|
||||
bool isSameSrcDeviceNum =
|
||||
(Expected.SrcDeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.SrcDeviceNum == Observed.SrcDeviceNum);
|
||||
bool isSameDstDeviceNum =
|
||||
(Expected.DstDeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DstDeviceNum == Observed.DstDeviceNum);
|
||||
return isSameOpType && isSameSize && isSameSrcAddr && isSameDstAddr &&
|
||||
isSameSrcDeviceNum && isSameDstDeviceNum;
|
||||
}
|
||||
|
||||
bool operator==(const TargetDataOpEmi &Expected,
|
||||
const TargetDataOpEmi &Observed) {
|
||||
bool isSameOpType = (Expected.OpType == Observed.OpType);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
bool isSameSize = (Expected.Bytes == std::numeric_limits<size_t>::min()) ||
|
||||
(Expected.Bytes == Observed.Bytes);
|
||||
bool isSameSrcAddr =
|
||||
(Expected.SrcAddr == std::numeric_limits<void *>::min()) ||
|
||||
(Expected.SrcAddr == Observed.SrcAddr);
|
||||
bool isSameDstAddr =
|
||||
(Expected.DstAddr == std::numeric_limits<void *>::min()) ||
|
||||
(Expected.DstAddr == Observed.DstAddr);
|
||||
bool isSameSrcDeviceNum =
|
||||
(Expected.SrcDeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.SrcDeviceNum == Observed.SrcDeviceNum);
|
||||
bool isSameDstDeviceNum =
|
||||
(Expected.DstDeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DstDeviceNum == Observed.DstDeviceNum);
|
||||
return isSameOpType && isSameEndpoint && isSameSize && isSameSrcAddr &&
|
||||
isSameDstAddr && isSameSrcDeviceNum && isSameDstDeviceNum;
|
||||
}
|
||||
|
||||
bool operator==(const TargetSubmit &Expected, const TargetSubmit &Observed) {
|
||||
bool isSameReqNumTeams =
|
||||
(Expected.RequestedNumTeams == Observed.RequestedNumTeams);
|
||||
return isSameReqNumTeams;
|
||||
}
|
||||
|
||||
bool operator==(const TargetSubmitEmi &Expected,
|
||||
const TargetSubmitEmi &Observed) {
|
||||
bool isSameReqNumTeams =
|
||||
(Expected.RequestedNumTeams == Observed.RequestedNumTeams);
|
||||
bool isSameEndpoint = (Expected.Endpoint == Observed.Endpoint);
|
||||
return isSameReqNumTeams && isSameEndpoint;
|
||||
}
|
||||
|
||||
bool operator==(const DeviceInitialize &Expected,
|
||||
const DeviceInitialize &Observed) {
|
||||
bool isSameDeviceNum = (Expected.DeviceNum == Observed.DeviceNum);
|
||||
bool isSameType =
|
||||
(Expected.Type == std::numeric_limits<const char *>::min()) ||
|
||||
((Expected.Type == Observed.Type) ||
|
||||
(strcmp(Expected.Type, Observed.Type) == 0));
|
||||
bool isSameDevice =
|
||||
(Expected.Device == std::numeric_limits<ompt_device_t *>::min()) ||
|
||||
(Expected.Device == Observed.Device);
|
||||
return isSameDeviceNum && isSameType && isSameDevice;
|
||||
}
|
||||
|
||||
bool operator==(const DeviceFinalize &Expected,
|
||||
const DeviceFinalize &Observed) {
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
return isSameDeviceNum;
|
||||
}
|
||||
|
||||
bool operator==(const DeviceLoad &Expected, const DeviceLoad &Observed) {
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
bool isSameSize = (Expected.Bytes == std::numeric_limits<size_t>::min()) ||
|
||||
(Expected.Bytes == Observed.Bytes);
|
||||
return isSameDeviceNum && isSameSize;
|
||||
}
|
||||
|
||||
bool operator==(const BufferRequest &Expected, const BufferRequest &Observed) {
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
bool isSameSize = (Expected.Bytes == std::numeric_limits<size_t *>::min()) ||
|
||||
(Expected.Bytes == Observed.Bytes);
|
||||
return isSameDeviceNum && isSameSize;
|
||||
}
|
||||
|
||||
bool operator==(const BufferComplete &Expected,
|
||||
const BufferComplete &Observed) {
|
||||
bool isSameDeviceNum =
|
||||
(Expected.DeviceNum == std::numeric_limits<int>::min()) ||
|
||||
(Expected.DeviceNum == Observed.DeviceNum);
|
||||
bool isSameSize = (Expected.Bytes == std::numeric_limits<size_t>::min()) ||
|
||||
(Expected.Bytes == Observed.Bytes);
|
||||
return isSameDeviceNum && isSameSize;
|
||||
}
|
||||
|
||||
bool operator==(const BufferRecord &Expected, const BufferRecord &Observed) {
|
||||
bool isSameType = (Expected.Record.type == Observed.Record.type);
|
||||
bool isSameTargetId =
|
||||
(Expected.Record.target_id == std::numeric_limits<ompt_id_t>::min()) ||
|
||||
(Expected.Record.target_id == Observed.Record.target_id);
|
||||
if (!(isSameType && isSameTargetId))
|
||||
return false;
|
||||
bool isEqual = true;
|
||||
ompt_device_time_t ObservedDurationNs =
|
||||
Observed.Record.record.target_data_op.end_time - Observed.Record.time;
|
||||
switch (Expected.Record.type) {
|
||||
case ompt_callback_target:
|
||||
isEqual &= (Expected.Record.record.target.kind ==
|
||||
std::numeric_limits<ompt_target_t>::min()) ||
|
||||
(Expected.Record.record.target.kind ==
|
||||
Observed.Record.record.target.kind);
|
||||
isEqual &= (Expected.Record.record.target.endpoint ==
|
||||
std::numeric_limits<ompt_scope_endpoint_t>::min()) ||
|
||||
(Expected.Record.record.target.endpoint ==
|
||||
Observed.Record.record.target.endpoint);
|
||||
isEqual &= (Expected.Record.record.target.device_num ==
|
||||
std::numeric_limits<int>::min()) ||
|
||||
(Expected.Record.record.target.device_num ==
|
||||
Observed.Record.record.target.device_num);
|
||||
break;
|
||||
case ompt_callback_target_data_op:
|
||||
isEqual &= (Expected.Record.record.target_data_op.optype ==
|
||||
std::numeric_limits<ompt_target_data_op_t>::min()) ||
|
||||
(Expected.Record.record.target_data_op.optype ==
|
||||
Observed.Record.record.target_data_op.optype);
|
||||
isEqual &= (Expected.Record.record.target_data_op.bytes ==
|
||||
std::numeric_limits<size_t>::min()) ||
|
||||
(Expected.Record.record.target_data_op.bytes ==
|
||||
Observed.Record.record.target_data_op.bytes);
|
||||
isEqual &= (Expected.Record.record.target_data_op.src_addr ==
|
||||
std::numeric_limits<void *>::min()) ||
|
||||
(Expected.Record.record.target_data_op.src_addr ==
|
||||
Observed.Record.record.target_data_op.src_addr);
|
||||
isEqual &= (Expected.Record.record.target_data_op.dest_addr ==
|
||||
std::numeric_limits<void *>::min()) ||
|
||||
(Expected.Record.record.target_data_op.dest_addr ==
|
||||
Observed.Record.record.target_data_op.dest_addr);
|
||||
isEqual &= (Expected.Record.record.target_data_op.src_device_num ==
|
||||
std::numeric_limits<int>::min()) ||
|
||||
(Expected.Record.record.target_data_op.src_device_num ==
|
||||
Observed.Record.record.target_data_op.src_device_num);
|
||||
isEqual &= (Expected.Record.record.target_data_op.dest_device_num ==
|
||||
std::numeric_limits<int>::min()) ||
|
||||
(Expected.Record.record.target_data_op.dest_device_num ==
|
||||
Observed.Record.record.target_data_op.dest_device_num);
|
||||
isEqual &= (Expected.Record.record.target_data_op.host_op_id ==
|
||||
std::numeric_limits<ompt_id_t>::min()) ||
|
||||
(Expected.Record.record.target_data_op.host_op_id ==
|
||||
Observed.Record.record.target_data_op.host_op_id);
|
||||
isEqual &= (Expected.Record.record.target_data_op.codeptr_ra ==
|
||||
std::numeric_limits<void *>::min()) ||
|
||||
(Expected.Record.record.target_data_op.codeptr_ra ==
|
||||
Observed.Record.record.target_data_op.codeptr_ra);
|
||||
if (Expected.Record.record.target_data_op.end_time !=
|
||||
std::numeric_limits<ompt_device_time_t>::min()) {
|
||||
isEqual &=
|
||||
ObservedDurationNs <= Expected.Record.record.target_data_op.end_time;
|
||||
}
|
||||
isEqual &= ObservedDurationNs >= Expected.Record.time;
|
||||
break;
|
||||
case ompt_callback_target_submit:
|
||||
ObservedDurationNs =
|
||||
Observed.Record.record.target_kernel.end_time - Observed.Record.time;
|
||||
isEqual &= (Expected.Record.record.target_kernel.requested_num_teams ==
|
||||
std::numeric_limits<unsigned int>::min()) ||
|
||||
(Expected.Record.record.target_kernel.requested_num_teams ==
|
||||
Observed.Record.record.target_kernel.requested_num_teams);
|
||||
isEqual &= (Expected.Record.record.target_kernel.granted_num_teams ==
|
||||
std::numeric_limits<unsigned int>::min()) ||
|
||||
(Expected.Record.record.target_kernel.granted_num_teams ==
|
||||
Observed.Record.record.target_kernel.granted_num_teams);
|
||||
isEqual &= (Expected.Record.record.target_kernel.host_op_id ==
|
||||
std::numeric_limits<ompt_id_t>::min()) ||
|
||||
(Expected.Record.record.target_kernel.host_op_id ==
|
||||
Observed.Record.record.target_kernel.host_op_id);
|
||||
if (Expected.Record.record.target_kernel.end_time !=
|
||||
std::numeric_limits<ompt_device_time_t>::min()) {
|
||||
isEqual &=
|
||||
ObservedDurationNs <= Expected.Record.record.target_kernel.end_time;
|
||||
}
|
||||
isEqual &= ObservedDurationNs >= Expected.Record.time;
|
||||
break;
|
||||
default:
|
||||
assert(false && "Encountered invalid record type");
|
||||
}
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace omptest
|
@ -1,181 +0,0 @@
|
||||
//===- Logging.cpp - General logging class implementation -------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implements ompTest-tailored logging.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
using namespace omptest;
|
||||
using namespace logging;
|
||||
|
||||
Logger::Logger(Level LogLevel, std::ostream &OutStream, bool FormatOutput)
|
||||
: LoggingLevel(LogLevel), OutStream(OutStream), FormatOutput(FormatOutput) {
|
||||
// Flush any buffered output
|
||||
OutStream << std::flush;
|
||||
}
|
||||
|
||||
Logger::~Logger() {
|
||||
// Flush any buffered output
|
||||
OutStream << std::flush;
|
||||
}
|
||||
|
||||
std::map<Level, std::set<FormatOption>> AggregatedFormatOptions{
|
||||
{Level::Diagnostic, {FormatOption::ColorLightBlue}},
|
||||
{Level::Info, {FormatOption::ColorLightGray}},
|
||||
{Level::Warning, {FormatOption::ColorLightYellow}},
|
||||
{Level::Error, {FormatOption::ColorRed}},
|
||||
{Level::Critical, {FormatOption::ColorLightRed}},
|
||||
{Level::Default, {FormatOption::None}},
|
||||
{Level::ExpectedEvent, {FormatOption::Bold, FormatOption::ColorCyan}},
|
||||
{Level::ObservedEvent, {FormatOption::ColorCyan}},
|
||||
{Level::OffendingEvent, {FormatOption::ColorYellow}}};
|
||||
|
||||
const char *logging::to_string(Level LogLevel) {
|
||||
switch (LogLevel) {
|
||||
case Level::Diagnostic:
|
||||
return "Diagnostic";
|
||||
case Level::Info:
|
||||
return "Info";
|
||||
case Level::Warning:
|
||||
return "Warning";
|
||||
case Level::Error:
|
||||
return "Error";
|
||||
case Level::Critical:
|
||||
return "Critical";
|
||||
case Level::Silent:
|
||||
return "Silent";
|
||||
default:
|
||||
assert(false && "Requested string representation for unknown LogLevel");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
std::string logging::getFormatSequence(Level LogLevel) {
|
||||
auto Options = AggregatedFormatOptions[LogLevel];
|
||||
std::stringstream SS{"\033["};
|
||||
SS << "\033[";
|
||||
if (!Options.empty()) {
|
||||
for (auto &Option : AggregatedFormatOptions[LogLevel])
|
||||
SS << int(Option) << ';';
|
||||
SS.seekp(-1, SS.cur);
|
||||
SS << 'm';
|
||||
} else {
|
||||
// Fallback to None / reset formatting
|
||||
SS << "0m";
|
||||
}
|
||||
return SS.str();
|
||||
}
|
||||
|
||||
std::string logging::format(const std::string &Message, FormatOption Option) {
|
||||
std::stringstream SS{"\033["};
|
||||
SS << "\033[";
|
||||
SS << int(Option) << 'm' << Message << "\033[0m";
|
||||
return SS.str();
|
||||
}
|
||||
|
||||
std::string logging::format(const std::string &Message,
|
||||
std::set<FormatOption> Options) {
|
||||
std::stringstream SS{"\033["};
|
||||
SS << "\033[";
|
||||
for (auto &Option : Options)
|
||||
SS << int(Option) << ';';
|
||||
SS.seekp(-1, SS.cur);
|
||||
SS << 'm' << Message << "\033[0m";
|
||||
return SS.str();
|
||||
}
|
||||
|
||||
void Logger::log(const std::string &Message, Level LogLevel) const {
|
||||
// Serialize logging
|
||||
std::lock_guard<std::mutex> Lock(LogMutex);
|
||||
|
||||
if (LoggingLevel > LogLevel)
|
||||
return;
|
||||
|
||||
if (FormatOutput) {
|
||||
OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)
|
||||
<< "] " << Message << getFormatSequence() << std::endl;
|
||||
} else {
|
||||
OutStream << '[' << to_string(LogLevel) << "] " << Message << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logEventMismatch(const std::string &Message,
|
||||
const omptest::OmptAssertEvent &OffendingEvent,
|
||||
Level LogLevel) const {
|
||||
// Serialize logging
|
||||
std::lock_guard<std::mutex> Lock(LogMutex);
|
||||
if (LoggingLevel > LogLevel)
|
||||
return;
|
||||
|
||||
if (FormatOutput) {
|
||||
OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)
|
||||
<< "] " << getFormatSequence()
|
||||
<< format(Message, AggregatedFormatOptions[LogLevel])
|
||||
<< "\n\tOffending event name='"
|
||||
<< format(OffendingEvent.getEventName(),
|
||||
AggregatedFormatOptions[Level::OffendingEvent])
|
||||
<< "'\n\tOffending='"
|
||||
<< format(OffendingEvent.toString(),
|
||||
AggregatedFormatOptions[Level::OffendingEvent])
|
||||
<< '\'' << std::endl;
|
||||
} else {
|
||||
OutStream << '[' << to_string(LogLevel) << "] " << Message
|
||||
<< "\n\tOffending event name='" << OffendingEvent.getEventName()
|
||||
<< "'\n\tOffending='" << OffendingEvent.toString() << '\''
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::logEventMismatch(const std::string &Message,
|
||||
const omptest::OmptAssertEvent &ExpectedEvent,
|
||||
const omptest::OmptAssertEvent &ObservedEvent,
|
||||
Level LogLevel) const {
|
||||
// Serialize logging
|
||||
std::lock_guard<std::mutex> Lock(LogMutex);
|
||||
if (LoggingLevel > LogLevel)
|
||||
return;
|
||||
|
||||
if (FormatOutput) {
|
||||
OutStream << getFormatSequence(LogLevel) << '[' << to_string(LogLevel)
|
||||
<< "] " << Message << getFormatSequence()
|
||||
<< "\n\tExpected event name='"
|
||||
<< format(ExpectedEvent.getEventName(),
|
||||
AggregatedFormatOptions[Level::ExpectedEvent])
|
||||
<< "' observe='"
|
||||
<< format(to_string(ExpectedEvent.getEventExpectedState()),
|
||||
AggregatedFormatOptions[Level::ExpectedEvent])
|
||||
<< "'\n\tObserved event name='"
|
||||
<< format(ObservedEvent.getEventName(),
|
||||
AggregatedFormatOptions[Level::ObservedEvent])
|
||||
<< "'\n\tExpected='"
|
||||
<< format(ExpectedEvent.toString(),
|
||||
AggregatedFormatOptions[Level::ExpectedEvent])
|
||||
<< "'\n\tObserved='"
|
||||
<< format(ObservedEvent.toString(),
|
||||
AggregatedFormatOptions[Level::ObservedEvent])
|
||||
<< '\'' << std::endl;
|
||||
} else {
|
||||
OutStream << '[' << to_string(LogLevel) << "] " << Message
|
||||
<< "\n\tExpected event name='" << ExpectedEvent.getEventName()
|
||||
<< "' observe='"
|
||||
<< to_string(ExpectedEvent.getEventExpectedState())
|
||||
<< "'\n\tObserved event name='" << ObservedEvent.getEventName()
|
||||
<< "'\n\tExpected='" << ExpectedEvent.toString()
|
||||
<< "'\n\tObserved='" << ObservedEvent.toString() << '\''
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::setFormatOutput(bool Enabled) { FormatOutput = Enabled; }
|
||||
|
||||
Level Logger::getLoggingLevel() const { return LoggingLevel; }
|
||||
|
||||
void Logger::setLoggingLevel(Level LogLevel) { LoggingLevel = LogLevel; }
|
@ -1,587 +0,0 @@
|
||||
//===- OmptAssertEvent.cpp - Assertion event implementations ----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implements assertion event CTORs, for generally all observable events.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OmptAssertEvent.h"
|
||||
#include <omp-tools.h>
|
||||
|
||||
using namespace omptest;
|
||||
|
||||
const char *omptest::to_string(ObserveState State) {
|
||||
switch (State) {
|
||||
case ObserveState::Generated:
|
||||
return "Generated";
|
||||
case ObserveState::Always:
|
||||
return "Always";
|
||||
case ObserveState::Never:
|
||||
return "Never";
|
||||
default:
|
||||
assert(false && "Requested string representation for unknown ObserveState");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
OmptAssertEvent::OmptAssertEvent(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
internal::InternalEvent *IE)
|
||||
: Name(Name), Group(Group), ExpectedState(Expected), TheEvent(IE) {}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::AssertionSyncPoint(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, const std::string &SyncPointName) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::AssertionSyncPoint(SyncPointName));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::AssertionSuspend(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::AssertionSuspend());
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ThreadBegin(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_thread_t ThreadType) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::ThreadBegin(ThreadType));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ThreadEnd(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected, new internal::ThreadEnd());
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ParallelBegin(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int NumThreads) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::ParallelBegin(NumThreads));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ParallelEnd(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_data_t *ParallelData,
|
||||
ompt_data_t *EncounteringTaskData,
|
||||
int Flags, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::ParallelEnd(ParallelData,
|
||||
EncounteringTaskData, Flags,
|
||||
CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::Work(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_work_t WorkType,
|
||||
ompt_scope_endpoint_t Endpoint, ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData, uint64_t Count,
|
||||
const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::Work(WorkType, Endpoint, ParallelData,
|
||||
TaskData, Count, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::Dispatch(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
ompt_dispatch_t Kind, ompt_data_t Instance) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::Dispatch(ParallelData, TaskData, Kind, Instance));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TaskCreate(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame, ompt_data_t *NewTaskData,
|
||||
int Flags, int HasDependences, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::TaskCreate(EncounteringTaskData, EncounteringTaskFrame,
|
||||
NewTaskData, Flags, HasDependences, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TaskSchedule(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected, new internal::TaskSchedule());
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ImplicitTask(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData, ompt_data_t *TaskData,
|
||||
unsigned int ActualParallelism, unsigned int Index, int Flags) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::ImplicitTask(Endpoint, ParallelData,
|
||||
TaskData, ActualParallelism,
|
||||
Index, Flags));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::SyncRegion(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_sync_region_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint, ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::SyncRegion(Kind, Endpoint, ParallelData,
|
||||
TaskData, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::Target(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint, int DeviceNum,
|
||||
ompt_data_t *TaskData, ompt_id_t TargetId,
|
||||
const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::Target(Kind, Endpoint, DeviceNum,
|
||||
TaskData, TargetId, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::TargetEmi(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint, int DeviceNum,
|
||||
ompt_data_t *TaskData, ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::TargetEmi(Kind, Endpoint, DeviceNum,
|
||||
TaskData, TargetTaskData,
|
||||
TargetData, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetDataOp(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr, int SrcDeviceNum,
|
||||
void *DstAddr, int DstDeviceNum, size_t Bytes, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::TargetDataOp(
|
||||
TargetId, HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetDataOp(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_data_op_t OpType, size_t Bytes,
|
||||
void *SrcAddr, void *DstAddr, int SrcDeviceNum, int DstDeviceNum,
|
||||
ompt_id_t TargetId, ompt_id_t HostOpId, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::TargetDataOp(
|
||||
TargetId, HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetDataOpEmi(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetTaskData, ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
ompt_target_data_op_t OpType, void *SrcAddr, int SrcDeviceNum,
|
||||
void *DstAddr, int DstDeviceNum, size_t Bytes, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::TargetDataOpEmi(Endpoint, TargetTaskData, TargetData,
|
||||
HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetDataOpEmi(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_target_data_op_t OpType,
|
||||
ompt_scope_endpoint_t Endpoint, size_t Bytes, void *SrcAddr, void *DstAddr,
|
||||
int SrcDeviceNum, int DstDeviceNum, ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::TargetDataOpEmi(Endpoint, TargetTaskData, TargetData,
|
||||
HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetSubmit(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_id_t TargetId,
|
||||
ompt_id_t HostOpId,
|
||||
unsigned int RequestedNumTeams) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::TargetSubmit(TargetId, HostOpId, RequestedNumTeams));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetSubmit(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
unsigned int RequestedNumTeams,
|
||||
ompt_id_t TargetId,
|
||||
ompt_id_t HostOpId) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::TargetSubmit(TargetId, HostOpId, RequestedNumTeams));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetSubmitEmi(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId,
|
||||
unsigned int RequestedNumTeams) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::TargetSubmitEmi(Endpoint, TargetData,
|
||||
HostOpId,
|
||||
RequestedNumTeams));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::TargetSubmitEmi(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
unsigned int RequestedNumTeams,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *TargetData,
|
||||
ompt_id_t *HostOpId) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::TargetSubmitEmi(Endpoint, TargetData,
|
||||
HostOpId,
|
||||
RequestedNumTeams));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::ControlTool(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected, new internal::ControlTool());
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::DeviceInitialize(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum, const char *Type,
|
||||
ompt_device_t *Device, ompt_function_lookup_t LookupFn,
|
||||
const char *DocumentationStr) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::DeviceInitialize(DeviceNum, Type, Device,
|
||||
LookupFn,
|
||||
DocumentationStr));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::DeviceFinalize(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int DeviceNum) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::DeviceFinalize(DeviceNum));
|
||||
}
|
||||
|
||||
OmptAssertEvent
|
||||
OmptAssertEvent::DeviceLoad(const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum,
|
||||
const char *Filename, int64_t OffsetInFile,
|
||||
void *VmaInFile, size_t Bytes, void *HostAddr,
|
||||
void *DeviceAddr, uint64_t ModuleId) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(
|
||||
EName, EGroup, Expected,
|
||||
new internal::DeviceLoad(DeviceNum, Filename, OffsetInFile, VmaInFile,
|
||||
Bytes, HostAddr, DeviceAddr, ModuleId));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::DeviceUnload(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected, new internal::DeviceUnload());
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRequest(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
int DeviceNum,
|
||||
ompt_buffer_t **Buffer,
|
||||
size_t *Bytes) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRequest(DeviceNum, Buffer, Bytes));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferComplete(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, int DeviceNum, ompt_buffer_t *Buffer,
|
||||
size_t Bytes, ompt_buffer_cursor_t Begin, int BufferOwned) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferComplete(DeviceNum, Buffer, Bytes,
|
||||
Begin, BufferOwned));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(const std::string &Name,
|
||||
const std::string &Group,
|
||||
const ObserveState &Expected,
|
||||
ompt_record_ompt_t *Record) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecord(Record));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type, ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint, int DeviceNum, ompt_id_t TaskId,
|
||||
ompt_id_t TargetId, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
|
||||
if (Type != ompt_callback_target)
|
||||
assert(false && "CTOR only suited for type: 'ompt_callback_target'");
|
||||
|
||||
ompt_record_target_t Subrecord{Kind, Endpoint, DeviceNum,
|
||||
TaskId, TargetId, CodeptrRA};
|
||||
|
||||
ompt_record_ompt_t *RecordPtr =
|
||||
(ompt_record_ompt_t *)malloc(sizeof(ompt_record_ompt_t));
|
||||
memset(RecordPtr, 0, sizeof(ompt_record_ompt_t));
|
||||
RecordPtr->type = Type;
|
||||
RecordPtr->time = expectedDefault(ompt_device_time_t);
|
||||
RecordPtr->thread_id = expectedDefault(ompt_id_t);
|
||||
RecordPtr->target_id = TargetId;
|
||||
RecordPtr->record.target = Subrecord;
|
||||
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecord(RecordPtr));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_target_data_op_t OpType, size_t Bytes,
|
||||
std::pair<ompt_device_time_t, ompt_device_time_t> Timeframe, void *SrcAddr,
|
||||
void *DstAddr, int SrcDeviceNum, int DstDeviceNum, ompt_id_t TargetId,
|
||||
ompt_id_t HostOpId, const void *CodeptrRA) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
|
||||
if (Type != ompt_callback_target_data_op)
|
||||
assert(false &&
|
||||
"CTOR only suited for type: 'ompt_callback_target_data_op'");
|
||||
|
||||
ompt_record_target_data_op_t Subrecord{
|
||||
HostOpId, OpType, SrcAddr, SrcDeviceNum, DstAddr,
|
||||
DstDeviceNum, Bytes, Timeframe.second, CodeptrRA};
|
||||
|
||||
ompt_record_ompt_t *RecordPtr =
|
||||
(ompt_record_ompt_t *)malloc(sizeof(ompt_record_ompt_t));
|
||||
memset(RecordPtr, 0, sizeof(ompt_record_ompt_t));
|
||||
RecordPtr->type = Type;
|
||||
RecordPtr->time = Timeframe.first;
|
||||
RecordPtr->thread_id = expectedDefault(ompt_id_t);
|
||||
RecordPtr->target_id = TargetId;
|
||||
RecordPtr->record.target_data_op = Subrecord;
|
||||
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecord(RecordPtr));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_target_data_op_t OpType, size_t Bytes,
|
||||
ompt_device_time_t MinimumTimeDelta, void *SrcAddr, void *DstAddr,
|
||||
int SrcDeviceNum, int DstDeviceNum, ompt_id_t TargetId, ompt_id_t HostOpId,
|
||||
const void *CodeptrRA) {
|
||||
return BufferRecord(Name, Group, Expected, Type, OpType, Bytes,
|
||||
{MinimumTimeDelta, expectedDefault(ompt_device_time_t)},
|
||||
SrcAddr, DstAddr, SrcDeviceNum, DstDeviceNum, TargetId,
|
||||
HostOpId, CodeptrRA);
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
std::pair<ompt_device_time_t, ompt_device_time_t> Timeframe,
|
||||
unsigned int RequestedNumTeams, unsigned int GrantedNumTeams,
|
||||
ompt_id_t TargetId, ompt_id_t HostOpId) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
|
||||
bool isDefault = (Timeframe.first == expectedDefault(ompt_device_time_t));
|
||||
isDefault &= (Timeframe.second == expectedDefault(ompt_device_time_t));
|
||||
isDefault &= (RequestedNumTeams == expectedDefault(unsigned int));
|
||||
isDefault &= (GrantedNumTeams == expectedDefault(unsigned int));
|
||||
isDefault &= (TargetId == expectedDefault(ompt_id_t));
|
||||
isDefault &= (HostOpId == expectedDefault(ompt_id_t));
|
||||
|
||||
ompt_record_ompt_t *RecordPtr =
|
||||
(ompt_record_ompt_t *)malloc(sizeof(ompt_record_ompt_t));
|
||||
memset(RecordPtr, 0, sizeof(ompt_record_ompt_t));
|
||||
RecordPtr->type = Type;
|
||||
|
||||
// This handles the simplest occurrence of a device tracing record
|
||||
// We can only check for Type -- since all other properties are set to default
|
||||
if (isDefault) {
|
||||
RecordPtr->time = expectedDefault(ompt_device_time_t);
|
||||
RecordPtr->thread_id = expectedDefault(ompt_id_t);
|
||||
RecordPtr->target_id = expectedDefault(ompt_id_t);
|
||||
if (Type == ompt_callback_target) {
|
||||
ompt_record_target_t Subrecord{expectedDefault(ompt_target_t),
|
||||
expectedDefault(ompt_scope_endpoint_t),
|
||||
expectedDefault(int),
|
||||
expectedDefault(ompt_id_t),
|
||||
expectedDefault(ompt_id_t),
|
||||
expectedDefault(void *)};
|
||||
RecordPtr->record.target = Subrecord;
|
||||
}
|
||||
|
||||
if (Type == ompt_callback_target_data_op) {
|
||||
ompt_record_target_data_op_t Subrecord{
|
||||
expectedDefault(ompt_id_t), expectedDefault(ompt_target_data_op_t),
|
||||
expectedDefault(void *), expectedDefault(int),
|
||||
expectedDefault(void *), expectedDefault(int),
|
||||
expectedDefault(size_t), expectedDefault(ompt_device_time_t),
|
||||
expectedDefault(void *)};
|
||||
RecordPtr->record.target_data_op = Subrecord;
|
||||
}
|
||||
|
||||
if (Type == ompt_callback_target_submit) {
|
||||
ompt_record_target_kernel_t Subrecord{
|
||||
expectedDefault(ompt_id_t), expectedDefault(unsigned int),
|
||||
expectedDefault(unsigned int), expectedDefault(ompt_device_time_t)};
|
||||
RecordPtr->record.target_kernel = Subrecord;
|
||||
}
|
||||
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecord(RecordPtr));
|
||||
}
|
||||
|
||||
if (Type != ompt_callback_target_submit)
|
||||
assert(false && "CTOR only suited for type: 'ompt_callback_target_submit'");
|
||||
|
||||
ompt_record_target_kernel_t Subrecord{HostOpId, RequestedNumTeams,
|
||||
GrantedNumTeams, Timeframe.second};
|
||||
|
||||
RecordPtr->time = Timeframe.first;
|
||||
RecordPtr->thread_id = expectedDefault(ompt_id_t);
|
||||
RecordPtr->target_id = TargetId;
|
||||
RecordPtr->record.target_kernel = Subrecord;
|
||||
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecord(RecordPtr));
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecord(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_callbacks_t Type,
|
||||
ompt_device_time_t MinimumTimeDelta, unsigned int RequestedNumTeams,
|
||||
unsigned int GrantedNumTeams, ompt_id_t TargetId, ompt_id_t HostOpId) {
|
||||
return BufferRecord(Name, Group, Expected, Type,
|
||||
{MinimumTimeDelta, expectedDefault(ompt_device_time_t)},
|
||||
RequestedNumTeams, GrantedNumTeams, TargetId, HostOpId);
|
||||
}
|
||||
|
||||
OmptAssertEvent OmptAssertEvent::BufferRecordDeallocation(
|
||||
const std::string &Name, const std::string &Group,
|
||||
const ObserveState &Expected, ompt_buffer_t *Buffer) {
|
||||
auto EName = getName(Name);
|
||||
auto EGroup = getGroup(Group);
|
||||
return OmptAssertEvent(EName, EGroup, Expected,
|
||||
new internal::BufferRecordDeallocation(Buffer));
|
||||
}
|
||||
|
||||
std::string OmptAssertEvent::getEventName() const { return Name; }
|
||||
|
||||
std::string OmptAssertEvent::getEventGroup() const { return Group; }
|
||||
|
||||
ObserveState OmptAssertEvent::getEventExpectedState() const {
|
||||
return ExpectedState;
|
||||
}
|
||||
|
||||
internal::EventTy OmptAssertEvent::getEventType() const {
|
||||
return TheEvent->Type;
|
||||
}
|
||||
|
||||
internal::InternalEvent *OmptAssertEvent::getEvent() const {
|
||||
return TheEvent.get();
|
||||
}
|
||||
|
||||
std::string OmptAssertEvent::toString(bool PrefixEventName) const {
|
||||
std::string S;
|
||||
if (PrefixEventName)
|
||||
S.append(getEventName()).append(": ");
|
||||
S.append((TheEvent == nullptr) ? "OmptAssertEvent" : TheEvent->toString());
|
||||
return S;
|
||||
}
|
||||
|
||||
bool omptest::operator==(const OmptAssertEvent &A, const OmptAssertEvent &B) {
|
||||
assert(A.TheEvent.get() != nullptr && "A is valid");
|
||||
assert(B.TheEvent.get() != nullptr && "B is valid");
|
||||
|
||||
return A.TheEvent->Type == B.TheEvent->Type &&
|
||||
A.TheEvent->equals(B.TheEvent.get());
|
||||
}
|
@ -1,484 +0,0 @@
|
||||
//===- OmptAsserter.cpp - Asserter-related implementations ------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// Implements all asserter-related class methods, like: notifications, handling
|
||||
/// of groups or determination of the testcase state.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OmptAsserter.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace omptest;
|
||||
using namespace internal;
|
||||
|
||||
// Initialize static members
|
||||
std::mutex OmptAsserter::StaticMemberAccessMutex;
|
||||
std::weak_ptr<OmptEventGroupInterface>
|
||||
OmptAsserter::EventGroupInterfaceInstance;
|
||||
std::weak_ptr<logging::Logger> OmptAsserter::LoggingInstance;
|
||||
|
||||
OmptAsserter::OmptAsserter() {
|
||||
// Protect static members access
|
||||
std::lock_guard<std::mutex> Lock(StaticMemberAccessMutex);
|
||||
|
||||
// Upgrade OmptEventGroupInterface weak_ptr to shared_ptr
|
||||
{
|
||||
EventGroups = EventGroupInterfaceInstance.lock();
|
||||
if (!EventGroups) {
|
||||
// Coordinator doesn't exist or was previously destroyed, create a new
|
||||
// one.
|
||||
EventGroups = std::make_shared<OmptEventGroupInterface>();
|
||||
// Store a weak reference to it
|
||||
EventGroupInterfaceInstance = EventGroups;
|
||||
}
|
||||
// EventGroups is now a valid shared_ptr, either to a new or existing
|
||||
// instance.
|
||||
}
|
||||
|
||||
// Upgrade logging::Logger weak_ptr to shared_ptr
|
||||
{
|
||||
Log = LoggingInstance.lock();
|
||||
if (!Log) {
|
||||
// Coordinator doesn't exist or was previously destroyed, create a new
|
||||
// one.
|
||||
Log = std::make_shared<logging::Logger>();
|
||||
// Store a weak reference to it
|
||||
LoggingInstance = Log;
|
||||
}
|
||||
// Log is now a valid shared_ptr, either to a new or existing instance.
|
||||
}
|
||||
}
|
||||
|
||||
void OmptListener::setActive(bool Enabled) { Active = Enabled; }
|
||||
|
||||
bool OmptListener::isActive() { return Active; }
|
||||
|
||||
bool OmptListener::isSuppressedEventType(EventTy EvTy) {
|
||||
return SuppressedEvents.find(EvTy) != SuppressedEvents.end();
|
||||
}
|
||||
|
||||
void OmptListener::permitEvent(EventTy EvTy) { SuppressedEvents.erase(EvTy); }
|
||||
|
||||
void OmptListener::suppressEvent(EventTy EvTy) {
|
||||
SuppressedEvents.insert(EvTy);
|
||||
}
|
||||
|
||||
void OmptAsserter::insert(OmptAssertEvent &&AE) {
|
||||
assert(false && "Base class 'insert' has undefined semantics.");
|
||||
}
|
||||
|
||||
void OmptAsserter::notify(OmptAssertEvent &&AE) {
|
||||
// Ignore notifications while inactive
|
||||
if (!isActive() || isSuppressedEventType(AE.getEventType()))
|
||||
return;
|
||||
|
||||
this->notifyImpl(std::move(AE));
|
||||
}
|
||||
|
||||
AssertState OmptAsserter::checkState() { return State; }
|
||||
|
||||
bool OmptAsserter::verifyEventGroups(const OmptAssertEvent &ExpectedEvent,
|
||||
const OmptAssertEvent &ObservedEvent) {
|
||||
assert(ExpectedEvent.getEventType() == ObservedEvent.getEventType() &&
|
||||
"Type mismatch: Expected != Observed event type");
|
||||
assert(EventGroups && "Missing EventGroups interface");
|
||||
|
||||
// Ignore all events within "default" group
|
||||
auto GroupName = ExpectedEvent.getEventGroup();
|
||||
|
||||
if (GroupName == "default")
|
||||
return true;
|
||||
|
||||
// Get a pointer to the observed internal event
|
||||
auto Event = ObservedEvent.getEvent();
|
||||
|
||||
switch (Event->Type) {
|
||||
case EventTy::Target:
|
||||
if (auto E = static_cast<const internal::Target *>(Event)) {
|
||||
if (E->Endpoint == ompt_scope_begin) {
|
||||
// Add new group since we entered a Target Region
|
||||
EventGroups->addActiveEventGroup(GroupName,
|
||||
AssertEventGroup{E->TargetId});
|
||||
} else if (E->Endpoint == ompt_scope_end) {
|
||||
// Deprecate group since we return from a Target Region
|
||||
EventGroups->deprecateActiveEventGroup(GroupName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case EventTy::TargetEmi:
|
||||
if (auto E = static_cast<const internal::TargetEmi *>(Event)) {
|
||||
if (E->Endpoint == ompt_scope_begin) {
|
||||
// Add new group since we entered a Target Region
|
||||
EventGroups->addActiveEventGroup(
|
||||
GroupName, AssertEventGroup{E->TargetData->value});
|
||||
} else if (E->Endpoint == ompt_scope_end) {
|
||||
// Deprecate group since we return from a Target Region
|
||||
EventGroups->deprecateActiveEventGroup(GroupName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case EventTy::TargetDataOp:
|
||||
if (auto E = static_cast<const internal::TargetDataOp *>(Event))
|
||||
return EventGroups->checkActiveEventGroups(GroupName,
|
||||
AssertEventGroup{E->TargetId});
|
||||
|
||||
return false;
|
||||
case EventTy::TargetDataOpEmi:
|
||||
if (auto E = static_cast<const internal::TargetDataOpEmi *>(Event))
|
||||
return EventGroups->checkActiveEventGroups(
|
||||
GroupName, AssertEventGroup{E->TargetData->value});
|
||||
|
||||
return false;
|
||||
case EventTy::TargetSubmit:
|
||||
if (auto E = static_cast<const internal::TargetSubmit *>(Event))
|
||||
return EventGroups->checkActiveEventGroups(GroupName,
|
||||
AssertEventGroup{E->TargetId});
|
||||
|
||||
return false;
|
||||
case EventTy::TargetSubmitEmi:
|
||||
if (auto E = static_cast<const internal::TargetSubmitEmi *>(Event))
|
||||
return EventGroups->checkActiveEventGroups(
|
||||
GroupName, AssertEventGroup{E->TargetData->value});
|
||||
|
||||
return false;
|
||||
case EventTy::BufferRecord:
|
||||
// BufferRecords are delivered asynchronously: also check deprecated groups.
|
||||
if (auto E = static_cast<const internal::BufferRecord *>(Event))
|
||||
return (EventGroups->checkActiveEventGroups(
|
||||
GroupName, AssertEventGroup{E->Record.target_id}) ||
|
||||
EventGroups->checkDeprecatedEventGroups(
|
||||
GroupName, AssertEventGroup{E->Record.target_id}));
|
||||
return false;
|
||||
// Some event types do not need any handling
|
||||
case EventTy::ThreadBegin:
|
||||
case EventTy::ThreadEnd:
|
||||
case EventTy::ParallelBegin:
|
||||
case EventTy::ParallelEnd:
|
||||
case EventTy::Work:
|
||||
case EventTy::Dispatch:
|
||||
case EventTy::TaskCreate:
|
||||
case EventTy::Dependences:
|
||||
case EventTy::TaskDependence:
|
||||
case EventTy::TaskSchedule:
|
||||
case EventTy::ImplicitTask:
|
||||
case EventTy::Masked:
|
||||
case EventTy::SyncRegion:
|
||||
case EventTy::MutexAcquire:
|
||||
case EventTy::Mutex:
|
||||
case EventTy::NestLock:
|
||||
case EventTy::Flush:
|
||||
case EventTy::Cancel:
|
||||
case EventTy::DeviceInitialize:
|
||||
case EventTy::DeviceFinalize:
|
||||
case EventTy::DeviceLoad:
|
||||
case EventTy::DeviceUnload:
|
||||
case EventTy::BufferRequest:
|
||||
case EventTy::BufferComplete:
|
||||
case EventTy::BufferRecordDeallocation:
|
||||
return true;
|
||||
// Some event types must not be encountered
|
||||
case EventTy::None:
|
||||
case EventTy::AssertionSyncPoint:
|
||||
case EventTy::AssertionSuspend:
|
||||
default:
|
||||
Log->log("Observed invalid event type: " + Event->toString(),
|
||||
logging::Level::Critical);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OmptAsserter::setOperationMode(AssertMode Mode) { OperationMode = Mode; }
|
||||
|
||||
void OmptSequencedAsserter::insert(OmptAssertEvent &&AE) {
|
||||
std::lock_guard<std::mutex> Lock(AssertMutex);
|
||||
Events.emplace_back(std::move(AE));
|
||||
}
|
||||
|
||||
void OmptSequencedAsserter::notifyImpl(OmptAssertEvent &&AE) {
|
||||
std::lock_guard<std::mutex> Lock(AssertMutex);
|
||||
// Ignore notifications while inactive, or for suppressed events
|
||||
if (Events.empty() || !isActive() || isSuppressedEventType(AE.getEventType()))
|
||||
return;
|
||||
|
||||
++NumNotifications;
|
||||
|
||||
// Note: Order of these checks has semantic meaning.
|
||||
// (1) Synchronization points should fail if there are remaining events,
|
||||
// otherwise pass. (2) Regular notification while no further events are
|
||||
// expected: fail. (3) Assertion suspension relies on a next expected event
|
||||
// being available. (4) All other cases are considered 'regular' and match the
|
||||
// next expected against the observed event. (5+6) Depending on the state /
|
||||
// mode we signal failure if no other check has done already, or signaled pass
|
||||
// by early-exit.
|
||||
if (consumeSyncPoint(AE) || // Handle observed SyncPoint event
|
||||
checkExcessNotify(AE) || // Check for remaining expected
|
||||
consumeSuspend() || // Handle requested suspend
|
||||
consumeRegularEvent(AE) || // Handle regular event
|
||||
AssertionSuspended || // Ignore fail, if suspended
|
||||
OperationMode == AssertMode::Relaxed) // Ignore fail, if Relaxed op-mode
|
||||
return;
|
||||
|
||||
Log->logEventMismatch("[OmptSequencedAsserter] The events are not equal",
|
||||
Events[NextEvent], AE);
|
||||
State = AssertState::Fail;
|
||||
}
|
||||
|
||||
bool OmptSequencedAsserter::consumeSyncPoint(
|
||||
const omptest::OmptAssertEvent &AE) {
|
||||
if (AE.getEventType() == EventTy::AssertionSyncPoint) {
|
||||
auto NumRemainingEvents = getRemainingEventCount();
|
||||
// Upon encountering a SyncPoint, all events should have been processed
|
||||
if (NumRemainingEvents == 0)
|
||||
return true;
|
||||
|
||||
Log->logEventMismatch(
|
||||
"[OmptSequencedAsserter] Encountered SyncPoint while still awaiting " +
|
||||
std::to_string(NumRemainingEvents) + " events. Asserted " +
|
||||
std::to_string(NumSuccessfulAsserts) + "/" +
|
||||
std::to_string(Events.size()) + " events successfully.",
|
||||
AE);
|
||||
State = AssertState::Fail;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing to process: continue.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OmptSequencedAsserter::checkExcessNotify(
|
||||
const omptest::OmptAssertEvent &AE) {
|
||||
if (NextEvent >= Events.size()) {
|
||||
// If we are not expecting any more events and passively asserting: return
|
||||
if (AssertionSuspended)
|
||||
return true;
|
||||
|
||||
Log->logEventMismatch(
|
||||
"[OmptSequencedAsserter] Too many events to check (" +
|
||||
std::to_string(NumNotifications) + "). Asserted " +
|
||||
std::to_string(NumSuccessfulAsserts) + "/" +
|
||||
std::to_string(Events.size()) + " events successfully.",
|
||||
AE);
|
||||
State = AssertState::Fail;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remaining expected events present: continue.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OmptSequencedAsserter::consumeSuspend() {
|
||||
// On AssertionSuspend -- enter 'passive' assertion.
|
||||
// Since we may encounter multiple, successive AssertionSuspend events, loop
|
||||
// until we hit the next non-AssertionSuspend event.
|
||||
while (Events[NextEvent].getEventType() == EventTy::AssertionSuspend) {
|
||||
AssertionSuspended = true;
|
||||
// We just hit the very last event: indicate early exit.
|
||||
if (++NextEvent >= Events.size())
|
||||
return true;
|
||||
}
|
||||
|
||||
// Continue with remaining notification logic.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OmptSequencedAsserter::consumeRegularEvent(
|
||||
const omptest::OmptAssertEvent &AE) {
|
||||
// If we are actively asserting, increment the event counter.
|
||||
// Otherwise: If passively asserting, we will keep waiting for a match.
|
||||
auto &E = Events[NextEvent];
|
||||
if (E == AE && verifyEventGroups(E, AE)) {
|
||||
if (E.getEventExpectedState() == ObserveState::Always) {
|
||||
++NumSuccessfulAsserts;
|
||||
} else if (E.getEventExpectedState() == ObserveState::Never) {
|
||||
Log->logEventMismatch(
|
||||
"[OmptSequencedAsserter] Encountered forbidden event", E, AE);
|
||||
State = AssertState::Fail;
|
||||
}
|
||||
|
||||
// Return to active assertion
|
||||
if (AssertionSuspended)
|
||||
AssertionSuspended = false;
|
||||
|
||||
// Match found, increment index and indicate early exit (success).
|
||||
++NextEvent;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Continue with remaining notification logic.
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t OmptSequencedAsserter::getRemainingEventCount() {
|
||||
return std::count_if(Events.begin(), Events.end(),
|
||||
[](const omptest::OmptAssertEvent &E) {
|
||||
return E.getEventExpectedState() ==
|
||||
ObserveState::Always;
|
||||
}) -
|
||||
NumSuccessfulAsserts;
|
||||
}
|
||||
|
||||
AssertState OmptSequencedAsserter::checkState() {
|
||||
// This is called after the testcase executed.
|
||||
// Once reached the number of successful notifications should be equal to the
|
||||
// number of expected events. However, there may still be excluded as well as
|
||||
// special asserter events remaining in the sequence.
|
||||
for (size_t i = NextEvent; i < Events.size(); ++i) {
|
||||
auto &E = Events[i];
|
||||
if (E.getEventExpectedState() == ObserveState::Always) {
|
||||
State = AssertState::Fail;
|
||||
Log->logEventMismatch("[OmptSequencedAsserter] Expected event was not "
|
||||
"encountered (Remaining events: " +
|
||||
std::to_string(getRemainingEventCount()) + ")",
|
||||
E);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return State;
|
||||
}
|
||||
|
||||
void OmptEventAsserter::insert(OmptAssertEvent &&AE) {
|
||||
std::lock_guard<std::mutex> Lock(AssertMutex);
|
||||
Events.emplace_back(std::move(AE));
|
||||
}
|
||||
|
||||
void OmptEventAsserter::notifyImpl(OmptAssertEvent &&AE) {
|
||||
std::lock_guard<std::mutex> Lock(AssertMutex);
|
||||
if (Events.empty() || !isActive() || isSuppressedEventType(AE.getEventType()))
|
||||
return;
|
||||
|
||||
if (NumEvents == 0)
|
||||
NumEvents = Events.size();
|
||||
|
||||
++NumNotifications;
|
||||
|
||||
if (AE.getEventType() == EventTy::AssertionSyncPoint) {
|
||||
auto NumRemainingEvents = getRemainingEventCount();
|
||||
// Upon encountering a SyncPoint, all events should have been processed
|
||||
if (NumRemainingEvents == 0)
|
||||
return;
|
||||
|
||||
Log->logEventMismatch(
|
||||
"[OmptEventAsserter] Encountered SyncPoint while still awaiting " +
|
||||
std::to_string(NumRemainingEvents) + " events. Asserted " +
|
||||
std::to_string(NumSuccessfulAsserts) + " events successfully.",
|
||||
AE);
|
||||
State = AssertState::Fail;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < Events.size(); ++i) {
|
||||
auto &E = Events[i];
|
||||
if (E == AE && verifyEventGroups(E, AE)) {
|
||||
if (E.getEventExpectedState() == ObserveState::Always) {
|
||||
Events.erase(Events.begin() + i);
|
||||
++NumSuccessfulAsserts;
|
||||
} else if (E.getEventExpectedState() == ObserveState::Never) {
|
||||
Log->logEventMismatch("[OmptEventAsserter] Encountered forbidden event",
|
||||
E, AE);
|
||||
State = AssertState::Fail;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (OperationMode == AssertMode::Strict) {
|
||||
Log->logEventMismatch("[OmptEventAsserter] Too many events to check (" +
|
||||
std::to_string(NumNotifications) +
|
||||
"). Asserted " +
|
||||
std::to_string(NumSuccessfulAsserts) +
|
||||
" events successfully. (Remaining events: " +
|
||||
std::to_string(getRemainingEventCount()) + ")",
|
||||
AE);
|
||||
State = AssertState::Fail;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
size_t OmptEventAsserter::getRemainingEventCount() {
|
||||
return std::count_if(
|
||||
Events.begin(), Events.end(), [](const omptest::OmptAssertEvent &E) {
|
||||
return E.getEventExpectedState() == ObserveState::Always;
|
||||
});
|
||||
}
|
||||
|
||||
AssertState OmptEventAsserter::checkState() {
|
||||
// This is called after the testcase executed.
|
||||
// Once reached no more expected events should be in the queue
|
||||
for (const auto &E : Events) {
|
||||
// Check if any of the remaining events were expected to be observed
|
||||
if (E.getEventExpectedState() == ObserveState::Always) {
|
||||
State = AssertState::Fail;
|
||||
Log->logEventMismatch("[OmptEventAsserter] Expected event was not "
|
||||
"encountered (Remaining events: " +
|
||||
std::to_string(getRemainingEventCount()) + ")",
|
||||
E);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return State;
|
||||
}
|
||||
|
||||
void OmptEventReporter::notify(OmptAssertEvent &&AE) {
|
||||
if (!isActive() || isSuppressedEventType(AE.getEventType()))
|
||||
return;
|
||||
|
||||
// Prepare notification, containing the newline to avoid stream interleaving.
|
||||
auto Notification{AE.toString()};
|
||||
Notification.push_back('\n');
|
||||
OutStream << Notification;
|
||||
}
|
||||
|
||||
bool OmptEventGroupInterface::addActiveEventGroup(
|
||||
const std::string &GroupName, omptest::AssertEventGroup Group) {
|
||||
std::lock_guard<std::mutex> Lock(GroupMutex);
|
||||
auto EventGroup = ActiveEventGroups.find(GroupName);
|
||||
if (EventGroup != ActiveEventGroups.end() &&
|
||||
EventGroup->second.TargetRegion == Group.TargetRegion)
|
||||
return false;
|
||||
ActiveEventGroups.emplace(GroupName, Group);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OmptEventGroupInterface::deprecateActiveEventGroup(
|
||||
const std::string &GroupName) {
|
||||
std::lock_guard<std::mutex> Lock(GroupMutex);
|
||||
auto EventGroup = ActiveEventGroups.find(GroupName);
|
||||
auto DeprecatedEventGroup = DeprecatedEventGroups.find(GroupName);
|
||||
if (EventGroup == ActiveEventGroups.end() &&
|
||||
DeprecatedEventGroup != DeprecatedEventGroups.end())
|
||||
return false;
|
||||
DeprecatedEventGroups.emplace(GroupName, EventGroup->second);
|
||||
ActiveEventGroups.erase(GroupName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OmptEventGroupInterface::checkActiveEventGroups(
|
||||
const std::string &GroupName, omptest::AssertEventGroup Group) {
|
||||
std::lock_guard<std::mutex> Lock(GroupMutex);
|
||||
auto EventGroup = ActiveEventGroups.find(GroupName);
|
||||
return (EventGroup != ActiveEventGroups.end() &&
|
||||
EventGroup->second.TargetRegion == Group.TargetRegion);
|
||||
}
|
||||
|
||||
bool OmptEventGroupInterface::checkDeprecatedEventGroups(
|
||||
const std::string &GroupName, omptest::AssertEventGroup Group) {
|
||||
std::lock_guard<std::mutex> Lock(GroupMutex);
|
||||
auto EventGroup = DeprecatedEventGroups.find(GroupName);
|
||||
return (EventGroup != DeprecatedEventGroups.end() &&
|
||||
EventGroup->second.TargetRegion == Group.TargetRegion);
|
||||
}
|
@ -1,445 +0,0 @@
|
||||
//===- OmptCallbackHandler.cpp - OMPT Callback handling impl. ---*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the OMPT callback handling implementations.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OmptCallbackHandler.h"
|
||||
|
||||
using namespace omptest;
|
||||
|
||||
OmptCallbackHandler *Handler = nullptr;
|
||||
|
||||
OmptCallbackHandler &OmptCallbackHandler::get() {
|
||||
if (Handler == nullptr)
|
||||
Handler = new OmptCallbackHandler();
|
||||
|
||||
return *Handler;
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::subscribe(OmptListener *Listener) {
|
||||
Subscribers.push_back(Listener);
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::clearSubscribers() {
|
||||
replay();
|
||||
|
||||
Subscribers.clear();
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::replay() {
|
||||
if (!RecordAndReplay)
|
||||
return;
|
||||
|
||||
for (auto &E : RecordedEvents)
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(std::move(E));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleThreadBegin(ompt_thread_t ThreadType,
|
||||
ompt_data_t *ThreadData) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::ThreadBegin(
|
||||
"Thread Begin", "", ObserveState::Generated, ThreadType));
|
||||
return;
|
||||
}
|
||||
|
||||
// Initial thread event likely to preceed assertion registration, so skip
|
||||
if (ThreadType == ompt_thread_initial)
|
||||
return;
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::ThreadBegin(
|
||||
"Thread Begin", "", ObserveState::Generated, ThreadType));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleThreadEnd(ompt_data_t *ThreadData) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(
|
||||
OmptAssertEvent::ThreadEnd("Thread End", "", ObserveState::Generated));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(
|
||||
OmptAssertEvent::ThreadEnd("Thread End", "", ObserveState::Generated));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTaskCreate(
|
||||
ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame, ompt_data_t *NewTaskData,
|
||||
int Flags, int HasDependences, const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TaskCreate(
|
||||
"Task Create", "", ObserveState::Generated, EncounteringTaskData,
|
||||
EncounteringTaskFrame, NewTaskData, Flags, HasDependences, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TaskCreate(
|
||||
"Task Create", "", ObserveState::Generated, EncounteringTaskData,
|
||||
EncounteringTaskFrame, NewTaskData, Flags, HasDependences, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTaskSchedule(ompt_data_t *PriorTaskData,
|
||||
ompt_task_status_t PriorTaskStatus,
|
||||
ompt_data_t *NextTaskData) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TaskSchedule("Task Schedule", "",
|
||||
ObserveState::Generated));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TaskSchedule("Task Schedule", "",
|
||||
ObserveState::Generated));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleImplicitTask(ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData,
|
||||
unsigned int ActualParallelism,
|
||||
unsigned int Index, int Flags) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::ImplicitTask(
|
||||
"Implicit Task", "", ObserveState::Generated, Endpoint, ParallelData,
|
||||
TaskData, ActualParallelism, Index, Flags));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::ImplicitTask(
|
||||
"Implicit Task", "", ObserveState::Generated, Endpoint, ParallelData,
|
||||
TaskData, ActualParallelism, Index, Flags));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleParallelBegin(
|
||||
ompt_data_t *EncounteringTaskData,
|
||||
const ompt_frame_t *EncounteringTaskFrame, ompt_data_t *ParallelData,
|
||||
unsigned int RequestedParallelism, int Flags, const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::ParallelBegin(
|
||||
"Parallel Begin", "", ObserveState::Generated, RequestedParallelism));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::ParallelBegin(
|
||||
"Parallel Begin", "", ObserveState::Generated, RequestedParallelism));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleParallelEnd(ompt_data_t *ParallelData,
|
||||
ompt_data_t *EncounteringTaskData,
|
||||
int Flags, const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::ParallelEnd("Parallel End", "",
|
||||
ObserveState::Generated));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::ParallelEnd("Parallel End", "",
|
||||
ObserveState::Generated));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleDeviceInitialize(
|
||||
int DeviceNum, const char *Type, ompt_device_t *Device,
|
||||
ompt_function_lookup_t LookupFn, const char *DocumentationStr) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::DeviceInitialize(
|
||||
"Device Inititalize", "", ObserveState::Generated, DeviceNum, Type,
|
||||
Device, LookupFn, DocumentationStr));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::DeviceInitialize(
|
||||
"Device Inititalize", "", ObserveState::Generated, DeviceNum, Type,
|
||||
Device, LookupFn, DocumentationStr));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleDeviceFinalize(int DeviceNum) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::DeviceFinalize(
|
||||
"Device Finalize", "", ObserveState::Generated, DeviceNum));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::DeviceFinalize(
|
||||
"Device Finalize", "", ObserveState::Generated, DeviceNum));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTarget(ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum, ompt_data_t *TaskData,
|
||||
ompt_id_t TargetId,
|
||||
const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::Target("Target", "", ObserveState::Generated,
|
||||
Kind, Endpoint, DeviceNum, TaskData,
|
||||
TargetId, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::Target("Target", "", ObserveState::Generated,
|
||||
Kind, Endpoint, DeviceNum, TaskData,
|
||||
TargetId, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTargetEmi(ompt_target_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
int DeviceNum, ompt_data_t *TaskData,
|
||||
ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData,
|
||||
const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TargetEmi(
|
||||
"Target EMI", "", ObserveState::Generated, Kind, Endpoint, DeviceNum,
|
||||
TaskData, TargetTaskData, TargetData, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TargetEmi(
|
||||
"Target EMI", "", ObserveState::Generated, Kind, Endpoint, DeviceNum,
|
||||
TaskData, TargetTaskData, TargetData, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTargetSubmit(ompt_id_t TargetId,
|
||||
ompt_id_t HostOpId,
|
||||
unsigned int RequestedNumTeams) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TargetSubmit("Target Submit", "",
|
||||
ObserveState::Generated, TargetId,
|
||||
HostOpId, RequestedNumTeams));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TargetSubmit("Target Submit", "",
|
||||
ObserveState::Generated, TargetId,
|
||||
HostOpId, RequestedNumTeams));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTargetSubmitEmi(
|
||||
ompt_scope_endpoint_t Endpoint, ompt_data_t *TargetData,
|
||||
ompt_id_t *HostOpId, unsigned int RequestedNumTeams) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TargetSubmitEmi(
|
||||
"Target Submit EMI", "", ObserveState::Generated, Endpoint, TargetData,
|
||||
HostOpId, RequestedNumTeams));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TargetSubmitEmi(
|
||||
"Target Submit EMI", "", ObserveState::Generated, Endpoint, TargetData,
|
||||
HostOpId, RequestedNumTeams));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTargetDataOp(
|
||||
ompt_id_t TargetId, ompt_id_t HostOpId, ompt_target_data_op_t OpType,
|
||||
void *SrcAddr, int SrcDeviceNum, void *DstAddr, int DstDeviceNum,
|
||||
size_t Bytes, const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TargetDataOp(
|
||||
"Target Data Op", "", ObserveState::Generated, TargetId, HostOpId,
|
||||
OpType, SrcAddr, SrcDeviceNum, DstAddr, DstDeviceNum, Bytes,
|
||||
CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TargetDataOp(
|
||||
"Target Data Op", "", ObserveState::Generated, TargetId, HostOpId,
|
||||
OpType, SrcAddr, SrcDeviceNum, DstAddr, DstDeviceNum, Bytes,
|
||||
CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleTargetDataOpEmi(
|
||||
ompt_scope_endpoint_t Endpoint, ompt_data_t *TargetTaskData,
|
||||
ompt_data_t *TargetData, ompt_id_t *HostOpId, ompt_target_data_op_t OpType,
|
||||
void *SrcAddr, int SrcDeviceNum, void *DstAddr, int DstDeviceNum,
|
||||
size_t Bytes, const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::TargetDataOpEmi(
|
||||
"Target Data Op EMI", "", ObserveState::Generated, Endpoint,
|
||||
TargetTaskData, TargetData, HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::TargetDataOpEmi(
|
||||
"Target Data Op EMI", "", ObserveState::Generated, Endpoint,
|
||||
TargetTaskData, TargetData, HostOpId, OpType, SrcAddr, SrcDeviceNum,
|
||||
DstAddr, DstDeviceNum, Bytes, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleDeviceLoad(int DeviceNum, const char *Filename,
|
||||
int64_t OffsetInFile,
|
||||
void *VmaInFile, size_t Bytes,
|
||||
void *HostAddr, void *DeviceAddr,
|
||||
uint64_t ModuleId) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::DeviceLoad(
|
||||
"Device Load", "", ObserveState::Generated, DeviceNum, Filename,
|
||||
OffsetInFile, VmaInFile, Bytes, HostAddr, DeviceAddr, ModuleId));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::DeviceLoad(
|
||||
"Device Load", "", ObserveState::Generated, DeviceNum, Filename,
|
||||
OffsetInFile, VmaInFile, Bytes, HostAddr, DeviceAddr, ModuleId));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleDeviceUnload(int DeviceNum, uint64_t ModuleId) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::DeviceUnload("Device Unload", "",
|
||||
ObserveState::Generated));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::DeviceUnload("Device Unload", "",
|
||||
ObserveState::Generated));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleBufferRequest(int DeviceNum,
|
||||
ompt_buffer_t **Buffer,
|
||||
size_t *Bytes) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::BufferRequest("Buffer Request", "",
|
||||
ObserveState::Generated,
|
||||
DeviceNum, Buffer, Bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::BufferRequest("Buffer Request", "",
|
||||
ObserveState::Generated, DeviceNum,
|
||||
Buffer, Bytes));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleBufferComplete(int DeviceNum,
|
||||
ompt_buffer_t *Buffer,
|
||||
size_t Bytes,
|
||||
ompt_buffer_cursor_t Begin,
|
||||
int BufferOwned) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::BufferComplete(
|
||||
"Buffer Complete", "", ObserveState::Generated, DeviceNum, Buffer,
|
||||
Bytes, Begin, BufferOwned));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::BufferComplete(
|
||||
"Buffer Complete", "", ObserveState::Generated, DeviceNum, Buffer,
|
||||
Bytes, Begin, BufferOwned));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleBufferRecord(ompt_record_ompt_t *Record) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::BufferRecord("Buffer Record", "",
|
||||
ObserveState::Generated, Record));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::BufferRecord("Buffer Record", "",
|
||||
ObserveState::Generated, Record));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleBufferRecordDeallocation(
|
||||
ompt_buffer_t *Buffer) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::BufferRecordDeallocation(
|
||||
"Buffer Deallocation", "", ObserveState::Generated, Buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::BufferRecordDeallocation(
|
||||
"Buffer Deallocation", "", ObserveState::Generated, Buffer));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleWork(ompt_work_t WorkType,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData, uint64_t Count,
|
||||
const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::Work("Work", "", ObserveState::Generated,
|
||||
WorkType, Endpoint, ParallelData,
|
||||
TaskData, Count, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::Work("Work", "", ObserveState::Generated,
|
||||
WorkType, Endpoint, ParallelData, TaskData,
|
||||
Count, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleSyncRegion(ompt_sync_region_t Kind,
|
||||
ompt_scope_endpoint_t Endpoint,
|
||||
ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData,
|
||||
const void *CodeptrRA) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::SyncRegion(
|
||||
"SyncRegion", "", ObserveState::Generated, Kind, Endpoint, ParallelData,
|
||||
TaskData, CodeptrRA));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::SyncRegion(
|
||||
"SyncRegion", "", ObserveState::Generated, Kind, Endpoint, ParallelData,
|
||||
TaskData, CodeptrRA));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleDispatch(ompt_data_t *ParallelData,
|
||||
ompt_data_t *TaskData,
|
||||
ompt_dispatch_t Kind,
|
||||
ompt_data_t Instance) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::Dispatch("Dispatch", "",
|
||||
ObserveState::Generated, ParallelData,
|
||||
TaskData, Kind, Instance));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::Dispatch("Dispatch", "", ObserveState::Generated,
|
||||
ParallelData, TaskData, Kind,
|
||||
Instance));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::handleAssertionSyncPoint(
|
||||
const std::string &SyncPointName) {
|
||||
if (RecordAndReplay) {
|
||||
recordEvent(OmptAssertEvent::AssertionSyncPoint(
|
||||
"Assertion SyncPoint", "", ObserveState::Generated, SyncPointName));
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &S : Subscribers)
|
||||
S->notify(OmptAssertEvent::AssertionSyncPoint(
|
||||
"Assertion SyncPoint", "", ObserveState::Generated, SyncPointName));
|
||||
}
|
||||
|
||||
void OmptCallbackHandler::recordEvent(OmptAssertEvent &&Event) {
|
||||
RecordedEvents.emplace_back(std::forward<OmptAssertEvent>(Event));
|
||||
}
|
@ -1,504 +0,0 @@
|
||||
//===- OmptTester.cpp - ompTest OMPT tool implementation --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file represents the core implementation file for the ompTest library.
|
||||
/// It provides the actual OMPT tool implementation: registers callbacks, etc.
|
||||
/// OMPT callbacks are passed to their corresponding handler, which in turn
|
||||
/// notifies all registered asserters.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OmptTester.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace omptest;
|
||||
|
||||
// Callback handler, which receives and relays OMPT callbacks
|
||||
extern OmptCallbackHandler *Handler;
|
||||
|
||||
// EventListener, which actually prints the OMPT events
|
||||
static OmptEventReporter *EventReporter;
|
||||
|
||||
// From openmp/runtime/test/ompt/callback.h
|
||||
#define register_ompt_callback_t(name, type) \
|
||||
do { \
|
||||
type f_##name = &on_##name; \
|
||||
if (ompt_set_callback(name, (ompt_callback_t)f_##name) == ompt_set_never) \
|
||||
printf("0: Could not register callback '" #name "'\n"); \
|
||||
} while (0)
|
||||
|
||||
#define register_ompt_callback(name) register_ompt_callback_t(name, name##_t)
|
||||
|
||||
#define OMPT_BUFFER_REQUEST_SIZE 256
|
||||
|
||||
#ifdef OPENMP_LIBOMPTEST_BUILD_STANDALONE
|
||||
std::map<std::string, TestSuite> TestRegistrar::Tests;
|
||||
#endif
|
||||
|
||||
static std::atomic<ompt_id_t> NextOpId{0x8000000000000001};
|
||||
static bool UseEMICallbacks = false;
|
||||
static bool UseTracing = false;
|
||||
static bool RunAsTestSuite = false;
|
||||
static bool ColoredLog = false;
|
||||
|
||||
// OMPT entry point handles
|
||||
static ompt_set_trace_ompt_t ompt_set_trace_ompt = 0;
|
||||
static ompt_start_trace_t ompt_start_trace = 0;
|
||||
static ompt_flush_trace_t ompt_flush_trace = 0;
|
||||
static ompt_stop_trace_t ompt_stop_trace = 0;
|
||||
static ompt_get_record_ompt_t ompt_get_record_ompt = 0;
|
||||
static ompt_advance_buffer_cursor_t ompt_advance_buffer_cursor = 0;
|
||||
static ompt_get_record_type_t ompt_get_record_type_fn = 0;
|
||||
|
||||
// OMPT device side tracing: Currently traced devices
|
||||
typedef std::unordered_set<ompt_device_t *> OmptDeviceSetTy;
|
||||
typedef std::unique_ptr<OmptDeviceSetTy> OmptDeviceSetPtrTy;
|
||||
static OmptDeviceSetPtrTy TracedDevices;
|
||||
|
||||
// OMPT callbacks
|
||||
|
||||
// Trace record callbacks
|
||||
static void on_ompt_callback_buffer_request(int device_num,
|
||||
ompt_buffer_t **buffer,
|
||||
size_t *bytes) {
|
||||
*bytes = OMPT_BUFFER_REQUEST_SIZE;
|
||||
*buffer = malloc(*bytes);
|
||||
OmptCallbackHandler::get().handleBufferRequest(device_num, buffer, bytes);
|
||||
}
|
||||
|
||||
// Note: This callback must handle a null begin cursor. Currently,
|
||||
// ompt_get_record_ompt, print_record_ompt, and
|
||||
// ompt_advance_buffer_cursor handle a null cursor.
|
||||
static void on_ompt_callback_buffer_complete(
|
||||
int device_num, ompt_buffer_t *buffer,
|
||||
size_t bytes, /* bytes returned in this callback */
|
||||
ompt_buffer_cursor_t begin, int buffer_owned) {
|
||||
OmptCallbackHandler::get().handleBufferComplete(device_num, buffer, bytes,
|
||||
begin, buffer_owned);
|
||||
|
||||
int Status = 1;
|
||||
ompt_buffer_cursor_t CurrentPos = begin;
|
||||
while (Status) {
|
||||
ompt_record_ompt_t *Record = ompt_get_record_ompt(buffer, CurrentPos);
|
||||
if (ompt_get_record_type_fn(buffer, CurrentPos) != ompt_record_ompt) {
|
||||
printf("Warning: received non-ompt type buffer object\n");
|
||||
}
|
||||
// TODO: Sometimes it may happen that the retrieved record may be null?!
|
||||
// Only handle non-null records
|
||||
if (Record != nullptr)
|
||||
OmptCallbackHandler::get().handleBufferRecord(Record);
|
||||
Status = ompt_advance_buffer_cursor(/*device=*/NULL, buffer, bytes,
|
||||
CurrentPos, &CurrentPos);
|
||||
}
|
||||
if (buffer_owned) {
|
||||
OmptCallbackHandler::get().handleBufferRecordDeallocation(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static ompt_set_result_t set_trace_ompt(ompt_device_t *Device) {
|
||||
if (!ompt_set_trace_ompt)
|
||||
return ompt_set_error;
|
||||
|
||||
if (UseEMICallbacks) {
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1,
|
||||
/*etype=*/ompt_callback_target_emi);
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1,
|
||||
/*etype=*/ompt_callback_target_data_op_emi);
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1,
|
||||
/*etype=*/ompt_callback_target_submit_emi);
|
||||
} else {
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1, /*etype=*/ompt_callback_target);
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1,
|
||||
/*etype=*/ompt_callback_target_data_op);
|
||||
ompt_set_trace_ompt(Device, /*enable=*/1,
|
||||
/*etype=*/ompt_callback_target_submit);
|
||||
}
|
||||
|
||||
return ompt_set_always;
|
||||
}
|
||||
|
||||
/////// HOST-RELATED //////
|
||||
|
||||
static void on_ompt_callback_thread_begin(ompt_thread_t thread_type,
|
||||
ompt_data_t *thread_data) {
|
||||
OmptCallbackHandler::get().handleThreadBegin(thread_type, thread_data);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_thread_end(ompt_data_t *thread_data) {
|
||||
OmptCallbackHandler::get().handleThreadEnd(thread_data);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_parallel_begin(
|
||||
ompt_data_t *encountering_task_data,
|
||||
const ompt_frame_t *encountering_task_frame, ompt_data_t *parallel_data,
|
||||
unsigned int requested_parallelism, int flags, const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleParallelBegin(
|
||||
encountering_task_data, encountering_task_frame, parallel_data,
|
||||
requested_parallelism, flags, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_parallel_end(ompt_data_t *parallel_data,
|
||||
ompt_data_t *encountering_task_data,
|
||||
int flags, const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleParallelEnd(
|
||||
parallel_data, encountering_task_data, flags, codeptr_ra);
|
||||
}
|
||||
|
||||
static void
|
||||
on_ompt_callback_task_create(ompt_data_t *encountering_task_data,
|
||||
const ompt_frame_t *encountering_task_frame,
|
||||
ompt_data_t *new_task_data, int flags,
|
||||
int has_dependences, const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleTaskCreate(
|
||||
encountering_task_data, encountering_task_frame, new_task_data, flags,
|
||||
has_dependences, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_task_schedule(ompt_data_t *prior_task_data,
|
||||
ompt_task_status_t prior_task_status,
|
||||
ompt_data_t *next_task_data) {
|
||||
OmptCallbackHandler::get().handleTaskSchedule(
|
||||
prior_task_data, prior_task_status, next_task_data);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_implicit_task(ompt_scope_endpoint_t endpoint,
|
||||
ompt_data_t *parallel_data,
|
||||
ompt_data_t *task_data,
|
||||
unsigned int actual_parallelism,
|
||||
unsigned int index, int flags) {
|
||||
OmptCallbackHandler::get().handleImplicitTask(
|
||||
endpoint, parallel_data, task_data, actual_parallelism, index, flags);
|
||||
}
|
||||
|
||||
// Callbacks as of Table 19.4, which are not considered required for a minimal
|
||||
// conforming OMPT implementation.
|
||||
static void on_ompt_callback_work(ompt_work_t work_type,
|
||||
ompt_scope_endpoint_t endpoint,
|
||||
ompt_data_t *parallel_data,
|
||||
ompt_data_t *task_data, uint64_t count,
|
||||
const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleWork(work_type, endpoint, parallel_data,
|
||||
task_data, count, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_dispatch(ompt_data_t *parallel_data,
|
||||
ompt_data_t *task_data,
|
||||
ompt_dispatch_t kind,
|
||||
ompt_data_t instance) {
|
||||
OmptCallbackHandler::get().handleDispatch(parallel_data, task_data, kind,
|
||||
instance);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_sync_region(ompt_sync_region_t kind,
|
||||
ompt_scope_endpoint_t endpoint,
|
||||
ompt_data_t *parallel_data,
|
||||
ompt_data_t *task_data,
|
||||
const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleSyncRegion(kind, endpoint, parallel_data,
|
||||
task_data, codeptr_ra);
|
||||
}
|
||||
|
||||
/////// DEVICE-RELATED //////
|
||||
|
||||
// Synchronous callbacks
|
||||
static void on_ompt_callback_device_initialize(int device_num, const char *type,
|
||||
ompt_device_t *device,
|
||||
ompt_function_lookup_t lookup,
|
||||
const char *documentation) {
|
||||
OmptCallbackHandler::get().handleDeviceInitialize(device_num, type, device,
|
||||
lookup, documentation);
|
||||
if (!UseTracing)
|
||||
return;
|
||||
|
||||
if (!lookup) {
|
||||
printf("Trace collection disabled on device %d\n", device_num);
|
||||
return;
|
||||
}
|
||||
|
||||
ompt_set_trace_ompt = (ompt_set_trace_ompt_t)lookup("ompt_set_trace_ompt");
|
||||
ompt_start_trace = (ompt_start_trace_t)lookup("ompt_start_trace");
|
||||
ompt_flush_trace = (ompt_flush_trace_t)lookup("ompt_flush_trace");
|
||||
ompt_stop_trace = (ompt_stop_trace_t)lookup("ompt_stop_trace");
|
||||
ompt_get_record_ompt = (ompt_get_record_ompt_t)lookup("ompt_get_record_ompt");
|
||||
ompt_advance_buffer_cursor =
|
||||
(ompt_advance_buffer_cursor_t)lookup("ompt_advance_buffer_cursor");
|
||||
|
||||
ompt_get_record_type_fn =
|
||||
(ompt_get_record_type_t)lookup("ompt_get_record_type");
|
||||
if (!ompt_get_record_type_fn) {
|
||||
printf("Warning: No function ompt_get_record_type found in device "
|
||||
"callbacks\n");
|
||||
}
|
||||
|
||||
static bool IsDeviceMapInitialized = false;
|
||||
if (!IsDeviceMapInitialized) {
|
||||
TracedDevices = std::make_unique<OmptDeviceSetTy>();
|
||||
IsDeviceMapInitialized = true;
|
||||
}
|
||||
|
||||
set_trace_ompt(device);
|
||||
|
||||
// In many scenarios, this is a good place to start the
|
||||
// trace. If start_trace is called from the main program before this
|
||||
// callback is dispatched, the start_trace handle will be null. This
|
||||
// is because this device_init callback is invoked during the first
|
||||
// target construct implementation.
|
||||
|
||||
start_trace(device);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_device_finalize(int device_num) {
|
||||
OmptCallbackHandler::get().handleDeviceFinalize(device_num);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_device_load(int device_num, const char *filename,
|
||||
int64_t offset_in_file,
|
||||
void *vma_in_file, size_t bytes,
|
||||
void *host_addr, void *device_addr,
|
||||
uint64_t module_id) {
|
||||
OmptCallbackHandler::get().handleDeviceLoad(
|
||||
device_num, filename, offset_in_file, vma_in_file, bytes, host_addr,
|
||||
device_addr, module_id);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_device_unload(int device_num, uint64_t module_id) {
|
||||
OmptCallbackHandler::get().handleDeviceUnload(device_num, module_id);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_data_op(
|
||||
ompt_id_t target_id, ompt_id_t host_op_id, ompt_target_data_op_t optype,
|
||||
void *src_addr, int src_device_num, void *dest_addr, int dest_device_num,
|
||||
size_t bytes, const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleTargetDataOp(
|
||||
target_id, host_op_id, optype, src_addr, src_device_num, dest_addr,
|
||||
dest_device_num, bytes, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target(ompt_target_t kind,
|
||||
ompt_scope_endpoint_t endpoint,
|
||||
int device_num, ompt_data_t *task_data,
|
||||
ompt_id_t target_id,
|
||||
const void *codeptr_ra) {
|
||||
OmptCallbackHandler::get().handleTarget(kind, endpoint, device_num, task_data,
|
||||
target_id, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_submit(ompt_id_t target_id,
|
||||
ompt_id_t host_op_id,
|
||||
unsigned int requested_num_teams) {
|
||||
OmptCallbackHandler::get().handleTargetSubmit(target_id, host_op_id,
|
||||
requested_num_teams);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_data_op_emi(
|
||||
ompt_scope_endpoint_t endpoint, ompt_data_t *target_task_data,
|
||||
ompt_data_t *target_data, ompt_id_t *host_op_id,
|
||||
ompt_target_data_op_t optype, void *src_addr, int src_device_num,
|
||||
void *dest_addr, int dest_device_num, size_t bytes,
|
||||
const void *codeptr_ra) {
|
||||
assert(codeptr_ra != 0 && "Unexpected null codeptr");
|
||||
// Both src and dest must not be null
|
||||
// However, for omp_target_alloc only the END call holds a value for one of
|
||||
// the two entries
|
||||
if (optype != ompt_target_data_alloc)
|
||||
assert((src_addr != 0 || dest_addr != 0) && "Both src and dest addr null");
|
||||
if (endpoint == ompt_scope_begin)
|
||||
*host_op_id = NextOpId.fetch_add(1, std::memory_order_relaxed);
|
||||
OmptCallbackHandler::get().handleTargetDataOpEmi(
|
||||
endpoint, target_task_data, target_data, host_op_id, optype, src_addr,
|
||||
src_device_num, dest_addr, dest_device_num, bytes, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_emi(ompt_target_t kind,
|
||||
ompt_scope_endpoint_t endpoint,
|
||||
int device_num, ompt_data_t *task_data,
|
||||
ompt_data_t *target_task_data,
|
||||
ompt_data_t *target_data,
|
||||
const void *codeptr_ra) {
|
||||
assert(codeptr_ra != 0 && "Unexpected null codeptr");
|
||||
if (endpoint == ompt_scope_begin)
|
||||
target_data->value = NextOpId.fetch_add(1, std::memory_order_relaxed);
|
||||
OmptCallbackHandler::get().handleTargetEmi(kind, endpoint, device_num,
|
||||
task_data, target_task_data,
|
||||
target_data, codeptr_ra);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_submit_emi(
|
||||
ompt_scope_endpoint_t endpoint, ompt_data_t *target_data,
|
||||
ompt_id_t *host_op_id, unsigned int requested_num_teams) {
|
||||
OmptCallbackHandler::get().handleTargetSubmitEmi(
|
||||
endpoint, target_data, host_op_id, requested_num_teams);
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_map(ompt_id_t target_id,
|
||||
unsigned int nitems, void **host_addr,
|
||||
void **device_addr, size_t *bytes,
|
||||
unsigned int *mapping_flags,
|
||||
const void *codeptr_ra) {
|
||||
assert(0 && "Target map callback is unimplemented");
|
||||
}
|
||||
|
||||
static void on_ompt_callback_target_map_emi(ompt_data_t *target_data,
|
||||
unsigned int nitems,
|
||||
void **host_addr,
|
||||
void **device_addr, size_t *bytes,
|
||||
unsigned int *mapping_flags,
|
||||
const void *codeptr_ra) {
|
||||
assert(0 && "Target map emi callback is unimplemented");
|
||||
}
|
||||
|
||||
/// Load the value of a given boolean environmental variable.
|
||||
bool getBoolEnvironmentVariable(const char *VariableName) {
|
||||
if (VariableName == nullptr)
|
||||
return false;
|
||||
if (const char *EnvValue = std::getenv(VariableName)) {
|
||||
std::string S{EnvValue};
|
||||
for (auto &C : S)
|
||||
C = (char)std::tolower(C);
|
||||
if (S == "1" || S == "on" || S == "true" || S == "yes")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Called by the OMP runtime to initialize the OMPT
|
||||
int ompt_initialize(ompt_function_lookup_t lookup, int initial_device_num,
|
||||
ompt_data_t *tool_data) {
|
||||
ompt_set_callback_t ompt_set_callback = nullptr;
|
||||
ompt_set_callback = (ompt_set_callback_t)lookup("ompt_set_callback");
|
||||
if (!ompt_set_callback)
|
||||
return 0; // failure
|
||||
|
||||
UseEMICallbacks = getBoolEnvironmentVariable("OMPTEST_USE_OMPT_EMI");
|
||||
UseTracing = getBoolEnvironmentVariable("OMPTEST_USE_OMPT_TRACING");
|
||||
RunAsTestSuite = getBoolEnvironmentVariable("OMPTEST_RUN_AS_TESTSUITE");
|
||||
ColoredLog = getBoolEnvironmentVariable("OMPTEST_LOG_COLORED");
|
||||
|
||||
register_ompt_callback(ompt_callback_thread_begin);
|
||||
register_ompt_callback(ompt_callback_thread_end);
|
||||
register_ompt_callback(ompt_callback_parallel_begin);
|
||||
register_ompt_callback(ompt_callback_parallel_end);
|
||||
register_ompt_callback(ompt_callback_work);
|
||||
// register_ompt_callback(ompt_callback_dispatch);
|
||||
register_ompt_callback(ompt_callback_task_create);
|
||||
// register_ompt_callback(ompt_callback_dependences);
|
||||
// register_ompt_callback(ompt_callback_task_dependence);
|
||||
register_ompt_callback(ompt_callback_task_schedule);
|
||||
register_ompt_callback(ompt_callback_implicit_task);
|
||||
// register_ompt_callback(ompt_callback_masked);
|
||||
register_ompt_callback(ompt_callback_sync_region);
|
||||
// register_ompt_callback(ompt_callback_mutex_acquire);
|
||||
// register_ompt_callback(ompt_callback_mutex);
|
||||
// register_ompt_callback(ompt_callback_nestLock);
|
||||
// register_ompt_callback(ompt_callback_flush);
|
||||
// register_ompt_callback(ompt_callback_cancel);
|
||||
register_ompt_callback(ompt_callback_device_initialize);
|
||||
register_ompt_callback(ompt_callback_device_finalize);
|
||||
register_ompt_callback(ompt_callback_device_load);
|
||||
register_ompt_callback(ompt_callback_device_unload);
|
||||
|
||||
if (UseEMICallbacks) {
|
||||
register_ompt_callback(ompt_callback_target_emi);
|
||||
register_ompt_callback(ompt_callback_target_submit_emi);
|
||||
register_ompt_callback(ompt_callback_target_data_op_emi);
|
||||
register_ompt_callback(ompt_callback_target_map_emi);
|
||||
} else {
|
||||
register_ompt_callback(ompt_callback_target);
|
||||
register_ompt_callback(ompt_callback_target_submit);
|
||||
register_ompt_callback(ompt_callback_target_data_op);
|
||||
register_ompt_callback(ompt_callback_target_map);
|
||||
}
|
||||
|
||||
// Construct & subscribe the reporter, so it gets notified of events
|
||||
EventReporter = new OmptEventReporter();
|
||||
OmptCallbackHandler::get().subscribe(EventReporter);
|
||||
|
||||
if (RunAsTestSuite)
|
||||
EventReporter->setActive(false);
|
||||
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
void ompt_finalize(ompt_data_t *tool_data) {
|
||||
assert(Handler && "Callback handler should be present at this point");
|
||||
assert(EventReporter && "EventReporter should be present at this point");
|
||||
delete Handler;
|
||||
delete EventReporter;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/// Called from the OMP Runtime to start / initialize the tool
|
||||
ompt_start_tool_result_t *ompt_start_tool(unsigned int omp_version,
|
||||
const char *runtime_version) {
|
||||
static ompt_start_tool_result_t ompt_start_tool_result = {
|
||||
&ompt_initialize, &ompt_finalize, {0}};
|
||||
return &ompt_start_tool_result;
|
||||
}
|
||||
|
||||
int start_trace(ompt_device_t *Device) {
|
||||
if (!ompt_start_trace)
|
||||
return 0;
|
||||
|
||||
// Start tracing this device (add to set)
|
||||
assert(TracedDevices->find(Device) == TracedDevices->end() &&
|
||||
"Device already present in the map");
|
||||
TracedDevices->insert(Device);
|
||||
|
||||
return ompt_start_trace(Device, &on_ompt_callback_buffer_request,
|
||||
&on_ompt_callback_buffer_complete);
|
||||
}
|
||||
|
||||
int flush_trace(ompt_device_t *Device) {
|
||||
if (!ompt_flush_trace)
|
||||
return 0;
|
||||
return ompt_flush_trace(Device);
|
||||
}
|
||||
|
||||
int flush_traced_devices() {
|
||||
if (!ompt_flush_trace || TracedDevices == nullptr)
|
||||
return 0;
|
||||
|
||||
size_t NumFlushedDevices = 0;
|
||||
for (auto Device : *TracedDevices)
|
||||
if (ompt_flush_trace(Device) == 1)
|
||||
++NumFlushedDevices;
|
||||
|
||||
// Provide time to process triggered assert events
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
return (NumFlushedDevices == TracedDevices->size());
|
||||
}
|
||||
|
||||
int stop_trace(ompt_device_t *Device) {
|
||||
if (!ompt_stop_trace)
|
||||
return 0;
|
||||
|
||||
// Stop tracing this device (erase from set)
|
||||
assert(TracedDevices->find(Device) != TracedDevices->end() &&
|
||||
"Device not present in the map");
|
||||
TracedDevices->erase(Device);
|
||||
|
||||
return ompt_stop_trace(Device);
|
||||
}
|
||||
|
||||
// This is primarily used to stop unwanted prints from happening.
|
||||
void libomptest_global_eventreporter_set_active(bool State) {
|
||||
assert(EventReporter && "EventReporter should be present at this point");
|
||||
EventReporter->setActive(State);
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,147 +0,0 @@
|
||||
//===- OmptTesterStandalone.cpp - Standalone unit testing impl. -*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file represents the 'standalone' ompTest unit testing core
|
||||
/// implementation, defining the general test suite and test case execution.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "OmptTesterStandalone.h"
|
||||
#include "OmptCallbackHandler.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace omptest;
|
||||
|
||||
Error TestCase::exec() {
|
||||
Error E;
|
||||
E.Fail = false;
|
||||
|
||||
if (IsDisabled)
|
||||
return E;
|
||||
|
||||
OmptCallbackHandler::get().subscribe(SequenceAsserter.get());
|
||||
OmptCallbackHandler::get().subscribe(SetAsserter.get());
|
||||
OmptCallbackHandler::get().subscribe(EventReporter.get());
|
||||
|
||||
execImpl();
|
||||
|
||||
// Actively flush potential in-flight trace records
|
||||
flush_traced_devices();
|
||||
|
||||
// We remove subscribers to not be notified of events after our test case
|
||||
// finished.
|
||||
OmptCallbackHandler::get().clearSubscribers();
|
||||
omptest::AssertState SequenceResultState = SequenceAsserter->checkState();
|
||||
omptest::AssertState SetResultState = SetAsserter->checkState();
|
||||
bool AnyFail = SequenceResultState == omptest::AssertState::Fail ||
|
||||
SetResultState == omptest::AssertState::Fail;
|
||||
bool AllPass = SequenceResultState == omptest::AssertState::Pass &&
|
||||
SetResultState == omptest::AssertState::Pass;
|
||||
if (ExpectedState == omptest::AssertState::Pass && AnyFail)
|
||||
E.Fail = true;
|
||||
else if (ExpectedState == omptest::AssertState::Fail && AllPass)
|
||||
E.Fail = true;
|
||||
if (AnyFail)
|
||||
ResultState = omptest::AssertState::Fail;
|
||||
return E;
|
||||
}
|
||||
|
||||
TestSuite::TestSuite(TestSuite &&O) {
|
||||
Name = O.Name;
|
||||
TestCases.swap(O.TestCases);
|
||||
}
|
||||
|
||||
void TestSuite::setup() {}
|
||||
|
||||
void TestSuite::teardown() {}
|
||||
|
||||
TestSuite::TestCaseVec::iterator TestSuite::begin() {
|
||||
return TestCases.begin();
|
||||
}
|
||||
|
||||
TestSuite::TestCaseVec::iterator TestSuite::end() { return TestCases.end(); }
|
||||
|
||||
TestRegistrar &TestRegistrar::get() {
|
||||
static TestRegistrar TR;
|
||||
return TR;
|
||||
}
|
||||
|
||||
std::vector<TestSuite> TestRegistrar::getTestSuites() {
|
||||
std::vector<TestSuite> TSs;
|
||||
for (auto &[k, v] : Tests)
|
||||
TSs.emplace_back(std::move(v));
|
||||
return TSs;
|
||||
}
|
||||
|
||||
void TestRegistrar::addCaseToSuite(TestCase *TC, std::string TSName) {
|
||||
auto &TS = Tests[TSName];
|
||||
if (TS.Name.empty())
|
||||
TS.Name = TSName;
|
||||
TS.TestCases.emplace_back(TC);
|
||||
}
|
||||
|
||||
Registerer::Registerer(TestCase *TC, const std::string SuiteName) {
|
||||
std::cout << "Adding " << TC->Name << " to " << SuiteName << std::endl;
|
||||
TestRegistrar::get().addCaseToSuite(TC, SuiteName);
|
||||
}
|
||||
|
||||
int Runner::run() {
|
||||
int ErrorCount = 0;
|
||||
for (auto &TS : TestSuites) {
|
||||
std::cout << "\n======\nExecuting for " << TS.Name << std::endl;
|
||||
TS.setup();
|
||||
for (auto &TC : TS) {
|
||||
std::cout << "\nExecuting " << TC->Name << std::endl;
|
||||
if (Error Err = TC->exec()) {
|
||||
reportError(Err);
|
||||
abortOrKeepGoing();
|
||||
++ErrorCount;
|
||||
}
|
||||
}
|
||||
TS.teardown();
|
||||
}
|
||||
printSummary();
|
||||
return ErrorCount;
|
||||
}
|
||||
|
||||
void Runner::reportError(const Error &Err) {}
|
||||
|
||||
void Runner::abortOrKeepGoing() {}
|
||||
|
||||
void Runner::printSummary() {
|
||||
std::cout << "\n====== SUMMARY\n";
|
||||
for (auto &TS : TestSuites) {
|
||||
std::cout << " - " << TS.Name;
|
||||
for (auto &TC : TS) {
|
||||
std::string Result;
|
||||
if (TC->IsDisabled) {
|
||||
Result = "-#-#-";
|
||||
} else if (TC->ResultState == TC->ExpectedState) {
|
||||
if (TC->ResultState == omptest::AssertState::Pass)
|
||||
Result = "PASS";
|
||||
else if (TC->ResultState == omptest::AssertState::Fail)
|
||||
Result = "XFAIL";
|
||||
} else {
|
||||
if (TC->ResultState == omptest::AssertState::Fail)
|
||||
Result = "FAIL";
|
||||
else if (TC->ResultState == omptest::AssertState::Pass)
|
||||
Result = "UPASS";
|
||||
}
|
||||
std::cout << "\n " << std::setw(5) << Result << " : " << TC->Name;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# Add ompTest unit tests to check-openmp.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
# Target: ompTest library unit tests
|
||||
file(GLOB UNITTEST_SOURCES "unittests/*.cpp")
|
||||
add_executable(omptest-unittests ${UNITTEST_SOURCES})
|
||||
|
||||
# Add local and LLVM-provided GoogleTest include directories.
|
||||
target_include_directories(omptest-unittests PRIVATE
|
||||
../include
|
||||
${LLVM_THIRD_PARTY_DIR}/unittest/googletest/include)
|
||||
|
||||
target_link_libraries(omptest-unittests PRIVATE omptest)
|
||||
|
||||
set_target_properties(omptest-unittests PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Add ompTest unit tests to check-openmp
|
||||
add_openmp_testsuite(check-ompt-omptest "Running OMPT ompTest unit tests"
|
||||
${CMAKE_CURRENT_BINARY_DIR} DEPENDS omptest-unittests)
|
||||
|
||||
# Configure the lit.site.cfg.in file
|
||||
set(AUTO_GEN_COMMENT "## Autogenerated by OPENMP_TOOLS_OMPTEST_TEST "
|
||||
"configuration.\n# Do not edit!")
|
||||
configure_file(lit.site.cfg.in lit.site.cfg @ONLY)
|
@ -1,26 +0,0 @@
|
||||
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
||||
# Configuration file for the 'lit' test runner.
|
||||
|
||||
import os
|
||||
import lit.formats
|
||||
|
||||
# Tell pylint that we know config and lit_config exist somewhere.
|
||||
if 'PYLINT_IMPORT' in os.environ:
|
||||
config = object()
|
||||
lit_config = object()
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'OMPT ompTest'
|
||||
|
||||
# suffixes: A list of file extensions to treat as test files.
|
||||
config.suffixes = ['']
|
||||
|
||||
# test_source_root: The root path where tests are located.
|
||||
config.test_source_root = config.test_obj_root
|
||||
|
||||
# test_exec_root: The root object directory where output is placed
|
||||
config.test_exec_root = config.test_obj_root
|
||||
|
||||
# test format, match (omptest-)unittests
|
||||
# Matched binaries (GoogleTests) are executed
|
||||
config.test_format = lit.formats.GoogleTest(".", "unittests")
|
@ -1,9 +0,0 @@
|
||||
@AUTO_GEN_COMMENT@
|
||||
|
||||
config.test_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
|
||||
|
||||
import lit.llvm
|
||||
lit.llvm.initialize(lit_config, config)
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg")
|
@ -1,358 +0,0 @@
|
||||
#include "OmptAliases.h"
|
||||
#include "OmptAsserter.h"
|
||||
#include <omp-tools.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace omptest;
|
||||
using OAE = omptest::OmptAssertEvent;
|
||||
using OS = omptest::ObserveState;
|
||||
|
||||
/// SequencedAsserter test-fixture class to avoid code duplication among tests.
|
||||
class OmptSequencedAsserterTest : public testing::Test {
|
||||
protected:
|
||||
OmptSequencedAsserterTest() {
|
||||
// Construct default sequenced asserter
|
||||
SeqAsserter = std::make_unique<omptest::OmptSequencedAsserter>();
|
||||
|
||||
// Silence all potential log prints
|
||||
SeqAsserter->getLog()->setLoggingLevel(logging::Level::Critical);
|
||||
}
|
||||
|
||||
std::unique_ptr<omptest::OmptSequencedAsserter> SeqAsserter;
|
||||
};
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, DefaultState) {
|
||||
// Assertion should neither start as 'deactivated' nor 'suspended'
|
||||
ASSERT_EQ(SeqAsserter->isActive(), true);
|
||||
ASSERT_EQ(SeqAsserter->AssertionSuspended, false);
|
||||
|
||||
// Assertion should begin with event ID zero
|
||||
ASSERT_EQ(SeqAsserter->NextEvent, 0);
|
||||
|
||||
// Assertion should begin without previous notifications or assertions
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
|
||||
// There should be no expected events
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), true);
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 0);
|
||||
|
||||
// Default mode should be Strict
|
||||
ASSERT_NE(SeqAsserter->getOperationMode(), AssertMode::Relaxed);
|
||||
ASSERT_EQ(SeqAsserter->getOperationMode(), AssertMode::Strict);
|
||||
|
||||
// Default state should be passing
|
||||
ASSERT_NE(SeqAsserter->getState(), AssertState::Fail);
|
||||
ASSERT_EQ(SeqAsserter->getState(), AssertState::Pass);
|
||||
ASSERT_NE(SeqAsserter->checkState(), AssertState::Fail);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, IgnoreNotificationsWhenEmpty) {
|
||||
// ParallelBegin events are suppressed by default
|
||||
auto SuppressedEvent = OAE::ParallelBegin(
|
||||
/*Name=*/"ParBegin", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*NumThreads=*/3);
|
||||
|
||||
// DeviceFinalize events are not ignored by default
|
||||
auto IgnoredEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
|
||||
// Situation: There is nothing to assert.
|
||||
// Result: All notifications are ignored.
|
||||
// Hence, check that the perceived count of notifications remains unchanged
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
|
||||
SeqAsserter->notify(std::move(SuppressedEvent));
|
||||
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
SeqAsserter->notify(std::move(IgnoredEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, IgnoreNotificationsWhileDeactivated) {
|
||||
auto ExpectedEvent = OAE::DeviceUnload(
|
||||
/*Name=*/"DevUnload", /*Group=*/"", /*Expected=*/OS::Always);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), false);
|
||||
|
||||
// Deactivate asserter, effectively ignoring notifications
|
||||
SeqAsserter->setActive(false);
|
||||
ASSERT_EQ(SeqAsserter->isActive(), false);
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
|
||||
// DeviceFinalize events are not ignored by default
|
||||
auto IgnoredEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->notify(std::move(IgnoredEvent));
|
||||
|
||||
// Assertion was deactivated: No change
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
|
||||
SeqAsserter->setActive(true);
|
||||
ASSERT_EQ(SeqAsserter->isActive(), true);
|
||||
|
||||
auto ObservedEvent = OAE::DeviceUnload(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always);
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
|
||||
// Assertion was activated, one notification expected
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, AddEvent) {
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 0);
|
||||
auto ExpectedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
// Sanity check: Notifications should not be triggered
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
// Adding an expected event must change the event count but not the state
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, AddEventIgnoreSuppressed) {
|
||||
auto ExpectedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
// ParallelBegin events are suppressed by default
|
||||
auto SuppressedEvent = OAE::ParallelBegin(
|
||||
/*Name=*/"ParBegin", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*NumThreads=*/3);
|
||||
// Situation: There is one expected event and ParallelBegins are suppressed.
|
||||
// Notification count remains unchanged for suppressed events
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
SeqAsserter->notify(std::move(SuppressedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, AddEventObservePass) {
|
||||
auto ExpectedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
// DeviceFinalize events are not ignored by default
|
||||
auto ObservedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, AddEventObserveFail) {
|
||||
auto ExpectedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
// DeviceFinalize events are not ignored by default
|
||||
// Provide wrong DeviceNum
|
||||
auto ObservedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/23);
|
||||
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
// Observed and expected event do not match: Fail
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Fail);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, AddEventObserveDifferentType) {
|
||||
auto ExpectedEvent = OAE::DeviceUnload(
|
||||
/*Name=*/"DevUnload", /*Group=*/"", /*Expected=*/OS::Always);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
// DeviceFinalize events are not ignored by default
|
||||
auto ObservedEvent = OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7);
|
||||
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
// Observed and expected event do not match: Fail
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Fail);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, CheckTargetGroupNoEffect) {
|
||||
// Situation: Groups are designed to be used as an indicator -WITHIN- target
|
||||
// regions. Hence, comparing two target regions w.r.t. their groups has no
|
||||
// effect on pass or fail.
|
||||
|
||||
auto ExpectedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), false);
|
||||
|
||||
// Deactivate asserter, effectively ignoring notifications
|
||||
SeqAsserter->setActive(false);
|
||||
ASSERT_EQ(SeqAsserter->isActive(), false);
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
|
||||
// Target events are not ignored by default
|
||||
auto ObservedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN, /*DeviceNum=*/7,
|
||||
/*TaskData=*/nullptr, /*TargetId=*/23, /*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
|
||||
// Assertion was deactivated: No change
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 1);
|
||||
|
||||
// Re-activate asserter
|
||||
SeqAsserter->setActive(true);
|
||||
ASSERT_EQ(SeqAsserter->isActive(), true);
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
|
||||
// Actually observe a target event from "AnotherGroup"
|
||||
auto AnotherObservedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"AnotherGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN, /*DeviceNum=*/7,
|
||||
/*TaskData=*/nullptr, /*TargetId=*/23, /*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->notify(std::move(AnotherObservedEvent));
|
||||
|
||||
// Observed all expected events; groups of target regions do not affect pass
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 0);
|
||||
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, CheckSyncPoint) {
|
||||
auto ExpectedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), false);
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 1);
|
||||
|
||||
// Target events are not ignored by default
|
||||
auto ObservedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN, /*DeviceNum=*/7,
|
||||
/*TaskData=*/nullptr, /*TargetId=*/23, /*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
|
||||
SeqAsserter->notify(OAE::AssertionSyncPoint(
|
||||
/*Name=*/"", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*SyncPointName=*/"SyncPoint 1"));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 2);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 1);
|
||||
|
||||
// All events processed: SyncPoint "passes"
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
|
||||
auto AnotherExpectedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr);
|
||||
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 0);
|
||||
SeqAsserter->insert(std::move(AnotherExpectedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 1);
|
||||
|
||||
// Remaining events present: SyncPoint "fails"
|
||||
SeqAsserter->notify(OAE::AssertionSyncPoint(
|
||||
/*Name=*/"", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*SyncPointName=*/"SyncPoint 2"));
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Fail);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, CheckExcessNotify) {
|
||||
auto ExpectedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), false);
|
||||
ASSERT_EQ(SeqAsserter->getRemainingEventCount(), 1);
|
||||
|
||||
// Target events are not ignored by default
|
||||
auto ObservedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN, /*DeviceNum=*/7,
|
||||
/*TaskData=*/nullptr, /*TargetId=*/23, /*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->notify(std::move(ObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
|
||||
// All events processed: pass
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
|
||||
// Target events are not ignored by default
|
||||
auto AnotherObservedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN, /*DeviceNum=*/7,
|
||||
/*TaskData=*/nullptr, /*TargetId=*/23, /*CodeptrRA=*/nullptr);
|
||||
|
||||
// No more events expected: notify "fails"
|
||||
SeqAsserter->notify(std::move(AnotherObservedEvent));
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 2);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Fail);
|
||||
}
|
||||
|
||||
TEST_F(OmptSequencedAsserterTest, CheckSuspend) {
|
||||
SeqAsserter->insert(OAE::AssertionSuspend(
|
||||
/*Name=*/"", /*Group=*/"", /*Expected=*/OS::Never));
|
||||
ASSERT_EQ(SeqAsserter->Events.empty(), false);
|
||||
|
||||
// Being notified while the next expected event is a "suspend" should change
|
||||
// the asserter's state
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->AssertionSuspended, false);
|
||||
SeqAsserter->notify(OAE::DeviceFinalize(
|
||||
/*Name=*/"DevFini", /*Group=*/"", /*Expected=*/OS::Always,
|
||||
/*DeviceNum=*/7));
|
||||
ASSERT_EQ(SeqAsserter->AssertionSuspended, true);
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 1);
|
||||
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 0);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
|
||||
auto ExpectedEvent = OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr);
|
||||
SeqAsserter->insert(std::move(ExpectedEvent));
|
||||
|
||||
// Being notified with an observed event, which matches the next expected
|
||||
// event, resumes assertion (suspended = false)
|
||||
ASSERT_EQ(SeqAsserter->AssertionSuspended, true);
|
||||
SeqAsserter->notify(OAE::Target(
|
||||
/*Name=*/"Target", /*Group=*/"MyTargetGroup", /*Expected=*/OS::Always,
|
||||
/*Kind=*/TARGET, /*Endpoint=*/BEGIN,
|
||||
/*DeviceNum=*/7, /*TaskData=*/nullptr, /*TargetId=*/23,
|
||||
/*CodeptrRA=*/nullptr));
|
||||
ASSERT_EQ(SeqAsserter->AssertionSuspended, false);
|
||||
|
||||
ASSERT_EQ(SeqAsserter->getNotificationCount(), 2);
|
||||
ASSERT_EQ(SeqAsserter->getSuccessfulAssertionCount(), 1);
|
||||
ASSERT_EQ(SeqAsserter->checkState(), AssertState::Pass);
|
||||
}
|
@ -1,530 +0,0 @@
|
||||
#include "InternalEvent.h"
|
||||
#include <omp-tools.h>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace omptest;
|
||||
|
||||
TEST(InternalEvent_toString, AssertionSyncPoint) {
|
||||
internal::AssertionSyncPoint SP{/*Name=*/"Test Sync Point"};
|
||||
|
||||
EXPECT_EQ(SP.toString(), "Assertion SyncPoint: 'Test Sync Point'");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, ThreadBegin) {
|
||||
internal::ThreadBegin TB{/*ThreadType=*/ompt_thread_t::ompt_thread_initial};
|
||||
|
||||
EXPECT_EQ(TB.toString(), "OMPT Callback ThreadBegin: ThreadType=1");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, ThreadEnd) {
|
||||
internal::ThreadEnd TE{};
|
||||
|
||||
EXPECT_EQ(TE.toString(), "OMPT Callback ThreadEnd");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, ParallelBegin) {
|
||||
internal::ParallelBegin PB{/*NumThreads=*/31};
|
||||
|
||||
EXPECT_EQ(PB.toString(), "OMPT Callback ParallelBegin: NumThreads=31");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, ParallelEnd) {
|
||||
internal::ParallelEnd PE{/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*EncounteringTaskData=*/(ompt_data_t *)0x22,
|
||||
/*Flags=*/31,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
EXPECT_EQ(PE.toString(), "OMPT Callback ParallelEnd");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, Work) {
|
||||
internal::Work WK{/*WorkType=*/ompt_work_t::ompt_work_loop_dynamic,
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_beginend,
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Count=*/31,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
EXPECT_EQ(WK.toString(),
|
||||
"OMPT Callback Work: work_type=11 endpoint=3 parallel_data=0x11 "
|
||||
"task_data=0x22 count=31 codeptr=0x33");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, Dispatch_iteration) {
|
||||
ompt_data_t DI{.value = 31};
|
||||
internal::Dispatch D{/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_iteration,
|
||||
/*Instance=*/DI};
|
||||
|
||||
EXPECT_EQ(D.toString(), "OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=1 instance=[it=31]");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, Dispatch_section) {
|
||||
ompt_data_t DI{.ptr = (void *)0x33};
|
||||
internal::Dispatch D{/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_section,
|
||||
/*Instance=*/DI};
|
||||
|
||||
EXPECT_EQ(D.toString(), "OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=2 instance=[ptr=0x33]");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, Dispatch_chunks) {
|
||||
ompt_dispatch_chunk_t DC{.start = 7, .iterations = 31};
|
||||
ompt_data_t DI{.ptr = (void *)&DC};
|
||||
|
||||
internal::Dispatch DLoop{
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_ws_loop_chunk,
|
||||
/*Instance=*/DI};
|
||||
|
||||
internal::Dispatch DTask{
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_taskloop_chunk,
|
||||
/*Instance=*/DI};
|
||||
|
||||
internal::Dispatch DDist{
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_distribute_chunk,
|
||||
/*Instance=*/DI};
|
||||
|
||||
ompt_data_t DINull{.ptr = nullptr};
|
||||
internal::Dispatch DDistNull{
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*Kind=*/ompt_dispatch_t::ompt_dispatch_distribute_chunk,
|
||||
/*Instance=*/DINull};
|
||||
|
||||
EXPECT_EQ(DLoop.toString(),
|
||||
"OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=3 instance=[chunk=(start=7, iterations=31)]");
|
||||
|
||||
EXPECT_EQ(DTask.toString(),
|
||||
"OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=4 instance=[chunk=(start=7, iterations=31)]");
|
||||
|
||||
EXPECT_EQ(DDist.toString(),
|
||||
"OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=5 instance=[chunk=(start=7, iterations=31)]");
|
||||
|
||||
EXPECT_EQ(DDistNull.toString(), "OMPT Callback Dispatch: parallel_data=0x11 "
|
||||
"task_data=0x22 kind=5");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TaskCreate) {
|
||||
internal::TaskCreate TC{/*EncounteringTaskData=*/(ompt_data_t *)0x11,
|
||||
/*EncounteringTaskFrame=*/(const ompt_frame_t *)0x22,
|
||||
/*NewTaskData=*/(ompt_data_t *)0x33,
|
||||
/*Flags=*/7,
|
||||
/*HasDependences=*/31,
|
||||
/*CodeptrRA=*/(const void *)0x44};
|
||||
|
||||
EXPECT_EQ(TC.toString(),
|
||||
"OMPT Callback TaskCreate: encountering_task_data=0x11 "
|
||||
"encountering_task_frame=0x22 new_task_data=0x33 flags=7 "
|
||||
"has_dependences=31 codeptr=0x44");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, ImplicitTask) {
|
||||
internal::ImplicitTask IT{
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*ActualParallelism=*/7,
|
||||
/*Index=*/31,
|
||||
/*Flags=*/127};
|
||||
|
||||
EXPECT_EQ(IT.toString(),
|
||||
"OMPT Callback ImplicitTask: endpoint=1 parallel_data=0x11 "
|
||||
"task_data=0x22 actual_parallelism=7 index=31 flags=127");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, SyncRegion) {
|
||||
internal::SyncRegion SR{
|
||||
/*Kind=*/ompt_sync_region_t::ompt_sync_region_taskwait,
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_end,
|
||||
/*ParallelData=*/(ompt_data_t *)0x11,
|
||||
/*TaskData=*/(ompt_data_t *)0x22,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
EXPECT_EQ(SR.toString(), "OMPT Callback SyncRegion: kind=5 endpoint=2 "
|
||||
"parallel_data=0x11 task_data=0x22 codeptr=0x33");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, Target) {
|
||||
internal::Target T{/*Kind=*/ompt_target_t::ompt_target_enter_data_nowait,
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_end,
|
||||
/*DeviceNum=*/7,
|
||||
/*TaskData=*/(ompt_data_t *)0x11,
|
||||
/*TargetId=*/(ompt_id_t)31,
|
||||
/*CodeptrRA=*/(const void *)0x22};
|
||||
|
||||
EXPECT_EQ(T.toString(), "Callback Target: target_id=31 kind=10 "
|
||||
"endpoint=2 device_num=7 code=0x22");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TargetEmi) {
|
||||
ompt_data_t TaskData{.value = 31};
|
||||
ompt_data_t TargetTaskData{.value = 127};
|
||||
ompt_data_t TargetData{.value = 8191};
|
||||
|
||||
internal::TargetEmi T{/*Kind=*/ompt_target_t::ompt_target_update,
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*DeviceNum=*/7,
|
||||
/*TaskData=*/(ompt_data_t *)&TaskData,
|
||||
/*TargetTaskData=*/(ompt_data_t *)&TargetTaskData,
|
||||
/*TargetData=*/(ompt_data_t *)&TargetData,
|
||||
/*CodeptrRA=*/(const void *)0x11};
|
||||
|
||||
internal::TargetEmi TDataNull{
|
||||
/*Kind=*/ompt_target_t::ompt_target_update,
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*DeviceNum=*/7,
|
||||
/*TaskData=*/(ompt_data_t *)&TaskData,
|
||||
/*TargetTaskData=*/(ompt_data_t *)nullptr,
|
||||
/*TargetData=*/(ompt_data_t *)&TargetData,
|
||||
/*CodeptrRA=*/(const void *)0x11};
|
||||
|
||||
std::ostringstream StreamT1;
|
||||
std::ostringstream StreamT2;
|
||||
std::string CallBackPrefix{
|
||||
"Callback Target EMI: kind=4 endpoint=1 device_num=7"};
|
||||
StreamT1 << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamT1 << " task_data=" << &TaskData << " (0x1f)";
|
||||
StreamT1 << " target_task_data=" << &TargetTaskData << " (0x7f)";
|
||||
StreamT1 << " target_data=" << &TargetData << " (0x1fff)";
|
||||
StreamT1 << " code=0x11";
|
||||
|
||||
StreamT2 << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamT2 << " task_data=" << &TaskData << " (0x1f)";
|
||||
StreamT2 << " target_task_data=(nil) (0x0)";
|
||||
StreamT2 << " target_data=" << &TargetData << " (0x1fff)";
|
||||
StreamT2 << " code=0x11";
|
||||
|
||||
EXPECT_EQ(T.toString(), StreamT1.str());
|
||||
EXPECT_EQ(TDataNull.toString(), StreamT2.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TargetDataOp) {
|
||||
internal::TargetDataOp TDO{
|
||||
/*TargetId=*/7,
|
||||
/*HostOpId=*/31,
|
||||
/*OpType=*/ompt_target_data_op_t::ompt_target_data_associate,
|
||||
/*SrcAddr=*/(void *)0x11,
|
||||
/*SrcDeviceNum=*/127,
|
||||
/*DstAddr=*/(void *)0x22,
|
||||
/*DstDeviceNum=*/8191,
|
||||
/*Bytes=*/4096,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
EXPECT_EQ(
|
||||
TDO.toString(),
|
||||
" Callback DataOp: target_id=7 host_op_id=31 optype=5 src=0x11 "
|
||||
"src_device_num=127 dest=0x22 dest_device_num=8191 bytes=4096 code=0x33");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TargetDataOpEmi) {
|
||||
ompt_data_t TargetTaskData{.value = 31};
|
||||
ompt_data_t TargetData{.value = 127};
|
||||
ompt_id_t HostOpId = 8191;
|
||||
|
||||
internal::TargetDataOpEmi TDO{
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*TargetTaskData=*/(ompt_data_t *)&TargetTaskData,
|
||||
/*TargetData=*/(ompt_data_t *)&TargetData,
|
||||
/*HostOpId=*/(ompt_id_t *)&HostOpId,
|
||||
/*OpType=*/ompt_target_data_op_t::ompt_target_data_disassociate,
|
||||
/*SrcAddr=*/(void *)0x11,
|
||||
/*SrcDeviceNum=*/1,
|
||||
/*DstAddr=*/(void *)0x22,
|
||||
/*DstDeviceNum=*/2,
|
||||
/*Bytes=*/4096,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
// Set HostOpId=nullptr
|
||||
internal::TargetDataOpEmi TDO_HostOpIdNull{
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*TargetTaskData=*/(ompt_data_t *)&TargetTaskData,
|
||||
/*TargetData=*/(ompt_data_t *)&TargetData,
|
||||
/*HostOpId=*/(ompt_id_t *)nullptr,
|
||||
/*OpType=*/ompt_target_data_op_t::ompt_target_data_disassociate,
|
||||
/*SrcAddr=*/(void *)0x11,
|
||||
/*SrcDeviceNum=*/1,
|
||||
/*DstAddr=*/(void *)0x22,
|
||||
/*DstDeviceNum=*/2,
|
||||
/*Bytes=*/4096,
|
||||
/*CodeptrRA=*/(const void *)0x33};
|
||||
|
||||
std::ostringstream StreamTDO1;
|
||||
std::ostringstream StreamTDO2;
|
||||
std::string CallBackPrefix{" Callback DataOp EMI: endpoint=1 optype=6"};
|
||||
std::string CallBackSuffix{
|
||||
" src=0x11 src_device_num=1 dest=0x22 dest_device_num=2 "
|
||||
"bytes=4096 code=0x33"};
|
||||
StreamTDO1 << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamTDO1 << " target_task_data=" << &TargetTaskData << " (0x1f)";
|
||||
StreamTDO1 << " target_data=" << &TargetData << " (0x7f)";
|
||||
StreamTDO1 << " host_op_id=" << &HostOpId << " (0x1fff)";
|
||||
StreamTDO1 << CallBackSuffix;
|
||||
|
||||
StreamTDO2 << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamTDO2 << " target_task_data=" << &TargetTaskData << " (0x1f)";
|
||||
StreamTDO2 << " target_data=" << &TargetData << " (0x7f)";
|
||||
StreamTDO2 << " host_op_id=(nil) (0x0)";
|
||||
StreamTDO2 << CallBackSuffix;
|
||||
|
||||
EXPECT_EQ(TDO.toString(), StreamTDO1.str());
|
||||
EXPECT_EQ(TDO_HostOpIdNull.toString(), StreamTDO2.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TargetSubmit) {
|
||||
internal::TargetSubmit TS{/*TargetId=*/7,
|
||||
/*HostOpId=*/31,
|
||||
/*RequestedNumTeams=*/127};
|
||||
|
||||
EXPECT_EQ(TS.toString(),
|
||||
" Callback Submit: target_id=7 host_op_id=31 req_num_teams=127");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, TargetSubmitEmi) {
|
||||
ompt_data_t TargetData{.value = 127};
|
||||
ompt_id_t HostOpId = 8191;
|
||||
internal::TargetSubmitEmi TS{
|
||||
/*Endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*TargetData=*/(ompt_data_t *)&TargetData,
|
||||
/*HostOpId=*/(ompt_id_t *)&HostOpId,
|
||||
/*RequestedNumTeams=*/7};
|
||||
|
||||
std::ostringstream StreamTS;
|
||||
std::string CallBackPrefix{
|
||||
" Callback Submit EMI: endpoint=1 req_num_teams=7"};
|
||||
StreamTS << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamTS << " target_data=" << &TargetData << " (0x7f)";
|
||||
StreamTS << " host_op_id=" << &HostOpId << " (0x1fff)";
|
||||
|
||||
EXPECT_EQ(TS.toString(), StreamTS.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, DeviceInitialize) {
|
||||
const char *Type = "DeviceType";
|
||||
const char *DocStr = "DocumentationString";
|
||||
|
||||
internal::DeviceInitialize DI{/*DeviceNum=*/7,
|
||||
/*Type=*/Type,
|
||||
/*Device=*/(ompt_device_t *)0x11,
|
||||
/*LookupFn=*/(ompt_function_lookup_t)0x22,
|
||||
/*DocStr=*/DocStr};
|
||||
|
||||
internal::DeviceInitialize DINull{/*DeviceNum=*/0,
|
||||
/*Type=*/nullptr,
|
||||
/*Device=*/nullptr,
|
||||
/*LookupFn=*/(ompt_function_lookup_t)0x0,
|
||||
/*DocStr=*/nullptr};
|
||||
|
||||
std::ostringstream StreamDI;
|
||||
std::string CallBackPrefix{"Callback Init: device_num=7 type=DeviceType "
|
||||
"device=0x11 lookup=0x22 doc="};
|
||||
StreamDI << CallBackPrefix << std::showbase << std::hex;
|
||||
StreamDI << (uint64_t)DocStr;
|
||||
EXPECT_EQ(DI.toString(), StreamDI.str());
|
||||
|
||||
// TODO This looks inconsistent: (null) vs. (nil)
|
||||
EXPECT_EQ(DINull.toString(), "Callback Init: device_num=0 type=(null) "
|
||||
"device=(nil) lookup=(nil) doc=(nil)");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, DeviceFinalize) {
|
||||
internal::DeviceFinalize DF{/*DeviceNum=*/7};
|
||||
|
||||
EXPECT_EQ(DF.toString(), "Callback Fini: device_num=7");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, DeviceLoad) {
|
||||
const char *Filename = "FilenameToLoad";
|
||||
|
||||
internal::DeviceLoad DL{/*DeviceNum=*/7,
|
||||
/*Filename=*/Filename,
|
||||
/*OffsetInFile=*/31,
|
||||
/*VmaInFile=*/(void *)0x11,
|
||||
/*Bytes=*/127,
|
||||
/*HostAddr=*/(void *)0x22,
|
||||
/*DeviceAddr=*/(void *)0x33,
|
||||
/*ModuleId=*/8191};
|
||||
|
||||
internal::DeviceLoad DLNull{/*DeviceNum=*/0,
|
||||
/*Filename=*/nullptr,
|
||||
/*OffsetInFile=*/0,
|
||||
/*VmaInFile=*/nullptr,
|
||||
/*Bytes=*/0,
|
||||
/*HostAddr=*/nullptr,
|
||||
/*DeviceAddr=*/nullptr,
|
||||
/*ModuleId=*/0};
|
||||
|
||||
EXPECT_EQ(
|
||||
DL.toString(),
|
||||
"Callback Load: device_num:7 module_id:8191 "
|
||||
"filename:FilenameToLoad host_addr:0x22 device_addr:0x33 bytes:127");
|
||||
|
||||
// TODO This looks inconsistent: (null) vs. (nil) and ':' instead of '='
|
||||
EXPECT_EQ(DLNull.toString(),
|
||||
"Callback Load: device_num:0 module_id:0 filename:(null) "
|
||||
"host_addr:(nil) device_addr:(nil) bytes:0");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRequest) {
|
||||
size_t Bytes = 7;
|
||||
ompt_buffer_t *Buffer = (void *)0x11;
|
||||
|
||||
internal::BufferRequest BR{/*DeviceNum=*/31,
|
||||
/*Buffer=*/&Buffer,
|
||||
/*Bytes=*/&Bytes};
|
||||
|
||||
internal::BufferRequest BRNull{/*DeviceNum=*/127,
|
||||
/*Buffer=*/nullptr,
|
||||
/*Bytes=*/nullptr};
|
||||
|
||||
EXPECT_EQ(BR.toString(),
|
||||
"Allocated 7 bytes at 0x11 in buffer request callback");
|
||||
EXPECT_EQ(BRNull.toString(),
|
||||
"Allocated 0 bytes at (nil) in buffer request callback");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferComplete) {
|
||||
ompt_buffer_t *Buffer = (void *)0x11;
|
||||
|
||||
internal::BufferComplete BC{/*DeviceNum=*/7,
|
||||
/*Buffer=*/Buffer,
|
||||
/*Bytes=*/127,
|
||||
/*Begin=*/8191,
|
||||
/*BufferOwned=*/1};
|
||||
|
||||
internal::BufferComplete BCNull{/*DeviceNum=*/0,
|
||||
/*Buffer=*/nullptr,
|
||||
/*Bytes=*/0,
|
||||
/*Begin=*/0,
|
||||
/*BufferOwned=*/0};
|
||||
|
||||
EXPECT_EQ(BC.toString(),
|
||||
"Executing buffer complete callback: 7 0x11 127 0x1fff 1");
|
||||
EXPECT_EQ(BCNull.toString(),
|
||||
"Executing buffer complete callback: 0 (nil) 0 (nil) 0");
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRecordInvalid) {
|
||||
ompt_record_ompt_t InvalidRecord{
|
||||
/*type=*/ompt_callbacks_t::ompt_callback_parallel_begin,
|
||||
/*time=*/7,
|
||||
/*thread_id=*/31,
|
||||
/*target_id=*/127,
|
||||
/*record=*/{.parallel_begin = {}}};
|
||||
|
||||
internal::BufferRecord BRNull{/*RecordPtr=*/nullptr};
|
||||
internal::BufferRecord BRInvalid{/*RecordPtr=*/&InvalidRecord};
|
||||
|
||||
std::ostringstream StreamBRInvalid;
|
||||
StreamBRInvalid << "rec=" << std::showbase << std::hex << &InvalidRecord;
|
||||
StreamBRInvalid << " type=3 (unsupported record type)";
|
||||
|
||||
EXPECT_EQ(BRNull.toString(), "rec=(nil) type=0 (unsupported record type)");
|
||||
EXPECT_EQ(BRInvalid.toString(), StreamBRInvalid.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRecordTarget) {
|
||||
ompt_record_target_t SubRecordTarget{
|
||||
/*kind=*/ompt_target_t::ompt_target_update,
|
||||
/*endpoint=*/ompt_scope_endpoint_t::ompt_scope_begin,
|
||||
/*device_num=*/2,
|
||||
/*task_id=*/127,
|
||||
/*target_id=*/31,
|
||||
/*codeptr_ra=*/(const void *)0x11};
|
||||
|
||||
ompt_record_ompt_t TargetRecord{
|
||||
/*type=*/ompt_callbacks_t::ompt_callback_target,
|
||||
/*time=*/7,
|
||||
/*thread_id=*/29,
|
||||
/*target_id=*/31,
|
||||
/*record*/ {.target = SubRecordTarget}};
|
||||
|
||||
internal::BufferRecord BR{/*RecordPtr=*/&TargetRecord};
|
||||
|
||||
std::ostringstream StreamBR;
|
||||
StreamBR << "rec=" << std::showbase << std::hex << &TargetRecord;
|
||||
StreamBR << " type=8 (Target task) time=7 thread_id=29 target_id=31 kind=4";
|
||||
StreamBR << " endpoint=1 device=2 task_id=127 codeptr=0x11";
|
||||
|
||||
EXPECT_EQ(BR.toString(), StreamBR.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRecordDataOp) {
|
||||
ompt_record_target_data_op_t SubRecordTargetDataOp{
|
||||
/*host_op_id=*/7,
|
||||
/*optype=*/ompt_target_data_op_t::ompt_target_data_alloc_async,
|
||||
/*src_addr=*/(void *)0x11,
|
||||
/*src_device_num=*/1,
|
||||
/*dest_addr=*/(void *)0x22,
|
||||
/*dest_device_num=*/2,
|
||||
/*bytes=*/127,
|
||||
/*end_time=*/128,
|
||||
/*codeptr_ra=*/(const void *)0x33,
|
||||
};
|
||||
|
||||
ompt_record_ompt_t DataOpRecord{
|
||||
/*type=*/ompt_callbacks_t::ompt_callback_target_data_op_emi,
|
||||
/*time=*/8,
|
||||
/*thread_id=*/3,
|
||||
/*target_id=*/5,
|
||||
/*record=*/{.target_data_op = SubRecordTargetDataOp}};
|
||||
|
||||
internal::BufferRecord BR{/*RecordPtr=*/&DataOpRecord};
|
||||
|
||||
std::ostringstream StreamBR;
|
||||
StreamBR << "rec=" << std::showbase << std::hex << &DataOpRecord;
|
||||
StreamBR << " type=34 (Target data op) time=8 thread_id=3 target_id=5";
|
||||
StreamBR << " host_op_id=7 optype=17 src_addr=0x11 src_device=1";
|
||||
StreamBR << " dest_addr=0x22 dest_device=2 bytes=127 end_time=128";
|
||||
StreamBR << " duration=120 ns codeptr=0x33";
|
||||
|
||||
EXPECT_EQ(BR.toString(), StreamBR.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRecordKernel) {
|
||||
ompt_record_target_kernel_t SubRecordTargetKernel{
|
||||
/*host_op_id=*/11,
|
||||
/*requested_num_teams=*/127,
|
||||
/*granted_num_teams=*/63,
|
||||
/*end_time=*/8191,
|
||||
};
|
||||
|
||||
ompt_record_ompt_t KernelRecord{
|
||||
/*type=*/ompt_callbacks_t::ompt_callback_target_submit_emi,
|
||||
/*time=*/9,
|
||||
/*thread_id=*/19,
|
||||
/*target_id=*/33,
|
||||
/*record=*/{.target_kernel = SubRecordTargetKernel}};
|
||||
|
||||
internal::BufferRecord BR{/*RecordPtr=*/&KernelRecord};
|
||||
|
||||
std::ostringstream StreamBR;
|
||||
StreamBR << "rec=" << std::showbase << std::hex << &KernelRecord;
|
||||
StreamBR << " type=35 (Target kernel) time=9 thread_id=19 target_id=33";
|
||||
StreamBR << " host_op_id=11 requested_num_teams=127 granted_num_teams=63";
|
||||
StreamBR << " end_time=8191 duration=8182 ns";
|
||||
|
||||
EXPECT_EQ(BR.toString(), StreamBR.str());
|
||||
}
|
||||
|
||||
TEST(InternalEvent_toString, BufferRecordDeallocation) {
|
||||
internal::BufferRecordDeallocation BRD{/*Buffer=*/(ompt_record_ompt_t *)0x11};
|
||||
internal::BufferRecordDeallocation BRDNull{/*Buffer=*/nullptr};
|
||||
|
||||
EXPECT_EQ(BRD.toString(), "Deallocated 0x11");
|
||||
EXPECT_EQ(BRDNull.toString(), "Deallocated (nil)");
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
#include "InternalEvent.h"
|
||||
#include <omp-tools.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace omptest;
|
||||
using namespace util;
|
||||
|
||||
TEST(InternalUtility, ExpectedDefault_Integer) {
|
||||
// int: -2147483648 (decimal) = 0x80000000 (hexadecimal)
|
||||
EXPECT_EQ(expectedDefault(int), 0x80000000);
|
||||
EXPECT_EQ(expectedDefault(int), (0x1 << 31));
|
||||
// int64_t: -9223372036854775808 (decimal) = 0x8000000000000000 (hexadecimal)
|
||||
EXPECT_EQ(expectedDefault(int64_t), 0x8000000000000000);
|
||||
EXPECT_EQ(expectedDefault(int64_t), (0x1L << 63));
|
||||
}
|
||||
|
||||
TEST(InternalUtility, ExpectedDefault_Zero) {
|
||||
// Expectedly zero
|
||||
EXPECT_EQ(expectedDefault(size_t), 0);
|
||||
EXPECT_EQ(expectedDefault(unsigned int), 0);
|
||||
EXPECT_EQ(expectedDefault(ompt_id_t), 0);
|
||||
EXPECT_EQ(expectedDefault(ompt_dispatch_t), 0);
|
||||
EXPECT_EQ(expectedDefault(ompt_device_time_t), 0);
|
||||
}
|
||||
|
||||
TEST(InternalUtility, ExpectedDefault_Nullpointer) {
|
||||
// Expectedly nullptr
|
||||
EXPECT_EQ(expectedDefault(const char *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(const void *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(int *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(void *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(ompt_data_t *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(ompt_device_t *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(ompt_frame_t *), nullptr);
|
||||
EXPECT_EQ(expectedDefault(ompt_function_lookup_t), nullptr);
|
||||
EXPECT_EQ(expectedDefault(ompt_id_t *), nullptr);
|
||||
}
|
||||
|
||||
TEST(InternalUtility, MakeHexString_PointerValues) {
|
||||
// IsPointer should only affect zero value
|
||||
EXPECT_EQ(makeHexString(0, /*IsPointer=*/true), "(nil)");
|
||||
EXPECT_EQ(makeHexString(0, /*IsPointer=*/false), "0x0");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true), "0xff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/false), "0xff");
|
||||
}
|
||||
|
||||
TEST(InternalUtility, MakeHexString_MinimumBytes) {
|
||||
// Return a minimum length, based on the (minimum) requested bytes
|
||||
EXPECT_EQ(makeHexString(15, /*IsPointer=*/true, /*MinBytes=*/0), "0xf");
|
||||
EXPECT_EQ(makeHexString(15, /*IsPointer=*/true, /*MinBytes=*/1), "0x0f");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/0), "0xff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/1), "0xff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/2), "0x00ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/3), "0x0000ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/4),
|
||||
"0x000000ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/5),
|
||||
"0x00000000ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/6),
|
||||
"0x0000000000ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/7),
|
||||
"0x000000000000ff");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/8),
|
||||
"0x00000000000000ff");
|
||||
|
||||
// Default to four bytes, if request exceeds eight byte range
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true, /*MinBytes=*/9),
|
||||
"0x000000ff");
|
||||
|
||||
// Disregard requested minimum byte width, if actual value exceeds it
|
||||
EXPECT_EQ(makeHexString(1024, /*IsPointer=*/true, /*MinBytes=*/1), "0x400");
|
||||
}
|
||||
|
||||
TEST(InternalUtility, MakeHexString_HexBase) {
|
||||
// Cut off "0x" when requested
|
||||
EXPECT_EQ(makeHexString(0, /*IsPointer=*/true, /*MinBytes=*/0,
|
||||
/*ShowHexBase=*/false),
|
||||
"(nil)");
|
||||
EXPECT_EQ(makeHexString(0, /*IsPointer=*/false, /*MinBytes=*/0,
|
||||
/*ShowHexBase=*/false),
|
||||
"0");
|
||||
EXPECT_EQ(makeHexString(0, /*IsPointer=*/false, /*MinBytes=*/1,
|
||||
/*ShowHexBase=*/false),
|
||||
"00");
|
||||
EXPECT_EQ(makeHexString(255, /*IsPointer=*/true,
|
||||
/*MinBytes=*/2,
|
||||
/*ShowHexBase=*/false),
|
||||
"00ff");
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
#include "OmptAssertEvent.h"
|
||||
#include "OmptAsserter.h"
|
||||
#include "OmptTester.h"
|
||||
#include <omp-tools.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using OS = omptest::ObserveState;
|
||||
using OAE = omptest::OmptAssertEvent;
|
||||
|
||||
TEST(CompareOperatorTests, ThreadBeginIdentity) {
|
||||
auto TBInitial =
|
||||
OAE::ThreadBegin("dflt", "", OS::Always, ompt_thread_initial);
|
||||
auto TBWorker = OAE::ThreadBegin("dflt", "", OS::Always, ompt_thread_worker);
|
||||
auto TBOther = OAE::ThreadBegin("dflt", "", OS::Always, ompt_thread_other);
|
||||
auto TBUnknown =
|
||||
OAE::ThreadBegin("dflt", "", OS::Always, ompt_thread_unknown);
|
||||
|
||||
ASSERT_EQ(TBInitial, TBInitial);
|
||||
ASSERT_EQ(TBWorker, TBWorker);
|
||||
ASSERT_EQ(TBOther, TBOther);
|
||||
ASSERT_EQ(TBUnknown, TBUnknown);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, ThreadEndIdentity) {
|
||||
auto TE = OAE::ThreadEnd("dflt", "", OS::Always);
|
||||
|
||||
ASSERT_EQ(TE, TE);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, ParallelBeginIdentity) {
|
||||
auto PBNumT = OAE::ParallelBegin("thrdenable", "", OS::Always, 3);
|
||||
|
||||
ASSERT_EQ(PBNumT, PBNumT);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, ParallelEndIdentity) {
|
||||
auto PEDflt = OAE::ParallelEnd("dflt", "", OS::Always);
|
||||
// TODO: Add cases with parallel data set, task data set, flags
|
||||
|
||||
ASSERT_EQ(PEDflt, PEDflt);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, WorkIdentity) {
|
||||
auto WDLoopBgn =
|
||||
OAE::Work("loopbgn", "", OS::Always, ompt_work_loop, ompt_scope_begin);
|
||||
auto WDLoopEnd =
|
||||
OAE::Work("loopend", "", OS::Always, ompt_work_loop, ompt_scope_end);
|
||||
|
||||
ASSERT_EQ(WDLoopBgn, WDLoopBgn);
|
||||
ASSERT_EQ(WDLoopEnd, WDLoopEnd);
|
||||
|
||||
auto WDSectionsBgn = OAE::Work("sectionsbgn", "", OS::Always,
|
||||
ompt_work_sections, ompt_scope_begin);
|
||||
auto WDSectionsEnd = OAE::Work("sectionsend", "", OS::Always,
|
||||
ompt_work_sections, ompt_scope_end);
|
||||
|
||||
// TODO: singleexecutor, single_other, workshare, distribute, taskloop, scope,
|
||||
// loop_static, loop_dynamic, loop_guided, loop_other
|
||||
|
||||
ASSERT_EQ(WDSectionsBgn, WDSectionsBgn);
|
||||
ASSERT_EQ(WDSectionsEnd, WDSectionsEnd);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, DispatchIdentity) {
|
||||
auto DIDflt = OAE::Dispatch("dflt", "", OS::Always);
|
||||
|
||||
ASSERT_EQ(DIDflt, DIDflt);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, TaskCreateIdentity) {
|
||||
auto TCDflt = OAE::TaskCreate("dflt", "", OS::Always);
|
||||
|
||||
ASSERT_EQ(TCDflt, TCDflt);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, TaskScheduleIdentity) {
|
||||
auto TS = OAE::TaskSchedule("dflt", "", OS::Always);
|
||||
|
||||
ASSERT_EQ(TS, TS);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, ImplicitTaskIdentity) {
|
||||
auto ITDfltBgn =
|
||||
OAE::ImplicitTask("dfltbgn", "", OS::Always, ompt_scope_begin);
|
||||
auto ITDfltEnd = OAE::ImplicitTask("dfltend", "", OS::Always, ompt_scope_end);
|
||||
|
||||
ASSERT_EQ(ITDfltBgn, ITDfltBgn);
|
||||
ASSERT_EQ(ITDfltEnd, ITDfltEnd);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, SyncRegionIdentity) {
|
||||
auto SRDfltBgn =
|
||||
OAE::SyncRegion("srdfltbgn", "", OS::Always,
|
||||
ompt_sync_region_barrier_explicit, ompt_scope_begin);
|
||||
auto SRDfltEnd =
|
||||
OAE::SyncRegion("srdfltend", "", OS::Always,
|
||||
ompt_sync_region_barrier_explicit, ompt_scope_end);
|
||||
|
||||
ASSERT_EQ(SRDfltBgn, SRDfltBgn);
|
||||
ASSERT_EQ(SRDfltEnd, SRDfltEnd);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, TargetIdentity) {
|
||||
auto TargetDfltBgn =
|
||||
OAE::Target("dfltbgn", "", OS::Always, ompt_target, ompt_scope_begin);
|
||||
auto TargetDfltEnd =
|
||||
OAE::Target("dfltend", "", OS::Always, ompt_target, ompt_scope_end);
|
||||
|
||||
ASSERT_EQ(TargetDfltBgn, TargetDfltBgn);
|
||||
ASSERT_EQ(TargetDfltEnd, TargetDfltEnd);
|
||||
|
||||
auto TargetDevBgn = OAE::Target("tgtdevbgn", "", OS::Always, ompt_target,
|
||||
ompt_scope_begin, 1);
|
||||
auto TargetDevEnd =
|
||||
OAE::Target("tgtdevend", "", OS::Always, ompt_target, ompt_scope_end, 1);
|
||||
|
||||
ASSERT_EQ(TargetDevBgn, TargetDevBgn);
|
||||
ASSERT_EQ(TargetDevEnd, TargetDevEnd);
|
||||
}
|
||||
|
||||
TEST(CompareOperatorTests, BufferRecordIdentity) {
|
||||
// Default, no time limit or anything
|
||||
auto BRDflt =
|
||||
OAE::BufferRecord("dflt", "", OS::Always, ompt_callback_target_submit);
|
||||
|
||||
// Minimum time set, no max time
|
||||
auto BRMinSet = OAE::BufferRecord("minset", "", OS::Always,
|
||||
ompt_callback_target_submit, 10);
|
||||
|
||||
// Minimum time and maximum time set
|
||||
auto BRMinMaxSet = OAE::BufferRecord("minmaxset", "", OS::Always,
|
||||
ompt_callback_target_submit, {10, 100});
|
||||
|
||||
ASSERT_EQ(BRDflt, BRDflt);
|
||||
ASSERT_EQ(BRMinSet, BRMinSet);
|
||||
ASSERT_EQ(BRMinMaxSet, BRMinMaxSet);
|
||||
}
|
||||
|
||||
// Add main definition
|
||||
OMPTEST_TESTSUITE_MAIN()
|
@ -1,13 +1,10 @@
|
||||
set(ORC_RT_HEADERS
|
||||
orc-rt-c/ExternC.h
|
||||
orc-rt-c/WrapperFunctionResult.h
|
||||
orc-rt-c/orc-rt.h
|
||||
orc-rt/BitmaskEnum.h
|
||||
orc-rt/Compiler.h
|
||||
orc-rt/Error.h
|
||||
orc-rt/Math.h
|
||||
orc-rt/RTTI.h
|
||||
orc-rt/WrapperFunctionResult.h
|
||||
orc-rt/move_only_function.h
|
||||
orc-rt/span.h
|
||||
)
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*===- ExternC.h - C API for the ORC runtime ----------------------*- C -*-===*\
|
||||
|* *|
|
||||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|
||||
|* Exceptions. *|
|
||||
|* See https://llvm.org/LICENSE.txt for license information. *|
|
||||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|
||||
|* *|
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|* *|
|
||||
|* This file defines the C API for the ORC runtime *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef ORC_RT_C_EXTERNC_H
|
||||
#define ORC_RT_C_EXTERNC_H
|
||||
|
||||
/* Helper to suppress strict prototype warnings. */
|
||||
#ifdef __clang__
|
||||
#define ORC_RT_C_STRICT_PROTOTYPES_BEGIN \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic error \"-Wstrict-prototypes\"")
|
||||
#define ORC_RT_C_STRICT_PROTOTYPES_END _Pragma("clang diagnostic pop")
|
||||
#else
|
||||
#define ORC_RT_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define ORC_RT_C_STRICT_PROTOTYPES_END
|
||||
#endif
|
||||
|
||||
/* Helper to wrap C code for C++ */
|
||||
#ifdef __cplusplus
|
||||
#define ORC_RT_C_EXTERN_C_BEGIN \
|
||||
extern "C" { \
|
||||
ORC_RT_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define ORC_RT_C_EXTERN_C_END \
|
||||
ORC_RT_C_STRICT_PROTOTYPES_END \
|
||||
}
|
||||
#else
|
||||
#define ORC_RT_C_EXTERN_C_BEGIN ORC_RT_C_STRICT_PROTOTYPES_BEGIN
|
||||
#define ORC_RT_C_EXTERN_C_END ORC_RT_C_STRICT_PROTOTYPES_END
|
||||
#endif
|
||||
|
||||
#endif /* ORC_RT_C_EXTERNC_H */
|
@ -1,178 +0,0 @@
|
||||
/*===----- WrapperFunctionResult.h - blob-of-bytes container -----*- C -*-===*\
|
||||
|* *|
|
||||
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|
||||
|* Exceptions. *|
|
||||
|* See https://llvm.org/LICENSE.txt for license information. *|
|
||||
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|
||||
|* *|
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|* *|
|
||||
|* Defines orc_rt_WrapperFunctionResult and related APIs. *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef ORC_RT_C_WRAPPERFUNCTIONRESULT_H
|
||||
#define ORC_RT_C_WRAPPERFUNCTIONRESULT_H
|
||||
|
||||
#include "orc-rt-c/ExternC.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
ORC_RT_C_EXTERN_C_BEGIN
|
||||
|
||||
typedef union {
|
||||
char *ValuePtr;
|
||||
char Value[sizeof(char *)];
|
||||
} orc_rt_WrapperFunctionResultDataUnion;
|
||||
|
||||
/**
|
||||
* orc_rt_WrapperFunctionResult is a kind of C-SmallVector with an
|
||||
* out-of-band error state.
|
||||
*
|
||||
* If Size == 0 and Data.ValuePtr is non-zero then the value is in the
|
||||
* 'out-of-band error' state, and Data.ValuePtr points at a malloc-allocated,
|
||||
* null-terminated string error message.
|
||||
*
|
||||
* If Size <= sizeof(orc_rt_WrapperFunctionResultData) then the value is in
|
||||
* the 'small' state and the content is held in the first Size bytes of
|
||||
* Data.Value.
|
||||
*
|
||||
* If Size > sizeof(orc_rt_WrapperFunctionResultData) then the value is in the
|
||||
* 'large' state and the content is held in the first Size bytes of the
|
||||
* memory pointed to by Data.ValuePtr. This memory must have been allocated by
|
||||
* malloc, and will be freed with free when this value is destroyed.
|
||||
*/
|
||||
typedef struct {
|
||||
orc_rt_WrapperFunctionResultDataUnion Data;
|
||||
size_t Size;
|
||||
} orc_rt_WrapperFunctionResult;
|
||||
|
||||
/**
|
||||
* Zero-initialize an orc_rt_WrapperFunctionResult.
|
||||
*/
|
||||
static inline void
|
||||
orc_rt_WrapperFunctionResultInit(orc_rt_WrapperFunctionResult *R) {
|
||||
R->Size = 0;
|
||||
R->Data.ValuePtr = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an orc_rt_WrapperFunctionResult with an uninitialized buffer of
|
||||
* size Size. The buffer is returned via the DataPtr argument.
|
||||
*/
|
||||
static inline orc_rt_WrapperFunctionResult
|
||||
orc_rt_WrapperFunctionResultAllocate(size_t Size) {
|
||||
orc_rt_WrapperFunctionResult R;
|
||||
R.Size = Size;
|
||||
// If Size is 0 ValuePtr must be 0 or it is considered an out-of-band error.
|
||||
R.Data.ValuePtr = 0;
|
||||
if (Size > sizeof(R.Data.Value))
|
||||
R.Data.ValuePtr = (char *)malloc(Size);
|
||||
return R;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an orc_rt_WrapperFunctionResult from the given data range.
|
||||
*/
|
||||
static inline orc_rt_WrapperFunctionResult
|
||||
orc_rt_CreateWrapperFunctionResultFromRange(const char *Data, size_t Size) {
|
||||
orc_rt_WrapperFunctionResult R;
|
||||
R.Size = Size;
|
||||
if (R.Size > sizeof(R.Data.Value)) {
|
||||
char *Tmp = (char *)malloc(Size);
|
||||
memcpy(Tmp, Data, Size);
|
||||
R.Data.ValuePtr = Tmp;
|
||||
} else
|
||||
memcpy(R.Data.Value, Data, Size);
|
||||
return R;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an orc_rt_WrapperFunctionResult by copying the given string,
|
||||
* including the null-terminator.
|
||||
*
|
||||
* This function copies the input string. The client is responsible for freeing
|
||||
* the ErrMsg arg.
|
||||
*/
|
||||
static inline orc_rt_WrapperFunctionResult
|
||||
orc_rt_CreateWrapperFunctionResultFromString(const char *Source) {
|
||||
return orc_rt_CreateWrapperFunctionResultFromRange(Source,
|
||||
strlen(Source) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an orc_rt_WrapperFunctionResult representing an out-of-band
|
||||
* error.
|
||||
*
|
||||
* This function copies the input string. The client is responsible for freeing
|
||||
* the ErrMsg arg.
|
||||
*/
|
||||
static inline orc_rt_WrapperFunctionResult
|
||||
orc_rt_CreateWrapperFunctionResultFromOutOfBandError(const char *ErrMsg) {
|
||||
orc_rt_WrapperFunctionResult R;
|
||||
R.Size = 0;
|
||||
char *Tmp = (char *)malloc(strlen(ErrMsg) + 1);
|
||||
strcpy(Tmp, ErrMsg);
|
||||
R.Data.ValuePtr = Tmp;
|
||||
return R;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called to destroy orc_rt_WrapperFunctionResult values
|
||||
* regardless of their state.
|
||||
*/
|
||||
static inline void
|
||||
orc_rt_DisposeWrapperFunctionResult(orc_rt_WrapperFunctionResult *R) {
|
||||
if (R->Size > sizeof(R->Data.Value) || (R->Size == 0 && R->Data.ValuePtr))
|
||||
free(R->Data.ValuePtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a pointer to the data contained in the given
|
||||
* orc_rt_WrapperFunctionResult.
|
||||
*/
|
||||
static inline char *
|
||||
orc_rt_WrapperFunctionResultData(orc_rt_WrapperFunctionResult *R) {
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
|
||||
"Cannot get data for out-of-band error value");
|
||||
return R->Size > sizeof(R->Data.Value) ? R->Data.ValuePtr : R->Data.Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely get the size of the given orc_rt_WrapperFunctionResult.
|
||||
*
|
||||
* Asserts that we're not trying to access the size of an error value.
|
||||
*/
|
||||
static inline size_t
|
||||
orc_rt_WrapperFunctionResultSize(const orc_rt_WrapperFunctionResult *R) {
|
||||
assert((R->Size != 0 || R->Data.ValuePtr == NULL) &&
|
||||
"Cannot get size for out-of-band error value");
|
||||
return R->Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if this value is equivalent to a value just initialized by
|
||||
* orc_rt_WrapperFunctionResultInit, 0 otherwise.
|
||||
*/
|
||||
static inline size_t
|
||||
orc_rt_WrapperFunctionResultEmpty(const orc_rt_WrapperFunctionResult *R) {
|
||||
return R->Size == 0 && R->Data.ValuePtr == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the out-of-band error string for this
|
||||
* orc_rt_WrapperFunctionResult, or null if there is no error.
|
||||
*
|
||||
* The orc_rt_WrapperFunctionResult retains ownership of the error
|
||||
* string, so it should be copied if the caller wishes to preserve it.
|
||||
*/
|
||||
static inline const char *orc_rt_WrapperFunctionResultGetOutOfBandError(
|
||||
const orc_rt_WrapperFunctionResult *R) {
|
||||
return R->Size == 0 ? R->Data.ValuePtr : 0;
|
||||
}
|
||||
|
||||
ORC_RT_C_EXTERN_C_END
|
||||
|
||||
#endif /* ORC_RT_WRAPPERFUNCTIONRESULT_H */
|
@ -1,106 +0,0 @@
|
||||
//===---- WrapperFunctionResult.h -- blob-of-bytes container ----*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Defines WrapperFunctionResult and related APIs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef ORC_RT_WRAPPERFUNCTIONRESULT_H
|
||||
#define ORC_RT_WRAPPERFUNCTIONRESULT_H
|
||||
|
||||
#include "orc-rt-c/WrapperFunctionResult.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace orc_rt {
|
||||
|
||||
/// A C++ convenience wrapper for orc_rt_WrapperFunctionResult. Auto-disposes
|
||||
/// the contained result on destruction.
|
||||
class WrapperFunctionResult {
|
||||
public:
|
||||
/// Create a default WrapperFunctionResult.
|
||||
WrapperFunctionResult() { orc_rt_WrapperFunctionResultInit(&R); }
|
||||
|
||||
/// Create a WrapperFunctionResult from a WrapperFunctionResult. This
|
||||
/// instance takes ownership of the result object and will automatically
|
||||
/// call dispose on the result upon destruction.
|
||||
WrapperFunctionResult(orc_rt_WrapperFunctionResult R) : R(R) {}
|
||||
|
||||
WrapperFunctionResult(const WrapperFunctionResult &) = delete;
|
||||
WrapperFunctionResult &operator=(const WrapperFunctionResult &) = delete;
|
||||
|
||||
WrapperFunctionResult(WrapperFunctionResult &&Other) {
|
||||
orc_rt_WrapperFunctionResultInit(&R);
|
||||
std::swap(R, Other.R);
|
||||
}
|
||||
|
||||
WrapperFunctionResult &operator=(WrapperFunctionResult &&Other) {
|
||||
orc_rt_WrapperFunctionResult Tmp;
|
||||
orc_rt_WrapperFunctionResultInit(&Tmp);
|
||||
std::swap(Tmp, Other.R);
|
||||
std::swap(R, Tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~WrapperFunctionResult() { orc_rt_DisposeWrapperFunctionResult(&R); }
|
||||
|
||||
/// Relinquish ownership of and return the
|
||||
/// orc_rt_WrapperFunctionResult.
|
||||
orc_rt_WrapperFunctionResult release() {
|
||||
orc_rt_WrapperFunctionResult Tmp;
|
||||
orc_rt_WrapperFunctionResultInit(&Tmp);
|
||||
std::swap(R, Tmp);
|
||||
return Tmp;
|
||||
}
|
||||
|
||||
/// Get a pointer to the data contained in this instance.
|
||||
char *data() { return orc_rt_WrapperFunctionResultData(&R); }
|
||||
|
||||
/// Returns the size of the data contained in this instance.
|
||||
size_t size() const { return orc_rt_WrapperFunctionResultSize(&R); }
|
||||
|
||||
/// Returns true if this value is equivalent to a default-constructed
|
||||
/// WrapperFunctionResult.
|
||||
bool empty() const { return orc_rt_WrapperFunctionResultEmpty(&R); }
|
||||
|
||||
/// Create a WrapperFunctionResult with the given size and return a pointer
|
||||
/// to the underlying memory.
|
||||
static WrapperFunctionResult allocate(size_t Size) {
|
||||
WrapperFunctionResult R;
|
||||
R.R = orc_rt_WrapperFunctionResultAllocate(Size);
|
||||
return R;
|
||||
}
|
||||
|
||||
/// Copy from the given char range.
|
||||
static WrapperFunctionResult copyFrom(const char *Source, size_t Size) {
|
||||
return orc_rt_CreateWrapperFunctionResultFromRange(Source, Size);
|
||||
}
|
||||
|
||||
/// Copy from the given null-terminated string (includes the null-terminator).
|
||||
static WrapperFunctionResult copyFrom(const char *Source) {
|
||||
return orc_rt_CreateWrapperFunctionResultFromString(Source);
|
||||
}
|
||||
|
||||
/// Create an out-of-band error by copying the given string.
|
||||
static WrapperFunctionResult createOutOfBandError(const char *Msg) {
|
||||
return orc_rt_CreateWrapperFunctionResultFromOutOfBandError(Msg);
|
||||
}
|
||||
|
||||
/// If this value is an out-of-band error then this returns the error message,
|
||||
/// otherwise returns nullptr.
|
||||
const char *getOutOfBandError() const {
|
||||
return orc_rt_WrapperFunctionResultGetOutOfBandError(&R);
|
||||
}
|
||||
|
||||
private:
|
||||
orc_rt_WrapperFunctionResult R;
|
||||
};
|
||||
|
||||
} // namespace orc_rt
|
||||
|
||||
#endif // ORC_RT_WRAPPERFUNCTIONRESULT_H
|
@ -16,7 +16,6 @@ add_orc_rt_unittest(CoreTests
|
||||
ErrorTest.cpp
|
||||
MathTest.cpp
|
||||
RTTITest.cpp
|
||||
WrapperFunctionResultTest.cpp
|
||||
move_only_function-test.cpp
|
||||
span-test.cpp
|
||||
DISABLE_LLVM_LINK_LLVM_DYLIB
|
||||
|
@ -1,60 +0,0 @@
|
||||
//===-- wrapper_function_utils_test.cpp -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of the ORC runtime.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "orc-rt-c/WrapperFunctionResult.h"
|
||||
#include "orc-rt/WrapperFunctionResult.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace orc_rt;
|
||||
|
||||
namespace {
|
||||
constexpr const char *TestString = "test string";
|
||||
} // end anonymous namespace
|
||||
|
||||
TEST(WrapperFunctionUtilsTest, DefaultWrapperFunctionResult) {
|
||||
WrapperFunctionResult R;
|
||||
EXPECT_TRUE(R.empty());
|
||||
EXPECT_EQ(R.size(), 0U);
|
||||
EXPECT_EQ(R.getOutOfBandError(), nullptr);
|
||||
}
|
||||
|
||||
TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCStruct) {
|
||||
orc_rt_WrapperFunctionResult CR =
|
||||
orc_rt_CreateWrapperFunctionResultFromString(TestString);
|
||||
WrapperFunctionResult R(CR);
|
||||
EXPECT_EQ(R.size(), strlen(TestString) + 1);
|
||||
EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
|
||||
EXPECT_FALSE(R.empty());
|
||||
EXPECT_EQ(R.getOutOfBandError(), nullptr);
|
||||
}
|
||||
|
||||
TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromRange) {
|
||||
auto R = WrapperFunctionResult::copyFrom(TestString, strlen(TestString) + 1);
|
||||
EXPECT_EQ(R.size(), strlen(TestString) + 1);
|
||||
EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
|
||||
EXPECT_FALSE(R.empty());
|
||||
EXPECT_EQ(R.getOutOfBandError(), nullptr);
|
||||
}
|
||||
|
||||
TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromCString) {
|
||||
auto R = WrapperFunctionResult::copyFrom(TestString);
|
||||
EXPECT_EQ(R.size(), strlen(TestString) + 1);
|
||||
EXPECT_TRUE(strcmp(R.data(), TestString) == 0);
|
||||
EXPECT_FALSE(R.empty());
|
||||
EXPECT_EQ(R.getOutOfBandError(), nullptr);
|
||||
}
|
||||
|
||||
TEST(WrapperFunctionUtilsTest, WrapperFunctionResultFromOutOfBandError) {
|
||||
auto R = WrapperFunctionResult::createOutOfBandError(TestString);
|
||||
EXPECT_FALSE(R.empty());
|
||||
EXPECT_TRUE(strcmp(R.getOutOfBandError(), TestString) == 0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user