mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
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.
423 lines
14 KiB
Mathematica
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.
|
|
%---------------------------------------------------------------------------%
|