#!/bin/sh # vim: ts=4 sw=4 expandtab #---------------------------------------------------------------------------# # Copyright (C) 2002, 2004 The University of Melbourne. # This file may only be copied under the terms of the GNU General # Public License - see the file COPYING in the Mercury distribution. #---------------------------------------------------------------------------# # # This script generates the files mercury_profiling_builtin.[ch] in the # runtime directory, files which contain the C declarations and code of the # primitives needed for the deep profiling of the unify and operations # on builtin types. (The Mercury declarations are in profiling_builtin.m # in the library.) # # It should be executed in the runtime directory. prefix="mercury__profiling_builtin__" tmp_code="/tmp/make_port_code_$$" tmp_prolog="/tmp/make_port_code_prolog$$" tmp_declare_entry="/tmp/make_port_code_decl_$$" tmp_define_entry="/tmp/make_port_code_defn_$$" tmp_init_entry="/tmp/make_port_code_init_$$" tmp_hlc="/tmp/make_port_code_hlc_$$" trap "/bin/rm $tmp_code $tmp_prolog $tmp_declare_entry $tmp_define_entry $tmp_init_entry $tmp_hlc" 0 1 2 3 15 > ${tmp_code} > ${tmp_declare_entry} > ${tmp_define_entry} > ${tmp_init_entry} > ${tmp_hlc} cat > ${tmp_prolog} << END // Copyright (C) 2002 The University of Melbourne. // Copyright (C) 2016, 2018 The Mercury team. // This file is distributed under the terms specified in COPYING.LIB. // The contents of this file were generated by the make_port_code script // in the tools directory. Do not edit. // // The function of the code in this module is described in the paper on deep // profiling by Thomas Conway and Zoltan Somogyi. END source="mercury_profiling_builtin.c" header="mercury_profiling_builtin.h" module="runtime_profiling_builtin_module" protect="MR_MERCURY_PROFILING_BUILTIN_H" for impl in ac sr do case $impl in ac) IMPL=AC ;; sr) IMPL=SR ;; esac for detism in det semi non do case $detism in det) ports="call exit" ;; semi) ports="call exit fail" ;; non) ports="call exit redo fail" ;; esac for port in $ports do case $port in call) file="mercury_deep_call_port_body.h" portdef="MR_CALL_PORT" return="MR_proceed();" if test $detism = non then outermost_define="#define" else outermost_define="#undef " fi decls= inputs="ProcLayout" outputs="TopCSD MiddleCSD" if test $impl = sr then outputs="$outputs OldOutermostActivationPtr" fi if test $detism = non then outputs="$outputs NewOutermostActivationPtr" fi ;; exit|fail) file="mercury_deep_leave_port_body.h" if test $port = exit then portdef="MR_EXIT_PORT" return="MR_proceed();" else portdef="MR_FAIL_PORT" return="MR_r1 = MR_FALSE; MR_proceed();" fi outermost_define="#undef " inputs="TopCSD MiddleCSD" outputs="" if test $impl = sr then inputs="$inputs OldOutermostActivationPtr" fi ;; redo) file="mercury_deep_redo_port_body.h" portdef="MR_REDO_PORT" return="MR_r1 = MR_FALSE; MR_proceed();" outermost_define="#undef " inputs="MiddleCSD NewOutermostActivationPtr" outputs="" ;; esac arity=0 for arg in ${inputs} ${outputs} do arity=`expr ${arity} + 1` done name="${detism}_${port}_port_code_${impl}_${arity}_0" hlcname="${detism}_${port}_port_code_${impl}_${arity}_p_0" msgname="${detism}_${port}_port_code_${impl}" ( echo "" echo "MR_define_entry(${prefix}${name});" echo "{" for arg in ${inputs} ${outputs} do echo "MR_Word ${arg};" done echo "" n=1 for arg in ${inputs} do echo "${arg} = MR_r${n};" n=`expr $n + 1` done echo "" echo "#define MR_PROCNAME \"${msgname}\"" echo "#define MR_VERSION_${IMPL}" echo "#define ${portdef}" echo "${outermost_define} MR_NEED_NEW_OUTERMOST" # We could do "echo "#include \"${file}\"" here to get a # smaller source file. However, if we did that, using gdb to # debug deep profiling would be harder, since gdb doesn't # handle breakpoints on multiply-included lines sensibly. cat ${file} echo "#undef MR_PROCNAME" echo "#undef MR_VERSION_${IMPL}" echo "#undef ${portdef}" echo "#undef MR_NEED_NEW_OUTERMOST" echo "" n=1 for arg in ${outputs} do echo "MR_r${n} = ${arg};" n=`expr $n + 1` done echo "}" echo ${return} ) >> ${tmp_code} decl="MR_declare_entry(${prefix}${name});" echo ${decl} >> ${tmp_declare_entry} defn="MR_define_extern_entry(${prefix}${name});" echo ${defn} >> ${tmp_define_entry} init="MR_init_entry_an(${prefix}${name});" echo ${init} >> ${tmp_init_entry} # We generate prototypes for these functions before the definition # to shut up the warning you would otherwise get. # # Note that the types in the prototype and the definition are # lies. This is OK, because the only reason why we have these # functions is that in the non-deep profiling grades, we need # their addresses, because the library/profiling_builtin.m declares # the corresponding predicates. These functions should never be # called, since the combination of hlc and deep profiling is not # (yet) supported. ( echo echo "extern void MR_CALL" echo "${prefix}${hlcname}(" line=" " n=1 for arg in ${inputs} ${outputs} do if test $n -gt 1 then line="${line}, void *arg${n}" else line="${line}void *arg${n}" fi n=`expr $n + 1` done echo "${line});" echo "void MR_CALL" echo "${prefix}${hlcname}(" line=" " n=1 for arg in ${inputs} ${outputs} do if test $n -gt 1 then line="${line}, void *arg${n}" else line="${line}void *arg${n}" fi n=`expr $n + 1` done echo "${line})" echo "{ MR_fatal_error(\"call to ${prefix}${hlcname}\"); }" ) >> ${tmp_hlc} done done done #---------------------------------------------------------------------------# # assemble the header file cat ${tmp_prolog} > ${header} cat >> ${header} << END #ifndef ${protect} #define ${protect} #include "mercury_goto.h" #ifndef MR_HIGHLEVEL_CODE END cat ${tmp_declare_entry} >> ${header} cat >> ${header} << END #endif // MR_HIGHLEVEL_CODE #endif // ${protect} END #---------------------------------------------------------------------------# # assemble the source file cat ${tmp_prolog} > ${source} cat >> ${source} << END #include "mercury_imp.h" #ifndef MR_HIGHLEVEL_CODE #include "mercury_deep_profiling_hand.h" #include "${header}" END cat ${tmp_define_entry} >> ${source} echo "MR_BEGIN_MODULE(${module})" >> ${source} cat ${tmp_init_entry} >> ${source} echo "MR_BEGIN_CODE" >> ${source} cat ${tmp_code} >> ${source} cat >> ${source} << END MR_END_MODULE #else // MR_HIGHLEVEL_CODE END cat ${tmp_hlc} >> ${source} cat >> ${source} << END #endif // ! MR_HIGHLEVEL_CODE // Ensure that the initialization code for the above module gets to run. /* INIT mercury_sys_init_${module} */ // Forward declarations to suppress gcc -Wmissing-decl warnings. void mercury_sys_init_${module}_init(void); void mercury_sys_init_${module}_init_type_tables(void); #ifdef MR_DEEP_PROFILING void mercury_sys_init_${module}_write_out_proc_statics(FILE *fp); #endif void mercury_sys_init_${module}_init(void) { #ifndef MR_HIGHLEVEL_CODE ${module}(); #endif } void mercury_sys_init_${module}_init_type_tables(void) { // No types to register. } #ifdef MR_DEEP_PROFILING void mercury_sys_init_${module}_write_out_proc_statics(FILE *fp) { // No proc_statics to write out. } #endif END exit 0