Files
mercury/browser/name_mangle.m
Fergus Henderson b9550e14c7 Apply some patches that had been previously applied to
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.
2001-01-11 05:59:31 +00:00

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
").
%-----------------------------------------------------------------------------%