Files
mercury/library/term_size_prof_builtin.m
Zoltan Somogyi 62d9fcbe4b Ignore (mostly) comments inside foreign_procs.
compiler/foreign.m:
    When returning the list of identifiers inside a foreign_proc's code,
    ignore the contents of comments. This means that warnings about
    variable names that occur in the foreign_proc's argument list
    but do not occur in the foreign_proc's code cannot be shut up anymore
    by mention the variable name in comments.

    The "mostly" part is that typecheck.m still looks at the bodies
    of foreign_procs without knowing about comments. Fixing that
    will be part a future change.

NEWS.md:
    Announce this breaking change.

compiler/fact_table_gen.m:
    When we try to generate a foreign_proc's body for a fact table
    but cannot do so due to the fact table file not being readable,
    add a marker to the predicate that the fact table is for.

compiler/hlds_markers.m:
    Update the documentation of the existing predicate marker
    we use for this.

compiler/make_hlds_warn.m:
    Do not warn about singleton variables in foreign_proc bodies
    that are empty due to missing fact table files.

library/array.m:
library/io.file.m:
library/profiling_builtin.m:
library/stm_builtin.m:
library/table_builtin.m:
library/term_size_prof_builtin.m:
tests/invalid/erroneous_throw_promise.m:
tests/invalid/foreign_procs_exist_type.m:
tests/invalid/foreign_purity_mismatch.m:
tests/invalid/gh72_errors.m:
tests/invalid_purity/purity.m:
tests/valid/solv.m:
    Shut up warnings about singletons in foreign_procs by adding a _ prefix
    to the names of the relevant arguments, and delete the comments
    that can no longer do that job.

tests/invalid/foreign_purity_mismatch.err_exp:
tests/invalid/gh72_errors.err_exp:
tests/invalid/gh72_errors.err_exp2:
tests/invalid/gh72_errors.err_exp3:
tests/invalid_purity/purity.err_exp:
    Expect updated line numbers.

tests/warnings/warn_return.{m,err_exp}:
    Extend this test case to test that

    - we DO warn about return statements outside comments, but
    - we DO NOT warn about return statements inside comments.
2026-01-28 13:34:30 +11:00

239 lines
7.5 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2003, 2005-2008 The University of Melbourne.
% Copyright (C) 2015, 2018, 2022, 2026 The Mercury team.
% This file is distributed under the terms specified in COPYING.LIB.
%---------------------------------------------------------------------------%
%
% File: term_size_prof.m.
% Author: zs.
% Stability: low.
%
% This file is automatically imported into every module when term size
% profiling is enabled. It contains support predicates used for term size
% profiling.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module term_size_prof_builtin.
:- interface.
% measure_size(Term, Size): return the size of Term as Size.
% The cost of the operation is independent of the size of Term;
% if Term points to the heap, it looks up the size stored at the
% starts of the cell.
%
:- pred measure_size(T::in, int::out) is det.
% measure_size_acc(Term, Size0, Size): similar to measure_size,
% but instead of returning just the size of term, it returns the
% size plus Size0.
%
:- pred measure_size_acc(T::in, int::in, int::out) is det.
% increment_size(Term, Incr): Term must be a term on the heap
% that is not fully ground, and whose size slot's contents represents
% the size of the term in its original binding state. When some of
% Term's free arguments are bound, we must increment its recorded size
% by Incr, the sum of the sizes of the terms bound to those arguments.
% This is what increment_size does. It is impure because it updates
% Term destructively.
%
:- impure pred increment_size(T::in, int::in) is det.
% This function is exactly like int.plus, and is also implemented
% as a builtin. It is duplicated in this module because only predicates
% and functions in builtin modules like this one are immune to dead
% procedure elimination.
%
:- func term_size_plus(int, int) = int.
% We want to take measurements only of the top-level invocations of
% the procedures in the complexity experiment, not the recursive
% invocations. This type says whether we are already executing the
% relevant procedure. Its definition should be kept in sync with
% MR_ComplexityIsActive in runtime/mercury_term_size.h.
:- type complexity_is_active
---> is_inactive
; is_active.
% For each procedure in the complexity experiment, we can take
% measurements for many different top-level invocations. Values
% of the complexity_slot type identify one of these invocations.
:- type complexity_slot == int.
:- impure pred complexity_is_active(complexity_is_active::out) is det.
:- impure pred complexity_call_proc(complexity_slot::out) is det.
:- impure pred complexity_exit_proc(complexity_slot::in) is det.
:- impure pred complexity_fail_proc(complexity_slot::in) is failure.
:- impure pred complexity_redo_proc(complexity_slot::in) is failure.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
% This module import is required by the Mercury clause for measure_size/2.
%
:- import_module require.
%---------------------------------------------------------------------------%
:- pragma foreign_decl("C", "
#ifndef MR_TERM_SIZE_PROFILING_GUARD
#define MR_TERM_SIZE_PROFILING_GUARD
#ifdef MR_RECORD_TERM_SIZES
#include ""mercury_term_size.h""
#endif // MR_RECORD_TERM_SIZES
#endif // MR_TERM_SIZE_PROFILING_GUARD
").
:- pragma foreign_proc("C",
measure_size(Term::in, Size::out),
[thread_safe, promise_pure, will_not_call_mercury, may_not_duplicate],
"{
#ifdef MR_RECORD_TERM_SIZES
MR_TypeInfo type_info;
type_info = (MR_TypeInfo) TypeInfo_for_T;
Size = MR_term_size(type_info, Term);
#ifdef MR_DEBUG_TERM_SIZES
if (MR_heapdebug && MR_lld_print_enabled) {
printf(""measure_size: %p -> %d\\n"",
(void *) Term, (int) Size);
}
#endif
#else
MR_fatal_error(""measure_size: term size profiling not enabled"");
#endif
}").
measure_size(_Value, Size) :-
( if semidet_succeed then
error("measure_size: not implemented")
else
Size = 0
).
:- pragma foreign_proc("C",
measure_size_acc(Term::in, Size0::in, Size::out),
[thread_safe, promise_pure, will_not_call_mercury, may_not_duplicate],
"{
#ifdef MR_RECORD_TERM_SIZES
MR_TypeInfo type_info;
type_info = (MR_TypeInfo) TypeInfo_for_T;
Size = MR_term_size(type_info, Term) + Size0;
#ifdef MR_DEBUG_TERM_SIZES
if (MR_heapdebug && MR_lld_print_enabled) {
printf(""measure_size_acc: %p + %d -> %d\\n"",
(void *) Term, (int) Size0, (int) Size);
}
#endif
#else
MR_fatal_error(""measure_size_acc: term size profiling not enabled"");
#endif
}").
measure_size_acc(_Value, Size0, Size) :-
( if semidet_succeed then
error("measure_size_acc: not implemented")
else
Size = Size0
).
:- pragma foreign_proc("C",
increment_size(Term::in, Incr::in),
[thread_safe, will_not_call_mercury, may_not_duplicate],
"{
#ifdef MR_RECORD_TERM_SIZES
#ifdef MR_DEBUG_TERM_SIZES
if (MR_heapdebug && MR_lld_print_enabled) {
printf(""increment_size: %p + %d\\n"",
(void *) Term, (int) Incr);
}
#endif
MR_mask_field(Term, -1) += Incr;
#else
MR_fatal_error(""increment_size: term size profiling not enabled"");
#endif
}").
increment_size(_Value, _Incr) :-
impure private_builtin.imp.
%---------------------------------------------------------------------------%
% None of the following predicates are designed to be called directly;
% they are designed only to hang foreign_procs onto.
:- pragma foreign_proc("C",
complexity_is_active(_IsActive::out),
[thread_safe, will_not_call_mercury],
"
MR_fatal_error(""complexity_mark_active"");
").
complexity_is_active(IsActive) :-
impure private_builtin.imp,
( if semidet_succeed then
error("complexity_mark_active: not implemented")
else
% Required only to avoid warnings; never executed.
IsActive = is_active
).
:- pragma foreign_proc("C",
complexity_call_proc(_Slot::out),
[thread_safe, will_not_call_mercury],
"
MR_fatal_error(""complexity_call_proc"");
").
complexity_call_proc(Slot) :-
impure private_builtin.imp,
% Required only to avoid warnings; never executed.
private_builtin.unsafe_type_cast(0, Slot).
:- pragma foreign_proc("C",
complexity_exit_proc(_Slot::in),
[thread_safe, will_not_call_mercury],
"
MR_fatal_error(""complexity_exit_proc"");
").
complexity_exit_proc(_Slot) :-
impure private_builtin.imp.
:- pragma foreign_proc("C",
complexity_fail_proc(_Slot::in),
[thread_safe, will_not_call_mercury],
"
MR_fatal_error(""complexity_fail_proc"");
").
complexity_fail_proc(_Slot) :-
impure private_builtin.imp,
fail.
:- pragma foreign_proc("C",
complexity_redo_proc(_Slot::in),
[thread_safe, will_not_call_mercury],
"
MR_fatal_error(""complexity_redo_proc"");
").
complexity_redo_proc(_Slot) :-
impure private_builtin.imp,
fail.
%---------------------------------------------------------------------------%
:- end_module term_size_prof_builtin.
%---------------------------------------------------------------------------%