Files
mercury/compiler/llds_out_code_addr.m
Zoltan Somogyi 5251f76ab6 Simplify the code writing out LLDS C code.
compiler/llds_out_util.m:
    Add decl_set_insert_new, which combines decl_set_is_member and
    decl_set_insert in their typical usage pattern.

compiler/layout_out.m:
compiler/llds_out_code_addr.m:
compiler/llds_out_data.m:
compiler/llds_out_file.m:
compiler/llds_out_global.m:
compiler/llds_out_instr.m:
compiler/rtti_out.m:
    Use decl_set_insert_new where applicable.

    Replace sequences of calls to io.write_{string,int}s with calls to
    io.format.
2022-10-01 19:27:54 +10:00

423 lines
14 KiB
Mathematica

%----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%----------------------------------------------------------------------------%
% Copyright (C) 2009 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.
%----------------------------------------------------------------------------%
%
% File: llds_out_code_addr.m.
% Main authors: conway, fjh, zs.
%
% This module defines the routines for printing out LLDS labels and code
% addresses.
%
%----------------------------------------------------------------------------%
:- module ll_backend.llds_out.llds_out_code_addr.
:- interface.
:- import_module backend_libs.
:- import_module backend_libs.name_mangle.
:- import_module ll_backend.llds.
:- import_module ll_backend.llds_out.llds_out_util.
:- import_module bool.
:- import_module io.
%----------------------------------------------------------------------------%
% output_record_code_addr_decls(Info, CodeAddr, ...) outputs the
% declarations of any extern symbols, etc. that need to be declared
% before output_code_addr(CodeAddr) is called.
%
:- pred output_record_code_addr_decls(llds_out_info::in,
io.text_output_stream::in, code_addr::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
:- pred output_record_code_addr_decls_format(llds_out_info::in,
io.text_output_stream::in, code_addr::in,
string::in, string::in, int::in, int::out, decl_set::in,
decl_set::out, io::di, io::uo) is det.
% Return the suffix after do_call_closure_ or do_call_class_method_
% represented by the given variant.
%
:- func ho_call_variant_to_string(ho_call_variant) = string.
% Output a label (used by garbage collection).
%
:- pred output_label(io.text_output_stream::in, label::in,
io::di, io::uo) is det.
:- pred output_label_no_prefix(io.text_output_stream::in, label::in,
io::di, io::uo) is det.
% Output a label with or without the standard mercury__ prefix.
%
:- pred output_label_maybe_prefix(io.text_output_stream::in,
maybe_add_label_prefix::in, label::in, io::di, io::uo) is det.
% Convert a label to a C string. The first argument controls whether
% we add a prefix ("mercury__") to the string.
%
:- func label_to_c_string(maybe_add_label_prefix, label) = string.
:- pred output_code_addr(io.text_output_stream::in, code_addr::in,
io::di, io::uo) is det.
:- type wrapper
---> wrapper_entry
; wrapper_label
; wrapper_none.
:- pred output_code_addr_from_pieces(io.text_output_stream::in,
string::in, bool::in, wrapper::in, io::di, io::uo) is det.
:- pred code_addr_to_string_base(code_addr::in,
string::out, bool::out, wrapper::out) is det.
:- pred output_label_as_code_addr(io.text_output_stream::in, label::in,
io::di, io::uo) is det.
:- func label_is_external_to_c_module(label) = bool.
%----------------------------------------------------------------------------%
%----------------------------------------------------------------------------%
:- implementation.
:- import_module libs.
:- import_module libs.optimization_options.
:- import_module int.
:- import_module list.
:- import_module string.
%----------------------------------------------------------------------------%
%
% Declare code addresses.
%
output_record_code_addr_decls(Info, Stream, CodeAddress, !DeclSet, !IO) :-
output_record_code_addr_decls_format(Info, Stream, CodeAddress,
"", "", 0, _, !DeclSet, !IO).
output_record_code_addr_decls_format(Info, Stream, CodeAddress,
FirstIndent, LaterIndent, !N, !DeclSet, !IO) :-
( if decl_set_insert_new(decl_code_addr(CodeAddress), !DeclSet) then
need_code_addr_decls(Info, CodeAddress, NeedDecl),
(
NeedDecl = yes,
output_indent(Stream, FirstIndent, LaterIndent, !.N, !IO),
!:N = !.N + 1,
output_code_addr_decls(Info, Stream, CodeAddress, !IO)
;
NeedDecl = no
)
else
true
).
:- pred need_code_addr_decls(llds_out_info::in, code_addr::in, bool::out)
is det.
need_code_addr_decls(Info, CodeAddr, Need) :-
(
CodeAddr = code_label(Label),
(
Label = entry_label(entry_label_exported, _),
Need = yes
;
Label = entry_label(entry_label_local, _),
Need = yes
;
Label = entry_label(entry_label_c_local, _),
Need = no
;
Label = internal_label(_, _),
Need = no
)
;
( CodeAddr = code_imported_proc(_)
; CodeAddr = do_trace_redo_fail_shallow
; CodeAddr = do_trace_redo_fail_deep
; CodeAddr = do_call_closure(_)
; CodeAddr = do_call_class_method(_)
; CodeAddr = do_not_reached
),
Need = yes
;
( CodeAddr = code_succip
; CodeAddr = do_succeed(_)
),
Need = no
;
( CodeAddr = do_redo
; CodeAddr = do_fail
),
UseMacro = Info ^ lout_use_macro_for_redo_fail,
(
UseMacro = use_macro_for_redo_fail,
Need = no
;
UseMacro = do_not_use_macro_for_redo_fail,
Need = yes
)
).
:- pred output_code_addr_decls(llds_out_info::in, io.text_output_stream::in,
code_addr::in, io::di, io::uo) is det.
output_code_addr_decls(Info, Stream, CodeAddr, !IO) :-
(
CodeAddr = code_label(Label),
output_label_as_code_addr_decls(Stream, Label, !IO)
;
CodeAddr = code_imported_proc(ProcLabel),
io.format(Stream, "MR_decl_entry(%s);\n",
[s(proc_label_to_c_string(do_not_add_label_prefix, ProcLabel))],
!IO)
;
( CodeAddr = code_succip
; CodeAddr = do_succeed(_)
)
;
CodeAddr = do_redo,
UseMacro = Info ^ lout_use_macro_for_redo_fail,
(
UseMacro = use_macro_for_redo_fail
;
UseMacro = do_not_use_macro_for_redo_fail,
io.write_string(Stream, "MR_declare_entry(MR_do_redo);\n", !IO)
)
;
CodeAddr = do_fail,
UseMacro = Info ^ lout_use_macro_for_redo_fail,
(
UseMacro = use_macro_for_redo_fail
;
UseMacro = do_not_use_macro_for_redo_fail,
io.write_string(Stream, "MR_declare_entry(MR_do_fail);\n", !IO)
)
;
CodeAddr = do_trace_redo_fail_shallow,
io.write_string(Stream,
"MR_declare_entry(MR_do_trace_redo_fail_shallow);\n", !IO)
;
CodeAddr = do_trace_redo_fail_deep,
io.write_string(Stream,
"MR_declare_entry(MR_do_trace_redo_fail_deep);\n", !IO)
;
CodeAddr = do_call_closure(Variant),
io.format(Stream,
"MR_declare_entry(mercury__do_call_closure_%s);\n",
[s(ho_call_variant_to_string(Variant))], !IO)
;
CodeAddr = do_call_class_method(Variant),
io.format(Stream,
"MR_declare_entry(mercury__do_call_class_method_%s);\n",
[s(ho_call_variant_to_string(Variant))], !IO)
;
CodeAddr = do_not_reached,
io.write_string(Stream, "MR_declare_entry(MR_do_not_reached);\n", !IO)
).
:- pred output_label_as_code_addr_decls(io.text_output_stream::in, label::in,
io::di, io::uo) is det.
output_label_as_code_addr_decls(Stream, Label, !IO) :-
(
Label = entry_label(entry_label_exported, ProcLabel),
io.write_string(Stream, "MR_decl_entry(", !IO),
output_label_no_prefix(Stream,
entry_label(entry_label_exported, ProcLabel), !IO),
io.write_string(Stream, ");\n", !IO)
;
Label = entry_label(entry_label_local, _ProcLabel)
;
Label = entry_label(entry_label_c_local, _ProcLabel)
;
Label = internal_label(_, _)
).
%----------------------------------------------------------------------------%
ho_call_variant_to_string(Variant) = Str :-
(
Variant = generic,
Str = "compact"
;
Variant = specialized_known(Num),
Str = int_to_string(Num)
).
%----------------------------------------------------------------------------%
%
% Output labels.
%
output_label(Stream, Label, !IO) :-
LabelStr = label_to_c_string(add_label_prefix, Label),
io.write_string(Stream, LabelStr, !IO).
output_label_no_prefix(Stream, Label, !IO) :-
LabelStr = label_to_c_string(do_not_add_label_prefix, Label),
io.write_string(Stream, LabelStr, !IO).
output_label_maybe_prefix(Stream, AddPrefix, Label, !IO) :-
LabelStr = label_to_c_string(AddPrefix, Label),
io.write_string(Stream, LabelStr, !IO).
label_to_c_string(AddPrefix, Label) = LabelStr :-
(
Label = entry_label(_, ProcLabel),
% Entry labels should have the same string form regardless of the
% entry label type, because we may refer to an entry label via
% different entry label types in different circumstances.
% For example, the entry label of a recursive unification predicate
% is referred to as local in type_info structures and as c_local
% in the recursive call, since the c_local is special cased in some
% circumstances, leading to better code.
LabelStr = proc_label_to_c_string(AddPrefix, ProcLabel)
;
Label = internal_label(Num, ProcLabel),
ProcLabelStr = proc_label_to_c_string(AddPrefix, ProcLabel),
string.int_to_string(Num, NumStr),
LabelStr = ProcLabelStr ++ "_i" ++ NumStr
).
%----------------------------------------------------------------------------%
%
% Output code addresses.
%
output_code_addr(Stream, CodeAddr, !IO) :-
code_addr_to_string_base(CodeAddr, BaseStr, NeedsPrefix, Wrapper),
output_code_addr_from_pieces(Stream, BaseStr, NeedsPrefix, Wrapper, !IO).
output_code_addr_from_pieces(Stream, BaseStr, NeedsPrefix, Wrapper, !IO) :-
(
Wrapper = wrapper_none,
(
NeedsPrefix = yes,
io.write_string(Stream, mercury_label_prefix, !IO)
;
NeedsPrefix = no
),
io.write_string(Stream, BaseStr, !IO)
;
Wrapper = wrapper_entry,
(
NeedsPrefix = yes,
% The _AP version of the macro adds the prefix.
io.format(Stream, "MR_ENTRY_AP(%s)", [s(BaseStr)], !IO)
;
NeedsPrefix = no,
io.format(Stream, "MR_ENTRY(%s)", [s(BaseStr)], !IO)
)
;
Wrapper = wrapper_label,
(
NeedsPrefix = yes,
% The _AP version of the macro adds the prefix.
io.format(Stream, "MR_LABEL_AP(%s)", [s(BaseStr)], !IO)
;
NeedsPrefix = no,
io.format(Stream, "MR_LABEL(%s)", [s(BaseStr)], !IO)
)
).
code_addr_to_string_base(CodeAddr, BaseStr, NeedsPrefix, Wrapper) :-
(
CodeAddr = code_label(Label),
BaseStr = label_to_c_string(do_not_add_label_prefix, Label),
NeedsPrefix = yes,
IsExternal = label_is_external_to_c_module(Label),
(
IsExternal = yes,
Wrapper = wrapper_entry
;
IsExternal = no,
Wrapper = wrapper_label
)
;
CodeAddr = code_imported_proc(ProcLabel),
BaseStr = proc_label_to_c_string(do_not_add_label_prefix, ProcLabel),
NeedsPrefix = yes,
Wrapper = wrapper_entry
;
CodeAddr = code_succip,
BaseStr = "MR_succip",
NeedsPrefix = no,
Wrapper = wrapper_none
;
CodeAddr = do_succeed(Last),
(
Last = no,
BaseStr = "MR_do_succeed"
;
Last = yes,
BaseStr = "MR_do_last_succeed"
),
NeedsPrefix = no,
Wrapper = wrapper_entry
;
(
CodeAddr = do_redo,
BaseStr = "MR_do_redo"
;
CodeAddr = do_fail,
BaseStr = "MR_do_fail"
;
CodeAddr = do_trace_redo_fail_shallow,
BaseStr = "MR_do_trace_redo_fail_shallow"
;
CodeAddr = do_trace_redo_fail_deep,
BaseStr = "MR_do_trace_redo_fail_deep"
;
CodeAddr = do_not_reached,
BaseStr = "MR_do_not_reached"
),
NeedsPrefix = no,
Wrapper = wrapper_entry
;
CodeAddr = do_call_closure(Variant),
BaseStr = "mercury__do_call_closure_" ++
ho_call_variant_to_string(Variant),
NeedsPrefix = no,
Wrapper = wrapper_entry
;
CodeAddr = do_call_class_method(Variant),
BaseStr = "mercury__do_call_class_method_" ++
ho_call_variant_to_string(Variant),
NeedsPrefix = no,
Wrapper = wrapper_entry
).
output_label_as_code_addr(Stream, Label, !IO) :-
label_as_code_addr_to_string(Label, Str),
io.write_string(Stream, Str, !IO).
:- pred label_as_code_addr_to_string(label::in, string::out) is det.
label_as_code_addr_to_string(Label, Str) :-
LabelStr = label_to_c_string(do_not_add_label_prefix, Label),
IsEntry = label_is_external_to_c_module(Label),
(
IsEntry = yes,
Str = "MR_ENTRY_AP(" ++ LabelStr ++ ")"
;
IsEntry = no,
Str = "MR_LABEL_AP(" ++ LabelStr ++ ")"
).
label_is_external_to_c_module(entry_label(entry_label_exported, _)) = yes.
label_is_external_to_c_module(entry_label(entry_label_local, _)) = yes.
label_is_external_to_c_module(entry_label(entry_label_c_local, _)) = no.
label_is_external_to_c_module(internal_label(_, _)) = no.
%---------------------------------------------------------------------------%
:- end_module llds_out_code_addr.
%---------------------------------------------------------------------------%