llvm.org GIT mirror llvm / 61b1851
Add profiling support for Intel Parallel Amplifier XE (VTune) for JITted code in LLVM. Also refactor the existing OProfile profiling code to reuse the same interfaces with the VTune profiling code. In addition, unit tests for the profiling interfaces were added. This patch was prepared by Andrew Kaylor and Daniel Malea, and reviewed in the llvm-commits list by Jim Grosbach git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152620 91177308-0d34-0410-b5e6-96231b3b80d8 Eli Bendersky 7 years ago
35 changed file(s) with 2385 addition(s) and 483 deletion(s). Raw diff Collapse all Expand all
154154 else()
155155 option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON)
156156 endif()
157
158 option(LLVM_USE_INTEL_JITEVENTS
159 "Use Intel JIT API to inform Intel(R) VTune(TM) Amplifier XE 2011 about JIT code"
160 OFF)
161
162 if( LLVM_USE_INTEL_JITEVENTS )
163 # Verify we are on a supported platform
164 if( CMAKE_SYSTEM_NAME MATCHES "Windows" OR CMAKE_SYSTEM_NAME MATCHES "Linux" )
165 # Directory where Intel Parallel Amplifier XE 2011 is installed.
166 if ( WIN32 )
167 set(LLVM_INTEL_JITEVENTS_DIR $ENV{VTUNE_AMPLIFIER_XE_2011_DIR})
168 else ( WIN32 )
169 set(LLVM_INTEL_JITEVENTS_DIR "/opt/intel/vtune_amplifier_xe_2011")
170 endif ( WIN32 )
171
172 # Set include and library search paths for Intel JIT Events API
173 set(LLVM_INTEL_JITEVENTS_INCDIR "${LLVM_INTEL_JITEVENTS_DIR}/include")
174
175 if ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
176 set(LLVM_INTEL_JITEVENTS_LIBDIR "${LLVM_INTEL_JITEVENTS_DIR}/lib64")
177 else ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
178 set(LLVM_INTEL_JITEVENTS_LIBDIR "${LLVM_INTEL_JITEVENTS_DIR}/lib32")
179 endif ( CMAKE_SIZEOF_VOID_P EQUAL 8 )
180 else()
181 message(FATAL_ERROR
182 "Intel JIT API support is available on Linux and Windows only.")
183 endif()
184 endif( LLVM_USE_INTEL_JITEVENTS )
185
186 option(LLVM_USE_OPROFILE
187 "Use opagent JIT interface to inform OProfile about JIT code" OFF)
188
189 # If enabled, ierify we are on a platform that supports oprofile.
190 if( LLVM_USE_OPROFILE )
191 if( NOT CMAKE_SYSTEM_NAME MATCHES "Linux" )
192 message(FATAL_ERROR "OProfile support is available on Linux only.")
193 endif( NOT CMAKE_SYSTEM_NAME MATCHES "Linux" )
194 endif( LLVM_USE_OPROFILE )
157195
158196 # Define an option controlling whether we should build for 32-bit on 64-bit
159197 # platforms, where supported.
342342 # Flags supported by the linker.
343343 # bfd ld / gold --version-script=file
344344 HAVE_LINK_VERSION_SCRIPT = @HAVE_LINK_VERSION_SCRIPT@
345
346 # Flags to control building support for Intel JIT Events API
347 USE_INTEL_JITEVENTS := @USE_INTEL_JITEVENTS@
348 INTEL_JITEVENTS_INCDIR := @INTEL_JITEVENTS_INCDIR@
349 INTEL_JITEVENTS_LIBDIR := @INTEL_JITEVENTS_LIBDIR@
350
351 # Flags to control building support for OProfile JIT API
352 USE_OPROFILE := @USE_OPROFILE@
11821182 *) llvm_cv_oppath="${withval}/lib/oprofile"
11831183 CPPFLAGS="-I${withval}/include";;
11841184 esac
1185 if test -n "$llvm_cv_oppath" ; then
1186 LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}"
1187 dnl Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537744:
1188 dnl libbfd is not included properly in libopagent in some Debian
1189 dnl versions. If libbfd isn't found at all, we assume opagent works
1190 dnl anyway.
1191 AC_SEARCH_LIBS(bfd_init, bfd, [], [])
1192 AC_SEARCH_LIBS(op_open_agent, opagent, [], [
1193 echo "Error! You need to have libopagent around."
1194 exit -1
1195 ])
1196 AC_CHECK_HEADER([opagent.h], [], [
1197 echo "Error! You need to have opagent.h around."
1198 exit -1
1199 ])
1200 fi
1185 case $llvm_cv_os_type in
1186 Linux)
1187 if test -n "$llvm_cv_oppath" ; then
1188 LIBS="$LIBS -lopagent -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}"
1189 dnl Work around http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=537744:
1190 dnl libbfd is not included properly in libopagent in some Debian
1191 dnl versions. If libbfd isn't found at all, we assume opagent works
1192 dnl anyway.
1193 AC_SEARCH_LIBS(bfd_init, bfd, [], [])
1194 AC_SEARCH_LIBS(op_open_agent, opagent, [], [
1195 echo "Error! You need to have libopagent around."
1196 exit -1
1197 ])
1198 AC_CHECK_HEADER([opagent.h], [], [
1199 echo "Error! You need to have opagent.h around."
1200 exit -1
1201 ])
1202 fi ;;
1203 *)
1204 AC_MSG_ERROR([OProfile support is available on Linux only.]) ;;
1205 esac
12011206 ],
12021207 [
12031208 AC_SUBST(USE_OPROFILE, [0])
12041209 ])
1205 AC_DEFINE_UNQUOTED([USE_OPROFILE],$USE_OPROFILE,
1210 AC_DEFINE_UNQUOTED([LLVM_USE_OPROFILE],$USE_OPROFILE,
12061211 [Define if we have the oprofile JIT-support library])
1212
1213 dnl Enable support for Intel JIT Events API.
1214 AC_ARG_WITH(intel-jitevents,
1215 AS_HELP_STRING([--with-intel-jitevents=],
1216 [Specify location of run-time support library for Intel JIT API (default=/opt/intel/vtune_amplifier_xe_2011)]),
1217 [
1218 case $llvm_cv_os_type in
1219 Linux|Win32|Cygwin|MingW) ;;
1220 *)
1221 AC_MSG_ERROR([
1222 Intel JIT API support is available on Linux and Windows only."]) ;;
1223 esac
1224
1225 AC_SUBST(USE_INTEL_JITEVENTS, [1])
1226 case "$llvm_cv_target_arch" in
1227 x86) llvm_intel_jitevents_archdir="lib32";;
1228 x86_64) llvm_intel_jitevents_archdir="lib64";;
1229 *) echo "Target architecture $llvm_cv_target_arch does not support Intel JIT Events API"
1230 exit -1;;
1231 esac
1232 INTEL_JITEVENTS_INCDIR="/opt/intel/vtune_amplifier_xe_2011/include"
1233 INTEL_JITEVENTS_LIBDIR="/opt/intel/vtune_amplifier_xe_2011/$llvm_intel_jitevents_archdir"
1234 case "$withval" in
1235 /* | [[A-Za-z]]:[[\\/]]*) INTEL_JITEVENTS_INCDIR=$withval/include
1236 INTEL_JITEVENTS_LIBDIR=$withval/$llvm_intel_jitevents_archdir ;;
1237 *) ;;
1238 esac
1239
1240 AC_SUBST(INTEL_JITEVENTS_INCDIR)
1241 AC_SUBST(INTEL_JITEVENTS_LIBDIR)
1242
1243 LIBS="$LIBS -L${INTEL_JITEVENTS_LIBDIR}"
1244 CPPFLAGS="$CPPFLAGS -I$INTEL_JITEVENTS_INCDIR"
1245
1246 AC_SEARCH_LIBS(iJIT_IsProfilingActive, jitprofiling, [], [
1247 echo "Error! Cannot find libjitprofiling.a. Please check path specified in flag --with-intel-jitevents"
1248 exit -1
1249 ])
1250 AC_CHECK_HEADER([jitprofiling.h], [], [
1251 echo "Error! Cannot find jitprofiling.h. Please check path specified in flag --with-intel-jitevents"
1252 exit -1
1253 ])
1254
1255 ],
1256 [
1257 AC_SUBST(USE_INTEL_JITEVENTS, [0])
1258 ])
1259 AC_DEFINE_UNQUOTED([LLVM_USE_INTEL_JITEVENTS],$USE_INTEL_JITEVENTS,
1260 [Define if we have the Intel JIT API runtime support library])
12071261
12081262 dnl===-----------------------------------------------------------------------===
12091263 dnl===
765765 COVERED_SWITCH_DEFAULT
766766 USE_UDIS86
767767 USE_OPROFILE
768 USE_INTEL_JITEVENTS
769 INTEL_JITEVENTS_INCDIR
770 INTEL_JITEVENTS_LIBDIR
768771 HAVE_PTHREAD
769772 HUGE_VAL_SANITY
770773 MMAP_FILE
14501453 --with-udis86= Use udis86 external x86 disassembler library
14511454 --with-oprofile=
14521455 Tell OProfile >= 0.9.4 how to symbolize JIT output
1456 --with-intel-jitevents=
1457 Specify location of run-time support library for
1458 Intel JIT API
1459 (default=/opt/intel/vtune_amplifier_xe_2011)
14531460
14541461 Some influential environment variables:
14551462 CC C compiler command
1039410401 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1039510402 lt_status=$lt_dlunknown
1039610403 cat > conftest.$ac_ext <
10397 #line 10398 "configure"
10404 #line 10405 "configure"
1039810405 #include "confdefs.h"
1039910406
1040010407 #if HAVE_DLFCN_H
1325913266 *) llvm_cv_oppath="${withval}/lib/oprofile"
1326013267 CPPFLAGS="-I${withval}/include";;
1326113268 esac
13262 if test -n "$llvm_cv_oppath" ; then
13263 LIBS="$LIBS -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}"
13264 { echo "$as_me:$LINENO: checking for library containing bfd_init" >&5
13269 case $llvm_cv_os_type in
13270 Linux)
13271 if test -n "$llvm_cv_oppath" ; then
13272 LIBS="$LIBS -lopagent -L${llvm_cv_oppath} -Wl,-rpath,${llvm_cv_oppath}"
13273 { echo "$as_me:$LINENO: checking for library containing bfd_init" >&5
1326513274 echo $ECHO_N "checking for library containing bfd_init... $ECHO_C" >&6; }
1326613275 if test "${ac_cv_search_bfd_init+set}" = set; then
1326713276 echo $ECHO_N "(cached) $ECHO_C" >&6
1336013369
1336113370 fi
1336213371
13363 { echo "$as_me:$LINENO: checking for library containing op_open_agent" >&5
13372 { echo "$as_me:$LINENO: checking for library containing op_open_agent" >&5
1336413373 echo $ECHO_N "checking for library containing op_open_agent... $ECHO_C" >&6; }
1336513374 if test "${ac_cv_search_op_open_agent+set}" = set; then
1336613375 echo $ECHO_N "(cached) $ECHO_C" >&6
1345913468
1346013469 else
1346113470
13462 echo "Error! You need to have libopagent around."
13463 exit -1
13464
13465 fi
13466
13467 if test "${ac_cv_header_opagent_h+set}" = set; then
13471 echo "Error! You need to have libopagent around."
13472 exit -1
13473
13474 fi
13475
13476 if test "${ac_cv_header_opagent_h+set}" = set; then
1346813477 { echo "$as_me:$LINENO: checking for opagent.h" >&5
1346913478 echo $ECHO_N "checking for opagent.h... $ECHO_C" >&6; }
1347013479 if test "${ac_cv_header_opagent_h+set}" = set; then
1362213631 :
1362313632 else
1362413633
13625 echo "Error! You need to have opagent.h around."
13626 exit -1
13627
13628 fi
13629
13630
13631 fi
13634 echo "Error! You need to have opagent.h around."
13635 exit -1
13636
13637 fi
13638
13639
13640 fi ;;
13641 *)
13642 { { echo "$as_me:$LINENO: error: OProfile support is available on Linux only." >&5
13643 echo "$as_me: error: OProfile support is available on Linux only." >&2;}
13644 { (exit 1); exit 1; }; } ;;
13645 esac
1363213646
1363313647 else
1363413648
1363913653
1364013654
1364113655 cat >>confdefs.h <<_ACEOF
13642 #define USE_OPROFILE $USE_OPROFILE
13656 #define LLVM_USE_OPROFILE $USE_OPROFILE
13657 _ACEOF
13658
13659
13660
13661 # Check whether --with-intel-jitevents was given.
13662 if test "${with_intel_jitevents+set}" = set; then
13663 withval=$with_intel_jitevents;
13664 case $llvm_cv_os_type in
13665 Linux|Win32|Cygwin|MingW) ;;
13666 *)
13667 { { echo "$as_me:$LINENO: error:
13668 Intel JIT API support is available on Linux and Windows only.\"" >&5
13669 echo "$as_me: error:
13670 Intel JIT API support is available on Linux and Windows only.\"" >&2;}
13671 { (exit 1); exit 1; }; } ;;
13672 esac
13673
13674 USE_INTEL_JITEVENTS=1
13675
13676 case "$llvm_cv_target_arch" in
13677 x86) llvm_intel_jitevents_archdir="lib32";;
13678 x86_64) llvm_intel_jitevents_archdir="lib64";;
13679 *) echo "Target architecture $llvm_cv_target_arch does not support Intel JIT Events API"
13680 exit -1;;
13681 esac
13682 INTEL_JITEVENTS_INCDIR="/opt/intel/vtune_amplifier_xe_2011/include"
13683 INTEL_JITEVENTS_LIBDIR="/opt/intel/vtune_amplifier_xe_2011/$llvm_intel_jitevents_archdir"
13684 case "$withval" in
13685 /* | [A-Za-z]:[\\/]*) INTEL_JITEVENTS_INCDIR=$withval/include
13686 INTEL_JITEVENTS_LIBDIR=$withval/$llvm_intel_jitevents_archdir ;;
13687 *) ;;
13688
13689 esac
13690
13691
13692
13693
13694 LIBS="$LIBS -L${INTEL_JITEVENTS_LIBDIR}"
13695 CPPFLAGS="$CPPFLAGS -I$INTEL_JITEVENTS_INCDIR"
13696
13697 { echo "$as_me:$LINENO: checking for library containing iJIT_IsProfilingActive" >&5
13698 echo $ECHO_N "checking for library containing iJIT_IsProfilingActive... $ECHO_C" >&6; }
13699 if test "${ac_cv_search_iJIT_IsProfilingActive+set}" = set; then
13700 echo $ECHO_N "(cached) $ECHO_C" >&6
13701 else
13702 ac_func_search_save_LIBS=$LIBS
13703 cat >conftest.$ac_ext <<_ACEOF
13704 /* confdefs.h. */
13705 _ACEOF
13706 cat confdefs.h >>conftest.$ac_ext
13707 cat >>conftest.$ac_ext <<_ACEOF
13708 /* end confdefs.h. */
13709
13710 /* Override any GCC internal prototype to avoid an error.
13711 Use char because int might match the return type of a GCC
13712 builtin and then its argument prototype would still apply. */
13713 #ifdef __cplusplus
13714 extern "C"
13715 #endif
13716 char iJIT_IsProfilingActive ();
13717 int
13718 main ()
13719 {
13720 return iJIT_IsProfilingActive ();
13721 ;
13722 return 0;
13723 }
13724 _ACEOF
13725 for ac_lib in '' jitprofiling; do
13726 if test -z "$ac_lib"; then
13727 ac_res="none required"
13728 else
13729 ac_res=-l$ac_lib
13730 LIBS="-l$ac_lib $ac_func_search_save_LIBS"
13731 fi
13732 rm -f conftest.$ac_objext conftest$ac_exeext
13733 if { (ac_try="$ac_link"
13734 case "(($ac_try" in
13735 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13736 *) ac_try_echo=$ac_try;;
13737 esac
13738 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13739 (eval "$ac_link") 2>conftest.er1
13740 ac_status=$?
13741 grep -v '^ *+' conftest.er1 >conftest.err
13742 rm -f conftest.er1
13743 cat conftest.err >&5
13744 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13745 (exit $ac_status); } &&
13746 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
13747 { (case "(($ac_try" in
13748 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13749 *) ac_try_echo=$ac_try;;
13750 esac
13751 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13752 (eval "$ac_try") 2>&5
13753 ac_status=$?
13754 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13755 (exit $ac_status); }; } &&
13756 { ac_try='test -s conftest$ac_exeext'
13757 { (case "(($ac_try" in
13758 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13759 *) ac_try_echo=$ac_try;;
13760 esac
13761 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13762 (eval "$ac_try") 2>&5
13763 ac_status=$?
13764 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13765 (exit $ac_status); }; }; then
13766 ac_cv_search_iJIT_IsProfilingActive=$ac_res
13767 else
13768 echo "$as_me: failed program was:" >&5
13769 sed 's/^/| /' conftest.$ac_ext >&5
13770
13771
13772 fi
13773
13774 rm -f core conftest.err conftest.$ac_objext \
13775 conftest$ac_exeext
13776 if test "${ac_cv_search_iJIT_IsProfilingActive+set}" = set; then
13777 break
13778 fi
13779 done
13780 if test "${ac_cv_search_iJIT_IsProfilingActive+set}" = set; then
13781 :
13782 else
13783 ac_cv_search_iJIT_IsProfilingActive=no
13784 fi
13785 rm conftest.$ac_ext
13786 LIBS=$ac_func_search_save_LIBS
13787 fi
13788 { echo "$as_me:$LINENO: result: $ac_cv_search_iJIT_IsProfilingActive" >&5
13789 echo "${ECHO_T}$ac_cv_search_iJIT_IsProfilingActive" >&6; }
13790 ac_res=$ac_cv_search_iJIT_IsProfilingActive
13791 if test "$ac_res" != no; then
13792 test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
13793
13794 else
13795
13796 echo "Error! Cannot find libjitprofiling.a. Please check path specified in flag --with-intel-jitevents"
13797 exit -1
13798
13799 fi
13800
13801 if test "${ac_cv_header_jitprofiling_h+set}" = set; then
13802 { echo "$as_me:$LINENO: checking for jitprofiling.h" >&5
13803 echo $ECHO_N "checking for jitprofiling.h... $ECHO_C" >&6; }
13804 if test "${ac_cv_header_jitprofiling_h+set}" = set; then
13805 echo $ECHO_N "(cached) $ECHO_C" >&6
13806 fi
13807 { echo "$as_me:$LINENO: result: $ac_cv_header_jitprofiling_h" >&5
13808 echo "${ECHO_T}$ac_cv_header_jitprofiling_h" >&6; }
13809 else
13810 # Is the header compilable?
13811 { echo "$as_me:$LINENO: checking jitprofiling.h usability" >&5
13812 echo $ECHO_N "checking jitprofiling.h usability... $ECHO_C" >&6; }
13813 cat >conftest.$ac_ext <<_ACEOF
13814 /* confdefs.h. */
13815 _ACEOF
13816 cat confdefs.h >>conftest.$ac_ext
13817 cat >>conftest.$ac_ext <<_ACEOF
13818 /* end confdefs.h. */
13819 $ac_includes_default
13820 #include
13821 _ACEOF
13822 rm -f conftest.$ac_objext
13823 if { (ac_try="$ac_compile"
13824 case "(($ac_try" in
13825 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13826 *) ac_try_echo=$ac_try;;
13827 esac
13828 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13829 (eval "$ac_compile") 2>conftest.er1
13830 ac_status=$?
13831 grep -v '^ *+' conftest.er1 >conftest.err
13832 rm -f conftest.er1
13833 cat conftest.err >&5
13834 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13835 (exit $ac_status); } &&
13836 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
13837 { (case "(($ac_try" in
13838 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13839 *) ac_try_echo=$ac_try;;
13840 esac
13841 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13842 (eval "$ac_try") 2>&5
13843 ac_status=$?
13844 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13845 (exit $ac_status); }; } &&
13846 { ac_try='test -s conftest.$ac_objext'
13847 { (case "(($ac_try" in
13848 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13849 *) ac_try_echo=$ac_try;;
13850 esac
13851 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13852 (eval "$ac_try") 2>&5
13853 ac_status=$?
13854 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13855 (exit $ac_status); }; }; then
13856 ac_header_compiler=yes
13857 else
13858 echo "$as_me: failed program was:" >&5
13859 sed 's/^/| /' conftest.$ac_ext >&5
13860
13861 ac_header_compiler=no
13862 fi
13863
13864 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
13865 { echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
13866 echo "${ECHO_T}$ac_header_compiler" >&6; }
13867
13868 # Is the header present?
13869 { echo "$as_me:$LINENO: checking jitprofiling.h presence" >&5
13870 echo $ECHO_N "checking jitprofiling.h presence... $ECHO_C" >&6; }
13871 cat >conftest.$ac_ext <<_ACEOF
13872 /* confdefs.h. */
13873 _ACEOF
13874 cat confdefs.h >>conftest.$ac_ext
13875 cat >>conftest.$ac_ext <<_ACEOF
13876 /* end confdefs.h. */
13877 #include
13878 _ACEOF
13879 if { (ac_try="$ac_cpp conftest.$ac_ext"
13880 case "(($ac_try" in
13881 *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
13882 *) ac_try_echo=$ac_try;;
13883 esac
13884 eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
13885 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
13886 ac_status=$?
13887 grep -v '^ *+' conftest.er1 >conftest.err
13888 rm -f conftest.er1
13889 cat conftest.err >&5
13890 echo "$as_me:$LINENO: \$? = $ac_status" >&5
13891 (exit $ac_status); } >/dev/null; then
13892 if test -s conftest.err; then
13893 ac_cpp_err=$ac_c_preproc_warn_flag
13894 ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
13895 else
13896 ac_cpp_err=
13897 fi
13898 else
13899 ac_cpp_err=yes
13900 fi
13901 if test -z "$ac_cpp_err"; then
13902 ac_header_preproc=yes
13903 else
13904 echo "$as_me: failed program was:" >&5
13905 sed 's/^/| /' conftest.$ac_ext >&5
13906
13907 ac_header_preproc=no
13908 fi
13909
13910 rm -f conftest.err conftest.$ac_ext
13911 { echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
13912 echo "${ECHO_T}$ac_header_preproc" >&6; }
13913
13914 # So? What about this header?
13915 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
13916 yes:no: )
13917 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: accepted by the compiler, rejected by the preprocessor!" >&5
13918 echo "$as_me: WARNING: jitprofiling.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
13919 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: proceeding with the compiler's result" >&5
13920 echo "$as_me: WARNING: jitprofiling.h: proceeding with the compiler's result" >&2;}
13921 ac_header_preproc=yes
13922 ;;
13923 no:yes:* )
13924 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: present but cannot be compiled" >&5
13925 echo "$as_me: WARNING: jitprofiling.h: present but cannot be compiled" >&2;}
13926 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: check for missing prerequisite headers?" >&5
13927 echo "$as_me: WARNING: jitprofiling.h: check for missing prerequisite headers?" >&2;}
13928 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: see the Autoconf documentation" >&5
13929 echo "$as_me: WARNING: jitprofiling.h: see the Autoconf documentation" >&2;}
13930 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: section \"Present But Cannot Be Compiled\"" >&5
13931 echo "$as_me: WARNING: jitprofiling.h: section \"Present But Cannot Be Compiled\"" >&2;}
13932 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: proceeding with the preprocessor's result" >&5
13933 echo "$as_me: WARNING: jitprofiling.h: proceeding with the preprocessor's result" >&2;}
13934 { echo "$as_me:$LINENO: WARNING: jitprofiling.h: in the future, the compiler will take precedence" >&5
13935 echo "$as_me: WARNING: jitprofiling.h: in the future, the compiler will take precedence" >&2;}
13936 ( cat <<\_ASBOX
13937 ## ------------------------------------ ##
13938 ## Report this to http://llvm.org/bugs/ ##
13939 ## ------------------------------------ ##
13940 _ASBOX
13941 ) | sed "s/^/$as_me: WARNING: /" >&2
13942 ;;
13943 esac
13944 { echo "$as_me:$LINENO: checking for jitprofiling.h" >&5
13945 echo $ECHO_N "checking for jitprofiling.h... $ECHO_C" >&6; }
13946 if test "${ac_cv_header_jitprofiling_h+set}" = set; then
13947 echo $ECHO_N "(cached) $ECHO_C" >&6
13948 else
13949 ac_cv_header_jitprofiling_h=$ac_header_preproc
13950 fi
13951 { echo "$as_me:$LINENO: result: $ac_cv_header_jitprofiling_h" >&5
13952 echo "${ECHO_T}$ac_cv_header_jitprofiling_h" >&6; }
13953
13954 fi
13955 if test $ac_cv_header_jitprofiling_h = yes; then
13956 :
13957 else
13958
13959 echo "Error! Cannot find jitprofiling.h. Please check path specified in flag --with-intel-jitevents"
13960 exit -1
13961
13962 fi
13963
13964
13965
13966
13967 else
13968
13969 USE_INTEL_JITEVENTS=0
13970
13971
13972 fi
13973
13974
13975 cat >>confdefs.h <<_ACEOF
13976 #define LLVM_USE_INTEL_JITEVENTS $USE_INTEL_JITEVENTS
1364313977 _ACEOF
1364413978
1364513979
2191222246 COVERED_SWITCH_DEFAULT!$COVERED_SWITCH_DEFAULT$ac_delim
2191322247 USE_UDIS86!$USE_UDIS86$ac_delim
2191422248 USE_OPROFILE!$USE_OPROFILE$ac_delim
22249 USE_INTEL_JITEVENTS!$USE_INTEL_JITEVENTS$ac_delim
22250 INTEL_JITEVENTS_INCDIR!$INTEL_JITEVENTS_INCDIR$ac_delim
22251 INTEL_JITEVENTS_LIBDIR!$INTEL_JITEVENTS_LIBDIR$ac_delim
2191522252 HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim
2191622253 HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim
2191722254 MMAP_FILE!$MMAP_FILE$ac_delim
2193722274 LTLIBOBJS!$LTLIBOBJS$ac_delim
2193822275 _ACEOF
2193922276
21940 if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 90; then
22277 if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 93; then
2194122278 break
2194222279 elif $ac_last_try; then
2194322280 { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
356356
Path to Clang's source directory. Defaults to tools/clang.
357357 Clang will not be built when it is empty or it does not point valid
358358 path.
359
360
LLVM_USE_OPROFILE:BOOL
361
Enable building OProfile JIT support. Defaults to OFF
362
363
LLVM_USE_INTEL_JITEVENTS:BOOL
364
Enable building support for Intel JIT Events API. Defaults to OFF
365
366
LLVM_INTEL_JITEVENTS_DIR:PATH
367
Path to installation of Intel(R) VTune(TM) Amplifier XE 2011,
368 used to locate the jitprofiling library. Default =
369 %VTUNE_AMPLIFIER_XE_2011_DIR% (Windows)
370 | /opt/intel/vtune_amplifier_xe_2011 (Linux)
371
359372
360373
361374
676676 /* Define to 1 if your declares `struct tm'. */
677677 #undef TM_IN_SYS_TIME
678678
679 /* Define if we have the oprofile JIT-support library */
680 #undef USE_OPROFILE
681
682679 /* Define if use udis86 library */
683680 #undef USE_UDIS86
684681
715712 /* Added by Kevin -- Maximum path length */
716713 #cmakedefine MAXPATHLEN ${MAXPATHLEN}
717714
715 /* Support for Intel JIT Events API is enabled */
716 #cmakedefine LLVM_USE_INTEL_JITEVENTS 1
717
718 /* Support for OProfile JIT API is enabled */
719 #cmakedefine LLVM_USE_OPROFILE 1
720
718721 #endif
614614 /* Installation prefix directory */
615615 #undef LLVM_PREFIX
616616
617 /* Define if we have the Intel JIT API runtime support library */
618 #undef LLVM_USE_INTEL_JITEVENTS
619
620 /* Define if we have the oprofile JIT-support library */
621 #undef LLVM_USE_OPROFILE
622
617623 /* Major version of the LLVM API */
618624 #undef LLVM_VERSION_MAJOR
619625
674680 /* Define to 1 if your declares `struct tm'. */
675681 #undef TM_IN_SYS_TIME
676682
677 /* Define if we have the oprofile JIT-support library */
678 #undef USE_OPROFILE
679
680683 /* Define if use udis86 library */
681684 #undef USE_UDIS86
682685
0 //===-- IntelJITEventsWrapper.h - Intel JIT Events API Wrapper --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a wrapper for the Intel JIT Events API. It allows for the
10 // implementation of the jitprofiling library to be swapped with an alternative
11 // implementation (for testing). To include this file, you must have the
12 // jitprofiling.h header available; it is available in Intel(R) VTune(TM)
13 // Amplifier XE 2011.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #ifndef INTEL_JIT_EVENTS_WRAPPER_H
18 #define INTEL_JIT_EVENTS_WRAPPER_H
19
20 #include
21
22 namespace llvm {
23
24 class IntelJITEventsWrapper {
25 // Function pointer types for testing implementation of Intel jitprofiling
26 // library
27 typedef int (*NotifyEventPtr)(iJIT_JVM_EVENT, void*);
28 typedef void (*RegisterCallbackExPtr)(void *, iJIT_ModeChangedEx );
29 typedef iJIT_IsProfilingActiveFlags (*IsProfilingActivePtr)(void);
30 typedef void (*FinalizeThreadPtr)(void);
31 typedef void (*FinalizeProcessPtr)(void);
32 typedef unsigned int (*GetNewMethodIDPtr)(void);
33
34 NotifyEventPtr NotifyEventFunc;
35 RegisterCallbackExPtr RegisterCallbackExFunc;
36 IsProfilingActivePtr IsProfilingActiveFunc;
37 FinalizeThreadPtr FinalizeThreadFunc;
38 FinalizeProcessPtr FinalizeProcessFunc;
39 GetNewMethodIDPtr GetNewMethodIDFunc;
40
41 public:
42 bool isAmplifierRunning() {
43 return iJIT_IsProfilingActive() == iJIT_SAMPLING_ON;
44 }
45
46 IntelJITEventsWrapper()
47 : NotifyEventFunc(::iJIT_NotifyEvent),
48 RegisterCallbackExFunc(::iJIT_RegisterCallbackEx),
49 IsProfilingActiveFunc(::iJIT_IsProfilingActive),
50 FinalizeThreadFunc(::FinalizeThread),
51 FinalizeProcessFunc(::FinalizeProcess),
52 GetNewMethodIDFunc(::iJIT_GetNewMethodID) {
53 }
54
55 IntelJITEventsWrapper(NotifyEventPtr NotifyEventImpl,
56 RegisterCallbackExPtr RegisterCallbackExImpl,
57 IsProfilingActivePtr IsProfilingActiveImpl,
58 FinalizeThreadPtr FinalizeThreadImpl,
59 FinalizeProcessPtr FinalizeProcessImpl,
60 GetNewMethodIDPtr GetNewMethodIDImpl)
61 : NotifyEventFunc(NotifyEventImpl),
62 RegisterCallbackExFunc(RegisterCallbackExImpl),
63 IsProfilingActiveFunc(IsProfilingActiveImpl),
64 FinalizeThreadFunc(FinalizeThreadImpl),
65 FinalizeProcessFunc(FinalizeProcessImpl),
66 GetNewMethodIDFunc(GetNewMethodIDImpl) {
67 }
68
69 // Sends an event anncouncing that a function has been emitted
70 // return values are event-specific. See Intel documentation for details.
71 int iJIT_NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
72 if (!NotifyEventFunc)
73 return -1;
74 return NotifyEventFunc(EventType, EventSpecificData);
75 }
76
77 // Registers a callback function to receive notice of profiling state changes
78 void iJIT_RegisterCallbackEx(void *UserData,
79 iJIT_ModeChangedEx NewModeCallBackFuncEx) {
80 if (RegisterCallbackExFunc)
81 RegisterCallbackExFunc(UserData, NewModeCallBackFuncEx);
82 }
83
84 // Returns the current profiler mode
85 iJIT_IsProfilingActiveFlags iJIT_IsProfilingActive(void) {
86 if (!IsProfilingActiveFunc)
87 return iJIT_NOTHING_RUNNING;
88 return IsProfilingActiveFunc();
89 }
90
91 // Generates a locally unique method ID for use in code registration
92 unsigned int iJIT_GetNewMethodID(void) {
93 if (!GetNewMethodIDFunc)
94 return -1;
95 return GetNewMethodIDFunc();
96 }
97 };
98
99 } //namespace llvm
100
101 #endif //INTEL_JIT_EVENTS_WRAPPER_H
1414 #ifndef LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H
1515 #define LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H
1616
17 #include "llvm/Config/config.h"
1718 #include "llvm/Support/DataTypes.h"
1819 #include "llvm/Support/DebugLoc.h"
1920
2223 namespace llvm {
2324 class Function;
2425 class MachineFunction;
26 class OProfileWrapper;
27 class IntelJITEventsWrapper;
2528
2629 /// JITEvent_EmittedFunctionDetails - Helper struct for containing information
2730 /// about a generated machine code function.
7174 /// to NotifyFunctionEmitted may have been destroyed by the time of the
7275 /// matching NotifyFreeingMachineCode call.
7376 virtual void NotifyFreeingMachineCode(void *) {}
77
78 #if LLVM_USE_INTEL_JITEVENTS
79 // Construct an IntelJITEventListener
80 static JITEventListener *createIntelJITEventListener();
81
82 // Construct an IntelJITEventListener with a test Intel JIT API implementation
83 static JITEventListener *createIntelJITEventListener(
84 IntelJITEventsWrapper* AlternativeImpl);
85 #else
86 static JITEventListener *createIntelJITEventListener() { return 0; }
87
88 static JITEventListener *createIntelJITEventListener(
89 IntelJITEventsWrapper* AlternativeImpl) {
90 return 0;
91 }
92 #endif // USE_INTEL_JITEVENTS
93
94 #if LLVM_USE_OPROFILE
95 // Construct an OProfileJITEventListener
96 static JITEventListener *createOProfileJITEventListener();
97
98 // Construct an OProfileJITEventListener with a test opagent implementation
99 static JITEventListener *createOProfileJITEventListener(
100 OProfileWrapper* AlternativeImpl);
101 #else
102
103 static JITEventListener *createOProfileJITEventListener() { return 0; }
104
105 static JITEventListener *createOProfileJITEventListener(
106 OProfileWrapper* AlternativeImpl) {
107 return 0;
108 }
109 #endif // USE_OPROFILE
110
74111 };
75
76 // This returns NULL if support isn't available.
77 JITEventListener *createOProfileJITEventListener();
78112
79113 } // end namespace llvm.
80114
81 #endif
115 #endif // defined LLVM_EXECUTION_ENGINE_JIT_EVENTLISTENER_H
0 //===-- OProfileWrapper.h - OProfile JIT API Wrapper ------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 // This file defines a OProfileWrapper object that detects if the oprofile
9 // daemon is running, and provides wrappers for opagent functions used to
10 // communicate with the oprofile JIT interface. The dynamic library libopagent
11 // does not need to be linked directly as this object lazily loads the library
12 // when the first op_ function is called.
13 //
14 // See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the
15 // definition of the interface.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #ifndef OPROFILE_WRAPPER_H
20 #define OPROFILE_WRAPPER_H
21
22 #include "llvm/Support/DataTypes.h"
23 #include
24
25 namespace llvm {
26
27
28 class OProfileWrapper {
29 typedef op_agent_t (*op_open_agent_ptr_t)();
30 typedef int (*op_close_agent_ptr_t)(op_agent_t);
31 typedef int (*op_write_native_code_ptr_t)(op_agent_t,
32 const char*,
33 uint64_t,
34 void const*,
35 const unsigned int);
36 typedef int (*op_write_debug_line_info_ptr_t)(op_agent_t,
37 void const*,
38 size_t,
39 struct debug_line_info const*);
40 typedef int (*op_unload_native_code_ptr_t)(op_agent_t, uint64_t);
41
42 // Also used for op_minor_version function which has the same signature
43 typedef int (*op_major_version_ptr_t)(void);
44
45 // This is not a part of the opagent API, but is useful nonetheless
46 typedef bool (*IsOProfileRunningPtrT)(void);
47
48
49 op_agent_t Agent;
50 op_open_agent_ptr_t OpenAgentFunc;
51 op_close_agent_ptr_t CloseAgentFunc;
52 op_write_native_code_ptr_t WriteNativeCodeFunc;
53 op_write_debug_line_info_ptr_t WriteDebugLineInfoFunc;
54 op_unload_native_code_ptr_t UnloadNativeCodeFunc;
55 op_major_version_ptr_t MajorVersionFunc;
56 op_major_version_ptr_t MinorVersionFunc;
57 IsOProfileRunningPtrT IsOProfileRunningFunc;
58
59 bool Initialized;
60
61 public:
62 OProfileWrapper();
63
64 // For testing with a mock opagent implementation, skips the dynamic load and
65 // the function resolution.
66 OProfileWrapper(op_open_agent_ptr_t OpenAgentImpl,
67 op_close_agent_ptr_t CloseAgentImpl,
68 op_write_native_code_ptr_t WriteNativeCodeImpl,
69 op_write_debug_line_info_ptr_t WriteDebugLineInfoImpl,
70 op_unload_native_code_ptr_t UnloadNativeCodeImpl,
71 op_major_version_ptr_t MajorVersionImpl,
72 op_major_version_ptr_t MinorVersionImpl,
73 IsOProfileRunningPtrT MockIsOProfileRunningImpl = 0)
74 : OpenAgentFunc(OpenAgentImpl),
75 CloseAgentFunc(CloseAgentImpl),
76 WriteNativeCodeFunc(WriteNativeCodeImpl),
77 WriteDebugLineInfoFunc(WriteDebugLineInfoImpl),
78 UnloadNativeCodeFunc(UnloadNativeCodeImpl),
79 MajorVersionFunc(MajorVersionImpl),
80 MinorVersionFunc(MinorVersionImpl),
81 IsOProfileRunningFunc(MockIsOProfileRunningImpl),
82 Initialized(true)
83 {
84 }
85
86 // Calls op_open_agent in the oprofile JIT library and saves the returned
87 // op_agent_t handle internally so it can be used when calling all the other
88 // op_* functions. Callers of this class do not need to keep track of
89 // op_agent_t objects.
90 bool op_open_agent();
91
92 int op_close_agent();
93 int op_write_native_code(const char* name,
94 uint64_t addr,
95 void const* code,
96 const unsigned int size);
97 int op_write_debug_line_info(void const* code,
98 size_t num_entries,
99 struct debug_line_info const* info);
100 int op_unload_native_code(uint64_t addr);
101 int op_major_version(void);
102 int op_minor_version(void);
103
104 // Returns true if the oprofiled process is running, the opagent library is
105 // loaded and a connection to the agent has been established, and false
106 // otherwise.
107 bool isAgentAvailable();
108
109 private:
110 // Loads the libopagent library and initializes this wrapper if the oprofile
111 // daemon is running
112 bool initialize();
113
114 // Searches /proc for the oprofile daemon and returns true if the process if
115 // found, or false otherwise.
116 bool checkForOProfileProcEntry();
117
118 bool isOProfileRunning();
119 };
120
121 } // namespace llvm
122
123 #endif //OPROFILE_WRAPPER_H
0
1
2 add_llvm_library(LLVMExecutionEngine
13 ExecutionEngine.cpp
24 ExecutionEngineBindings.cpp
79 add_subdirectory(JIT)
810 add_subdirectory(MCJIT)
911 add_subdirectory(RuntimeDyld)
12
13 if( LLVM_USE_OPROFILE )
14 add_subdirectory(OProfileJIT)
15 endif( LLVM_USE_OPROFILE )
16
17 if( LLVM_USE_INTEL_JITEVENTS )
18 add_subdirectory(IntelJITEvents)
19 endif( LLVM_USE_INTEL_JITEVENTS )
0 //===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Common functionality for JITEventListener implementations
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef EVENT_LISTENER_COMMON_H
14 #define EVENT_LISTENER_COMMON_H
15
16 #include "llvm/Metadata.h"
17 #include "llvm/Analysis/DebugInfo.h"
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/Support/ValueHandle.h"
20 #include "llvm/Support/Path.h"
21
22 namespace llvm {
23
24 namespace jitprofiling {
25
26 class FilenameCache {
27 // Holds the filename of each Scope, so that we can pass a null-terminated
28 // string into oprofile. Use an AssertingVH rather than a ValueMap because we
29 // shouldn't be modifying any MDNodes while this map is alive.
30 DenseMap, std::string> Filenames;
31 DenseMap, std::string> Paths;
32
33 public:
34 const char *getFilename(MDNode *Scope) {
35 std::string &Filename = Filenames[Scope];
36 if (Filename.empty()) {
37 DIScope DIScope(Scope);
38 Filename = DIScope.getFilename();
39 }
40 return Filename.c_str();
41 }
42
43 const char *getFullPath(MDNode *Scope) {
44 std::string &P = Paths[Scope];
45 if (P.empty()) {
46 DIScope DIScope(Scope);
47 StringRef DirName = DIScope.getDirectory();
48 StringRef FileName = DIScope.getFilename();
49 SmallString<256> FullPath;
50 if (DirName != "." && DirName != "") {
51 FullPath = DirName;
52 }
53 if (FileName != "") {
54 sys::path::append(FullPath, FileName);
55 }
56 P = FullPath.str();
57 }
58 return P.c_str();
59 }
60 };
61
62 } // namespace jitprofiling
63
64 } // namespace llvm
65
66 #endif //EVENT_LISTENER_COMMON_H
0
1 include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. )
2
3 set(system_libs
4 ${system_libs}
5 jitprofiling
6 )
7
8 add_llvm_library(LLVMIntelJITEvents
9 IntelJITEventListener.cpp
10 )
0 //===-- IntelJITEventListener.cpp - Tell Intel profiler about JITed code --===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a JITEventListener object to tell Intel(R) VTune(TM)
10 // Amplifier XE 2011 about JITted functions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Config/config.h"
15 #include "llvm/ExecutionEngine/JITEventListener.h"
16
17 #define DEBUG_TYPE "amplifier-jit-event-listener"
18 #include "llvm/Function.h"
19 #include "llvm/Metadata.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/OwningPtr.h"
22 #include "llvm/Analysis/DebugInfo.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/ExecutionEngine/IntelJITEventsWrapper.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include "llvm/Support/Errno.h"
28 #include "llvm/Support/ValueHandle.h"
29 #include "EventListenerCommon.h"
30
31 using namespace llvm;
32 using namespace llvm::jitprofiling;
33
34 namespace {
35
36 class IntelJITEventListener : public JITEventListener {
37 typedef DenseMap MethodIDMap;
38
39 IntelJITEventsWrapper& Wrapper;
40 MethodIDMap MethodIDs;
41 FilenameCache Filenames;
42
43 public:
44 IntelJITEventListener(IntelJITEventsWrapper& libraryWrapper)
45 : Wrapper(libraryWrapper) {
46 }
47
48 ~IntelJITEventListener() {
49 }
50
51 virtual void NotifyFunctionEmitted(const Function &F,
52 void *FnStart, size_t FnSize,
53 const EmittedFunctionDetails &Details);
54
55 virtual void NotifyFreeingMachineCode(void *OldPtr);
56 };
57
58 static LineNumberInfo LineStartToIntelJITFormat(
59 uintptr_t StartAddress,
60 uintptr_t Address,
61 DebugLoc Loc) {
62 LineNumberInfo Result;
63
64 Result.Offset = Address - StartAddress;
65 Result.LineNumber = Loc.getLine();
66
67 return Result;
68 }
69
70 static iJIT_Method_Load FunctionDescToIntelJITFormat(
71 IntelJITEventsWrapper& Wrapper,
72 const char* FnName,
73 uintptr_t FnStart,
74 size_t FnSize) {
75 iJIT_Method_Load Result;
76 memset(&Result, 0, sizeof(iJIT_Method_Load));
77
78 Result.method_id = Wrapper.iJIT_GetNewMethodID();
79 Result.method_name = const_cast(FnName);
80 Result.method_load_address = reinterpret_cast(FnStart);
81 Result.method_size = FnSize;
82
83 Result.class_id = 0;
84 Result.class_file_name = NULL;
85 Result.user_data = NULL;
86 Result.user_data_size = 0;
87 Result.env = iJDE_JittingAPI;
88
89 return Result;
90 }
91
92 // Adds the just-emitted function to the symbol table.
93 void IntelJITEventListener::NotifyFunctionEmitted(
94 const Function &F, void *FnStart, size_t FnSize,
95 const EmittedFunctionDetails &Details) {
96 iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(Wrapper,
97 F.getName().data(),
98 reinterpret_cast(FnStart),
99 FnSize);
100
101 std::vector LineInfo;
102
103 if (!Details.LineStarts.empty()) {
104 // Now convert the line number information from the address/DebugLoc
105 // format in Details to the offset/lineno in Intel JIT API format.
106
107 LineInfo.reserve(Details.LineStarts.size() + 1);
108
109 DebugLoc FirstLoc = Details.LineStarts[0].Loc;
110 assert(!FirstLoc.isUnknown()
111 && "LineStarts should not contain unknown DebugLocs");
112
113 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
114 DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
115 if (FunctionDI.Verify()) {
116 FunctionMessage.source_file_name = const_cast(
117 Filenames.getFullPath(FirstLocScope));
118
119 LineNumberInfo FirstLine;
120 FirstLine.Offset = 0;
121 FirstLine.LineNumber = FunctionDI.getLineNumber();
122 LineInfo.push_back(FirstLine);
123 }
124
125 for (std::vector::const_iterator I =
126 Details.LineStarts.begin(), E = Details.LineStarts.end();
127 I != E; ++I) {
128 // This implementation ignores the DebugLoc filename because the Intel
129 // JIT API does not support multiple source files associated with a single
130 // JIT function
131 LineInfo.push_back(LineStartToIntelJITFormat(
132 reinterpret_cast(FnStart),
133 I->Address,
134 I->Loc));
135
136 // If we have no file name yet for the function, use the filename from
137 // the first instruction that has one
138 if (FunctionMessage.source_file_name == 0) {
139 MDNode *scope = I->Loc.getScope(
140 Details.MF->getFunction()->getContext());
141 FunctionMessage.source_file_name = const_cast(
142 Filenames.getFullPath(scope));
143 }
144 }
145
146 FunctionMessage.line_number_size = LineInfo.size();
147 FunctionMessage.line_number_table = &*LineInfo.begin();
148 } else {
149 FunctionMessage.line_number_size = 0;
150 FunctionMessage.line_number_table = 0;
151 }
152
153 Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
154 &FunctionMessage);
155 MethodIDs[FnStart] = FunctionMessage.method_id;
156 }
157
158 void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
159 MethodIDMap::iterator I = MethodIDs.find(FnStart);
160 if (I != MethodIDs.end()) {
161 Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second);
162 MethodIDs.erase(I);
163 }
164 }
165
166 } // anonymous namespace.
167
168 namespace llvm {
169 JITEventListener *JITEventListener::createIntelJITEventListener() {
170 static OwningPtr JITProfilingWrapper(
171 new IntelJITEventsWrapper);
172 return new IntelJITEventListener(*JITProfilingWrapper);
173 }
174
175 // for testing
176 JITEventListener *JITEventListener::createIntelJITEventListener(
177 IntelJITEventsWrapper* TestImpl) {
178 return new IntelJITEventListener(*TestImpl);
179 }
180
181 } // namespace llvm
182
0 ;===- ./lib/ExecutionEngine/JITProfileAmplifier/LLVMBuild.txt --*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [common]
18
19 [component_0]
20 type = Library
21 name = IntelJITEvents
22 parent = ExecutionEngine
0 ##===- lib/ExecutionEngine/JITProfile/Makefile -------------*- Makefile -*-===##
1 #
2 # The LLVM Compiler Infrastructure
3 #
4 # This file is distributed under the University of Illinois Open Source
5 # License. See LICENSE.TXT for details.
6 #
7 ##===----------------------------------------------------------------------===##
8 LEVEL = ../../..
9 LIBRARYNAME = LLVMIntelJITEvents
10
11 include $(LEVEL)/Makefile.config
12
13 SOURCES := IntelJITEventListener.cpp
14 CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
15
16 include $(LLVM_SRC_ROOT)/Makefile.rules
66 JITDwarfEmitter.cpp
77 JITEmitter.cpp
88 JITMemoryManager.cpp
9 OProfileJITEventListener.cpp
109 )
+0
-192
lib/ExecutionEngine/JIT/OProfileJITEventListener.cpp less more
None //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a JITEventListener object that calls into OProfile to tell
10 // it about JITted functions. For now, we only record function names and sizes,
11 // but eventually we'll also record line number information.
12 //
13 // See http://oprofile.sourceforge.net/doc/devel/jit-interface.html for the
14 // definition of the interface we're using.
15 //
16 //===----------------------------------------------------------------------===//
17
18 #define DEBUG_TYPE "oprofile-jit-event-listener"
19 #include "llvm/Function.h"
20 #include "llvm/Metadata.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/Analysis/DebugInfo.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/ExecutionEngine/JITEventListener.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/ValueHandle.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Support/Errno.h"
29 #include "llvm/Config/config.h"
30 #include
31 using namespace llvm;
32
33 #if USE_OPROFILE
34
35 #include
36
37 namespace {
38
39 class OProfileJITEventListener : public JITEventListener {
40 op_agent_t Agent;
41 public:
42 OProfileJITEventListener();
43 ~OProfileJITEventListener();
44
45 virtual void NotifyFunctionEmitted(const Function &F,
46 void *FnStart, size_t FnSize,
47 const EmittedFunctionDetails &Details);
48 virtual void NotifyFreeingMachineCode(void *OldPtr);
49 };
50
51 OProfileJITEventListener::OProfileJITEventListener()
52 : Agent(op_open_agent()) {
53 if (Agent == NULL) {
54 const std::string err_str = sys::StrError();
55 DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
56 } else {
57 DEBUG(dbgs() << "Connected to OProfile agent.\n");
58 }
59 }
60
61 OProfileJITEventListener::~OProfileJITEventListener() {
62 if (Agent != NULL) {
63 if (op_close_agent(Agent) == -1) {
64 const std::string err_str = sys::StrError();
65 DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
66 << err_str << "\n");
67 } else {
68 DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
69 }
70 }
71 }
72
73 class FilenameCache {
74 // Holds the filename of each Scope, so that we can pass a null-terminated
75 // string into oprofile. Use an AssertingVH rather than a ValueMap because we
76 // shouldn't be modifying any MDNodes while this map is alive.
77 DenseMap, std::string> Filenames;
78
79 public:
80 const char *getFilename(MDNode *Scope) {
81 std::string &Filename = Filenames[Scope];
82 if (Filename.empty()) {
83 Filename = DIScope(Scope).getFilename();
84 }
85 return Filename.c_str();
86 }
87 };
88
89 static debug_line_info LineStartToOProfileFormat(
90 const MachineFunction &MF, FilenameCache &Filenames,
91 uintptr_t Address, DebugLoc Loc) {
92 debug_line_info Result;
93 Result.vma = Address;
94 Result.lineno = Loc.getLine();
95 Result.filename = Filenames.getFilename(
96 Loc.getScope(MF.getFunction()->getContext()));
97 DEBUG(dbgs() << "Mapping " << reinterpret_cast(Result.vma) << " to "
98 << Result.filename << ":" << Result.lineno << "\n");
99 return Result;
100 }
101
102 // Adds the just-emitted function to the symbol table.
103 void OProfileJITEventListener::NotifyFunctionEmitted(
104 const Function &F, void *FnStart, size_t FnSize,
105 const EmittedFunctionDetails &Details) {
106 assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
107 if (op_write_native_code(Agent, F.getName().data(),
108 reinterpret_cast(FnStart),
109 FnStart, FnSize) == -1) {
110 DEBUG(dbgs() << "Failed to tell OProfile about native function "
111 << F.getName() << " at ["
112 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
113 return;
114 }
115
116 if (!Details.LineStarts.empty()) {
117 // Now we convert the line number information from the address/DebugLoc
118 // format in Details to the address/filename/lineno format that OProfile
119 // expects. Note that OProfile 0.9.4 has a bug that causes it to ignore
120 // line numbers for addresses above 4G.
121 FilenameCache Filenames;
122 std::vector LineInfo;
123 LineInfo.reserve(1 + Details.LineStarts.size());
124
125 DebugLoc FirstLoc = Details.LineStarts[0].Loc;
126 assert(!FirstLoc.isUnknown()
127 && "LineStarts should not contain unknown DebugLocs");
128 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
129 DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
130 if (FunctionDI.Verify()) {
131 // If we have debug info for the function itself, use that as the line
132 // number of the first several instructions. Otherwise, after filling
133 // LineInfo, we'll adjust the address of the first line number to point at
134 // the start of the function.
135 debug_line_info line_info;
136 line_info.vma = reinterpret_cast(FnStart);
137 line_info.lineno = FunctionDI.getLineNumber();
138 line_info.filename = Filenames.getFilename(FirstLocScope);
139 LineInfo.push_back(line_info);
140 }
141
142 for (std::vector::const_iterator
143 I = Details.LineStarts.begin(), E = Details.LineStarts.end();
144 I != E; ++I) {
145 LineInfo.push_back(LineStartToOProfileFormat(
146 *Details.MF, Filenames, I->Address, I->Loc));
147 }
148
149 // In case the function didn't have line info of its own, adjust the first
150 // line info's address to include the start of the function.
151 LineInfo[0].vma = reinterpret_cast(FnStart);
152
153 if (op_write_debug_line_info(Agent, FnStart,
154 LineInfo.size(), &*LineInfo.begin()) == -1) {
155 DEBUG(dbgs()
156 << "Failed to tell OProfile about line numbers for native function "
157 << F.getName() << " at ["
158 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
159 }
160 }
161 }
162
163 // Removes the being-deleted function from the symbol table.
164 void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
165 assert(FnStart && "Invalid function pointer");
166 if (op_unload_native_code(Agent, reinterpret_cast(FnStart)) == -1) {
167 DEBUG(dbgs()
168 << "Failed to tell OProfile about unload of native function at "
169 << FnStart << "\n");
170 }
171 }
172
173 } // anonymous namespace.
174
175 namespace llvm {
176 JITEventListener *createOProfileJITEventListener() {
177 return new OProfileJITEventListener;
178 }
179 }
180
181 #else // USE_OPROFILE
182
183 namespace llvm {
184 // By defining this to return NULL, we can let clients call it unconditionally,
185 // even if they haven't configured with the OProfile libraries.
186 JITEventListener *createOProfileJITEventListener() {
187 return NULL;
188 }
189 } // namespace llvm
190
191 #endif // USE_OPROFILE
1515 ;===------------------------------------------------------------------------===;
1616
1717 [common]
18 subdirectories = Interpreter JIT MCJIT RuntimeDyld
18 subdirectories = Interpreter JIT MCJIT RuntimeDyld IntelJITEvents OProfileJIT
1919
2020 [component_0]
2121 type = Library
77 ##===----------------------------------------------------------------------===##
88 LEVEL = ../..
99 LIBRARYNAME = LLVMExecutionEngine
10
11 include $(LEVEL)/Makefile.config
12
1013 PARALLEL_DIRS = Interpreter JIT MCJIT RuntimeDyld
1114
12 include $(LEVEL)/Makefile.common
15 ifeq ($(USE_INTEL_JITEVENTS), 1)
16 PARALLEL_DIRS += IntelJITEvents
17 endif
18
19 ifeq ($(USE_OPROFILE), 1)
20 PARALLEL_DIRS += OProfileJIT
21 endif
22
23 include $(LLVM_SRC_ROOT)/Makefile.rules
0
1 include_directories( ${LLVM_OPROFILE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/.. )
2
3 add_llvm_library(LLVMOProfileJIT
4 OProfileJITEventListener.cpp
5 OProfileWrapper.cpp
6 )
0 ;===- ./lib/ExecutionEngine/OProfileJIT/LLVMBuild.txt ----------*- Conf -*--===;
1 ;
2 ; The LLVM Compiler Infrastructure
3 ;
4 ; This file is distributed under the University of Illinois Open Source
5 ; License. See LICENSE.TXT for details.
6 ;
7 ;===------------------------------------------------------------------------===;
8 ;
9 ; This is an LLVMBuild description file for the components in this subdirectory.
10 ;
11 ; For more information on the LLVMBuild system, please see:
12 ;
13 ; http://llvm.org/docs/LLVMBuild.html
14 ;
15 ;===------------------------------------------------------------------------===;
16
17 [common]
18
19 [component_0]
20 type = Library
21 name = OProfileJIT
22 parent = ExecutionEngine
0 ##===- lib/ExecutionEngine/OProfileJIT/Makefile ------------*- Makefile -*-===##
1 #
2 # The LLVM Compiler Infrastructure
3 #
4 # This file is distributed under the University of Illinois Open Source
5 # License. See LICENSE.TXT for details.
6 #
7 ##===----------------------------------------------------------------------===##
8 LEVEL = ../../..
9 LIBRARYNAME = LLVMOProfileJIT
10
11 include $(LEVEL)/Makefile.config
12
13 SOURCES += OProfileJITEventListener.cpp \
14 OProfileWrapper.cpp
15 CPPFLAGS += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
16
17 include $(LLVM_SRC_ROOT)/Makefile.rules
0 //===-- OProfileJITEventListener.cpp - Tell OProfile about JITted code ----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines a JITEventListener object that uses OProfileWrapper to tell
10 // oprofile about JITted functions, including source line information.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Config/config.h"
15 #include "llvm/ExecutionEngine/JITEventListener.h"
16
17 #define DEBUG_TYPE "oprofile-jit-event-listener"
18 #include "llvm/Function.h"
19 #include "llvm/ADT/OwningPtr.h"
20 #include "llvm/Analysis/DebugInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/ExecutionEngine/OProfileWrapper.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Support/Errno.h"
26 #include "EventListenerCommon.h"
27
28 #include
29 #include
30
31 using namespace llvm;
32 using namespace llvm::jitprofiling;
33
34 namespace {
35
36 class OProfileJITEventListener : public JITEventListener {
37 OProfileWrapper& Wrapper;
38
39 void initialize();
40
41 public:
42 OProfileJITEventListener(OProfileWrapper& LibraryWrapper)
43 : Wrapper(LibraryWrapper) {
44 initialize();
45 }
46
47 ~OProfileJITEventListener();
48
49 virtual void NotifyFunctionEmitted(const Function &F,
50 void *FnStart, size_t FnSize,
51 const JITEvent_EmittedFunctionDetails &Details);
52
53 virtual void NotifyFreeingMachineCode(void *OldPtr);
54 };
55
56 void OProfileJITEventListener::initialize() {
57 if (!Wrapper.op_open_agent()) {
58 const std::string err_str = sys::StrError();
59 DEBUG(dbgs() << "Failed to connect to OProfile agent: " << err_str << "\n");
60 } else {
61 DEBUG(dbgs() << "Connected to OProfile agent.\n");
62 }
63 }
64
65 OProfileJITEventListener::~OProfileJITEventListener() {
66 if (Wrapper.isAgentAvailable()) {
67 if (Wrapper.op_close_agent() == -1) {
68 const std::string err_str = sys::StrError();
69 DEBUG(dbgs() << "Failed to disconnect from OProfile agent: "
70 << err_str << "\n");
71 } else {
72 DEBUG(dbgs() << "Disconnected from OProfile agent.\n");
73 }
74 }
75 }
76
77 static debug_line_info LineStartToOProfileFormat(
78 const MachineFunction &MF, FilenameCache &Filenames,
79 uintptr_t Address, DebugLoc Loc) {
80 debug_line_info Result;
81 Result.vma = Address;
82 Result.lineno = Loc.getLine();
83 Result.filename = Filenames.getFilename(
84 Loc.getScope(MF.getFunction()->getContext()));
85 DEBUG(dbgs() << "Mapping " << reinterpret_cast(Result.vma) << " to "
86 << Result.filename << ":" << Result.lineno << "\n");
87 return Result;
88 }
89
90 // Adds the just-emitted function to the symbol table.
91 void OProfileJITEventListener::NotifyFunctionEmitted(
92 const Function &F, void *FnStart, size_t FnSize,
93 const JITEvent_EmittedFunctionDetails &Details) {
94 assert(F.hasName() && FnStart != 0 && "Bad symbol to add");
95 if (Wrapper.op_write_native_code(F.getName().data(),
96 reinterpret_cast(FnStart),
97 FnStart, FnSize) == -1) {
98 DEBUG(dbgs() << "Failed to tell OProfile about native function "
99 << F.getName() << " at ["
100 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
101 return;
102 }
103
104 if (!Details.LineStarts.empty()) {
105 // Now we convert the line number information from the address/DebugLoc
106 // format in Details to the address/filename/lineno format that OProfile
107 // expects. Note that OProfile 0.9.4 has a bug that causes it to ignore
108 // line numbers for addresses above 4G.
109 FilenameCache Filenames;
110 std::vector LineInfo;
111 LineInfo.reserve(1 + Details.LineStarts.size());
112
113 DebugLoc FirstLoc = Details.LineStarts[0].Loc;
114 assert(!FirstLoc.isUnknown()
115 && "LineStarts should not contain unknown DebugLocs");
116 MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
117 DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
118 if (FunctionDI.Verify()) {
119 // If we have debug info for the function itself, use that as the line
120 // number of the first several instructions. Otherwise, after filling
121 // LineInfo, we'll adjust the address of the first line number to point at
122 // the start of the function.
123 debug_line_info line_info;
124 line_info.vma = reinterpret_cast(FnStart);
125 line_info.lineno = FunctionDI.getLineNumber();
126 line_info.filename = Filenames.getFilename(FirstLocScope);
127 LineInfo.push_back(line_info);
128 }
129
130 for (std::vector::const_iterator
131 I = Details.LineStarts.begin(), E = Details.LineStarts.end();
132 I != E; ++I) {
133 LineInfo.push_back(LineStartToOProfileFormat(
134 *Details.MF, Filenames, I->Address, I->Loc));
135 }
136
137 // In case the function didn't have line info of its own, adjust the first
138 // line info's address to include the start of the function.
139 LineInfo[0].vma = reinterpret_cast(FnStart);
140
141 if (Wrapper.op_write_debug_line_info(FnStart, LineInfo.size(),
142 &*LineInfo.begin()) == -1) {
143 DEBUG(dbgs()
144 << "Failed to tell OProfile about line numbers for native function "
145 << F.getName() << " at ["
146 << FnStart << "-" << ((char*)FnStart + FnSize) << "]\n");
147 }
148 }
149 }
150
151 // Removes the being-deleted function from the symbol table.
152 void OProfileJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
153 assert(FnStart && "Invalid function pointer");
154 if (Wrapper.op_unload_native_code(reinterpret_cast(FnStart)) == -1) {
155 DEBUG(dbgs()
156 << "Failed to tell OProfile about unload of native function at "
157 << FnStart << "\n");
158 }
159 }
160
161 } // anonymous namespace.
162
163 namespace llvm {
164 JITEventListener *JITEventListener::createOProfileJITEventListener() {
165 static OwningPtr JITProfilingWrapper(new OProfileWrapper);
166 return new OProfileJITEventListener(*JITProfilingWrapper);
167 }
168
169 // for testing
170 JITEventListener *JITEventListener::createOProfileJITEventListener(
171 OProfileWrapper* TestImpl) {
172 return new OProfileJITEventListener(*TestImpl);
173 }
174
175 } // namespace llvm
176
0 //===-- OProfileWrapper.cpp - OProfile JIT API Wrapper implementation -----===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the interface in OProfileWrapper.h. It is responsible
10 // for loading the opagent dynamic library when the first call to an op_
11 // function occurs.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ExecutionEngine/OProfileWrapper.h"
16
17 #define DEBUG_TYPE "oprofile-wrapper"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Support/DynamicLibrary.h"
21 #include "llvm/Support/Mutex.h"
22 #include "llvm/Support/MutexGuard.h"
23 #include "llvm/ADT/SmallString.h"
24
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31
32 namespace {
33
34 // Global mutex to ensure a single thread initializes oprofile agent.
35 llvm::sys::Mutex OProfileInitializationMutex;
36
37 } // anonymous namespace
38
39 namespace llvm {
40
41 OProfileWrapper::OProfileWrapper()
42 : Agent(0),
43 OpenAgentFunc(0),
44 CloseAgentFunc(0),
45 WriteNativeCodeFunc(0),
46 WriteDebugLineInfoFunc(0),
47 UnloadNativeCodeFunc(0),
48 MajorVersionFunc(0),
49 MinorVersionFunc(0),
50 IsOProfileRunningFunc(0),
51 Initialized(false) {
52 }
53
54 bool OProfileWrapper::initialize() {
55 using namespace llvm;
56 using namespace llvm::sys;
57
58 MutexGuard Guard(OProfileInitializationMutex);
59
60 if (Initialized)
61 return OpenAgentFunc != 0;
62
63 Initialized = true;
64
65 // If the oprofile daemon is not running, don't load the opagent library
66 if (!isOProfileRunning()) {
67 DEBUG(dbgs() << "OProfile daemon is not detected.\n");
68 return false;
69 }
70
71 std::string error;
72 if(!DynamicLibrary::LoadLibraryPermanently("libopagent.so", &error)) {
73 DEBUG(dbgs()
74 << "OProfile connector library libopagent.so could not be loaded: "
75 << error << "\n");
76 }
77
78 // Get the addresses of the opagent functions
79 OpenAgentFunc = (op_open_agent_ptr_t)(intptr_t)
80 DynamicLibrary::SearchForAddressOfSymbol("op_open_agent");
81 CloseAgentFunc = (op_close_agent_ptr_t)(intptr_t)
82 DynamicLibrary::SearchForAddressOfSymbol("op_close_agent");
83 WriteNativeCodeFunc = (op_write_native_code_ptr_t)(intptr_t)
84 DynamicLibrary::SearchForAddressOfSymbol("op_write_native_code");
85 WriteDebugLineInfoFunc = (op_write_debug_line_info_ptr_t)(intptr_t)
86 DynamicLibrary::SearchForAddressOfSymbol("op_write_debug_line_info");
87 UnloadNativeCodeFunc = (op_unload_native_code_ptr_t)(intptr_t)
88 DynamicLibrary::SearchForAddressOfSymbol("op_unload_native_code");
89 MajorVersionFunc = (op_major_version_ptr_t)(intptr_t)
90 DynamicLibrary::SearchForAddressOfSymbol("op_major_version");
91 MinorVersionFunc = (op_major_version_ptr_t)(intptr_t)
92 DynamicLibrary::SearchForAddressOfSymbol("op_minor_version");
93
94 // With missing functions, we can do nothing
95 if (!OpenAgentFunc
96 || !CloseAgentFunc
97 || !WriteNativeCodeFunc
98 || !WriteDebugLineInfoFunc
99 || !UnloadNativeCodeFunc) {
100 OpenAgentFunc = 0;
101 CloseAgentFunc = 0;
102 WriteNativeCodeFunc = 0;
103 WriteDebugLineInfoFunc = 0;
104 UnloadNativeCodeFunc = 0;
105 return false;
106 }
107
108 return true;
109 }
110
111 bool OProfileWrapper::isOProfileRunning() {
112 if (IsOProfileRunningFunc != 0)
113 return IsOProfileRunningFunc();
114 return checkForOProfileProcEntry();
115 }
116
117 bool OProfileWrapper::checkForOProfileProcEntry() {
118 DIR* ProcDir;
119
120 ProcDir = opendir("/proc");
121 if (!ProcDir)
122 return false;
123
124 // Walk the /proc tree looking for the oprofile daemon
125 struct dirent* Entry;
126 while (0 != (Entry = readdir(ProcDir))) {
127 if (Entry->d_type == DT_DIR) {
128 // Build a path from the current entry name
129 SmallString<256> CmdLineFName;
130 raw_svector_ostream(CmdLineFName) << "/proc/" << Entry->d_name
131 << "/cmdline";
132
133 // Open the cmdline file
134 int CmdLineFD = open(CmdLineFName.c_str(), S_IRUSR);
135 if (CmdLineFD != -1) {
136 char ExeName[PATH_MAX+1];
137 char* BaseName = 0;
138
139 // Read the cmdline file
140 ssize_t NumRead = read(CmdLineFD, ExeName, PATH_MAX+1);
141 close(CmdLineFD);
142 ssize_t Idx = 0;
143
144 // Find the terminator for the first string
145 while (Idx < NumRead-1 && ExeName[Idx] != 0) {
146 Idx++;
147 }
148
149 // Go back to the last non-null character
150 Idx--;
151
152 // Find the last path separator in the first string
153 while (Idx > 0) {
154 if (ExeName[Idx] == '/') {
155 BaseName = ExeName + Idx + 1;
156 break;
157 }
158 Idx--;
159 }
160
161 // Test this to see if it is the oprofile daemon
162 if (BaseName != 0 && !strcmp("oprofiled", BaseName)) {
163 // If it is, we're done
164 closedir(ProcDir);
165 return true;
166 }
167 }
168 }
169 }
170
171 // We've looked through all the files and didn't find the daemon
172 closedir(ProcDir);
173 return false;
174 }
175
176 bool OProfileWrapper::op_open_agent() {
177 if (!Initialized)
178 initialize();
179
180 if (OpenAgentFunc != 0) {
181 Agent = OpenAgentFunc();
182 return Agent != 0;
183 }
184
185 return false;
186 }
187
188 int OProfileWrapper::op_close_agent() {
189 if (!Initialized)
190 initialize();
191
192 int ret = -1;
193 if (Agent && CloseAgentFunc) {
194 ret = CloseAgentFunc(Agent);
195 if (ret == 0) {
196 Agent = 0;
197 }
198 }
199 return ret;
200 }
201
202 bool OProfileWrapper::isAgentAvailable() {
203 return Agent != 0;
204 }
205
206 int OProfileWrapper::op_write_native_code(const char* Name,
207 uint64_t Addr,
208 void const* Code,
209 const unsigned int Size) {
210 if (!Initialized)
211 initialize();
212
213 if (Agent && WriteNativeCodeFunc)
214 return WriteNativeCodeFunc(Agent, Name, Addr, Code, Size);
215
216 return -1;
217 }
218
219 int OProfileWrapper::op_write_debug_line_info(
220 void const* Code,
221 size_t NumEntries,
222 struct debug_line_info const* Info) {
223 if (!Initialized)
224 initialize();
225
226 if (Agent && WriteDebugLineInfoFunc)
227 return WriteDebugLineInfoFunc(Agent, Code, NumEntries, Info);
228
229 return -1;
230 }
231
232 int OProfileWrapper::op_major_version() {
233 if (!Initialized)
234 initialize();
235
236 if (Agent && MajorVersionFunc)
237 return MajorVersionFunc();
238
239 return -1;
240 }
241
242 int OProfileWrapper::op_minor_version() {
243 if (!Initialized)
244 initialize();
245
246 if (Agent && MinorVersionFunc)
247 return MinorVersionFunc();
248
249 return -1;
250 }
251
252 int OProfileWrapper::op_unload_native_code(uint64_t Addr) {
253 if (!Initialized)
254 initialize();
255
256 if (Agent && UnloadNativeCodeFunc)
257 return UnloadNativeCodeFunc(Agent, Addr);
258
259 return -1;
260 }
261
262 } // namespace llvm
0
1 link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} )
2
3 set(LLVM_LINK_COMPONENTS mcjit jit interpreter nativecodegen bitreader asmparser selectiondag)
4
5 if( LLVM_USE_OPROFILE )
6 set(LLVM_LINK_COMPONENTS
7 ${LLVM_LINK_COMPONENTS}
8 OProfileJIT
9 )
10 endif( LLVM_USE_OPROFILE )
11
12 if( LLVM_USE_INTEL_JITEVENTS )
13 set(LLVM_LINK_COMPONENTS
14 ${LLVM_LINK_COMPONENTS}
15 IntelJITEvents
16 )
17 endif( LLVM_USE_INTEL_JITEVENTS )
118
219 add_llvm_tool(lli
320 lli.cpp
88
99 LEVEL := ../..
1010 TOOLNAME := lli
11
12 include $(LEVEL)/Makefile.config
13
1114 LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selectiondag
1215
13 include $(LEVEL)/Makefile.common
16 # If Intel JIT Events support is confiured, link against the LLVM Intel JIT
17 # Events interface library
18 ifeq ($(USE_INTEL_JITEVENTS), 1)
19 LINK_COMPONENTS += inteljitevents
20 endif
21
22 # If oprofile support is confiured, link against the LLVM oprofile interface
23 # library
24 ifeq ($(USE_OPROFILE), 1)
25 LINK_COMPONENTS += oprofilejit
26 endif
27
28 include $(LLVM_SRC_ROOT)/Makefile.rules
237237 exit(1);
238238 }
239239
240 EE->RegisterJITEventListener(createOProfileJITEventListener());
240 // The following functions have no effect if their respective profiling
241 // support wasn't enabled in the build configuration.
242 EE->RegisterJITEventListener(
243 JITEventListener::createOProfileJITEventListener());
244 EE->RegisterJITEventListener(
245 JITEventListener::createIntelJITEventListener());
241246
242247 EE->DisableLazyCompilation(NoLazyCompilation);
243248
8282 Analysis/ScalarEvolutionTest.cpp
8383 )
8484
85 if( LLVM_USE_INTEL_JITEVENTS )
86 include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} )
87 link_directories( ${LLVM_INTEL_JITEVENTS_LIBDIR} )
88 set(ProfileTestSources
89 ExecutionEngine/IntelJITEventListenerTest.cpp
90 )
91 set(LLVM_LINK_COMPONENTS
92 ${LLVM_LINK_COMPONENTS}
93 IntelJITEvents
94 )
95 endif( LLVM_USE_INTEL_JITEVENTS )
96
97 if( LLVM_USE_OPROFILE )
98 set(ProfileTestSources
99 ${ProfileTestSources}
100 ExecutionEngine/OProfileJITEventListenerTest.cpp
101 )
102 set(LLVM_LINK_COMPONENTS
103 ${LLVM_LINK_COMPONENTS}
104 OProfileJIT
105 )
106 endif( LLVM_USE_OPROFILE )
107
85108 add_llvm_unittest(ExecutionEngine
86109 ExecutionEngine/ExecutionEngineTest.cpp
110 ExecutionEngine/JITEventListenerTest.cpp
111 ${ProfileTestSources}
87112 )
88113
89114 set(JITTestsSources
90 ExecutionEngine/JIT/JITEventListenerTest.cpp
91115 ExecutionEngine/JIT/JITMemoryManagerTest.cpp
92116 ExecutionEngine/JIT/JITTest.cpp
93117 ExecutionEngine/JIT/MultiJITTest.cpp
0 //===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "JITEventListenerTestCommon.h"
10
11 using namespace llvm;
12
13 #include "llvm/ExecutionEngine/IntelJITEventsWrapper.h"
14
15 #include
16 #include
17
18 namespace {
19
20 // map of function ("method") IDs to source locations
21 NativeCodeMap ReportedDebugFuncs;
22
23 } // namespace
24
25 /// Mock implementaion of Intel JIT API jitprofiling library
26 namespace test_jitprofiling {
27
28 int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) {
29 switch (EventType) {
30 case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: {
31 EXPECT_TRUE(0 != EventSpecificData);
32 iJIT_Method_Load* msg = static_cast(EventSpecificData);
33
34 ReportedDebugFuncs[msg->method_id];
35
36 for(unsigned int i = 0; i < msg->line_number_size; ++i) {
37 EXPECT_TRUE(0 != msg->line_number_table);
38 std::pair loc(
39 std::string(msg->source_file_name),
40 msg->line_number_table[i].LineNumber);
41 ReportedDebugFuncs[msg->method_id].push_back(loc);
42 }
43 }
44 break;
45 case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: {
46 EXPECT_TRUE(0 != EventSpecificData);
47 unsigned int UnloadId
48 = *reinterpret_cast(EventSpecificData);
49 EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId));
50 }
51 default:
52 break;
53 }
54 return 0;
55 }
56
57 iJIT_IsProfilingActiveFlags IsProfilingActive(void) {
58 // for testing, pretend we have an Intel Parallel Amplifier XE 2011
59 // instance attached
60 return iJIT_SAMPLING_ON;
61 }
62
63 unsigned int GetNewMethodID(void) {
64 static unsigned int id = 0;
65 return ++id;
66 }
67
68 } //namespace test_jitprofiling
69
70 class IntelJITEventListenerTest
71 : public JITEventListenerTestBase {
72 public:
73 IntelJITEventListenerTest()
74 : JITEventListenerTestBase(
75 new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0,
76 test_jitprofiling::IsProfilingActive, 0, 0,
77 test_jitprofiling::GetNewMethodID))
78 {
79 EXPECT_TRUE(0 != MockWrapper);
80
81 Listener.reset(JITEventListener::createIntelJITEventListener(
82 MockWrapper.get()));
83 EXPECT_TRUE(0 != Listener);
84 EE->RegisterJITEventListener(Listener.get());
85 }
86 };
87
88 TEST_F(IntelJITEventListenerTest, NoDebugInfo) {
89 TestNoDebugInfo(ReportedDebugFuncs);
90 }
91
92 TEST_F(IntelJITEventListenerTest, SingleLine) {
93 TestSingleLine(ReportedDebugFuncs);
94 }
95
96 TEST_F(IntelJITEventListenerTest, MultipleLines) {
97 TestMultipleLines(ReportedDebugFuncs);
98 }
99
100 // This testcase is disabled because the Intel JIT API does not support a single
101 // JITted function with source lines associated with multiple files
102 /*
103 TEST_F(IntelJITEventListenerTest, MultipleFiles) {
104 TestMultipleFiles(ReportedDebugFuncs);
105 }
106 */
107
108 testing::Environment* const jit_env =
109 testing::AddGlobalTestEnvironment(new JITEnvironment);
None //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ExecutionEngine/JITEventListener.h"
10
11 #include "llvm/LLVMContext.h"
12 #include "llvm/Instructions.h"
13 #include "llvm/Module.h"
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/CodeGen/MachineCodeInfo.h"
16 #include "llvm/ExecutionEngine/JIT.h"
17 #include "llvm/Support/TypeBuilder.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "gtest/gtest.h"
20 #include
21
22 using namespace llvm;
23
24 int dummy;
25
26 namespace {
27
28 struct FunctionEmittedEvent {
29 // Indices are local to the RecordingJITEventListener, since the
30 // JITEventListener interface makes no guarantees about the order of
31 // calls between Listeners.
32 unsigned Index;
33 const Function *F;
34 void *Code;
35 size_t Size;
36 JITEvent_EmittedFunctionDetails Details;
37 };
38 struct FunctionFreedEvent {
39 unsigned Index;
40 void *Code;
41 };
42
43 struct RecordingJITEventListener : public JITEventListener {
44 std::vector EmittedEvents;
45 std::vector FreedEvents;
46
47 unsigned NextIndex;
48
49 RecordingJITEventListener() : NextIndex(0) {}
50
51 virtual void NotifyFunctionEmitted(const Function &F,
52 void *Code, size_t Size,
53 const EmittedFunctionDetails &Details) {
54 FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details};
55 EmittedEvents.push_back(Event);
56 }
57
58 virtual void NotifyFreeingMachineCode(void *OldPtr) {
59 FunctionFreedEvent Event = {NextIndex++, OldPtr};
60 FreedEvents.push_back(Event);
61 }
62 };
63
64 class JITEventListenerTest : public testing::Test {
65 protected:
66 JITEventListenerTest()
67 : M(new Module("module", getGlobalContext())),
68 EE(EngineBuilder(M)
69 .setEngineKind(EngineKind::JIT)
70 .create()) {
71 }
72
73 Module *M;
74 const OwningPtr EE;
75 };
76
77 Function *buildFunction(Module *M) {
78 Function *Result = Function::Create(
79 TypeBuilder::get(getGlobalContext()),
80 GlobalValue::ExternalLinkage, "id", M);
81 Value *Arg = Result->arg_begin();
82 BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
83 ReturnInst::Create(M->getContext(), Arg, BB);
84 return Result;
85 }
86
87 // Tests that a single JITEventListener follows JIT events accurately.
88 TEST_F(JITEventListenerTest, Simple) {
89 RecordingJITEventListener Listener;
90 EE->RegisterJITEventListener(&Listener);
91 Function *F1 = buildFunction(M);
92 Function *F2 = buildFunction(M);
93
94 void *F1_addr = EE->getPointerToFunction(F1);
95 void *F2_addr = EE->getPointerToFunction(F2);
96 EE->getPointerToFunction(F1); // Should do nothing.
97 EE->freeMachineCodeForFunction(F1);
98 EE->freeMachineCodeForFunction(F2);
99
100 ASSERT_EQ(2U, Listener.EmittedEvents.size());
101 ASSERT_EQ(2U, Listener.FreedEvents.size());
102
103 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
104 EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
105 EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
106 EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
107 << "We don't know how big the function will be, but it had better"
108 << " contain some bytes.";
109
110 EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
111 EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
112 EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
113 EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
114 << "We don't know how big the function will be, but it had better"
115 << " contain some bytes.";
116
117 EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
118 EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
119
120 EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
121 EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
122
123 F1->eraseFromParent();
124 F2->eraseFromParent();
125 }
126
127 // Tests that a single JITEventListener follows JIT events accurately.
128 TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
129 RecordingJITEventListener Listener1;
130 RecordingJITEventListener Listener2;
131 RecordingJITEventListener Listener3;
132 Function *F1 = buildFunction(M);
133 Function *F2 = buildFunction(M);
134
135 EE->RegisterJITEventListener(&Listener1);
136 EE->RegisterJITEventListener(&Listener2);
137 void *F1_addr = EE->getPointerToFunction(F1);
138 EE->RegisterJITEventListener(&Listener3);
139 EE->UnregisterJITEventListener(&Listener1);
140 void *F2_addr = EE->getPointerToFunction(F2);
141 EE->UnregisterJITEventListener(&Listener2);
142 EE->UnregisterJITEventListener(&Listener3);
143 EE->freeMachineCodeForFunction(F1);
144 EE->RegisterJITEventListener(&Listener2);
145 EE->RegisterJITEventListener(&Listener3);
146 EE->RegisterJITEventListener(&Listener1);
147 EE->freeMachineCodeForFunction(F2);
148 EE->UnregisterJITEventListener(&Listener1);
149 EE->UnregisterJITEventListener(&Listener2);
150 EE->UnregisterJITEventListener(&Listener3);
151
152 // Listener 1.
153 ASSERT_EQ(1U, Listener1.EmittedEvents.size());
154 ASSERT_EQ(1U, Listener1.FreedEvents.size());
155
156 EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
157 EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
158 EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
159 EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
160 << "We don't know how big the function will be, but it had better"
161 << " contain some bytes.";
162
163 EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
164 EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
165
166 // Listener 2.
167 ASSERT_EQ(2U, Listener2.EmittedEvents.size());
168 ASSERT_EQ(1U, Listener2.FreedEvents.size());
169
170 EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
171 EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
172 EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
173 EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
174 << "We don't know how big the function will be, but it had better"
175 << " contain some bytes.";
176
177 EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
178 EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
179 EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
180 EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
181 << "We don't know how big the function will be, but it had better"
182 << " contain some bytes.";
183
184 EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
185 EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
186
187 // Listener 3.
188 ASSERT_EQ(1U, Listener3.EmittedEvents.size());
189 ASSERT_EQ(1U, Listener3.FreedEvents.size());
190
191 EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
192 EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
193 EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
194 EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
195 << "We don't know how big the function will be, but it had better"
196 << " contain some bytes.";
197
198 EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
199 EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
200
201 F1->eraseFromParent();
202 F2->eraseFromParent();
203 }
204
205 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
206 RecordingJITEventListener Listener;
207 MachineCodeInfo MCI;
208 Function *F = buildFunction(M);
209
210 EE->RegisterJITEventListener(&Listener);
211 EE->runJITOnFunction(F, &MCI);
212 void *F_addr = EE->getPointerToFunction(F);
213 EE->freeMachineCodeForFunction(F);
214
215 ASSERT_EQ(1U, Listener.EmittedEvents.size());
216 ASSERT_EQ(1U, Listener.FreedEvents.size());
217
218 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
219 EXPECT_EQ(F, Listener.EmittedEvents[0].F);
220 EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
221 EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
222 EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
223
224 EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
225 EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
226 }
227
228 class JITEnvironment : public testing::Environment {
229 virtual void SetUp() {
230 // Required to create a JIT.
231 InitializeNativeTarget();
232 }
233 };
234 testing::Environment* const jit_env =
235 testing::AddGlobalTestEnvironment(new JITEnvironment);
236
237 } // anonymous namespace
0 //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/ExecutionEngine/JITEventListener.h"
10
11 #include "llvm/LLVMContext.h"
12 #include "llvm/Instructions.h"
13 #include "llvm/Module.h"
14 #include "llvm/ADT/OwningPtr.h"
15 #include "llvm/CodeGen/MachineCodeInfo.h"
16 #include "llvm/ExecutionEngine/JIT.h"
17 #include "llvm/Support/TypeBuilder.h"
18 #include "llvm/Support/TargetSelect.h"
19 #include "gtest/gtest.h"
20 #include
21
22 using namespace llvm;
23
24 int dummy;
25
26 namespace {
27
28 struct FunctionEmittedEvent {
29 // Indices are local to the RecordingJITEventListener, since the
30 // JITEventListener interface makes no guarantees about the order of
31 // calls between Listeners.
32 unsigned Index;
33 const Function *F;
34 void *Code;
35 size_t Size;
36 JITEvent_EmittedFunctionDetails Details;
37 };
38 struct FunctionFreedEvent {
39 unsigned Index;
40 void *Code;
41 };
42
43 struct RecordingJITEventListener : public JITEventListener {
44 std::vector EmittedEvents;
45 std::vector FreedEvents;
46
47 unsigned NextIndex;
48
49 RecordingJITEventListener() : NextIndex(0) {}
50
51 virtual void NotifyFunctionEmitted(const Function &F,
52 void *Code, size_t Size,
53 const EmittedFunctionDetails &Details) {
54 FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details};
55 EmittedEvents.push_back(Event);
56 }
57
58 virtual void NotifyFreeingMachineCode(void *OldPtr) {
59 FunctionFreedEvent Event = {NextIndex++, OldPtr};
60 FreedEvents.push_back(Event);
61 }
62 };
63
64 class JITEventListenerTest : public testing::Test {
65 protected:
66 JITEventListenerTest()
67 : M(new Module("module", getGlobalContext())),
68 EE(EngineBuilder(M)
69 .setEngineKind(EngineKind::JIT)
70 .create()) {
71 }
72
73 Module *M;
74 const OwningPtr EE;
75 };
76
77 Function *buildFunction(Module *M) {
78 Function *Result = Function::Create(
79 TypeBuilder::get(getGlobalContext()),
80 GlobalValue::ExternalLinkage, "id", M);
81 Value *Arg = Result->arg_begin();
82 BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
83 ReturnInst::Create(M->getContext(), Arg, BB);
84 return Result;
85 }
86
87 // Tests that a single JITEventListener follows JIT events accurately.
88 TEST_F(JITEventListenerTest, Simple) {
89 RecordingJITEventListener Listener;
90 EE->RegisterJITEventListener(&Listener);
91 Function *F1 = buildFunction(M);
92 Function *F2 = buildFunction(M);
93
94 void *F1_addr = EE->getPointerToFunction(F1);
95 void *F2_addr = EE->getPointerToFunction(F2);
96 EE->getPointerToFunction(F1); // Should do nothing.
97 EE->freeMachineCodeForFunction(F1);
98 EE->freeMachineCodeForFunction(F2);
99
100 ASSERT_EQ(2U, Listener.EmittedEvents.size());
101 ASSERT_EQ(2U, Listener.FreedEvents.size());
102
103 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
104 EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
105 EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
106 EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
107 << "We don't know how big the function will be, but it had better"
108 << " contain some bytes.";
109
110 EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
111 EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
112 EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
113 EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
114 << "We don't know how big the function will be, but it had better"
115 << " contain some bytes.";
116
117 EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
118 EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
119
120 EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
121 EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
122
123 F1->eraseFromParent();
124 F2->eraseFromParent();
125 }
126
127 // Tests that a single JITEventListener follows JIT events accurately.
128 TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
129 RecordingJITEventListener Listener1;
130 RecordingJITEventListener Listener2;
131 RecordingJITEventListener Listener3;
132 Function *F1 = buildFunction(M);
133 Function *F2 = buildFunction(M);
134
135 EE->RegisterJITEventListener(&Listener1);
136 EE->RegisterJITEventListener(&Listener2);
137 void *F1_addr = EE->getPointerToFunction(F1);
138 EE->RegisterJITEventListener(&Listener3);
139 EE->UnregisterJITEventListener(&Listener1);
140 void *F2_addr = EE->getPointerToFunction(F2);
141 EE->UnregisterJITEventListener(&Listener2);
142 EE->UnregisterJITEventListener(&Listener3);
143 EE->freeMachineCodeForFunction(F1);
144 EE->RegisterJITEventListener(&Listener2);
145 EE->RegisterJITEventListener(&Listener3);
146 EE->RegisterJITEventListener(&Listener1);
147 EE->freeMachineCodeForFunction(F2);
148 EE->UnregisterJITEventListener(&Listener1);
149 EE->UnregisterJITEventListener(&Listener2);
150 EE->UnregisterJITEventListener(&Listener3);
151
152 // Listener 1.
153 ASSERT_EQ(1U, Listener1.EmittedEvents.size());
154 ASSERT_EQ(1U, Listener1.FreedEvents.size());
155
156 EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
157 EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
158 EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
159 EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
160 << "We don't know how big the function will be, but it had better"
161 << " contain some bytes.";
162
163 EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
164 EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
165
166 // Listener 2.
167 ASSERT_EQ(2U, Listener2.EmittedEvents.size());
168 ASSERT_EQ(1U, Listener2.FreedEvents.size());
169
170 EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
171 EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
172 EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
173 EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
174 << "We don't know how big the function will be, but it had better"
175 << " contain some bytes.";
176
177 EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
178 EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
179 EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
180 EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
181 << "We don't know how big the function will be, but it had better"
182 << " contain some bytes.";
183
184 EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
185 EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
186
187 // Listener 3.
188 ASSERT_EQ(1U, Listener3.EmittedEvents.size());
189 ASSERT_EQ(1U, Listener3.FreedEvents.size());
190
191 EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
192 EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
193 EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
194 EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
195 << "We don't know how big the function will be, but it had better"
196 << " contain some bytes.";
197
198 EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
199 EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
200
201 F1->eraseFromParent();
202 F2->eraseFromParent();
203 }
204
205 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
206 RecordingJITEventListener Listener;
207 MachineCodeInfo MCI;
208 Function *F = buildFunction(M);
209
210 EE->RegisterJITEventListener(&Listener);
211 EE->runJITOnFunction(F, &MCI);
212 void *F_addr = EE->getPointerToFunction(F);
213 EE->freeMachineCodeForFunction(F);
214
215 ASSERT_EQ(1U, Listener.EmittedEvents.size());
216 ASSERT_EQ(1U, Listener.FreedEvents.size());
217
218 EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
219 EXPECT_EQ(F, Listener.EmittedEvents[0].F);
220 EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
221 EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
222 EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
223
224 EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
225 EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
226 }
227
228 class JITEnvironment : public testing::Environment {
229 virtual void SetUp() {
230 // Required to create a JIT.
231 InitializeNativeTarget();
232 }
233 };
234 testing::Environment* const jit_env =
235 testing::AddGlobalTestEnvironment(new JITEnvironment);
236
237 } // anonymous namespace
0 //===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===-------------------------------------------------------------------------------===//
8
9 #ifndef JIT_EVENT_LISTENER_TEST_COMMON_H
10 #define JIT_EVENT_LISTENER_TEST_COMMON_H
11
12 #include "llvm/Analysis/DIBuilder.h"
13 #include "llvm/Analysis/DebugInfo.h"
14 #include "llvm/CodeGen/MachineCodeInfo.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/ExecutionEngine/JIT.h"
17 #include "llvm/ExecutionEngine/JITEventListener.h"
18 #include "llvm/Instructions.h"
19 #include "llvm/Module.h"
20 #include "llvm/Support/IRBuilder.h"
21 #include "llvm/Support/Dwarf.h"
22 #include "llvm/Support/TypeBuilder.h"
23 #include "llvm/Support/TargetSelect.h"
24
25 #include "gtest/gtest.h"
26
27 #include
28 #include
29 #include
30
31 typedef std::vector > SourceLocations;
32 typedef std::map NativeCodeMap;
33
34 class JITEnvironment : public testing::Environment {
35 virtual void SetUp() {
36 // Required to create a JIT.
37 llvm::InitializeNativeTarget();
38 }
39 };
40
41 inline unsigned int getLine() {
42 return 12;
43 }
44
45 inline unsigned int getCol() {
46 return 0;
47 }
48
49 inline const char* getFilename() {
50 return "mock_source_file.cpp";
51 }
52
53 // Test fixture shared by tests for listener implementations
54 template
55 class JITEventListenerTestBase : public testing::Test {
56 protected:
57 llvm::OwningPtr MockWrapper;
58 llvm::OwningPtr Listener;
59
60 public:
61 llvm::Module* M;
62 llvm::MDNode* Scope;
63 llvm::ExecutionEngine* EE;
64 llvm::DIBuilder* DebugBuilder;
65 llvm::IRBuilder<> Builder;
66
67 JITEventListenerTestBase(WrapperT* w)
68 : MockWrapper(w)
69 , M(new llvm::Module("module", llvm::getGlobalContext()))
70 , EE(llvm::EngineBuilder(M)
71 .setEngineKind(llvm::EngineKind::JIT)
72 .setOptLevel(llvm::CodeGenOpt::None)
73 .create())
74 , DebugBuilder(new llvm::DIBuilder(*M))
75 , Builder(llvm::getGlobalContext())
76 {
77 DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus,
78 "JIT",
79 "JIT",
80 "JIT",
81 true,
82 "",
83 1);
84
85 Scope = DebugBuilder->createFile(getFilename(), ".");
86 }
87
88 llvm::Function *buildFunction(const SourceLocations& DebugLocations) {
89 using namespace llvm;
90
91 LLVMContext& GlobalContext = getGlobalContext();
92
93 SourceLocations::const_iterator CurrentDebugLocation
94 = DebugLocations.begin();
95
96 if (CurrentDebugLocation != DebugLocations.end()) {
97 DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(),
98 DebugBuilder->createFile(CurrentDebugLocation->first, "."));
99 Builder.SetCurrentDebugLocation(DebugLocation);
100 CurrentDebugLocation++;
101 }
102
103 Function *Result = Function::Create(
104 TypeBuilder::get(GlobalContext),
105 GlobalValue::ExternalLinkage, "id", M);
106 Value *Arg = Result->arg_begin();
107 BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
108 Builder.SetInsertPoint(BB);
109 Value* one = ConstantInt::get(GlobalContext, APInt(32, 1));
110 for(; CurrentDebugLocation != DebugLocations.end();
111 ++CurrentDebugLocation) {
112 Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one));
113 Builder.SetCurrentDebugLocation(
114 DebugLoc::get(CurrentDebugLocation->second, 0,
115 DebugBuilder->createFile(CurrentDebugLocation->first, ".")));
116 }
117 Builder.CreateRet(Arg);
118 return Result;
119 }
120
121 void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) {
122 SourceLocations DebugLocations;
123 llvm::Function* f = buildFunction(DebugLocations);
124 EXPECT_TRUE(0 != f);
125
126 //Cause JITting and callbacks to our listener
127 EXPECT_TRUE(0 != EE->getPointerToFunction(f));
128 EXPECT_TRUE(1 == ReportedDebugFuncs.size());
129
130 EE->freeMachineCodeForFunction(f);
131 EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
132 }
133
134 void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) {
135 SourceLocations DebugLocations;
136 DebugLocations.push_back(std::make_pair(std::string(getFilename()),
137 getLine()));
138 llvm::Function* f = buildFunction(DebugLocations);
139 EXPECT_TRUE(0 != f);
140
141 EXPECT_TRUE(0 != EE->getPointerToFunction(f));
142 EXPECT_TRUE(1 == ReportedDebugFuncs.size());
143 EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(),
144 getFilename());
145 EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine());
146
147 EE->freeMachineCodeForFunction(f);
148 EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
149 }
150
151 void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) {
152 using namespace std;
153
154 SourceLocations DebugLocations;
155 unsigned int c = 5;
156 for(unsigned int i = 0; i < c; ++i) {
157 DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i));
158 }
159
160 llvm::Function* f = buildFunction(DebugLocations);
161 EXPECT_TRUE(0 != f);
162
163 EXPECT_TRUE(0 != EE->getPointerToFunction(f));
164 EXPECT_TRUE(1 == ReportedDebugFuncs.size());
165 SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second;
166 EXPECT_EQ(c, FunctionInfo.size());
167
168 int VerifyCount = 0;
169 for(SourceLocations::iterator i = FunctionInfo.begin();
170 i != FunctionInfo.end();
171 ++i) {
172 EXPECT_STREQ(i->first.c_str(), getFilename());
173 EXPECT_EQ(i->second, getLine() + VerifyCount);
174 VerifyCount++;
175 }
176
177 EE->freeMachineCodeForFunction(f);
178 EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
179 }
180
181 void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) {
182
183 std::string secondFilename("another_file.cpp");
184
185 SourceLocations DebugLocations;
186 DebugLocations.push_back(std::make_pair(std::string(getFilename()),
187 getLine()));
188 DebugLocations.push_back(std::make_pair(secondFilename, getLine()));
189 llvm::Function* f = buildFunction(DebugLocations);
190 EXPECT_TRUE(0 != f);
191
192 EXPECT_TRUE(0 != EE->getPointerToFunction(f));
193 EXPECT_TRUE(1 == ReportedDebugFuncs.size());
194 SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second;
195 EXPECT_TRUE(2 == FunctionInfo.size());
196
197 EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename());
198 EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str());
199
200 EXPECT_EQ(FunctionInfo.at(0).second, getLine());
201 EXPECT_EQ(FunctionInfo.at(1).second, getLine());
202
203 EE->freeMachineCodeForFunction(f);
204 EXPECT_TRUE(ReportedDebugFuncs.size() == 0);
205 }
206 };
207
208 #endif //JIT_EVENT_LISTENER_TEST_COMMON_H
1212
1313 include $(LEVEL)/Makefile.config
1414
15 SOURCES := ExecutionEngineTest.cpp \
16 JITEventListenerTest.cpp
17
18 ifeq ($(USE_INTEL_JITEVENTS), 1)
19 # Build the Intel JIT Events interface tests
20 SOURCES += IntelJITEventListenerTest.cpp
21
22 # Add the Intel JIT Events include directory
23 CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR)
24
25 # Link against the LLVM Intel JIT Evens interface library
26 LINK_COMPONENTS += inteljitevents
27 endif
28
29 ifeq ($(USE_OPROFILE), 1)
30 # Build the OProfile JIT interface tests
31 SOURCES += OProfileJITEventListenerTest.cpp
32
33 # Link against the LLVM oprofile interface library
34 LINK_COMPONENTS += oprofilejit
35 endif
36
37
1538 PARALLEL_DIRS = JIT
1639
1740 include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
0 //===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===--------------------------------------------------------------------------------------===//
8
9 #include "llvm/ExecutionEngine/JITEventListener.h"
10 #include "llvm/ExecutionEngine/OProfileWrapper.h"
11 #include "JITEventListenerTestCommon.h"
12
13 #include
14 #include
15
16 using namespace llvm;
17
18 namespace {
19
20 struct OprofileNativeFunction {
21 const char* Name;
22 uint64_t Addr;
23 const void* CodePtr;
24 unsigned int CodeSize;
25
26 OprofileNativeFunction(const char* name,
27 uint64_t addr,
28 const void* code,
29 unsigned int size)
30 : Name(name)
31 , Addr(addr)
32 , CodePtr(code)
33 , CodeSize(size) {
34 }
35 };
36
37 typedef std::list NativeFunctionList;
38 typedef std::list NativeDebugList;
39 NativeFunctionList NativeFunctions;
40
41 NativeCodeMap ReportedDebugFuncs;
42
43 } // namespace
44
45 /// Mock implementaion of opagent library
46 namespace test_opagent {
47
48 op_agent_t globalAgent = reinterpret_cast(42);
49
50 op_agent_t open_agent()
51 {
52 // return non-null op_agent_t
53 return globalAgent;
54 }
55
56 int close_agent(op_agent_t agent)
57 {
58 EXPECT_EQ(globalAgent, agent);
59 return 0;
60 }
61
62 int write_native_code(op_agent_t agent,
63 const char* name,
64 uint64_t addr,
65 void const* code,
66 unsigned int size)
67 {
68 EXPECT_EQ(globalAgent, agent);
69 OprofileNativeFunction func(name, addr, code, size);
70 NativeFunctions.push_back(func);
71
72 // Verify no other registration has take place for the same address
73 EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end());
74
75 ReportedDebugFuncs[addr];
76 return 0;
77 }
78
79 int write_debug_line_info(op_agent_t agent,
80 void const* code,
81 size_t num_entries,
82 struct debug_line_info const* info)
83 {
84 EXPECT_EQ(globalAgent, agent);
85
86 //verify code has been loaded first
87 uint64_t addr = reinterpret_cast(code);
88 NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr);
89 EXPECT_TRUE(i != ReportedDebugFuncs.end());
90
91 NativeDebugList NativeInfo(info, info + num_entries);
92
93 SourceLocations locs;
94 for(NativeDebugList::iterator i = NativeInfo.begin();
95 i != NativeInfo.end();
96 ++i) {
97 locs.push_back(std::make_pair(std::string(i->filename), i->lineno));
98 }
99 ReportedDebugFuncs[addr] = locs;
100
101 return 0;
102 }
103
104 int unload_native_code(op_agent_t agent, uint64_t addr) {
105 EXPECT_EQ(globalAgent, agent);
106
107 //verify that something for the given JIT addr has been loaded first
108 NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr);
109 EXPECT_TRUE(i != ReportedDebugFuncs.end());
110 ReportedDebugFuncs.erase(i);
111 return 0;
112 }
113
114 int version() {
115 return 1;
116 }
117
118 bool is_oprofile_running() {
119 return true;
120 }
121
122 } //namespace test_opagent
123
124 class OProfileJITEventListenerTest
125 : public JITEventListenerTestBase
126 {
127 public:
128 OProfileJITEventListenerTest()
129 : JITEventListenerTestBase(
130 new OProfileWrapper(test_opagent::open_agent,
131 test_opagent::close_agent,
132 test_opagent::write_native_code,
133 test_opagent::write_debug_line_info,
134 test_opagent::unload_native_code,
135 test_opagent::version,
136 test_opagent::version,
137 test_opagent::is_oprofile_running))
138 {
139 EXPECT_TRUE(0 != MockWrapper);
140
141 Listener.reset(JITEventListener::createOProfileJITEventListener(
142 MockWrapper.get()));
143 EXPECT_TRUE(0 != Listener);
144 EE->RegisterJITEventListener(Listener.get());
145 }
146 };
147
148 TEST_F(OProfileJITEventListenerTest, NoDebugInfo) {
149 TestNoDebugInfo(ReportedDebugFuncs);
150 }
151
152 TEST_F(OProfileJITEventListenerTest, SingleLine) {
153 TestSingleLine(ReportedDebugFuncs);
154 }
155
156 TEST_F(OProfileJITEventListenerTest, MultipleLines) {
157 TestMultipleLines(ReportedDebugFuncs);
158 }
159
160 TEST_F(OProfileJITEventListenerTest, MultipleFiles) {
161 TestMultipleFiles(ReportedDebugFuncs);
162 }
163
164 testing::Environment* const jit_env =
165 testing::AddGlobalTestEnvironment(new JITEnvironment);