mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 21:04:00 +00:00
Estimated hours taken: 0.1 browser/name_mangle.m: Apply some patches that had been previously applied to extras/dynamic_linking/name_mangle.m but not to the copy here.
269 lines
8.2 KiB
Mathematica
269 lines
8.2 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% Copyright (C) 1998-2000 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU Library General
|
|
% Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
% File: name_mangle.m.
|
|
% Purpose: name mangling support.
|
|
% Main author: fjh.
|
|
% Stability: low.
|
|
|
|
% This module provides the proc_name_mangle/1 function, which takes a value of
|
|
% type `mercury_proc' and returns a string which is the symbol name for
|
|
% specified procedure, and which is suitable for use in a call to dl__sym.
|
|
%
|
|
% The details of name mangling are implementation-dependent, so unfortunately
|
|
% the values stored in the `mercury_proc' type might be subject to change
|
|
% in different Mercury implementations. Any code which creates or
|
|
% examines values of that type should be carefully isolated so that
|
|
% it can be easily changed if the representation of `mercury_proc' changes.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
:- module mdb__name_mangle.
|
|
:- interface.
|
|
|
|
% Given a mercury_proc specifying the module name,
|
|
% predicate or function indicator, predicate name, arity,
|
|
% and mode number of a Mercury procedure,
|
|
% return the label name of that procedure.
|
|
% The label name returned is suitable for passing to dl__sym.
|
|
%
|
|
:- func proc_name_mangle(mercury_proc) = string.
|
|
|
|
:- type mercury_proc --->
|
|
mercury_proc(is_pred_or_func, module_name, pred_name, arity, mode_num).
|
|
|
|
:- type is_pred_or_func
|
|
---> predicate
|
|
; function.
|
|
|
|
:- type module_name == sym_name.
|
|
|
|
:- type sym_name
|
|
---> qualified(sym_name, string)
|
|
; unqualified(string).
|
|
|
|
:- type pred_name == string.
|
|
|
|
:- type arity == int. % note that for functions that arity here
|
|
% does *not* include the function result
|
|
% e.g. int:'*' has arity 2, not 3.
|
|
|
|
:- type mode_num == int. % mode numbers start from zero
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
:- import_module string, char, int, list.
|
|
|
|
% XXX most of the code below is very similar to the code in
|
|
% compiler/llds_out.m. Any changes there may require changes here
|
|
% and vice versa.
|
|
|
|
%-----------------------------------------------------------------------------%
|
|
|
|
proc_name_mangle(MercuryProc) =
|
|
( high_level_code ->
|
|
mlds_proc_name_mangle(MercuryProc)
|
|
;
|
|
llds_proc_name_mangle(MercuryProc)
|
|
).
|
|
|
|
:- func llds_proc_name_mangle(mercury_proc) = string.
|
|
llds_proc_name_mangle(MercuryProc) = LabelName :-
|
|
MercuryProc = mercury_proc(PredOrFunc, Module, Name0, Arity, ModeNum),
|
|
sym_name_mangle(Module, ModuleName),
|
|
(
|
|
(
|
|
Module = unqualified("builtin")
|
|
;
|
|
Name0 = "main",
|
|
Arity = 2
|
|
)
|
|
% The conditions above define which labels are printed without
|
|
% module qualification.
|
|
->
|
|
LabelName0 = Name0
|
|
;
|
|
qualify_name(ModuleName, Name0, LabelName0)
|
|
),
|
|
name_mangle(LabelName0, LabelName1),
|
|
string__int_to_string(Arity, ArityString),
|
|
string__int_to_string(ModeNum, ModeNumString),
|
|
string__append_list([LabelName1, "_", ArityString, "_", ModeNumString],
|
|
LabelName2),
|
|
(
|
|
PredOrFunc = function,
|
|
string__append("fn__", LabelName2, LabelName3)
|
|
;
|
|
PredOrFunc = predicate,
|
|
LabelName3 = LabelName2
|
|
),
|
|
string__append("mercury__", LabelName3, LabelName4),
|
|
( use_asm_labels ->
|
|
string__append("_entry_", LabelName4, LabelName)
|
|
;
|
|
LabelName = LabelName4
|
|
).
|
|
|
|
:- func mlds_proc_name_mangle(mercury_proc) = string.
|
|
mlds_proc_name_mangle(MercuryProc) = LabelName :-
|
|
MercuryProc = mercury_proc(PredOrFunc, Module, Name0, Arity, ModeNum),
|
|
sym_name_mangle(Module, ModuleName),
|
|
(
|
|
PredOrFunc = predicate,
|
|
Name0 = "main",
|
|
Arity = 2
|
|
% The conditions above define which labels are printed without
|
|
% module qualification.
|
|
->
|
|
LabelName0 = Name0
|
|
;
|
|
qualify_name(ModuleName, Name0, LabelName0)
|
|
),
|
|
name_mangle(LabelName0, LabelName1),
|
|
(
|
|
PredOrFunc = predicate,
|
|
PredOrFuncString = "p",
|
|
ArityAsPred = Arity
|
|
;
|
|
PredOrFunc = function,
|
|
PredOrFuncString = "f",
|
|
ArityAsPred = Arity + 1
|
|
),
|
|
string__int_to_string(ArityAsPred, ArityString),
|
|
string__int_to_string(ModeNum, ModeNumString),
|
|
string__append_list([LabelName1, "_", ArityString, "_",
|
|
PredOrFuncString, "_", ModeNumString],
|
|
LabelName).
|
|
|
|
:- pred sym_name_mangle(sym_name, string).
|
|
:- mode sym_name_mangle(in, out) is det.
|
|
|
|
sym_name_mangle(unqualified(Name), MangledName) :-
|
|
name_mangle(Name, MangledName).
|
|
sym_name_mangle(qualified(ModuleName, PlainName), MangledName) :-
|
|
sym_name_mangle(ModuleName, MangledModuleName),
|
|
name_mangle(PlainName, MangledPlainName),
|
|
qualify_name(MangledModuleName, MangledPlainName,
|
|
MangledName).
|
|
|
|
% Convert a Mercury predicate name into something that can form
|
|
% part of a C identifier. This predicate is necessary because
|
|
% quoted names such as 'name with embedded spaces' are valid
|
|
% predicate names in Mercury.
|
|
|
|
:- pred name_mangle(string, string).
|
|
:- mode name_mangle(in, out) is det.
|
|
|
|
name_mangle(Name, MangledName) :-
|
|
(
|
|
string__is_alnum_or_underscore(Name)
|
|
->
|
|
% any names that start with `f_' are changed so that
|
|
% they start with `f__', so that we can use names starting
|
|
% with `f_' (followed by anything except an underscore)
|
|
% without fear of name collisions
|
|
(
|
|
string__append("f_", Suffix, Name)
|
|
->
|
|
string__append("f__", Suffix, MangledName)
|
|
;
|
|
MangledName = Name
|
|
)
|
|
;
|
|
convert_to_valid_c_identifier(Name, MangledName)
|
|
).
|
|
|
|
:- pred convert_to_valid_c_identifier(string, string).
|
|
:- mode convert_to_valid_c_identifier(in, out) is det.
|
|
|
|
convert_to_valid_c_identifier(String, Name) :-
|
|
(
|
|
name_conversion_table(String, Name0)
|
|
->
|
|
Name = Name0
|
|
;
|
|
convert_to_valid_c_identifier_2(String, Name0),
|
|
string__append("f", Name0, Name)
|
|
).
|
|
|
|
:- pred qualify_name(string, string, string).
|
|
:- mode qualify_name(in, in, out) is det.
|
|
|
|
qualify_name(Module0, Name0, Name) :-
|
|
string__append_list([Module0, "__", Name0], Name).
|
|
|
|
% A table used to convert Mercury functors into
|
|
% C identifiers. Feel free to add any new translations you want.
|
|
% The C identifiers should start with "f_",
|
|
% to avoid introducing name clashes.
|
|
% If the functor name is not found in the table, then
|
|
% we use a fall-back method which produces ugly names.
|
|
|
|
:- pred name_conversion_table(string, string).
|
|
:- mode name_conversion_table(in, out) is semidet.
|
|
|
|
name_conversion_table("\\=", "f_not_equal").
|
|
name_conversion_table(">=", "f_greater_or_equal").
|
|
name_conversion_table("=<", "f_less_or_equal").
|
|
name_conversion_table("=", "f_equal").
|
|
name_conversion_table("<", "f_less_than").
|
|
name_conversion_table(">", "f_greater_than").
|
|
name_conversion_table("-", "f_minus").
|
|
name_conversion_table("+", "f_plus").
|
|
name_conversion_table("*", "f_times").
|
|
name_conversion_table("/", "f_slash").
|
|
name_conversion_table(",", "f_comma").
|
|
name_conversion_table(";", "f_semicolon").
|
|
name_conversion_table("!", "f_cut").
|
|
|
|
% This is the fall-back method.
|
|
% Given a string, produce a C identifier
|
|
% for that string by concatenating the decimal
|
|
% expansions of the character codes in the string,
|
|
% separated by underlines.
|
|
% The C identifier will start with "f_"; this predicate
|
|
% constructs everything except the initial "f".
|
|
%
|
|
% For example, given the input "\n\t" we return "_10_8".
|
|
|
|
:- pred convert_to_valid_c_identifier_2(string, string).
|
|
:- mode convert_to_valid_c_identifier_2(in, out) is det.
|
|
|
|
convert_to_valid_c_identifier_2(String, Name) :-
|
|
(
|
|
string__first_char(String, Char, Rest)
|
|
->
|
|
char__to_int(Char, Code),
|
|
string__int_to_string(Code, CodeString),
|
|
string__append("_", CodeString, ThisCharString),
|
|
convert_to_valid_c_identifier_2(Rest, Name0),
|
|
string__append(ThisCharString, Name0, Name)
|
|
;
|
|
% String is the empty string
|
|
Name = String
|
|
).
|
|
|
|
:- pred use_asm_labels is semidet.
|
|
:- pragma c_code(use_asm_labels, [will_not_call_mercury, thread_safe], "
|
|
#ifdef USE_ASM_LABELS
|
|
SUCCESS_INDICATOR = TRUE;
|
|
#else
|
|
SUCCESS_INDICATOR = FALSE;
|
|
#endif
|
|
").
|
|
|
|
:- pred high_level_code is semidet.
|
|
:- pragma c_code(high_level_code, [will_not_call_mercury, thread_safe], "
|
|
#ifdef MR_HIGHLEVEL_CODE
|
|
SUCCESS_INDICATOR = TRUE;
|
|
#else
|
|
SUCCESS_INDICATOR = FALSE;
|
|
#endif
|
|
").
|
|
|
|
%-----------------------------------------------------------------------------%
|