16db8c59fSFangrui Song // RUN: %clangxx_xray -g -std=c++11 %s -o %t
26db8c59fSFangrui Song // RUN: rm -f fdr-logging-test-*
36db8c59fSFangrui Song // RUN: rm -f fdr-unwrite-test-*
46db8c59fSFangrui Song // RUN: XRAY_OPTIONS="patch_premain=false xray_logfile_base=fdr-logging-test- \
56db8c59fSFangrui Song // RUN: xray_mode=xray-fdr verbosity=1" \
66db8c59fSFangrui Song // RUN: XRAY_FDR_OPTIONS="func_duration_threshold_us=0" \
76db8c59fSFangrui Song // RUN: %run %t 2>&1 | FileCheck %s
86db8c59fSFangrui Song // RUN: XRAY_OPTIONS="patch_premain=false \
96db8c59fSFangrui Song // RUN: xray_logfile_base=fdr-unwrite-test- xray_mode=xray-fdr \
106db8c59fSFangrui Song // RUN: verbosity=1" \
116db8c59fSFangrui Song // RUN: XRAY_FDR_OPTIONS="func_duration_threshold_us=5000" \
126db8c59fSFangrui Song // RUN: %run %t 2>&1 | FileCheck %s
136db8c59fSFangrui Song // RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
146db8c59fSFangrui Song // RUN: "`ls fdr-logging-test-* | head -1`" \
156db8c59fSFangrui Song // RUN: | FileCheck %s --check-prefix=TRACE
166db8c59fSFangrui Song // RUN: %llvm_xray convert --symbolize --output-format=yaml -instr_map=%t \
176db8c59fSFangrui Song // RUN: "`ls fdr-unwrite-test-* | head -1`" \
186db8c59fSFangrui Song // RUN: | FileCheck %s --check-prefix=UNWRITE
196db8c59fSFangrui Song // RUN: rm fdr-logging-test-*
206db8c59fSFangrui Song // RUN: rm fdr-unwrite-test-*
21f7624b08SFangrui Song // UNSUPPORTED: target=powerpc64le-{{.*}}
22*75b0a996SAmi-zhang /// TODO: FDR logging arg1 handler(__xray_ArgLoggerEntry) hasn't implemented yet on LoongArch
23*75b0a996SAmi-zhang // UNSUPPORTED: target=loongarch64{{.*}}
246db8c59fSFangrui Song // REQUIRES: built-in-llvm-tree
256db8c59fSFangrui Song
266db8c59fSFangrui Song #include "xray/xray_log_interface.h"
276db8c59fSFangrui Song #include <cassert>
286db8c59fSFangrui Song #include <chrono>
296db8c59fSFangrui Song #include <cstdio>
306db8c59fSFangrui Song #include <iostream>
316db8c59fSFangrui Song #include <stdlib.h>
326db8c59fSFangrui Song #include <thread>
336db8c59fSFangrui Song #include <time.h>
346db8c59fSFangrui Song
356db8c59fSFangrui Song thread_local uint64_t var = 0;
fC()366db8c59fSFangrui Song [[clang::xray_always_instrument]] void __attribute__((noinline)) fC() { ++var; }
376db8c59fSFangrui Song
fB()386db8c59fSFangrui Song [[clang::xray_always_instrument]] void __attribute__((noinline)) fB() { fC(); }
396db8c59fSFangrui Song
fA()406db8c59fSFangrui Song [[clang::xray_always_instrument]] void __attribute__((noinline)) fA() { fB(); }
416db8c59fSFangrui Song
426db8c59fSFangrui Song [[clang::xray_always_instrument, clang::xray_log_args(1)]]
fArg(int)436db8c59fSFangrui Song void __attribute__((noinline)) fArg(int) { }
446db8c59fSFangrui Song
main(int argc,char * argv[])456db8c59fSFangrui Song int main(int argc, char *argv[]) {
466db8c59fSFangrui Song std::cout << "Logging before init." << std::endl;
476db8c59fSFangrui Song // CHECK: Logging before init.
486db8c59fSFangrui Song assert(__xray_log_select_mode("xray-fdr") ==
496db8c59fSFangrui Song XRayLogRegisterStatus::XRAY_REGISTRATION_OK);
506db8c59fSFangrui Song auto status =
516db8c59fSFangrui Song __xray_log_init_mode("xray-fdr", "buffer_size=16384:buffer_max=10");
526db8c59fSFangrui Song assert(status == XRayLogInitStatus::XRAY_LOG_INITIALIZED);
536db8c59fSFangrui Song std::cout << "Init status " << status << std::endl;
546db8c59fSFangrui Song // CHECK: Init status {{.*}}
556db8c59fSFangrui Song std::cout << "Patching..." << std::endl;
566db8c59fSFangrui Song // CHECK: Patching...
576db8c59fSFangrui Song __xray_patch();
586db8c59fSFangrui Song fA();
596db8c59fSFangrui Song fC();
606db8c59fSFangrui Song fB();
616db8c59fSFangrui Song fA();
626db8c59fSFangrui Song fC();
636db8c59fSFangrui Song std::thread other_thread([]() {
646db8c59fSFangrui Song fC();
656db8c59fSFangrui Song fB();
666db8c59fSFangrui Song fA();
676db8c59fSFangrui Song fArg(1);
686db8c59fSFangrui Song });
696db8c59fSFangrui Song other_thread.join();
706db8c59fSFangrui Song std::cout << "Joined" << std::endl;
716db8c59fSFangrui Song // CHECK: Joined
726db8c59fSFangrui Song std::cout << "Finalize status " << __xray_log_finalize() << std::endl;
736db8c59fSFangrui Song // CHECK: Finalize status {{.*}}
746db8c59fSFangrui Song fC();
756db8c59fSFangrui Song std::cout << "Main execution var = " << var << std::endl;
766db8c59fSFangrui Song // CHECK: Main execution var = 6
776db8c59fSFangrui Song std::cout << "Flush status " << __xray_log_flushLog() << std::endl;
786db8c59fSFangrui Song // CHECK: Flush status {{.*}}
796db8c59fSFangrui Song __xray_unpatch();
806db8c59fSFangrui Song return 0;
816db8c59fSFangrui Song }
826db8c59fSFangrui Song
836db8c59fSFangrui Song // Check that we're able to see two threads, each entering and exiting fA().
846db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDA:[0-9]+]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
856db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
866db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
876db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDA]], function: {{.*fA.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
886db8c59fSFangrui Song //
896db8c59fSFangrui Song // Do the same as above for fC()
906db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDC:[0-9]+]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
916db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
926db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
936db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDC]], function: {{.*fC.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
946db8c59fSFangrui Song
956db8c59fSFangrui Song // Do the same as above for fB()
966db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDB:[0-9]+]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
976db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD1]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
986db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS]], kind: function-enter, tsc: {{[0-9]+}}, data: '' }
996db8c59fSFangrui Song // TRACE: - { type: 0, func-id: [[FIDB]], function: {{.*fB.*}}, cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-{{exit|tail-exit}}, tsc: {{[0-9]+}}, data: '' }
1006db8c59fSFangrui Song
1016db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-enter-arg, tsc: {{[0-9]+}}, data: '' }
1026db8c59fSFangrui Song // TRACE-DAG: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-exit, tsc: {{[0-9]+}}, data: '' }
1036db8c59fSFangrui Song
1046db8c59fSFangrui Song // Assert that when unwriting is enabled with a high threshold time, all the function records are erased. A CPU switch could erroneously fail this test, but
1056db8c59fSFangrui Song // is unlikely given the test program.
1066db8c59fSFangrui Song // Even with a high threshold, arg1 logging is never unwritten.
1076db8c59fSFangrui Song // UNWRITE: header:
1086db8c59fSFangrui Song // UNWRITE: records:
1096db8c59fSFangrui Song // UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG:[0-9]+]], function: 'fArg(int)', args: [ 1 ], cpu: {{.*}}, thread: [[THREAD2:[0-9]+]], process: [[PROCESS:[0-9]+]], kind: function-enter-arg, tsc: {{[0-9]+}}, data: '' }
1106db8c59fSFangrui Song // UNWRITE-NEXT: - { type: 0, func-id: [[FIDARG]], function: 'fArg(int)', cpu: {{.*}}, thread: [[THREAD2]], process: [[PROCESS]], kind: function-exit, tsc: {{[0-9]+}}, data: '' }
1116db8c59fSFangrui Song // UNWRITE-NOT: function-enter
1126db8c59fSFangrui Song // UNWRITE-NOT: function-{{exit|tail-exit}}
113