123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1998 Institut National de Recherche en Informatique et *)(* en Automatique. *)(* *)(* All rights reserved. This file is distributed under the terms of *)(* the GNU Lesser General Public License version 2.1, with the *)(* special exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)(* Auxiliaries for type-based optimizations, e.g. array kinds *)openTypesopenAsttypesopenTypedtreeletscrape_tyenvty=matchget_desctywith|Tconstr_->letty=Ctype.expand_head_optenv(Ctype.correct_levelsty)inbeginmatchget_desctywith|Tconstr(p,_,_)->beginmatchEnv.find_typepenvwith|{type_kind=(Type_variant(_,Variant_unboxed)|Type_record(_,Record_unboxed_));_}->beginmatchTypedecl_unboxed.get_unboxed_type_representationenvtywith|None->ty|Somety2->ty2end|_->ty|exceptionNot_found->tyend|_->tyend|_->tyletscrapeenvty=get_desc(scrape_tyenvty)let_scrape_polyenvty=letty=scrape_tyenvtyinmatchget_desctywith|Tpoly(ty,_)->get_descty|d->dletis_function_typeenvty=matchscrapeenvtywith|Tarrow(_,lhs,rhs,_)->Some(lhs,rhs)|_->Noneletis_base_typeenvtybase_ty_path=matchscrapeenvtywith|Tconstr(p,_,_)->Path.samepbase_ty_path|_->falseletis_immediate=function|Type_immediacy.Unknown->false|Type_immediacy.Always->true|Type_immediacy.Always_on_64bits->(* In bytecode, we don't know at compile time whether we are
targeting 32 or 64 bits. *)!Clflags.native_code&&Sys.word_size=64typeclassification=|Int|Float|Lazy|Addr(* anything except a float or a lazy *)|Anyletclassifyenvty=letty=scrape_tyenvtyinifis_immediate(Ctype.immediacyenvty)thenIntelsematchget_desctywith|Tvar_|Tunivar_->Any|Tconstr(p,_args,_abbrev)->ifPath.samepPredef.path_floatthenFloatelseifPath.samepPredef.path_lazy_tthenLazyelseifPath.samepPredef.path_string||Path.samepPredef.path_bytes||Path.samepPredef.path_array||Path.samepPredef.path_nativeint||Path.samepPredef.path_int32||Path.samepPredef.path_int64thenAddrelsebegintrymatch(Env.find_typepenv).type_kindwith|Type_abstract->Any|Type_record_|Type_variant_|Type_open->AddrwithNot_found->(* This can happen due to e.g. missing -I options,
causing some .cmi files to be unavailable.
Maybe we should emit a warning. *)Anyend|Tarrow_|Ttuple_|Tpackage_|Tobject_|Tnil|Tvariant_->Addr|Tlink_|Tsubst_|Tpoly_|Tfield_->assertfalse(*
let array_type_kind env ty =
match scrape_poly env ty with
| Tconstr(p, [elt_ty], _) when Path.same p Predef.path_array ->
begin match classify env elt_ty with
| Any -> if Config.flat_float_array then Pgenarray else Paddrarray
| Float -> if Config.flat_float_array then Pfloatarray else Paddrarray
| Addr | Lazy -> Paddrarray
| Int -> Pintarray
end
| Tconstr(p, [], _) when Path.same p Predef.path_floatarray ->
Pfloatarray
| _ ->
(* This can happen with e.g. Obj.field *)
Pgenarray
let array_kind exp = array_type_kind exp.exp_env exp.exp_type
let array_pattern_kind pat = array_type_kind pat.pat_env pat.pat_type
let bigarray_decode_type env ty tbl dfl =
match scrape env ty with
| Tconstr(Pdot(Pident mod_id, type_name), [], _)
when Ident.name mod_id = "Stdlib__Bigarray" ->
begin try List.assoc type_name tbl with Not_found -> dfl end
| _ ->
dfl
let kind_table =
["float32_elt", Pbigarray_float32;
"float64_elt", Pbigarray_float64;
"int8_signed_elt", Pbigarray_sint8;
"int8_unsigned_elt", Pbigarray_uint8;
"int16_signed_elt", Pbigarray_sint16;
"int16_unsigned_elt", Pbigarray_uint16;
"int32_elt", Pbigarray_int32;
"int64_elt", Pbigarray_int64;
"int_elt", Pbigarray_caml_int;
"nativeint_elt", Pbigarray_native_int;
"complex32_elt", Pbigarray_complex32;
"complex64_elt", Pbigarray_complex64]
let layout_table =
["c_layout", Pbigarray_c_layout;
"fortran_layout", Pbigarray_fortran_layout]
let bigarray_type_kind_and_layout env typ =
match scrape env typ with
| Tconstr(_p, [_caml_type; elt_type; layout_type], _abbrev) ->
(bigarray_decode_type env elt_type kind_table Pbigarray_unknown,
bigarray_decode_type env layout_type layout_table
Pbigarray_unknown_layout)
| _ ->
(Pbigarray_unknown, Pbigarray_unknown_layout)
let value_kind env ty =
let ty = scrape_ty env ty in
if is_immediate (Ctype.immediacy env ty) then Pintval
else begin
match get_desc ty with
| Tconstr(p, _, _) when Path.same p Predef.path_float ->
Pfloatval
| Tconstr(p, _, _) when Path.same p Predef.path_int32 ->
Pboxedintval Pint32
| Tconstr(p, _, _) when Path.same p Predef.path_int64 ->
Pboxedintval Pint64
| Tconstr(p, _, _) when Path.same p Predef.path_nativeint ->
Pboxedintval Pnativeint
| _ ->
Pgenval
end
let function_return_value_kind env ty =
match is_function_type env ty with
| Some (_lhs, rhs) -> value_kind env rhs
| None -> Pgenval
*)(** Whether a forward block is needed for a lazy thunk on a value, i.e.
if the value can be represented as a float/forward/lazy *)letlazy_val_requires_forwardenvty=matchclassifyenvtywith|Any|Lazy->true|Float->false(* TODO: Config.flat_float_array *)|Addr|Int->false(** The compilation of the expression [lazy e] depends on the form of e:
constants, floats and identifiers are optimized. The optimization must be
taken into account when determining whether a recursive binding is safe. *)letclassify_lazy_argument:Typedtree.expression->[`Constant_or_function|`Float_that_cannot_be_shortcut|`Identifierof[`Forward_value|`Other]|`Other]=fune->matche.exp_descwith|Texp_constant(Const_int_|Const_char_|Const_string_|Const_int32_|Const_int64_|Const_nativeint_)|Texp_function_|Texp_construct(_,{cstr_arity=0},_)->`Constant_or_function|Texp_constant(Const_float_)->(* TODO: handle flat float array, either at configure time or from the
.merlin. *)`Constant_or_function|Texp_ident_whenlazy_val_requires_forwarde.exp_enve.exp_type->`Identifier`Forward_value|Texp_ident_->`Identifier`Other|_->`Other(*
let value_kind_union k1 k2 =
if k1 = k2 then k1
else Pgenval
*)