[m-rev.] for review: implement pragma export on the .NET backend.
Tyson Dowd
trd at miscrit.be
Wed Aug 22 22:14:21 AEST 2001
Hi,
===================================================================
Estimated hours taken: 8
Branches: main
Implement pragma export on the .NET backend.
We just generate a forwarding call from the "exported" name (which
occurs in the same class and module) to the specified predicate.
compiler/ml_code_gen.m:
Generate exports for IL as well as C.
compiler/mlds_to_il.m:
Generate a forwarding function for each exported predicate.
Put the forwarding function inside the wrapper class.
Generate a more specific error message if an return statement
has an empty list of return values.
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.98
diff -u -r1.98 ml_code_gen.m
--- compiler/ml_code_gen.m 7 Aug 2001 13:53:33 -0000 1.98
+++ compiler/ml_code_gen.m 22 Aug 2001 12:02:37 -0000
@@ -819,8 +819,8 @@
MLDSWantedForeignBodys = list__map(ConvBody,
WantedForeignBodys),
% XXX exports are only implemented for
- % C at the moment
- ( Lang = c ->
+ % C and IL at the moment
+ ( ( Lang = c ; Lang = il ) ->
ml_gen_pragma_export(ModuleInfo,
MLDS_PragmaExports)
;
Index: compiler/mlds_to_il.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
retrieving revision 1.76
diff -u -r1.76 mlds_to_il.m
--- compiler/mlds_to_il.m 16 Aug 2001 15:04:03 -0000 1.76
+++ compiler/mlds_to_il.m 22 Aug 2001 12:02:40 -0000
@@ -45,7 +45,6 @@
% [ ] Computed gotos need testing.
% [ ] :- extern doesn't work -- it needs to be treated like pragma c code.
% [ ] nested modules need testing
-% [ ] Implement pragma export.
% [ ] Fix issues with abstract types so that we can implement C
% pointers as MR_Box rather than MR_Word.
% [ ] When generating target_code, sometimes we output more calls than
@@ -194,7 +193,9 @@
%-----------------------------------------------------------------------------%
generate_il(MLDS, ILAsm, ForeignLangs, IO0, IO) :-
- mlds(MercuryModuleName, _, Imports, Defns) = transform_mlds(MLDS),
+
+ mlds(MercuryModuleName, _ForeignCode, Imports, Defns) =
+ transform_mlds(MLDS),
ModuleName = mercury_module_name_to_mlds(MercuryModuleName),
prog_out__sym_name_to_string(mlds_module_name_to_sym_name(ModuleName),
@@ -213,6 +214,7 @@
IlInfo0 = il_info_init(ModuleName, AssemblyName, Imports,
ILDataRep, DebugIlAsm, VerifiableCode, ByRefTailCalls),
+ % Generate code for all the methods.
list__map_foldl(mlds_defn_to_ilasm_decl, Defns, ILDecls,
IlInfo0, IlInfo),
@@ -276,11 +278,21 @@
:- func transform_mlds(mlds) = mlds.
transform_mlds(MLDS0) = MLDS :-
+ AllExports = list__condense(
+ list__map(
+ (func(mlds__foreign_code(_, _, Exports)) = Exports),
+ map__values(MLDS0 ^ foreign_code))
+ ),
+
+ % Generate the exports for this file, they will be placed
+ % into global methods.
+ list__map(mlds_export_to_mlds_defn, AllExports, ExportDefns),
+
list__filter((pred(D::in) is semidet :-
( D = mlds__defn(_, _, _, mlds__function(_, _, _))
; D = mlds__defn(_, _, _, mlds__data(_, _))
)
- ), MLDS0 ^ defns, MercuryCodeMembers, Others),
+ ), MLDS0 ^ defns ++ ExportDefns, MercuryCodeMembers, Others),
WrapperClass = wrapper_class(list__map(rename_defn, MercuryCodeMembers)),
% Note that ILASM requires that the type definitions in Others
% must precede the references to those types in WrapperClass.
@@ -1082,6 +1094,83 @@
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
+ % MLDS exports are converted into forwarding functions, which are
+ % marked as public, are given the specified name, and simply call to
+ % the "exported" function.
+ %
+ % They will be placed inside the "mercury_code" wrapper class with
+ % all the other procedures.
+ %
+ % XXX much of this code should be generalized and turned into a
+ % more general routine for generating MLDS forwarding functions.
+ % We could use almost the same approach for outline_foreign_code
+ % to generate the forwarding function.
+
+:- pred mlds_export_to_mlds_defn(mlds__pragma_export::in, mlds__defn::out)
+ is det.
+
+mlds_export_to_mlds_defn(
+ ml_pragma_export(ExportName, EntityName, Params, Context), Defn) :-
+ EntityName = qual(ModuleName, UnqualName),
+
+ Params = mlds__func_params(Inputs, RetTypes),
+ list__map_foldl((pred(RT::in, RV - Lval::out,
+ N0::in, N0 + 1::out) is det :-
+ VN = var_name("returnval" ++ int_to_string(N0), no),
+ RV = ml_gen_mlds_var_decl(var(VN), RT, no_initializer, Context),
+ Lval = var(qual(ModuleName, VN), RT)),
+ RetTypes, ReturnVars, 0, _),
+
+ EntNameToVarName = (func(EntName) = VarName :-
+ ( EntName = data(var(VarName0)) ->
+ VarName = qual(ModuleName, VarName0)
+ ;
+ error("exported method has argument without var name")
+ )
+ ),
+ ArgTypes = assoc_list__values(Inputs),
+ ArgRvals = list__map(
+ (func(EntName - Type) = lval(var(VarName, Type)) :-
+ VarName = EntNameToVarName(EntName)
+ ), Inputs),
+ ReturnVarDecls = assoc_list__keys(ReturnVars),
+ ReturnLvals = assoc_list__values(ReturnVars),
+ ReturnRvals = list__map((func(X) = lval(X)), ReturnLvals),
+
+ Signature = func_signature(ArgTypes, RetTypes),
+ (
+ UnqualName = function(PredLabel, ProcId, _MaybeSeq, _PredId)
+ ->
+ CodeRval = const(code_addr_const(proc(
+ qual(ModuleName, PredLabel - ProcId),
+ Signature)))
+ ;
+ error("exported entity is not a function")
+ ),
+
+ % XXX should we look for tail calls?
+ CallStatement = statement(
+ call(Signature, CodeRval, no, ArgRvals, ReturnLvals,
+ call), Context),
+ ReturnStatement = statement(return(ReturnRvals), Context),
+
+ Statement = statement(mlds__block(ReturnVarDecls,
+ ( ReturnRvals = [] ->
+ [CallStatement]
+ ;
+ [CallStatement, ReturnStatement]
+ )
+ ), Context),
+
+ DefnEntity = function(no, Params, defined_here(Statement)),
+
+ Flags = init_decl_flags(public, one_copy, non_virtual, overridable,
+ const, concrete),
+ Defn = defn(export(ExportName), Context, Flags, DefnEntity).
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
%
% Code for generating initializers.
%
@@ -1399,6 +1488,8 @@
context_node(Context),
LoadInstrs,
instr_node(ret)]) }
+ ; { Rvals = [] } ->
+ { unexpected(this_file, "empty list of return values") }
;
% MS IL doesn't support multiple return values
{ sorry(this_file, "multiple return values") }
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list