mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-13 21:04:00 +00:00
compiler/mlds.m:
Make two changes to mlds_type.
The simpler change is the deletion of the maybe(foreign_type_assertions)
field from the MLDS representations of Mercury types. It was never used,
because Mercury types that are defined in a foreign language that is
acceptable for the current MLDS target platform are represented
as mlds_foreign_type, not as mercury_type.
The more involved change is to change the representation of builtin types.
Until now, we had separate function symbols in mlds_type to represent
ints, uints, floats and chars, but not strings or values of the sized
types {int,uint}{8,16,32,64}; those had to be represented as Mercury types.
This is an unnecessary inconsistency. It also had two allowed
representations for ints, uints, floats and chars, which meant that
some of the code handling those conceptual types had to be duplicated
to handle both representations.
This diff provides mlds_builtin_type_{int(_),float,string,char} function
symbols to represent every builtin type, and changes mercury_type
to mercury_nb_type to make clear that it is NOT to be used for builtins
(the nb is short for "not builtin").
compiler/ml_code_util.m:
compiler/ml_util.m:
Delete functions that used to construct MLDS representations of builtin
types. The new representation of those types is so simple that using
such functions is no less cumbersome than writing down the representations
directly.
compiler/ml_accurate_gc.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/ml_disj_gen.m:
compiler/ml_foreign_proc_gen.m:
compiler/ml_global_data.m:
compiler/ml_lookup_switch.m:
compiler/ml_proc_gen.m:
compiler/ml_rename_classes.m:
compiler/ml_simplify_switch.m:
compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
compiler/ml_type_gen.m:
compiler/ml_unify_gen_construct.m:
compiler/ml_unify_gen_deconstruct.m:
compiler/ml_unify_gen_util.m:
compiler/mlds_dump.m:
compiler/mlds_to_c_data.m:
compiler/mlds_to_c_export.m:
compiler/mlds_to_c_func.m:
compiler/mlds_to_c_global.m:
compiler/mlds_to_c_stmt.m:
compiler/mlds_to_c_type.m:
compiler/mlds_to_cs_data.m:
compiler/mlds_to_cs_stmt.m:
compiler/mlds_to_cs_type.m:
compiler/mlds_to_java_data.m:
compiler/mlds_to_java_stmt.m:
compiler/mlds_to_java_type.m:
compiler/mlds_to_java_wrap.m:
compiler/rtti_to_mlds.m:
Conform to the changes above.
1231 lines
45 KiB
Mathematica
1231 lines
45 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 2000-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.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% Output MLDS lvals, rvals and initializers in Java.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module ml_backend.mlds_to_java_data.
|
|
:- interface.
|
|
|
|
:- import_module ml_backend.mlds.
|
|
:- import_module ml_backend.mlds_to_java_util.
|
|
:- import_module ml_backend.mlds_to_target_util.
|
|
|
|
:- import_module io.
|
|
:- import_module list.
|
|
:- import_module maybe.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred output_lval_for_java(java_out_info::in, mlds_lval::in,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred output_call_rval_for_java(java_out_info::in, mlds_rval::in,
|
|
io::di, io::uo) is det.
|
|
|
|
:- pred output_bracketed_rval_for_java(java_out_info::in, mlds_rval::in,
|
|
io::di, io::uo) is det.
|
|
|
|
:- pred output_rval_for_java(java_out_info::in, mlds_rval::in,
|
|
io::di, io::uo) is det.
|
|
|
|
:- pred output_boxed_rval_for_java(java_out_info::in, mlds_type::in,
|
|
mlds_rval::in, io::di, io::uo) is det.
|
|
|
|
% Output an Rval and if the Rval is an enumeration object append the string
|
|
% ".MR_value", so we can access its value field.
|
|
%
|
|
% XXX Note that this is necessary in some places, but not in others.
|
|
% For example, it is important to do so for switch statements, as the
|
|
% argument of a switch _must_ be an integer in Java. However, adding
|
|
% the .MR_value to assignments breaks some casting... At some point, we
|
|
% need to go through all the places where output_rval and
|
|
% output_rval_maybe_with_enum are called and make sure the correct one
|
|
% is being used.
|
|
%
|
|
:- pred output_rval_maybe_with_enum_for_java(java_out_info::in, mlds_rval::in,
|
|
io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- pred output_initializer_for_java(java_out_info::in, output_aux::in,
|
|
mlds_type::in, mlds_initializer::in, io::di, io::uo) is det.
|
|
|
|
:- pred output_initializer_alloc_only_for_java(java_out_info::in,
|
|
mlds_initializer::in, maybe(mlds_type)::in, io::di, io::uo) is det.
|
|
|
|
:- pred output_initializer_body_for_java(java_out_info::in,
|
|
mlds_initializer::in, maybe(mlds_type)::in, io::di, io::uo) is det.
|
|
|
|
:- pred output_initializer_body_list_for_java(java_out_info::in,
|
|
list(mlds_initializer)::in, io::di, io::uo) is det.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% We need to provide initializers for local variables to avoid problems
|
|
% with Java's rules for definite assignment. This mirrors the default
|
|
% Java initializers for class and instance variables.
|
|
%
|
|
:- func get_default_initializer_for_java(mlds_type) = string.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module backend_libs.
|
|
:- import_module backend_libs.builtin_ops.
|
|
:- import_module backend_libs.c_util.
|
|
:- import_module backend_libs.rtti.
|
|
:- import_module hlds.
|
|
:- import_module hlds.hlds_module.
|
|
:- import_module libs.
|
|
:- import_module libs.globals.
|
|
:- import_module mdbcomp.
|
|
:- import_module mdbcomp.sym_name.
|
|
:- import_module ml_backend.ml_util.
|
|
:- import_module ml_backend.mlds_to_java_name.
|
|
:- import_module ml_backend.mlds_to_java_type.
|
|
:- import_module parse_tree.
|
|
:- import_module parse_tree.java_names.
|
|
:- import_module parse_tree.prog_data.
|
|
:- import_module parse_tree.prog_type.
|
|
|
|
:- import_module bool.
|
|
:- import_module char.
|
|
:- import_module int.
|
|
:- import_module int8.
|
|
:- import_module int16.
|
|
:- import_module int32.
|
|
:- import_module int64.
|
|
:- import_module map.
|
|
:- import_module require.
|
|
:- import_module string.
|
|
:- import_module term.
|
|
:- import_module uint.
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
output_lval_for_java(Info, Lval, !IO) :-
|
|
(
|
|
Lval = ml_field(_MaybeTag, PtrRval, _PtrType, FieldId, FieldType),
|
|
(
|
|
FieldId = ml_field_offset(OffsetRval),
|
|
( if
|
|
( FieldType = mlds_generic_type
|
|
; FieldType = mercury_nb_type(type_variable(_, _), _)
|
|
)
|
|
then
|
|
true
|
|
else
|
|
% The field type for field(_, _, offset(_), _, _) lvals
|
|
% must be something that maps to MR_Box.
|
|
unexpected($pred, "unexpected field type")
|
|
),
|
|
% XXX We shouldn't need this cast here, but there are cases where
|
|
% it is needed and the MLDS doesn't seem to generate it.
|
|
io.write_string("((java.lang.Object[]) ", !IO),
|
|
output_rval_for_java(Info, PtrRval, !IO),
|
|
io.write_string(")[", !IO),
|
|
output_rval_for_java(Info, OffsetRval, !IO),
|
|
io.write_string("]", !IO)
|
|
;
|
|
FieldId = ml_field_named(QualFieldVarName, CtorType),
|
|
QualFieldVarName = qual_field_var_name(_, _, FieldVarName),
|
|
( if FieldVarName = fvn_data_tag then
|
|
% If the field we are trying to access is just a `data_tag'
|
|
% then it is a member of the base class.
|
|
output_bracketed_rval_for_java(Info, PtrRval, !IO),
|
|
io.write_string(".", !IO)
|
|
else if PtrRval = ml_self(_) then
|
|
% Suppress type cast on `this' keyword. This makes a difference
|
|
% when assigning to `final' member variables in constructor
|
|
% functions.
|
|
output_rval_for_java(Info, PtrRval, !IO),
|
|
io.write_string(".", !IO)
|
|
else
|
|
% Otherwise the field we are trying to access may be
|
|
% in a derived class. Objects are manipulated as instances
|
|
% of their base class, so we need to downcast to the derived
|
|
% class to access some fields.
|
|
io.write_string("((", !IO),
|
|
output_type_for_java(Info, CtorType, !IO),
|
|
io.write_string(") ", !IO),
|
|
output_bracketed_rval_for_java(Info, PtrRval, !IO),
|
|
io.write_string(").", !IO)
|
|
),
|
|
output_field_var_name_for_java(FieldVarName, !IO)
|
|
)
|
|
;
|
|
Lval = ml_mem_ref(Rval, _Type),
|
|
output_bracketed_rval_for_java(Info, Rval, !IO)
|
|
;
|
|
Lval = ml_target_global_var_ref(GlobalVarRef),
|
|
GlobalVarRef = env_var_ref(EnvVarName),
|
|
io.write_string("mercury_envvar_", !IO),
|
|
io.write_string(EnvVarName, !IO)
|
|
;
|
|
Lval = ml_global_var(QualGlobalVarName, _),
|
|
output_maybe_qualified_global_var_name_for_java(Info,
|
|
QualGlobalVarName, !IO)
|
|
;
|
|
Lval = ml_local_var(QualLocalVarName, _),
|
|
output_local_var_name_for_java(QualLocalVarName, !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
output_call_rval_for_java(Info, Rval, !IO) :-
|
|
( if
|
|
Rval = ml_const(Const),
|
|
Const = mlconst_code_addr(CodeAddr)
|
|
then
|
|
IsCall = yes,
|
|
mlds_output_code_addr_for_java(Info, CodeAddr, IsCall, !IO)
|
|
else
|
|
output_bracketed_rval_for_java(Info, Rval, !IO)
|
|
).
|
|
|
|
output_bracketed_rval_for_java(Info, Rval, !IO) :-
|
|
( if
|
|
% If it is just a variable name, then we don't need parentheses.
|
|
( Rval = ml_lval(ml_local_var(_,_))
|
|
; Rval = ml_lval(ml_global_var(_,_))
|
|
; Rval = ml_const(mlconst_code_addr(_))
|
|
)
|
|
then
|
|
output_rval_for_java(Info, Rval, !IO)
|
|
else
|
|
io.write_char('(', !IO),
|
|
output_rval_for_java(Info, Rval, !IO),
|
|
io.write_char(')', !IO)
|
|
).
|
|
|
|
output_rval_for_java(Info, Rval, !IO) :-
|
|
(
|
|
Rval = ml_lval(Lval),
|
|
output_lval_for_java(Info, Lval, !IO)
|
|
;
|
|
Rval = ml_mkword(_, _),
|
|
unexpected($pred, "tags not supported in Java")
|
|
;
|
|
Rval = ml_const(Const),
|
|
output_rval_const_for_java(Info, Const, !IO)
|
|
;
|
|
Rval = ml_cast(Type, SubRval),
|
|
output_cast_rval_for_java(Info, Type, SubRval, !IO)
|
|
;
|
|
Rval = ml_box(Type, SubRval),
|
|
output_boxed_rval_for_java(Info, Type, SubRval, !IO)
|
|
;
|
|
Rval = ml_unbox(Type, SubRval),
|
|
output_unboxed_rval_for_java(Info, Type, SubRval, !IO)
|
|
;
|
|
Rval = ml_unop(Unop, SubRval),
|
|
output_unop_for_java(Info, Unop, SubRval, !IO)
|
|
;
|
|
Rval = ml_binop(BinOp, RvalA, RvalB),
|
|
output_binop_for_java(Info, BinOp, RvalA, RvalB, !IO)
|
|
;
|
|
Rval = ml_mem_addr(_Lval),
|
|
unexpected($pred, "mem_addr(_) not supported")
|
|
;
|
|
Rval = ml_scalar_common(_),
|
|
% This reference is not the same as a mlds_data_addr const.
|
|
unexpected($pred, "ml_scalar_common")
|
|
;
|
|
Rval = ml_scalar_common_addr(ScalarCommon),
|
|
ScalarCommon = ml_scalar_common(ModuleName, _Type,
|
|
ml_scalar_common_type_num(TypeNum), RowNum),
|
|
ModuleSymName = mlds_module_name_to_sym_name(ModuleName),
|
|
mangle_sym_name_for_java(ModuleSymName, module_qual, "__",
|
|
MangledModuleName),
|
|
io.format("%s.MR_scalar_common_%d[%d]",
|
|
[s(MangledModuleName),i(TypeNum), i(RowNum)], !IO)
|
|
;
|
|
Rval = ml_vector_common_row_addr(VectorCommon, RowRval),
|
|
VectorCommon = ml_vector_common(_ModuleName, _Type,
|
|
ml_vector_common_type_num(TypeNum), StartRowNum, _NumRows),
|
|
% XXX Why do we print a "MangledModuleName." prefix for scalar common
|
|
% addresses but not for vector common addresses?
|
|
io.format("MR_vector_common_%d[%d + ",
|
|
[i(TypeNum), i(StartRowNum)], !IO),
|
|
output_rval_for_java(Info, RowRval, !IO),
|
|
io.write_string("]", !IO)
|
|
;
|
|
Rval = ml_self(_),
|
|
io.write_string("this", !IO)
|
|
).
|
|
|
|
:- pred output_cast_rval_for_java(java_out_info::in, mlds_type::in,
|
|
mlds_rval::in, io::di, io::uo) is det.
|
|
|
|
output_cast_rval_for_java(Info, Type, Expr, !IO) :-
|
|
% rtti_to_mlds.m generates casts from int to
|
|
% jmercury.runtime.PseudoTypeInfo, but for Java
|
|
% we need to treat these as constructions, not casts.
|
|
% Similarly for conversions from TypeCtorInfo to TypeInfo.
|
|
( if
|
|
Type = mlds_pseudo_type_info_type,
|
|
Expr = ml_const(mlconst_int(N))
|
|
then
|
|
maybe_output_comment_for_java(Info, "cast", !IO),
|
|
( if have_preallocated_pseudo_type_var_for_java(N) then
|
|
io.write_string("jmercury.runtime.PseudoTypeInfo.K", !IO),
|
|
io.write_int(N, !IO)
|
|
else
|
|
io.write_string("new jmercury.runtime.PseudoTypeInfo(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(")", !IO)
|
|
)
|
|
else if
|
|
( Type = mercury_nb_type(_, ctor_cat_system(cat_system_type_info))
|
|
; Type = mlds_type_info_type
|
|
)
|
|
then
|
|
% XXX We really should be able to tell if we are casting a
|
|
% TypeCtorInfo or a TypeInfo. Julien says that's probably going to
|
|
% be rather difficult as the compiler doesn't keep track of where
|
|
% type_ctor_infos are acting as type_infos properly.
|
|
maybe_output_comment_for_java(Info, "cast", !IO),
|
|
io.write_string("jmercury.runtime.TypeInfo_Struct.maybe_new(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(")", !IO)
|
|
else if
|
|
java_builtin_type(Type, "int", _, _)
|
|
then
|
|
io.write_string("(int) ", !IO),
|
|
output_rval_maybe_with_enum_for_java(Info, Expr, !IO)
|
|
else
|
|
io.write_string("(", !IO),
|
|
output_type_for_java(Info, Type, !IO),
|
|
io.write_string(") ", !IO),
|
|
output_rval_for_java(Info, Expr, !IO)
|
|
).
|
|
|
|
:- pred have_preallocated_pseudo_type_var_for_java(int::in) is semidet.
|
|
|
|
have_preallocated_pseudo_type_var_for_java(N) :-
|
|
% Corresponds to static members in class PseudoTypeInfo.
|
|
N >= 1,
|
|
N =< 5.
|
|
|
|
output_boxed_rval_for_java(Info, Type, Expr, !IO) :-
|
|
( if java_builtin_type(Type, _JavaName, JavaBoxedName, _) then
|
|
% valueOf may return cached instances instead of creating new objects.
|
|
io.write_string(JavaBoxedName, !IO),
|
|
io.write_string(".valueOf(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(")", !IO)
|
|
else
|
|
io.write_string("((java.lang.Object) (", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string("))", !IO)
|
|
).
|
|
|
|
:- pred output_unboxed_rval_for_java(java_out_info::in, mlds_type::in,
|
|
mlds_rval::in, io::di, io::uo) is det.
|
|
|
|
output_unboxed_rval_for_java(Info, Type, Expr, !IO) :-
|
|
( if java_builtin_type(Type, _, JavaBoxedName, UnboxMethod) then
|
|
io.write_string("((", !IO),
|
|
io.write_string(JavaBoxedName, !IO),
|
|
io.write_string(") ", !IO),
|
|
output_bracketed_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(").", !IO),
|
|
io.write_string(UnboxMethod, !IO),
|
|
io.write_string("()", !IO)
|
|
else
|
|
io.write_string("((", !IO),
|
|
output_type_for_java(Info, Type, !IO),
|
|
io.write_string(") ", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(")", !IO)
|
|
).
|
|
|
|
:- pred output_unop_for_java(java_out_info::in, builtin_ops.unary_op::in,
|
|
mlds_rval::in, io::di, io::uo) is det.
|
|
|
|
output_unop_for_java(Info, UnaryOp, Expr, !IO) :-
|
|
% For the Java back-end, there are no tags, so all the tagging operators
|
|
% are no-ops, except for `tag', which always returns zero (a tag of zero
|
|
% means there is no tag).
|
|
(
|
|
UnaryOp = tag,
|
|
io.write_string("/* tag */ 0", !IO)
|
|
;
|
|
( UnaryOp = strip_tag, UnaryOpStr = "/* strip_tag */ "
|
|
; UnaryOp = mkbody, UnaryOpStr = "/* mkbody */ "
|
|
; UnaryOp = unmkbody, UnaryOpStr = "/* unmkbody */ "
|
|
; UnaryOp = bitwise_complement(int_type_int), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_uint), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_int32), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_uint32), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_int64), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_uint64), UnaryOpStr = "~"
|
|
; UnaryOp = logical_not, UnaryOpStr = "!"
|
|
; UnaryOp = hash_string, UnaryOpStr = "mercury.String.hash_1_f_0"
|
|
; UnaryOp = hash_string2, UnaryOpStr = "mercury.String.hash2_1_f_0"
|
|
; UnaryOp = hash_string3, UnaryOpStr = "mercury.String.hash3_1_f_0"
|
|
; UnaryOp = hash_string4, UnaryOpStr = "mercury.String.hash4_1_f_0"
|
|
; UnaryOp = hash_string5, UnaryOpStr = "mercury.String.hash5_1_f_0"
|
|
; UnaryOp = hash_string6, UnaryOpStr = "mercury.String.hash6_1_f_0"
|
|
),
|
|
io.write_string(UnaryOpStr, !IO),
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
( UnaryOp = bitwise_complement(int_type_int8), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_uint8), UnaryOpStr = "~"
|
|
),
|
|
io.write_string("(byte)(", !IO),
|
|
io.write_string(UnaryOpStr, !IO),
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string("))", !IO)
|
|
;
|
|
( UnaryOp = bitwise_complement(int_type_int16), UnaryOpStr = "~"
|
|
; UnaryOp = bitwise_complement(int_type_uint16), UnaryOpStr = "~"
|
|
),
|
|
io.write_string("(short)(", !IO),
|
|
io.write_string(UnaryOpStr, !IO),
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, Expr, !IO),
|
|
io.write_string("))", !IO)
|
|
;
|
|
( UnaryOp = dword_float_get_word0
|
|
; UnaryOp = dword_float_get_word1
|
|
; UnaryOp = dword_int64_get_word0
|
|
; UnaryOp = dword_int64_get_word1
|
|
; UnaryOp = dword_uint64_get_word0
|
|
; UnaryOp = dword_uint64_get_word1
|
|
),
|
|
unexpected($pred, "invalid unary operator")
|
|
).
|
|
|
|
:- pred output_binop_for_java(java_out_info::in, binary_op::in, mlds_rval::in,
|
|
mlds_rval::in, io::di, io::uo) is det.
|
|
|
|
output_binop_for_java(Info, Op, X, Y, !IO) :-
|
|
(
|
|
Op = array_index(_Type),
|
|
output_bracketed_rval_for_java(Info, X, !IO),
|
|
io.write_string("[", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string("]", !IO)
|
|
;
|
|
Op = str_eq,
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(".equals(", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
( Op = str_ne, OpStr = "!="
|
|
; Op = str_lt, OpStr = "<"
|
|
; Op = str_gt, OpStr = ">"
|
|
; Op = str_le, OpStr = "<="
|
|
; Op = str_ge, OpStr = ">="
|
|
),
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(".compareTo(", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") ", !IO),
|
|
io.write_string(OpStr, !IO),
|
|
io.write_string(" 0)", !IO)
|
|
;
|
|
Op = str_cmp,
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(".compareTo(", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")) ", !IO)
|
|
;
|
|
Op = pointer_equal_conservative,
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(" == ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") ", !IO)
|
|
;
|
|
% XXX Should we abort for some of these?
|
|
( Op = int_add(int_type_int)
|
|
; Op = int_sub(int_type_int)
|
|
; Op = int_mul(int_type_int)
|
|
; Op = int_div(int_type_int)
|
|
; Op = int_mod(int_type_int)
|
|
; Op = unchecked_left_shift(int_type_int)
|
|
; Op = unchecked_right_shift(int_type_int)
|
|
; Op = bitwise_and(int_type_int)
|
|
; Op = bitwise_or(int_type_int)
|
|
; Op = bitwise_xor(int_type_int)
|
|
; Op = int_lt(int_type_int32)
|
|
; Op = int_gt(int_type_int32)
|
|
; Op = int_le(int_type_int32)
|
|
; Op = int_ge(int_type_int32)
|
|
; Op = int_add(int_type_int32)
|
|
; Op = int_sub(int_type_int32)
|
|
; Op = int_mul(int_type_int32)
|
|
; Op = int_div(int_type_int32)
|
|
; Op = int_mod(int_type_int32)
|
|
; Op = bitwise_and(int_type_int32)
|
|
; Op = bitwise_or(int_type_int32)
|
|
; Op = bitwise_xor(int_type_int32)
|
|
; Op = unchecked_left_shift(int_type_int32)
|
|
; Op = unchecked_right_shift(int_type_int32)
|
|
; Op = int_add(int_type_uint)
|
|
; Op = int_sub(int_type_uint)
|
|
; Op = int_mul(int_type_uint)
|
|
; Op = bitwise_and(int_type_uint)
|
|
; Op = bitwise_or(int_type_uint)
|
|
; Op = bitwise_xor(int_type_uint)
|
|
; Op = unchecked_left_shift(int_type_uint)
|
|
; Op = unchecked_right_shift(int_type_uint)
|
|
; Op = int_add(int_type_uint32)
|
|
; Op = int_sub(int_type_uint32)
|
|
; Op = int_mul(int_type_uint32)
|
|
; Op = bitwise_and(int_type_uint32)
|
|
; Op = bitwise_or(int_type_uint32)
|
|
; Op = bitwise_xor(int_type_uint32)
|
|
; Op = unchecked_left_shift(int_type_uint32)
|
|
; Op = unchecked_right_shift(int_type_uint32)
|
|
; Op = int_lt(int_type_int64)
|
|
; Op = int_gt(int_type_int64)
|
|
; Op = int_le(int_type_int64)
|
|
; Op = int_ge(int_type_int64)
|
|
; Op = int_add(int_type_int64)
|
|
; Op = int_sub(int_type_int64)
|
|
; Op = int_mul(int_type_int64)
|
|
; Op = int_div(int_type_int64)
|
|
; Op = int_mod(int_type_int64)
|
|
; Op = bitwise_and(int_type_int64)
|
|
; Op = bitwise_or(int_type_int64)
|
|
; Op = bitwise_xor(int_type_int64)
|
|
; Op = unchecked_left_shift(int_type_int64)
|
|
; Op = unchecked_right_shift(int_type_int64)
|
|
; Op = int_add(int_type_uint64)
|
|
; Op = int_sub(int_type_uint64)
|
|
; Op = int_mul(int_type_uint64)
|
|
; Op = bitwise_and(int_type_uint64)
|
|
; Op = bitwise_or(int_type_uint64)
|
|
; Op = bitwise_xor(int_type_uint64)
|
|
; Op = unchecked_left_shift(int_type_uint64)
|
|
; Op = unchecked_right_shift(int_type_uint64)
|
|
; Op = logical_and
|
|
; Op = logical_or
|
|
; Op = eq(_)
|
|
; Op = ne(_)
|
|
; Op = body
|
|
; Op = string_unsafe_index_code_unit
|
|
; Op = offset_str_eq(_)
|
|
; Op = int_lt(int_type_int)
|
|
; Op = int_gt(int_type_int)
|
|
; Op = int_le(int_type_int)
|
|
; Op = int_ge(int_type_int)
|
|
; Op = unsigned_le
|
|
; Op = float_plus
|
|
; Op = float_minus
|
|
; Op = float_times
|
|
; Op = float_divide
|
|
; Op = float_eq
|
|
; Op = float_ne
|
|
; Op = float_lt
|
|
; Op = float_gt
|
|
; Op = float_le
|
|
; Op = float_ge
|
|
; Op = float_from_dword
|
|
; Op = int64_from_dword
|
|
; Op = uint64_from_dword
|
|
; Op = compound_eq
|
|
; Op = compound_lt
|
|
; Op = int_lt(int_type_int8)
|
|
; Op = int_gt(int_type_int8)
|
|
; Op = int_le(int_type_int8)
|
|
; Op = int_ge(int_type_int8)
|
|
; Op = int_lt(int_type_int16)
|
|
; Op = int_gt(int_type_int16)
|
|
; Op = int_le(int_type_int16)
|
|
; Op = int_ge(int_type_int16)
|
|
),
|
|
( if rval_is_enum_object(X) then
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(".MR_value ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(".MR_value)", !IO)
|
|
else
|
|
io.write_string("(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
)
|
|
;
|
|
( Op = int_lt(int_type_uint)
|
|
; Op = int_gt(int_type_uint)
|
|
; Op = int_le(int_type_uint)
|
|
; Op = int_ge(int_type_uint)
|
|
; Op = int_lt(int_type_uint32)
|
|
; Op = int_gt(int_type_uint32)
|
|
; Op = int_le(int_type_uint32)
|
|
; Op = int_ge(int_type_uint32)
|
|
),
|
|
io.write_string("(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xffffffffL) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xffffffffL))", !IO)
|
|
;
|
|
( Op = int_lt(int_type_uint64), RelOpStr = "<"
|
|
; Op = int_gt(int_type_uint64), RelOpStr = ">"
|
|
; Op = int_le(int_type_uint64), RelOpStr = "<="
|
|
; Op = int_ge(int_type_uint64), RelOpStr = ">="
|
|
),
|
|
io.write_string("(java.lang.Long.compareUnsigned(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(", ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") ", !IO),
|
|
io.write_string(RelOpStr, !IO),
|
|
io.write_string(" 0)", !IO)
|
|
;
|
|
( Op = int_div(int_type_uint)
|
|
; Op = int_mod(int_type_uint)
|
|
; Op = int_div(int_type_uint32)
|
|
; Op = int_mod(int_type_uint32)
|
|
),
|
|
io.write_string("((int)(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xffffffffL) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xffffffffL)))", !IO)
|
|
;
|
|
Op = int_div(int_type_uint64),
|
|
io.write_string("java.lang.Long.divideUnsigned(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(", ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
Op = int_mod(int_type_uint64),
|
|
io.write_string("java.lang.Long.remainderUnsigned(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(", ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
( Op = int_add(int_type_int8)
|
|
; Op = int_sub(int_type_int8)
|
|
; Op = int_mul(int_type_int8)
|
|
; Op = int_div(int_type_int8)
|
|
; Op = int_mod(int_type_int8)
|
|
; Op = bitwise_and(int_type_int8)
|
|
; Op = bitwise_or(int_type_int8)
|
|
; Op = bitwise_xor(int_type_int8)
|
|
; Op = unchecked_left_shift(int_type_int8)
|
|
; Op = unchecked_right_shift(int_type_int8)
|
|
; Op = int_add(int_type_uint8)
|
|
; Op = int_sub(int_type_uint8)
|
|
; Op = int_mul(int_type_uint8)
|
|
; Op = bitwise_and(int_type_uint8)
|
|
; Op = bitwise_or(int_type_uint8)
|
|
; Op = bitwise_xor(int_type_uint8)
|
|
; Op = unchecked_left_shift(int_type_uint8)
|
|
),
|
|
io.write_string("(byte)(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
Op = unchecked_right_shift(int_type_uint8),
|
|
io.write_string("(byte)(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
( Op = int_lt(int_type_uint8)
|
|
; Op = int_gt(int_type_uint8)
|
|
; Op = int_le(int_type_uint8)
|
|
; Op = int_ge(int_type_uint8)
|
|
),
|
|
io.write_string("(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xff))", !IO)
|
|
;
|
|
( Op = int_div(int_type_uint8)
|
|
; Op = int_mod(int_type_uint8)
|
|
),
|
|
io.write_string("((byte)(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xff)))", !IO)
|
|
;
|
|
( Op = int_add(int_type_int16)
|
|
; Op = int_sub(int_type_int16)
|
|
; Op = int_mul(int_type_int16)
|
|
; Op = int_div(int_type_int16)
|
|
; Op = int_mod(int_type_int16)
|
|
; Op = bitwise_and(int_type_int16)
|
|
; Op = bitwise_or(int_type_int16)
|
|
; Op = bitwise_xor(int_type_int16)
|
|
; Op = unchecked_left_shift(int_type_int16)
|
|
; Op = unchecked_right_shift(int_type_int16)
|
|
; Op = int_add(int_type_uint16)
|
|
; Op = int_sub(int_type_uint16)
|
|
; Op = int_mul(int_type_uint16)
|
|
; Op = bitwise_and(int_type_uint16)
|
|
; Op = bitwise_or(int_type_uint16)
|
|
; Op = bitwise_xor(int_type_uint16)
|
|
; Op = unchecked_left_shift(int_type_uint16)
|
|
),
|
|
io.write_string("(short)(", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
Op = unchecked_right_shift(int_type_uint16),
|
|
io.write_string("(short)(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xffff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
( Op = int_lt(int_type_uint16)
|
|
; Op = int_gt(int_type_uint16)
|
|
; Op = int_le(int_type_uint16)
|
|
; Op = int_ge(int_type_uint16)
|
|
),
|
|
io.write_string("(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xffff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xffff))", !IO)
|
|
;
|
|
( Op = int_div(int_type_uint16)
|
|
; Op = int_mod(int_type_uint16)
|
|
),
|
|
io.write_string("((short)(((", !IO),
|
|
output_rval_for_java(Info, X, !IO),
|
|
io.write_string(") & 0xffff) ", !IO),
|
|
output_binary_op_for_java(Op, !IO),
|
|
io.write_string(" ((", !IO),
|
|
output_rval_for_java(Info, Y, !IO),
|
|
io.write_string(") & 0xffff)))", !IO)
|
|
).
|
|
|
|
output_rval_maybe_with_enum_for_java(Info, Rval, !IO) :-
|
|
output_rval_for_java(Info, Rval, !IO),
|
|
( if rval_is_enum_object(Rval) then
|
|
io.write_string(".MR_value", !IO)
|
|
else
|
|
true
|
|
).
|
|
|
|
:- pred output_binary_op_for_java(binary_op::in, io::di, io::uo) is det.
|
|
|
|
output_binary_op_for_java(Op, !IO) :-
|
|
(
|
|
( Op = int_add(_), OpStr = "+"
|
|
; Op = int_sub(_), OpStr = "-"
|
|
; Op = int_mul(_), OpStr = "*"
|
|
% NOTE: unsigned div and mod require special handling in Java.
|
|
% See output_binop/6 above.
|
|
; Op = int_div(_), OpStr = "/"
|
|
; Op = int_mod(_), OpStr = "%"
|
|
; Op = unchecked_left_shift(_), OpStr = "<<"
|
|
; Op = bitwise_and(_), OpStr = "&"
|
|
; Op = bitwise_or(_), OpStr = "|"
|
|
; Op = bitwise_xor(_), OpStr = "^"
|
|
; Op = logical_and, OpStr = "&&"
|
|
; Op = logical_or, OpStr = "||"
|
|
% NOTE: unsigned comparisons require special handling in Java.
|
|
% See output_binop/6 above.
|
|
; Op = eq(_), OpStr = "=="
|
|
; Op = ne(_), OpStr = "!="
|
|
; Op = int_lt(_), OpStr = "<"
|
|
; Op = int_gt(_), OpStr = ">"
|
|
; Op = int_le(_), OpStr = "<="
|
|
; Op = int_ge(_), OpStr = ">="
|
|
|
|
; Op = float_eq, OpStr = "=="
|
|
; Op = float_ne, OpStr = "!="
|
|
; Op = float_le, OpStr = "<="
|
|
; Op = float_ge, OpStr = ">="
|
|
; Op = float_lt, OpStr = "<"
|
|
; Op = float_gt, OpStr = ">"
|
|
|
|
; Op = float_plus, OpStr = "+"
|
|
; Op = float_minus, OpStr = "-"
|
|
; Op = float_times, OpStr = "*"
|
|
; Op = float_divide, OpStr = "/"
|
|
),
|
|
io.write_string(OpStr, !IO)
|
|
;
|
|
Op = unchecked_right_shift(IntType),
|
|
(
|
|
( IntType = int_type_int
|
|
; IntType = int_type_int8
|
|
; IntType = int_type_int16
|
|
; IntType = int_type_int32
|
|
; IntType = int_type_int64
|
|
),
|
|
OpStr = ">>"
|
|
;
|
|
( IntType = int_type_uint
|
|
; IntType = int_type_uint8
|
|
; IntType = int_type_uint16
|
|
; IntType = int_type_uint32
|
|
; IntType = int_type_uint64
|
|
),
|
|
OpStr = ">>>"
|
|
),
|
|
io.write_string(OpStr, !IO)
|
|
;
|
|
( Op = array_index(_)
|
|
; Op = body
|
|
; Op = float_from_dword
|
|
; Op = int64_from_dword
|
|
; Op = uint64_from_dword
|
|
; Op = offset_str_eq(_)
|
|
; Op = str_cmp
|
|
; Op = str_eq
|
|
; Op = str_ge
|
|
; Op = str_gt
|
|
; Op = str_le
|
|
; Op = str_lt
|
|
; Op = str_ne
|
|
; Op = string_unsafe_index_code_unit
|
|
; Op = pointer_equal_conservative
|
|
; Op = unsigned_le
|
|
; Op = compound_eq
|
|
; Op = compound_lt
|
|
),
|
|
unexpected($pred, "invalid binary operator")
|
|
).
|
|
|
|
:- pred output_rval_const_for_java(java_out_info::in, mlds_rval_const::in,
|
|
io::di, io::uo) is det.
|
|
|
|
output_rval_const_for_java(Info, Const, !IO) :-
|
|
(
|
|
Const = mlconst_true,
|
|
io.write_string("true", !IO)
|
|
;
|
|
Const = mlconst_false,
|
|
io.write_string("false", !IO)
|
|
;
|
|
Const = mlconst_int(N),
|
|
output_int_const_for_java(N, !IO)
|
|
;
|
|
Const = mlconst_uint(U),
|
|
% Java does not have unsigned integer literals.
|
|
% XXX perhaps we should output this in hexadecimal?
|
|
output_int_const_for_java(uint.cast_to_int(U), !IO)
|
|
;
|
|
Const = mlconst_int8(I8),
|
|
io.write_string("(byte)", !IO),
|
|
io.write_int8(I8, !IO)
|
|
;
|
|
Const = mlconst_uint8(U8),
|
|
io.write_string("(byte)", !IO),
|
|
io.write_int8(int8.cast_from_uint8(U8), !IO)
|
|
;
|
|
Const = mlconst_int16(I16),
|
|
io.write_string("(short)", !IO),
|
|
io.write_int16(I16, !IO)
|
|
;
|
|
Const = mlconst_uint16(U16),
|
|
io.write_string("(short)", !IO),
|
|
io.write_int16(int16.cast_from_uint16(U16), !IO)
|
|
;
|
|
Const = mlconst_int32(I32),
|
|
io.write_int32(I32, !IO)
|
|
;
|
|
Const = mlconst_uint32(U32),
|
|
io.write_int32(int32.cast_from_uint32(U32), !IO)
|
|
;
|
|
Const = mlconst_int64(I64),
|
|
io.write_int64(I64, !IO),
|
|
io.write_string("L", !IO)
|
|
;
|
|
Const = mlconst_uint64(U64),
|
|
io.write_int64(int64.cast_from_uint64(U64), !IO),
|
|
io.write_string("L", !IO)
|
|
;
|
|
Const = mlconst_char(N),
|
|
io.write_string("(", !IO),
|
|
output_int_const_for_java(N, !IO),
|
|
io.write_string(")", !IO)
|
|
;
|
|
Const = mlconst_enum(N, EnumType),
|
|
output_type_for_java(Info, EnumType, !IO),
|
|
io.write_string(".K", !IO),
|
|
output_int_const_for_java(N, !IO)
|
|
;
|
|
Const = mlconst_foreign(Lang, Value, _Type),
|
|
expect(unify(Lang, lang_java), $pred, "language other than Java."),
|
|
% XXX Should we parenthesize this?
|
|
io.write_string(Value, !IO)
|
|
;
|
|
Const = mlconst_float(FloatVal),
|
|
c_util.output_float_literal_cur_stream(FloatVal, !IO)
|
|
;
|
|
Const = mlconst_string(String),
|
|
io.write_string("""", !IO),
|
|
c_util.output_quoted_string_lang_cur_stream(literal_java,
|
|
String, !IO),
|
|
io.write_string("""", !IO)
|
|
;
|
|
Const = mlconst_multi_string(String),
|
|
io.write_string("""", !IO),
|
|
c_util.output_quoted_multi_string_lang_cur_stream(literal_java,
|
|
String, !IO),
|
|
io.write_string("""", !IO)
|
|
;
|
|
Const = mlconst_named_const(TargetPrefixes, NamedConst),
|
|
io.write_string(TargetPrefixes ^ java_prefix, !IO),
|
|
io.write_string(NamedConst, !IO)
|
|
;
|
|
Const = mlconst_code_addr(CodeAddr),
|
|
IsCall = no,
|
|
mlds_output_code_addr_for_java(Info, CodeAddr, IsCall, !IO)
|
|
;
|
|
Const = mlconst_data_addr_local_var(LocalVarName),
|
|
output_local_var_name_for_java(LocalVarName, !IO)
|
|
;
|
|
Const = mlconst_data_addr_global_var(ModuleName, GlobalVarName),
|
|
SymName = mlds_module_name_to_sym_name(ModuleName),
|
|
mangle_sym_name_for_java(SymName, module_qual, "__", ModuleNameStr),
|
|
io.write_string(ModuleNameStr, !IO),
|
|
io.write_string(".", !IO),
|
|
output_global_var_name_for_java(GlobalVarName, !IO)
|
|
;
|
|
Const = mlconst_data_addr_rtti(ModuleName, RttiId),
|
|
SymName = mlds_module_name_to_sym_name(ModuleName),
|
|
mangle_sym_name_for_java(SymName, module_qual, "__", ModuleNameStr),
|
|
io.write_string(ModuleNameStr, !IO),
|
|
io.write_string(".", !IO),
|
|
rtti.id_to_c_identifier(RttiId, RttiAddrName),
|
|
io.write_string(RttiAddrName, !IO)
|
|
;
|
|
Const = mlconst_data_addr_tabling(QualProcLabel, TablingId),
|
|
QualProcLabel = qual_proc_label(ModuleName, ProcLabel),
|
|
SymName = mlds_module_name_to_sym_name(ModuleName),
|
|
mangle_sym_name_for_java(SymName, module_qual, "__", ModuleNameStr),
|
|
io.write_string(ModuleNameStr, !IO),
|
|
io.write_string(".", !IO),
|
|
TablingPrefix = tabling_info_id_str(TablingId) ++ "_",
|
|
io.write_string(TablingPrefix, !IO),
|
|
mlds_output_proc_label_for_java(mlds_std_tabling_proc_label(ProcLabel),
|
|
!IO)
|
|
;
|
|
Const = mlconst_null(Type),
|
|
Initializer = get_default_initializer_for_java(Type),
|
|
io.write_string(Initializer, !IO)
|
|
).
|
|
|
|
:- pred output_int_const_for_java(int::in, io::di, io::uo) is det.
|
|
|
|
output_int_const_for_java(N, !IO) :-
|
|
% The Mercury compiler could be using 64-bit integers but Java has 32-bit
|
|
% ints. A literal 0xffffffff in a source file would be interpreted by a
|
|
% 64-bit Mercury compiler as 4294967295. If it is written out in decimal,
|
|
% a Java compiler would rightly complain because the integer is too large
|
|
% to fit in a 32-bit int. However, it won't complain if the literal is
|
|
% expressed in hexadecimal (nor as the negative decimal -1).
|
|
( if
|
|
N > 0,
|
|
N >> 31 = 1
|
|
then
|
|
% The bit pattern fits in 32 bits, but is too large to write as a
|
|
% positive decimal. This branch is unreachable on a 32-bit compiler.
|
|
io.format("0x%x", [i(N /\ 0xffffffff)], !IO)
|
|
else
|
|
io.write_int(N, !IO)
|
|
).
|
|
|
|
:- pred mlds_output_code_addr_for_java(java_out_info::in, mlds_code_addr::in,
|
|
bool::in, io::di, io::uo) is det.
|
|
|
|
mlds_output_code_addr_for_java(Info, CodeAddr, IsCall, !IO) :-
|
|
(
|
|
IsCall = no,
|
|
% Not a function call, so we are taking the address of the
|
|
% wrapper for that function (method).
|
|
io.write_string("new ", !IO),
|
|
AddrOfMap = Info ^ joi_addrof_map,
|
|
map.lookup(AddrOfMap, CodeAddr, CodeAddrWrapper),
|
|
CodeAddrWrapper = code_addr_wrapper(ClassName, MaybePtrNum),
|
|
io.write_string(ClassName, !IO),
|
|
io.write_string("_0(", !IO),
|
|
(
|
|
MaybePtrNum = yes(PtrNum),
|
|
io.write_int(PtrNum, !IO)
|
|
;
|
|
MaybePtrNum = no
|
|
),
|
|
io.write_string(")", !IO)
|
|
;
|
|
IsCall = yes,
|
|
CodeAddr = mlds_code_addr(QualFuncLabel, _Signature),
|
|
QualFuncLabel = qual_func_label(ModuleName, FuncLabel),
|
|
FuncLabel = mlds_func_label(ProcLabel, MaybeAux),
|
|
output_qual_name_prefix_java(ModuleName, module_qual, !IO),
|
|
mlds_output_proc_label_for_java(ProcLabel, !IO),
|
|
io.write_string(mlds_maybe_aux_func_id_to_suffix(MaybeAux), !IO)
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
% Succeeds iff the Rval represents an enumeration object in the Java
|
|
% backend. We need to check both Rvals that are variables and Rvals
|
|
% that are casts. We need to know this in order to append the field name
|
|
% to the object so we can access the value of the enumeration object.
|
|
%
|
|
:- pred rval_is_enum_object(mlds_rval::in) is semidet.
|
|
|
|
rval_is_enum_object(Rval) :-
|
|
Rval = ml_lval(Lval),
|
|
(
|
|
Lval = ml_local_var(_, Type)
|
|
;
|
|
Lval = ml_global_var(_, Type)
|
|
;
|
|
Lval = ml_field(_, _, _, _, Type)
|
|
),
|
|
type_is_enum(Type).
|
|
|
|
% Succeeds iff this type is a enumeration.
|
|
%
|
|
:- pred type_is_enum(mlds_type::in) is semidet.
|
|
|
|
type_is_enum(Type) :-
|
|
Type = mercury_nb_type(_, CtorCat),
|
|
CtorCat = ctor_cat_enum(_).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
output_initializer_for_java(Info, OutputAux, Type, Initializer, !IO) :-
|
|
(
|
|
( Initializer = init_obj(_)
|
|
; Initializer = init_struct(_, _)
|
|
; Initializer = init_array(_)
|
|
),
|
|
io.write_string(" = ", !IO),
|
|
% Due to cyclic references, we need to separate the allocation and
|
|
% initialisation steps of RTTI structures. If InitStyle is alloc_only
|
|
% then we output an initializer to allocate a structure without filling
|
|
% in the fields.
|
|
(
|
|
( OutputAux = oa_none
|
|
; OutputAux = oa_cname(_, _)
|
|
; OutputAux = oa_force_init
|
|
),
|
|
output_initializer_body_for_java(Info, Initializer,
|
|
yes(Type), !IO)
|
|
;
|
|
OutputAux = oa_alloc_only,
|
|
output_initializer_alloc_only_for_java(Info, Initializer,
|
|
yes(Type), !IO)
|
|
)
|
|
;
|
|
Initializer = no_initializer,
|
|
(
|
|
OutputAux = oa_force_init,
|
|
% Local variables need to be initialised to avoid warnings.
|
|
io.write_string(" = ", !IO),
|
|
io.write_string(get_default_initializer_for_java(Type), !IO)
|
|
;
|
|
( OutputAux = oa_none
|
|
; OutputAux = oa_cname(_, _)
|
|
; OutputAux = oa_alloc_only
|
|
)
|
|
)
|
|
).
|
|
|
|
output_initializer_alloc_only_for_java(Info, Initializer, MaybeType, !IO) :-
|
|
(
|
|
Initializer = no_initializer,
|
|
unexpected($pred, "no_initializer")
|
|
;
|
|
Initializer = init_obj(_),
|
|
unexpected($pred, "init_obj")
|
|
;
|
|
Initializer = init_struct(StructType, FieldInits),
|
|
io.write_string("new ", !IO),
|
|
( if
|
|
StructType = mercury_nb_type(_, CtorCat),
|
|
type_category_is_array(CtorCat) = is_array
|
|
then
|
|
Size = list.length(FieldInits),
|
|
io.format("java.lang.Object[%d]", [i(Size)], !IO)
|
|
else
|
|
output_type_for_java(Info, StructType, !IO),
|
|
io.write_string("()", !IO)
|
|
)
|
|
;
|
|
Initializer = init_array(ElementInits),
|
|
Size = list.length(ElementInits),
|
|
io.write_string("new ", !IO),
|
|
(
|
|
MaybeType = yes(Type),
|
|
type_to_string_for_java(Info, Type, String, ArrayDims),
|
|
io.write_string(String, !IO),
|
|
% Replace the innermost array dimension by the known size.
|
|
( if list.split_last(ArrayDims, Heads, 0) then
|
|
output_array_dimensions(Heads ++ [Size], !IO)
|
|
else
|
|
unexpected($pred, "missing array dimension")
|
|
)
|
|
;
|
|
MaybeType = no,
|
|
% XXX we need to know the type here
|
|
io.format("/* XXX init_array */ Object[%d]", [i(Size)], !IO)
|
|
)
|
|
).
|
|
|
|
output_initializer_body_for_java(Info, Initializer, MaybeType, !IO) :-
|
|
(
|
|
Initializer = no_initializer,
|
|
unexpected($pred, "no_initializer")
|
|
;
|
|
Initializer = init_obj(Rval),
|
|
output_rval_for_java(Info, Rval, !IO)
|
|
;
|
|
Initializer = init_struct(StructType, FieldInits),
|
|
io.write_string("new ", !IO),
|
|
output_type_for_java(Info, StructType, !IO),
|
|
IsArray = type_is_array_for_java(StructType),
|
|
io.write_string(if IsArray = is_array then " {" else "(", !IO),
|
|
output_initializer_body_list_for_java(Info, FieldInits, !IO),
|
|
io.write_char(if IsArray = is_array then '}' else ')', !IO)
|
|
;
|
|
Initializer = init_array(ElementInits),
|
|
io.write_string("new ", !IO),
|
|
(
|
|
MaybeType = yes(Type),
|
|
output_type_for_java(Info, Type, !IO)
|
|
;
|
|
MaybeType = no,
|
|
% XXX we need to know the type here
|
|
io.write_string("/* XXX init_array */ Object[]", !IO)
|
|
),
|
|
io.write_string(" {\n\t\t", !IO),
|
|
output_initializer_body_list_for_java(Info, ElementInits, !IO),
|
|
io.write_string("}", !IO)
|
|
).
|
|
|
|
output_initializer_body_list_for_java(Info, Inits, !IO) :-
|
|
io.write_list(Inits, ",\n\t\t",
|
|
( pred(Init::in, !.IO::di, !:IO::uo) is det :-
|
|
output_initializer_body_for_java(Info, Init, no, !IO)
|
|
), !IO).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
|
|
get_default_initializer_for_java(Type) = Initializer :-
|
|
(
|
|
Type = mercury_nb_type(_, CtorCat),
|
|
(
|
|
CtorCat = ctor_cat_builtin(_),
|
|
unexpected($pred, "mercury_nb_type but ctor_cat_builtin")
|
|
;
|
|
( CtorCat = ctor_cat_system(_)
|
|
; CtorCat = ctor_cat_higher_order
|
|
; CtorCat = ctor_cat_tuple
|
|
; CtorCat = ctor_cat_enum(_)
|
|
; CtorCat = ctor_cat_builtin_dummy
|
|
; CtorCat = ctor_cat_variable
|
|
; CtorCat = ctor_cat_void
|
|
; CtorCat = ctor_cat_user(_)
|
|
),
|
|
Initializer = "null"
|
|
)
|
|
;
|
|
( Type = mlds_builtin_type_int(_)
|
|
; Type = mlds_builtin_type_float
|
|
),
|
|
Initializer = "0"
|
|
;
|
|
Type = mlds_builtin_type_string,
|
|
Initializer = "null"
|
|
;
|
|
Type = mlds_builtin_type_char,
|
|
Initializer = "'\\u0000'"
|
|
;
|
|
Type = mlds_native_bool_type,
|
|
Initializer = "false"
|
|
;
|
|
Type = mlds_foreign_type(ForeignLangType),
|
|
( if
|
|
java_primitive_foreign_language_type(ForeignLangType, _, _,
|
|
_, Initializer0)
|
|
then
|
|
Initializer = Initializer0
|
|
else
|
|
Initializer = "null"
|
|
)
|
|
;
|
|
( Type = mlds_mercury_array_type(_)
|
|
; Type = mlds_cont_type(_)
|
|
; Type = mlds_commit_type
|
|
; Type = mlds_class_type(_)
|
|
; Type = mlds_array_type(_)
|
|
; Type = mlds_mostly_generic_array_type(_)
|
|
; Type = mlds_ptr_type(_)
|
|
; Type = mlds_func_type(_)
|
|
; Type = mlds_generic_type
|
|
; Type = mlds_generic_env_ptr_type
|
|
; Type = mlds_type_info_type
|
|
; Type = mlds_pseudo_type_info_type
|
|
; Type = mlds_rtti_type(_)
|
|
; Type = mlds_tabling_type(_)
|
|
),
|
|
Initializer = "null"
|
|
;
|
|
Type = mlds_unknown_type,
|
|
unexpected($pred, "variable has unknown_type")
|
|
).
|
|
|
|
%---------------------------------------------------------------------------%
|
|
:- end_module ml_backend.mlds_to_java_data.
|
|
%---------------------------------------------------------------------------%
|