mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-16 22:35:41 +00:00
Branches: main
Mangle symbols which would begin with a digit in generated Java code.
compiler/prog_foreign.m:
Add a version of name_mangle which mangles symbols beginning with a
digit, in the same way as if it contained a character not allowed in C
identifiers.
compiler/java_names.m:
compiler/mlds_to_java.m:
Call the new function.
Don't need to mangle a string in a spot.
compiler/name_mangle.m:
Update comments the file extras/dynamic_linking/name_mangle.m
which was removed a while ago.
compiler/ml_util.m:
Unrelated: make a simple change to defns_contain_main to use less
nondet stack space. I ran out of stack space when testing this change
on a particular module. The compiler was built in a debugging grade.
299 lines
11 KiB
Mathematica
299 lines
11 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 2003-2008 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: name_mangle.m.
|
|
%
|
|
% This module defines routines for generating and/or outputing identifiers
|
|
% for modules, predicates/functions, and procedures in forms that are
|
|
% syntactically acceptable in all our target languages, meaning C, Java
|
|
% and MSIL.
|
|
%
|
|
% NOTE: some parts of the name mangling routines are defined in
|
|
% prog_foreign.m because they are required by the frontend of the compiler,
|
|
% for generating makefile fragments etc.
|
|
%
|
|
% Warning: any changes to the name mangling algorithms implemented in this
|
|
% module may also require changes to profiler/demangle.m, util/mdemangle.c and
|
|
% compiler/prog_foreign.m.
|
|
%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- module backend_libs.name_mangle.
|
|
:- interface.
|
|
|
|
:- import_module backend_libs.rtti.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.prim_data.
|
|
|
|
:- import_module bool.
|
|
:- import_module io.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% Output a proc label, with the usual mercury_label_prefix prefix.
|
|
%
|
|
:- pred output_proc_label(proc_label::in, io::di, io::uo) is det.
|
|
|
|
% Output a proc label without the mercury_label_prefix prefix.
|
|
%
|
|
:- pred output_proc_label_no_prefix(proc_label::in, io::di, io::uo) is det.
|
|
|
|
% Output a proc label. The boolean controls whether mercury_label_prefix
|
|
% is added to it.
|
|
%
|
|
:- pred output_proc_label_maybe_prefix(proc_label::in, bool::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% Get a proc label string (used by procs which are exported to C).
|
|
% The boolean controls whether label_prefix is added to the string.
|
|
%
|
|
:- func proc_label_to_c_string(proc_label, bool) = string.
|
|
|
|
% Succeed iff the given name or sym_name doesn't need mangling.
|
|
%
|
|
:- pred name_doesnt_need_mangling(string::in) is semidet.
|
|
:- pred sym_name_doesnt_need_mangling(sym_name::in) is semidet.
|
|
|
|
% Create a name for base_typeclass_info.
|
|
%
|
|
:- func make_base_typeclass_info_name(tc_name, string) = string.
|
|
|
|
% Output the name for base_typeclass_info,
|
|
% with the appropriate mercury_data_prefix.
|
|
%
|
|
:- pred output_base_typeclass_info_name(tc_name::in, string::in,
|
|
io::di, io::uo) is det.
|
|
|
|
% Prints the name of the initialization function
|
|
% for a given module.
|
|
%
|
|
:- pred output_init_name(module_name::in, io::di, io::uo) is det.
|
|
|
|
% To ensure that Mercury labels don't clash with C symbols, we
|
|
% prefix them with the string returned by this function.
|
|
%
|
|
:- func mercury_label_prefix = string.
|
|
|
|
% To ensure that the names of global variables generated by the Mercury
|
|
% compiler don't clash with C symbols, we prefix them with the string
|
|
% returned by this function.
|
|
%
|
|
:- func mercury_var_prefix = string.
|
|
|
|
% All the C data structures we generate which are either fully static
|
|
% or static after initialization should have one of these yrefixes,
|
|
% to ensure that Mercury global variables don't clash with C symbols.
|
|
%
|
|
:- func mercury_data_prefix = string.
|
|
:- func mercury_scalar_common_array_prefix = string.
|
|
:- func mercury_vector_common_array_prefix = string.
|
|
|
|
% All the C types we generate should have this prefix to ensure
|
|
% that they don't clash with C symbols.
|
|
%
|
|
:- func mercury_common_type_prefix = string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module hlds.
|
|
:- import_module hlds.special_pred.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_foreign.
|
|
|
|
:- import_module int.
|
|
:- import_module list.
|
|
:- import_module string.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
output_proc_label(ProcLabel, !IO) :-
|
|
output_proc_label_maybe_prefix(ProcLabel, yes, !IO).
|
|
|
|
output_proc_label_no_prefix(ProcLabel, !IO) :-
|
|
output_proc_label_maybe_prefix(ProcLabel, no, !IO).
|
|
|
|
output_proc_label_maybe_prefix(ProcLabel, AddPrefix, !IO) :-
|
|
ProcLabelString = proc_label_to_c_string(ProcLabel, AddPrefix),
|
|
io.write_string(ProcLabelString, !IO).
|
|
|
|
proc_label_to_c_string(ProcLabel, AddPrefix) = ProcLabelString :-
|
|
(
|
|
ProcLabel = ordinary_proc_label(DefiningModule, PredOrFunc, PredModule,
|
|
PredName, Arity, ModeInt),
|
|
LabelName = make_pred_or_func_name(DefiningModule, PredOrFunc,
|
|
PredModule, PredName, Arity, AddPrefix),
|
|
(
|
|
PredOrFunc = pf_function,
|
|
OrigArity = Arity - 1
|
|
;
|
|
PredOrFunc = pf_predicate,
|
|
OrigArity = Arity
|
|
),
|
|
string.int_to_string(OrigArity, ArityString),
|
|
string.int_to_string(ModeInt, ModeNumString),
|
|
string.append_list([LabelName, "_", ArityString, "_", ModeNumString],
|
|
ProcLabelString)
|
|
;
|
|
ProcLabel = special_proc_label(Module, SpecialPredId, TypeModule,
|
|
TypeName, TypeArity, ModeInt),
|
|
% For a special proc, output a label of the form:
|
|
% mercury____<PredName>___<TypeModule>__<TypeName>_<TypeArity>_<Mode>
|
|
|
|
% Figure out the LabelName.
|
|
DummyArity = -1, % not used by make_pred_or_func_name.
|
|
TypeCtor = type_ctor(qualified(TypeModule, TypeName), TypeArity),
|
|
PredName = special_pred_name(SpecialPredId, TypeCtor),
|
|
LabelName = make_pred_or_func_name(unqualified(""), pf_predicate,
|
|
unqualified(""), PredName, DummyArity, AddPrefix),
|
|
|
|
% Figure out the ModeNumString.
|
|
string.int_to_string(TypeArity, TypeArityString),
|
|
string.int_to_string(ModeInt, ModeNumString),
|
|
|
|
% Mangle all the relevent names.
|
|
MangledModule = sym_name_mangle(Module),
|
|
MangledTypeModule = sym_name_mangle(TypeModule),
|
|
MangledTypeName = name_mangle(TypeName),
|
|
|
|
% Module-qualify the type name.
|
|
% To handle locally produced unification preds for imported types,
|
|
% we need to qualify it with both the module name of the
|
|
% type, and also (if it is different) the module name of the
|
|
% current module.
|
|
QualifiedMangledTypeName = qualify_name(MangledTypeModule,
|
|
MangledTypeName),
|
|
FullyQualifiedMangledTypeName = maybe_qualify_name(MangledModule,
|
|
QualifiedMangledTypeName),
|
|
|
|
% Join it all together.
|
|
string.append_list([LabelName, "_", FullyQualifiedMangledTypeName,
|
|
"_", TypeArityString, "_", ModeNumString], ProcLabelString)
|
|
).
|
|
|
|
% Make a name identifying a predicate or a function, given the
|
|
% defining module, predicate or function indicator, declaring module,
|
|
% predicate name, arity, and whether or not to add the
|
|
% mercury_label_prefix.
|
|
%
|
|
:- func make_pred_or_func_name(module_name, pred_or_func, module_name, string,
|
|
arity, bool) = string.
|
|
|
|
make_pred_or_func_name(DefiningModule, PredOrFunc, DeclaringModule,
|
|
Name0, Arity, AddPrefix) = LabelName :-
|
|
% WARNING: any changes to the name mangling algorithm here may also
|
|
% require changes to profiler/demangle.m, util/mdemangle.c and
|
|
% compiler/prog_foreign.m.
|
|
|
|
DeclaringModuleName = sym_name_mangle(DeclaringModule),
|
|
DefiningModuleName = sym_name_mangle(DefiningModule),
|
|
( dont_module_qualify_name(Name0, Arity) ->
|
|
LabelName0 = Name0
|
|
;
|
|
LabelName0 = qualify_name(DeclaringModuleName, Name0)
|
|
),
|
|
% If this is a specialized version of a predicate defined
|
|
% in some other module, then it needs both module prefixes.
|
|
( DefiningModule \= DeclaringModule ->
|
|
LabelName1 = DefiningModuleName ++ "__" ++ LabelName0
|
|
;
|
|
LabelName1 = LabelName0
|
|
),
|
|
LabelName2 = name_mangle(LabelName1),
|
|
(
|
|
PredOrFunc = pf_function,
|
|
LabelName3 = "fn__" ++ LabelName2
|
|
;
|
|
PredOrFunc = pf_predicate,
|
|
LabelName3 = LabelName2
|
|
),
|
|
(
|
|
AddPrefix = yes,
|
|
LabelName = mercury_label_prefix ++ LabelName3
|
|
;
|
|
AddPrefix = no,
|
|
LabelName = LabelName3
|
|
).
|
|
|
|
% Define the conditions for which labels are printed
|
|
% without module qualification.
|
|
%
|
|
:- pred dont_module_qualify_name(string::in, arity::in) is semidet.
|
|
|
|
dont_module_qualify_name(Name, Arity) :-
|
|
(
|
|
Name = "main",
|
|
Arity = 2
|
|
;
|
|
string.prefix(Name, "__")
|
|
).
|
|
|
|
name_doesnt_need_mangling(Name) :-
|
|
string.is_all_alnum_or_underscore(Name),
|
|
\+ string.append("f_", _Suffix, Name).
|
|
|
|
sym_name_doesnt_need_mangling(unqualified(Name)) :-
|
|
name_doesnt_need_mangling(Name).
|
|
sym_name_doesnt_need_mangling(qualified(ModuleName, PlainName)) :-
|
|
sym_name_doesnt_need_mangling(ModuleName),
|
|
name_doesnt_need_mangling(PlainName).
|
|
|
|
% Produces a string of the form Module__Name, unless Module__
|
|
% is already a prefix of Name.
|
|
%
|
|
:- func maybe_qualify_name(string, string) = string.
|
|
|
|
maybe_qualify_name(Module0, Name0) = Name :-
|
|
string.append(Module0, "__", UnderscoresModule),
|
|
( string.append(UnderscoresModule, _, Name0) ->
|
|
Name = Name0
|
|
;
|
|
string.append(UnderscoresModule, Name0, Name)
|
|
).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
output_base_typeclass_info_name(TCName, TypeNames, !IO) :-
|
|
Str = make_base_typeclass_info_name(TCName, TypeNames),
|
|
io.write_string(mercury_data_prefix, !IO),
|
|
io.write_string(Str, !IO).
|
|
|
|
make_base_typeclass_info_name(TCName, TypeNames) = Str :-
|
|
TCName = tc_name(ModuleName, ClassName, ClassArity),
|
|
ClassSym = qualified(ModuleName, ClassName),
|
|
MangledClassString = sym_name_mangle(ClassSym),
|
|
string.int_to_string(ClassArity, ArityString),
|
|
MangledTypeNames = name_mangle(TypeNames),
|
|
string.append_list(["base_typeclass_info_", MangledClassString,
|
|
"__arity", ArityString, "__", MangledTypeNames], Str).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
output_init_name(ModuleName, !IO) :-
|
|
InitName = make_init_name(ModuleName),
|
|
io.write_string(InitName, !IO).
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
mercury_label_prefix = "mercury__".
|
|
|
|
mercury_var_prefix = "mercury_var_".
|
|
|
|
mercury_data_prefix = "mercury_data_".
|
|
mercury_scalar_common_array_prefix = "mercury_common_".
|
|
mercury_vector_common_array_prefix = "mercury_vector_common_".
|
|
|
|
mercury_common_type_prefix = "mercury_type_".
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- end_module name_mangle.
|
|
%-----------------------------------------------------------------------------%
|