%-----------------------------------------------------------------------------% % vim: ft=mercury ts=4 sw=4 et %-----------------------------------------------------------------------------% % Copyright (C) 1996-2012 The University of Melbourne. % Copyright (C) 2013-2018 The Mercury team. % This file may only be copied under the terms of the GNU General % Public License - see the file COPYING in the Mercury distribution. %-----------------------------------------------------------------------------% % % File: export.m. % Main author: dgj, juliensf. % % This module defines predicates to produce the functions which are % exported to a foreign language via a `pragma foreign_export' declaration. % %-----------------------------------------------------------------------------% :- module backend_libs.export. :- interface. :- import_module hlds. :- import_module hlds.hlds_module. :- import_module hlds.hlds_pred. :- import_module mdbcomp. :- import_module mdbcomp.sym_name. :- import_module parse_tree. :- import_module parse_tree.prog_data. :- import_module parse_tree.prog_foreign. :- import_module io. %-----------------------------------------------------------------------------% % From the module_info, get a list of foreign_export_decls, each of which % holds information about the declaration of a foreign function named in a % `pragma foreign_export' declaration, which is used to allow a call to % be made to a Mercury procedure from the foreign language. % :- pred get_foreign_export_decls(module_info::in, foreign_export_decls::out) is det. % From the module_info, get a list of foreign_export_defns, each of which % is a string containing the foreign code for defining a foreign function % named in a `pragma foreign_export' decl. % :- pred get_foreign_export_defns(module_info::in, foreign_export_defns::out) is det. % Produce an interface file containing declarations for the exported % foreign functions (if required in this foreign language). % % This procedure is used for both the MLDS and LLDS back-ends. % :- pred produce_header_file(module_info::in, foreign_export_decls::in, module_name::in, io::di, io::uo) is det. %-----------------------------------------------------------------------------% % Utilities for generating C code which interfaces with Mercury. % The {MLDS,LLDS}->C backends and fact tables use this code. % Generate C code to convert an rval (represented as a string), from % a C type to a Mercury C type (i.e. convert strings and floats to % words) and return the resulting C code as a string. % :- pred convert_type_to_mercury(string::in, mer_type::in, arg_loc::in, string::out) is det. % Generate C code to convert an rval (represented as a string), from % a Mercury C type to a C type (i.e. convert words to strings and % floats if required) and return the resulting C code as a string. % :- pred convert_type_from_mercury(arg_loc::in, string::in, mer_type::in, string::out) is det. % Succeeds iff the given C type is known by the compiler to be an integer % or pointer type the same size as MR_Word. % :- pred c_type_is_word_sized_int_or_ptr(string::in) is semidet. %-----------------------------------------------------------------------------% %-----------------------------------------------------------------------------% :- implementation. :- import_module backend_libs.c_util. :- import_module backend_libs.foreign. :- import_module backend_libs.name_mangle. :- import_module backend_libs.proc_label. :- import_module check_hlds. :- import_module check_hlds.type_util. :- import_module hlds.arg_info. :- import_module hlds.code_model. :- import_module hlds.hlds_data. :- import_module hlds.hlds_llds. :- import_module hlds.pred_table. :- import_module hlds.status. :- import_module libs. :- import_module libs.compiler_util. :- import_module libs.file_util. :- import_module libs.globals. :- import_module libs.options. :- import_module mdbcomp.prim_data. :- import_module parse_tree.file_names. :- import_module parse_tree.module_cmds. :- import_module parse_tree.prog_data_foreign. :- import_module parse_tree.prog_type. :- import_module parse_tree.prog_util. :- import_module assoc_list. :- import_module bool. :- import_module cord. :- import_module int. :- import_module io.file. :- import_module library. :- import_module list. :- import_module map. :- import_module maybe. :- import_module pair. :- import_module require. :- import_module string. :- import_module term_context. %-----------------------------------------------------------------------------% get_foreign_export_decls(ModuleInfo, ForeignExportDecls) :- module_info_get_pred_id_table(ModuleInfo, PredIdTable), module_info_get_foreign_decl_codes_user(ModuleInfo, ForeignDeclCodeUserCord), module_info_get_foreign_decl_codes_aux(ModuleInfo, ForeignDeclCodeAuxCord), ForeignDeclCodes = cord.list(ForeignDeclCodeUserCord ++ ForeignDeclCodeAuxCord), module_info_get_pragma_exported_procs(ModuleInfo, ExportedProcsCord), get_foreign_export_decls_loop(ModuleInfo, PredIdTable, cord.list(ExportedProcsCord), ExportDecls), ForeignExportDecls = foreign_export_decls(ForeignDeclCodes, ExportDecls). :- pred get_foreign_export_decls_loop(module_info::in, pred_id_table::in, list(pragma_exported_proc)::in, list(foreign_export_decl)::out) is det. get_foreign_export_decls_loop(_, _, [], []). get_foreign_export_decls_loop(ModuleInfo, PredIdTable, [HeadExportedProc | TailExportedProcs], [HeadExportDecl | TailExportDecls]) :- HeadExportedProc = pragma_exported_proc(Lang, PredId, ProcId, ExportName, _Context), ( Lang = lang_c, get_export_info_for_lang_c(ModuleInfo, PredIdTable, PredId, ProcId, _HowToDeclare, RetType, _DeclareReturnVal, _FailureAction, _SuccessAction, HeadArgInfoTypes), get_argument_declarations_for_lang_c(ModuleInfo, no, HeadArgInfoTypes, ArgDecls) ; ( Lang = lang_csharp ; Lang = lang_java ), sorry($pred, ":- pragma foreign_export for non-C backends.") ), HeadExportDecl = foreign_export_decl(Lang, RetType, ExportName, ArgDecls), get_foreign_export_decls_loop(ModuleInfo, PredIdTable, TailExportedProcs, TailExportDecls). %-----------------------------------------------------------------------------% get_foreign_export_defns(ModuleInfo, ExportedProcsCode) :- module_info_get_pragma_exported_procs(ModuleInfo, ExportedProcsCord), module_info_get_predicate_table(ModuleInfo, PredicateTable), predicate_table_get_pred_id_table(PredicateTable, PredIdTable), export_procs_to_c(ModuleInfo, PredIdTable, cord.list(ExportedProcsCord), ExportedProcsCode). :- pred export_procs_to_c(module_info::in, pred_id_table::in, list(pragma_exported_proc)::in, list(foreign_export_defn)::out) is det. export_procs_to_c(_ModuleInfo, _PredIdTable, [], []). export_procs_to_c(ModuleInfo, PredIdTable, [ExportedProc | ExportedProcs], [ExportDefn | ExportDefns]) :- export_proc_to_c(ModuleInfo, PredIdTable, ExportedProc, ExportDefn), export_procs_to_c(ModuleInfo, PredIdTable, ExportedProcs, ExportDefns). % For each exported procedure, produce a C function. % The code we generate is in the form % % MR_declare_entry(