%-----------------------------------------------------------------------------% % 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 outputting 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 mdbcomp.sym_name. %-----------------------------------------------------------------------------% :- type maybe_add_label_prefix ---> do_not_add_label_prefix ; add_label_prefix. % 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(maybe_add_label_prefix, proc_label) = 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. :- func make_base_typeclass_info_name_with_data_prefix(tc_name, string) = string. % 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 prefixes, % 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.pred_name. :- 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. %-----------------------------------------------------------------------------% proc_label_to_c_string(AddPrefix, ProcLabel) = ProcLabelString :- ( ProcLabel = ordinary_proc_label(DefiningModule, PredOrFunc, PredModule, PredName, Arity, ModeNum), LabelName = make_pred_or_func_name(DefiningModule, PredOrFunc, PredModule, PredName, Arity, AddPrefix), ( PredOrFunc = pf_function, OrigArity = Arity - 1 ; PredOrFunc = pf_predicate, OrigArity = Arity ), ProcLabelString = string.format("%s_%d_%d", [s(LabelName), i(OrigArity), i(ModeNum)]) ; ProcLabel = special_proc_label(Module, SpecialPredId, TypeModule, TypeName, TypeArity, ModeNum), % For a special proc, output a label of the form: % mercury___________ % Figure out the LabelName. DummyArity = -1, % not used by make_pred_or_func_name. TypeCtor = type_ctor(qualified(TypeModule, TypeName), TypeArity), PredName = uci_pred_name(SpecialPredId, TypeCtor), LabelName = make_pred_or_func_name(unqualified(""), pf_predicate, unqualified(""), PredName, DummyArity, AddPrefix), % Mangle all the relevant 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. ProcLabelString = string.format("%s_%s_%d_%d", [s(LabelName), s(FullyQualifiedMangledTypeName), i(TypeArity), i(ModeNum)]) ). % 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, maybe_add_label_prefix) = 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), ( if dont_module_qualify_name(Name0, Arity) then LabelName0 = Name0 else 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. ( if DefiningModule \= DeclaringModule then LabelName1 = DefiningModuleName ++ "__" ++ LabelName0 else LabelName1 = LabelName0 ), LabelName2 = name_mangle(LabelName1), ( PredOrFunc = pf_function, LabelName3 = "fn__" ++ LabelName2 ; PredOrFunc = pf_predicate, LabelName3 = LabelName2 ), ( AddPrefix = add_label_prefix, LabelName = mercury_label_prefix ++ LabelName3 ; AddPrefix = do_not_add_label_prefix, 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), not 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), ( if string.append(UnderscoresModule, _, Name0) then Name = Name0 else string.append(UnderscoresModule, Name0, Name) ). %-----------------------------------------------------------------------------% make_base_typeclass_info_name(TCName, TypeNames) = Str :- TCName = tc_name(ModuleName, ClassName, ClassArity), ClassSym = qualified(ModuleName, ClassName), MangledClassString = sym_name_mangle(ClassSym), MangledTypeNames = name_mangle(TypeNames), Str = string.format("base_typeclass_info_%s__arity%d__%s", [s(MangledClassString), i(ClassArity), s(MangledTypeNames)]). make_base_typeclass_info_name_with_data_prefix(TCName, TypeNames) = Str :- Str = mercury_data_prefix ++ make_base_typeclass_info_name(TCName, TypeNames). %-----------------------------------------------------------------------------% 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 backend_libs.name_mangle. %-----------------------------------------------------------------------------%