1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072(**************************************************************************)(* *)(* OCaml *)(* *)(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)(* *)(* Copyright 1996 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. *)(* *)(**************************************************************************)(* Description of primitive functions *)openMiscopenParsetreemoduleString=Misc_stdlib.Stringtypeunboxed_or_untagged_integer=|Unboxed_int64|Unboxed_nativeint|Unboxed_int32|Untagged_int16|Untagged_int8|Untagged_inttypeunboxed_float=Unboxed_float64|Unboxed_float32typeunboxed_vector=Unboxed_vec128|Unboxed_vec256|Unboxed_vec512typeboxed_integer=Boxed_int64|Boxed_nativeint|Boxed_int32typeboxed_float=Boxed_float64|Boxed_float32typeboxed_vector=Boxed_vec128|Boxed_vec256|Boxed_vec512typenative_repr=|Repr_poly|Same_as_ocaml_reprofJkind_types.Sort.Const.t|Unboxed_floatofboxed_float|Unboxed_vectorofboxed_vector|Unboxed_or_untagged_integerofunboxed_or_untagged_integertypeeffects=No_effects|Only_generative_effects|Arbitrary_effectstypecoeffects=No_coeffects|Has_coeffectstypemode=|Prim_local|Prim_global|Prim_polytype'reprdescription_gen={prim_name:string;(* Name of primitive or C function *)prim_arity:int;(* Number of arguments *)prim_alloc:bool;(* Does it allocates or raise? *)prim_c_builtin:bool;(* Is the compiler allowed to replace it? *)prim_effects:effects;prim_coeffects:coeffects;prim_native_name:string;(* Name of C function for the nat. code gen. *)prim_native_repr_args:(mode*'repr)list;prim_native_repr_res:mode*'repr;prim_is_layout_poly:bool}typedescription=native_reprdescription_gentypeerror=|Old_style_float_with_native_repr_attribute|Old_style_float_with_non_value|Old_style_noalloc_with_noalloc_attribute|No_native_primitive_with_repr_attribute|No_native_primitive_with_non_value|Inconsistent_attributes_for_effects|Inconsistent_noalloc_attributes_for_effects|Invalid_representation_polymorphic_attribute|Invalid_native_repr_for_primitiveofstringexceptionErrorofLocation.t*errortypevalue_check=Bad_attribute|Bad_layout|Ok_valueletcheck_ocaml_value=function|_,Same_as_ocaml_repr(BaseValue)->Ok_value|_,Same_as_ocaml_repr_|_,Repr_poly->Bad_layout|_,Unboxed_float_|_,Unboxed_vector_|_,Unboxed_or_untagged_integer_->Bad_attributeletis_builtin_prim_namename=String.lengthname>0&&name.[0]='%'letrecmake_prim_repr_argsarityx=ifarity=0then[]elsex::make_prim_repr_args(arity-1)xletmake~name~alloc~c_builtin~effects~coeffects~native_name~native_repr_args~native_repr_res~is_layout_poly={prim_name=name;prim_arity=List.lengthnative_repr_args;prim_alloc=alloc;prim_c_builtin=c_builtin;prim_effects=effects;prim_coeffects=coeffects;prim_native_name=native_name;prim_native_repr_args=native_repr_args;prim_native_repr_res=native_repr_res;prim_is_layout_poly=is_layout_poly}letparse_declarationvaldecl~native_repr_args~native_repr_res~is_layout_poly=letarity=List.lengthnative_repr_argsinletname,native_name,old_style_noalloc,old_style_float=matchvaldecl.pval_primwith|name::"noalloc"::name2::"float"::_->(name,name2,true,true)|name::"noalloc"::name2::_->(name,name2,true,false)|name::name2::"float"::_->(name,name2,false,true)|name::"noalloc"::_->(name,"",true,false)|name::name2::_->(name,name2,false,false)|name::_->(name,"",false,false)|[]->fatal_error"Primitive.parse_declaration"inletnoalloc_attribute=Attr_helper.has_no_payload_attribute"noalloc"valdecl.pval_attributesinletbuiltin_attribute=Attr_helper.has_no_payload_attribute"builtin"valdecl.pval_attributesinletno_effects_attribute=Attr_helper.has_no_payload_attribute"no_effects"valdecl.pval_attributesinletonly_generative_effects_attribute=Attr_helper.has_no_payload_attribute"only_generative_effects"valdecl.pval_attributesinletis_builtin_prim=is_builtin_prim_namenameinletprim_is_layout_poly=matchis_builtin_prim,is_layout_polywith|false,true->raise(Error(valdecl.pval_loc,Invalid_representation_polymorphic_attribute))|_,b->binifno_effects_attribute&&only_generative_effects_attributethenraise(Error(valdecl.pval_loc,Inconsistent_attributes_for_effects));leteffects=ifno_effects_attributethenNo_effectselseifonly_generative_effects_attributethenOnly_generative_effectselseArbitrary_effectsinletno_coeffects_attribute=Attr_helper.has_no_payload_attribute"no_coeffects"valdecl.pval_attributesinletcoeffects=ifno_coeffects_attributethenNo_coeffectselseHas_coeffectsinifold_style_floatthenList.iter(funrepr->matchcheck_ocaml_valuereprwith|Ok_value->()|Bad_attribute->raise(Error(valdecl.pval_loc,Old_style_float_with_native_repr_attribute))|Bad_layout->raise(Error(valdecl.pval_loc,Old_style_float_with_non_value)))(native_repr_res::native_repr_args);ifold_style_noalloc&&noalloc_attributethenraise(Error(valdecl.pval_loc,Old_style_noalloc_with_noalloc_attribute));(* The compiler used to assume "noalloc" with "float", we just make this
explicit now (GPR#167): *)letold_style_noalloc=old_style_noalloc||old_style_floatinifold_style_floatthenLocation.deprecatedvaldecl.pval_loc"[@@unboxed] + [@@noalloc] should be used\n\
instead of \"float\""elseifold_style_noallocthenLocation.deprecatedvaldecl.pval_loc"[@@noalloc] should be used instead of \"noalloc\"";ifnative_name=""thenList.iter(funrepr->matchcheck_ocaml_valuereprwith|Ok_value->()|Bad_attribute->raise(Error(valdecl.pval_loc,No_native_primitive_with_repr_attribute))|Bad_layout->(* Built-in primitives don't need a native version. *)ifnotis_builtin_primthenraise(Error(valdecl.pval_loc,No_native_primitive_with_non_value)))(native_repr_res::native_repr_args);letnoalloc=old_style_noalloc||noalloc_attributeinifnoalloc&&only_generative_effects_attributethenraise(Error(valdecl.pval_loc,Inconsistent_noalloc_attributes_for_effects));letnative_repr_args,native_repr_res=ifold_style_floatthen(make_prim_repr_argsarity(Prim_global,Unboxed_floatBoxed_float64),(Prim_global,Unboxed_floatBoxed_float64))else(native_repr_args,native_repr_res)in{prim_name=name;prim_arity=arity;prim_alloc=notnoalloc;prim_c_builtin=builtin_attribute;prim_effects=effects;prim_coeffects=coeffects;prim_native_name=native_name;prim_native_repr_args=native_repr_args;prim_native_repr_res=native_repr_res;prim_is_layout_poly}openOutcometreeletadd_attribute_listtyattrs=List.fold_left(funtyattr->Otyp_attribute(ty,attr))tyattrsletrecadd_native_repr_attributestyattrs=matchty,attrswith(* Otyp_poly case might have been added in e.g. tree_of_value_description *)|Otyp_poly(vars,ty),_->Otyp_poly(vars,add_native_repr_attributestyattrs)|Otyp_arrow(label,am,a,Otyp_ret(rm,r)),attr_l::rest->letr=add_native_repr_attributesrrestinleta=add_attribute_listaattr_linOtyp_arrow(label,am,a,Otyp_ret(rm,r))|_,[attr_l]->add_attribute_listtyattr_l|_->assert(List.for_all(funx->x=[])attrs);tyletoattr_unboxed={oattr_name="unboxed"}letoattr_untagged={oattr_name="untagged"}letoattr_noalloc={oattr_name="noalloc"}letoattr_builtin={oattr_name="builtin"}letoattr_no_effects={oattr_name="no_effects"}letoattr_only_generative_effects={oattr_name="only_generative_effects"}letoattr_no_coeffects={oattr_name="no_coeffects"}letoattr_local_opt={oattr_name="local_opt"}letoattr_layout_poly={oattr_name="layout_poly"}letprintposig_val_decl=letprims=ifp.prim_native_name<>""then[p.prim_name;p.prim_native_name]else[p.prim_name]inletfor_allf=List.for_allfp.prim_native_repr_args&&fp.prim_native_repr_resinletneeds_unboxed_attribute=function|_,Same_as_ocaml_repr(BaseValue)|_,Repr_poly|_,Unboxed_or_untagged_integer(Untagged_int|Untagged_int8|Untagged_int16)->false|_,Unboxed_float_|_,Unboxed_vector_|_,Unboxed_or_untagged_integer(Unboxed_int64|Unboxed_int32|Unboxed_nativeint)->true|_,Same_as_ocaml_repr(BaseVoid)->false(* The [@unboxed] attribute is not supported on void in our compiler
or the upstream compiler. *)|_,Same_as_ocaml_repr_->(* We require [@unboxed] for non-value types in upstream-compatible code,
but treat it as optional otherwise. We thus print the [@unboxed]
attribute only in the case it's required and leave it out when it's
not. That's why we call [erasable_extensions_only] here. *)Language_extension.erasable_extensions_only()inletis_untagged=function|_,Unboxed_or_untagged_integer(Untagged_int8|Untagged_int16)->Language_extension.erasable_extensions_only()|_,Unboxed_or_untagged_integer(Untagged_int)->true|_,Same_as_ocaml_repr_|_,Unboxed_float_|_,Unboxed_vector_|_,Unboxed_or_untagged_integer(Unboxed_int64|Unboxed_int32|Unboxed_nativeint)|_,Repr_poly->falseinletall_unboxed=for_allneeds_unboxed_attributeinletall_untagged=for_allis_untaggedinletattrs=ifp.prim_allocthen[]else[oattr_noalloc]inletattrs=ifp.prim_c_builtinthenoattr_builtin::attrselseattrsinletattrs=matchp.prim_effectswith|No_effects->oattr_no_effects::attrs|Only_generative_effects->oattr_only_generative_effects::attrs|Arbitrary_effects->attrsinletattrs=matchp.prim_coeffectswith|No_coeffects->oattr_no_coeffects::attrs|Has_coeffects->attrsinletattrs=ifall_unboxedthenoattr_unboxed::attrselseifall_untaggedthenoattr_untagged::attrselseattrsinletattrs=ifp.prim_is_layout_polythenoattr_layout_poly::attrselseattrsinletattrs_of_mode_and_repr(m,repr)=(matchmwith|Prim_local|Prim_global->[]|Prim_poly->[oattr_local_opt])@(matchreprwith|Same_as_ocaml_repr(BaseValue)|Repr_poly->[]|Unboxed_float_|Unboxed_vector_|Unboxed_or_untagged_integer(Unboxed_int32|Unboxed_int64|Unboxed_nativeint)->ifall_unboxedthen[]else[oattr_unboxed]|Unboxed_or_untagged_integer(Untagged_int|Untagged_int8|Untagged_int16)->ifall_untaggedthen[]else[oattr_untagged]|Same_as_ocaml_repr_->ifall_unboxed||not(needs_unboxed_attribute(m,repr))then[]else[oattr_unboxed])inlettype_attrs=List.mapattrs_of_mode_and_reprp.prim_native_repr_args@[attrs_of_mode_and_reprp.prim_native_repr_res]in{osig_val_declwithoval_prims=prims;oval_type=add_native_repr_attributesosig_val_decl.oval_typetype_attrs;oval_attributes=attrs}letnative_namep=ifp.prim_native_name<>""thenp.prim_native_nameelsep.prim_nameletbyte_namep=p.prim_nameletunboxed_or_untagged_integer=function|Boxed_int32->Unboxed_int32|Boxed_nativeint->Unboxed_nativeint|Boxed_int64->Unboxed_int64letunboxed_float=function|Boxed_float32->Unboxed_float32|Boxed_float64->Unboxed_float64letunboxed_vector=function|Boxed_vec128->Unboxed_vec128|Boxed_vec256->Unboxed_vec256|Boxed_vec512->Unboxed_vec512(* Since these are just constant constructors, we can just use polymorphic equality and
comparison at no performance loss. We still match on the variants to prove here that
they are all constant constructors. *)letequal_unboxed_or_untagged_integer((Unboxed_int64|Unboxed_nativeint|Unboxed_int32|Untagged_int16|Untagged_int8|Untagged_int)asi1)i2=i1=i2letequal_unboxed_float((Unboxed_float32|Unboxed_float64)asf1)f2=f1=f2letcompare_unboxed_float((Unboxed_float32|Unboxed_float64)asf1)f2=Stdlib.comparef1f2letequal_unboxed_vector((Unboxed_vec128|Unboxed_vec256|Unboxed_vec512)asv1)v2=v1=v2letcompare_unboxed_vector((Unboxed_vec128|Unboxed_vec256|Unboxed_vec512)asv1)v2=Stdlib.comparev1v2letequal_boxed_integerbi1bi2=equal_unboxed_or_untagged_integer(unboxed_or_untagged_integerbi1)(unboxed_or_untagged_integerbi2)letequal_boxed_floatbf1bf2=equal_unboxed_float(unboxed_floatbf1)(unboxed_floatbf2)letequal_boxed_vectorbv1bv2=equal_unboxed_vector(unboxed_vectorbv1)(unboxed_vectorbv2)letcompare_boxed_floatbf1bf2=compare_unboxed_float(unboxed_floatbf1)(unboxed_floatbf2)letcompare_boxed_vectorbv1bv2=compare_unboxed_vector(unboxed_vectorbv1)(unboxed_vectorbv2)letequal_unboxed_vector_sizev1v2=(* For the purposes of layouts/native representations,
vectors of the same width are equal. *)matchv1,v2with|Unboxed_vec128,Unboxed_vec128->true|Unboxed_vec256,Unboxed_vec256->true|Unboxed_vec512,Unboxed_vec512->true|(Unboxed_vec128|Unboxed_vec256|Unboxed_vec512),_->falseletequal_native_reprnr1nr2=matchnr1,nr2with|Repr_poly,Repr_poly->true|Repr_poly,(Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_|Same_as_ocaml_repr_)|(Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_|Same_as_ocaml_repr_),Repr_poly->false|Same_as_ocaml_reprs1,Same_as_ocaml_reprs2->Jkind_types.Sort.Const.equals1s2|Same_as_ocaml_repr_,(Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_)->false|Unboxed_floatf1,Unboxed_floatf2->equal_boxed_floatf1f2|Unboxed_float_,(Same_as_ocaml_repr_|Unboxed_or_untagged_integer_|Unboxed_vector_)->false|Unboxed_vectorvi1,Unboxed_vectorvi2->equal_unboxed_vector_size(unboxed_vectorvi1)(unboxed_vectorvi2)|Unboxed_vector_,(Same_as_ocaml_repr_|Unboxed_float_|Unboxed_or_untagged_integer_)->false|Unboxed_or_untagged_integerbi1,Unboxed_or_untagged_integerbi2->equal_unboxed_or_untagged_integerbi1bi2|Unboxed_or_untagged_integer_,(Same_as_ocaml_repr_|Unboxed_float_|Unboxed_vector_)->falseletequal_effectsef1ef2=matchef1,ef2with|No_effects,No_effects->true|No_effects,(Only_generative_effects|Arbitrary_effects)->false|Only_generative_effects,Only_generative_effects->true|Only_generative_effects,(No_effects|Arbitrary_effects)->false|Arbitrary_effects,Arbitrary_effects->true|Arbitrary_effects,(No_effects|Only_generative_effects)->falseletequal_coeffectscf1cf2=matchcf1,cf2with|No_coeffects,No_coeffects->true|No_coeffects,Has_coeffects->false|Has_coeffects,Has_coeffects->true|Has_coeffects,No_coeffects->falseletnative_name_is_externalp=letnat_name=native_namepinnat_name<>""&&nat_name.[0]<>'%'moduleRepr_check=structtyperesult=|Wrong_arity|Wrong_repr|Successletargs_res_reprsprim=(prim.prim_native_repr_args@[prim.prim_native_repr_res])|>List.mapsndletisrepr=equal_native_reprreprletany=fun_->trueletvalue_or_unboxed_or_untagged=function|Same_as_ocaml_repr(BaseValue)|Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_->true|Same_as_ocaml_repr_|Repr_poly->falseletsort_is_product:Jkind_types.Sort.Const.t->bool=function|Product_->true|Base_->false|Univar_->Misc.fatal_error"sort_is_product: univar"letvalid_c_stub_arg=function|Same_as_ocaml_reprs->not(sort_is_products)|Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_|Repr_poly->trueletvalid_c_stub_return=function|Same_as_ocaml_repr(Base_)|Unboxed_float_|Unboxed_or_untagged_integer_|Unboxed_vector_|Repr_poly->true|Same_as_ocaml_repr(Product[s1;s2])->not(sort_is_products1)&¬(sort_is_products2)|Same_as_ocaml_repr(Product_)->false|Same_as_ocaml_repr(Univar_)->Misc.fatal_error"valid_c_stub_return: univar"letcheckchecksprim=letreprs=args_res_reprspriminifList.lengthreprs<>List.lengthchecksthenWrong_arityelseifnot(List.for_all2(funfx->fx)checksreprs)thenWrong_reprelseSuccessletexactlyrequired=check(List.mapisrequired)letsame_arg_res_repr_with_arityarityprim=letrepr=sndprim.prim_native_repr_resinexactly(List.init(arity+1)(fun_->repr))primletno_non_value_reprprim=letarity=List.lengthprim.prim_native_repr_argsincheck(List.init(arity+1)(fun_->value_or_unboxed_or_untagged))primletcheck_c_stubprim=(* C externals are allowed to return a tuple, but may not take products as
arguments or return products with more than two elements. *)letarity=List.lengthprim.prim_native_repr_argsinletchecks=(List.initarity(fun_->valid_c_stub_arg))@[valid_c_stub_return]incheckchecksprimend(* Note: [any] here is not the same as jkind [any]. It means we allow any
[native_repr] for the corresponding argument or return. It's [Typedecl]'s
responsibility to check that types in externals are representable or marked
with [@layout_poly] (see [make_native_repr] and the note above
[error_if_containing_unexpected_jkind]). Here we have more speicific checks
for individual primitives. *)letprim_has_valid_reprs~locprim=letopenRepr_checkinletmoduleC=Jkind_types.Sort.Constinletcheck=(* Corresponds to [indexing_primitives] in [translprim.ml]. *)letstringlike_indexing_primitives=letwidths:(_*_*Jkind_types.Sort.Const.t)list=[("8","",C.value);("i8","",C.value);("16","",C.value);("i16","",C.value);("32","",C.value);("f32","",C.value);("64","",C.value);("a128","",C.value);("u128","",C.value);("a256","",C.value);("u256","",C.value);("a512","",C.value);("u512","",C.value);("8","#",C.bits8);("i8","#",C.bits8);("16","#",C.bits16);("i16","#",C.bits16);("32","#",C.bits32);("f32","#",C.float32);("64","#",C.bits64);("a128","#",C.vec128);("u128","#",C.vec128);("a256","#",C.vec256);("u256","#",C.vec256);("a512","#",C.vec512);("u512","#",C.vec512);]inletindices:(_*Jkind_types.Sort.Const.t)list=[("",C.value);("_indexed_by_nativeint#",C.word);("_indexed_by_int8#",C.bits8);("_indexed_by_int16#",C.bits16);("_indexed_by_int32#",C.bits32);("_indexed_by_int64#",C.bits64);]inletcombiners=[(Printf.sprintf"%%caml_%s_get%s%s%s%s",funindex_kindwidth_kind->[Same_as_ocaml_reprC.value;Same_as_ocaml_reprindex_kind;Same_as_ocaml_reprwidth_kind;]);(Printf.sprintf"%%caml_%s_set%s%s%s%s",funindex_kindwidth_kind->[Same_as_ocaml_reprC.value;Same_as_ocaml_reprindex_kind;Same_as_ocaml_reprwidth_kind;Same_as_ocaml_reprC.value;]);]in(let(let*)xf=List.concat_mapfxinlet*container=["bigstring";"bytes";"string"]inlet*safe_sigil=["";"u"]inlet*index_sigil,index_kind=indicesinlet*width_sigil,unboxed_sigil,width_kind=widthsinlet*combine_string,combine_repr=combinersinletstring=combine_stringcontainerwidth_sigilsafe_sigilunboxed_sigilindex_sigilinletreprs=combine_reprindex_kindwidth_kindin[(string,reprs)])|>List.to_seq|>funseq->String.Map.add_seqseqString.Map.emptyin(* Corresponds to [array_vec_primitives] in [translprim.ml]. *)letvector_array_indexing_primitives=letvector_sizes=[("128","",C.value);("128","#",C.vec128);("256","",C.value);("256","#",C.vec256);("512","",C.value);("512","#",C.vec512);]inletarray_types=["float_array";"floatarray";"unboxed_float_array";"unboxed_float32_array";"int_array";"unboxed_int64_array";"unboxed_int32_array";"untagged_int16_array";"untagged_int8_array";"unboxed_nativeint_array";]inletsafe_sigils=["";"u"]inletindices=[("",C.value);("_indexed_by_nativeint#",C.word);("_indexed_by_int8#",C.bits8);("_indexed_by_int16#",C.bits16);("_indexed_by_int32#",C.bits32);("_indexed_by_int64#",C.bits64);]inletcombiners=[(Printf.sprintf"%%caml_%s_get%s%s%s%s",funindex_kindvector_kind->[Same_as_ocaml_reprC.value;Same_as_ocaml_reprindex_kind;Same_as_ocaml_reprvector_kind;]);(Printf.sprintf"%%caml_%s_set%s%s%s%s",funindex_kindvector_kind->[Same_as_ocaml_reprC.value;Same_as_ocaml_reprindex_kind;Same_as_ocaml_reprvector_kind;Same_as_ocaml_reprC.value;]);]in(let(let*)xf=List.concat_mapfxinlet*array_type=array_typesinlet*safe_sigil=safe_sigilsinlet*size_str,unboxed_sigil,vector_kind=vector_sizesinlet*index_suffix,index_kind=indicesinlet*combine_string,combine_repr=combinersinletstring=combine_stringarray_typesize_strsafe_sigilunboxed_sigilindex_suffixinletreprs=combine_reprindex_kindvector_kindin[(string,reprs)])|>List.to_seq|>funseq->String.Map.add_seqseqString.Map.emptyinmatchprim.prim_namewith|"%identity"|"%opaque"|"%obj_magic"->same_arg_res_repr_with_arity1|"%ignore"->check[any;is(Same_as_ocaml_reprC.value)]|"%revapply"->check[any;is(Same_as_ocaml_reprC.value);any]|"%apply"->check[is(Same_as_ocaml_reprC.value);any;any](* This doesn't prevent
{|
external get : float# array -> int -> int32# =
"%array_safe_get"
|}
but the same is true for types:
{|
external get : float array -> int -> int32 =
"%array_safe_get"
|}
*)|"%array_safe_get"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);any]|"%array_safe_set"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);any]|"%array_unsafe_set"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);any;is(Same_as_ocaml_reprC.value)]|"%array_safe_get_indexed_by_int64#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any]|"%array_safe_set_indexed_by_int64#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get_indexed_by_int64#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any]|"%array_unsafe_set_indexed_by_int64#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any;is(Same_as_ocaml_reprC.value)]|"%array_safe_get_indexed_by_int32#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits32);any]|"%array_safe_set_indexed_by_int32#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits32);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get_indexed_by_int32#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits32);any]|"%array_unsafe_set_indexed_by_int32#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits32);any;is(Same_as_ocaml_reprC.value)]|"%array_safe_get_indexed_by_int16#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits16);any]|"%array_safe_set_indexed_by_int16#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits16);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get_indexed_by_int16#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits16);any]|"%array_unsafe_set_indexed_by_int16#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits16);any;is(Same_as_ocaml_reprC.value)]|"%array_safe_get_indexed_by_int8#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits8);any]|"%array_safe_set_indexed_by_int8#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits8);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get_indexed_by_int8#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits8);any]|"%array_unsafe_set_indexed_by_int8#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits8);any;is(Same_as_ocaml_reprC.value)]|"%array_safe_get_indexed_by_nativeint#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.word);any]|"%array_safe_set_indexed_by_nativeint#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.word);any;is(Same_as_ocaml_reprC.value)]|"%array_unsafe_get_indexed_by_nativeint#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.word);any]|"%array_unsafe_set_indexed_by_nativeint#"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.word);any;is(Same_as_ocaml_reprC.value)]|"%makearray_dynamic"->check[is(Same_as_ocaml_reprC.value);any;is(Same_as_ocaml_reprC.value);]|"%makearray_dynamic_uninit"->(* Restrictions on this primitive are checked in [Translprim] *)check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);]|"%array_element_size_in_bytes"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.value);]|"%peek"|"%poke"->(* Arities and layouts of these primitives are checked in [Translprim] *)fun_->Success|"%unsafe_get_idx"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any]|"%unsafe_get_idx_imm"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any]|"%unsafe_set_idx"->check[is(Same_as_ocaml_reprC.value);is(Same_as_ocaml_reprC.bits64);any;is(Same_as_ocaml_reprC.value);]|"%unsafe_get_ptr"->check[is(Same_as_ocaml_repr(C.Product[C.value;C.bits64]));any]|"%unsafe_get_ptr_imm"->check[is(Same_as_ocaml_repr(C.Product[C.value;C.bits64]));any]|"%unsafe_set_ptr"->check[is(Same_as_ocaml_repr(C.Product[C.value;C.bits64]));any;is(Same_as_ocaml_reprC.value);]|"%box_float"->exactly[Same_as_ocaml_reprC.float64;Same_as_ocaml_reprC.value]|"%unbox_float"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.float64]|"%box_float32"->exactly[Same_as_ocaml_reprC.float32;Same_as_ocaml_reprC.value]|"%unbox_float32"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.float32]|"%box_nativeint"->exactly[Same_as_ocaml_reprC.word;Same_as_ocaml_reprC.value]|"%unbox_nativeint"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.word]|"%domain_index"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.untagged_immediate]|"%tag_int"->exactly[Same_as_ocaml_reprC.untagged_immediate;Same_as_ocaml_reprC.value]|"%untag_int"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.untagged_immediate]|"%tag_int8"->exactly[Same_as_ocaml_reprC.bits8;Same_as_ocaml_reprC.value]|"%untag_int8"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.bits8]|"%tag_int16"->exactly[Same_as_ocaml_reprC.bits16;Same_as_ocaml_reprC.value]|"%untag_int16"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.bits16]|"%box_int32"->exactly[Same_as_ocaml_reprC.bits32;Same_as_ocaml_reprC.value]|"%unbox_int32"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.bits32]|"%box_int64"->exactly[Same_as_ocaml_reprC.bits64;Same_as_ocaml_reprC.value]|"%unbox_int64"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.bits64]|"%unbox_unit"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.void]|"%box_vec128"->exactly[Same_as_ocaml_reprC.vec128;Same_as_ocaml_reprC.value]|"%unbox_vec128"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.vec128]|"%box_vec256"->exactly[Same_as_ocaml_reprC.vec256;Same_as_ocaml_reprC.value]|"%unbox_vec256"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.vec256]|"%join_vec256"->exactly[Same_as_ocaml_reprC.vec128;Same_as_ocaml_reprC.vec128;Same_as_ocaml_reprC.vec256]|"%split_vec256"->exactly[Same_as_ocaml_reprC.vec256;Same_as_ocaml_repr(Product[C.vec128;C.vec128])]|"%box_vec512"->exactly[Same_as_ocaml_reprC.vec512;Same_as_ocaml_reprC.value]|"%unbox_vec512"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.vec512]|"%reinterpret_tagged_int63_as_unboxed_int64"->exactly[Same_as_ocaml_reprC.value;Same_as_ocaml_reprC.bits64]|"%reinterpret_unboxed_int64_as_tagged_int63"->exactly[Same_as_ocaml_reprC.bits64;Same_as_ocaml_reprC.value]|name->(matchString.Map.find_optnamestringlike_indexing_primitiveswith|Somereprs->exactlyreprs|None->matchString.Map.find_optnamevector_array_indexing_primitiveswith|Somereprs->exactlyreprs|None->letmoduleI=Scalar.OperationinmatchI.With_percent_prefix.of_stringnamewith|intrinsic->exactly(List.map(funsort->Same_as_ocaml_reprsort)(I.sortintrinsic))|exceptionNot_found->ifis_builtin_prim_namenamethenno_non_value_repr(* These can probably support non-value reprs if the
need arises:
{|
| "%send"
| "%sendself"
| "%sendcache"
|}
*)elsecheck_c_stub)inmatchcheckprimwith|Success->()|Wrong_arity->(* There's already an arity check in translprim that catches this. We will
defer to that logic. We are only checking the arity of some built-in
primitives here but not all, and it would be weird to raise different
errors dependent on the [prim_name]. *)()|Wrong_repr->raise(Error(loc,Invalid_native_repr_for_primitive(prim.prim_name)))letprim_can_contain_layout_anyprim=matchprim.prim_namewith|"%array_length"|"%array_blit"|"%array_safe_get"|"%array_safe_set"|"%array_unsafe_get"|"%array_unsafe_set"|"%array_safe_get_indexed_by_int64#"|"%array_safe_set_indexed_by_int64#"|"%array_unsafe_get_indexed_by_int64#"|"%array_unsafe_set_indexed_by_int64#"|"%array_safe_get_indexed_by_int32#"|"%array_safe_set_indexed_by_int32#"|"%array_unsafe_get_indexed_by_int32#"|"%array_unsafe_set_indexed_by_int32#"|"%array_safe_get_indexed_by_nativeint#"|"%array_safe_set_indexed_by_nativeint#"|"%array_unsafe_get_indexed_by_nativeint#"|"%array_unsafe_set_indexed_by_nativeint#"->false|_->truemoduleStyle=Misc.Styleletreport_errorppferr=matcherrwith|Old_style_float_with_native_repr_attribute->Format_doc.fprintfppf"Cannot use %a in conjunction with %a/%a."Style.inline_code"float"Style.inline_code"[@unboxed]"Style.inline_code"[@untagged]"|Old_style_float_with_non_value->Format_doc.fprintfppf"Cannot use %a in conjunction with \
types of non-value layouts."Style.inline_code"float"|Old_style_noalloc_with_noalloc_attribute->Format_doc.fprintfppf"Cannot use %a in conjunction with %a."Style.inline_code"noalloc"Style.inline_code"[@@noalloc]"|No_native_primitive_with_repr_attribute->Format_doc.fprintfppf"@[The native code version of the primitive is mandatory@ \
when attributes %a or %a are present.@]"Style.inline_code"[@untagged]"Style.inline_code"[@unboxed]"|No_native_primitive_with_non_value->Format_doc.fprintfppf"@[The native code version of the primitive is mandatory@ \
for types with non-value layouts.@]"|Inconsistent_attributes_for_effects->Format_doc.fprintfppf"At most one of %a and %a can be specified."Style.inline_code"[@no_effects]"Style.inline_code"[@only_generative_effects]"|Inconsistent_noalloc_attributes_for_effects->Format_doc.fprintfppf"Cannot use %a in conjunction with %a."Style.inline_code"[@@no_generative_effects]"Style.inline_code"[@@noalloc]"|Invalid_representation_polymorphic_attribute->Format_doc.fprintfppf"Attribute %a can only be used \
on built-in primitives."Style.inline_code"[@layout_poly]"|Invalid_native_repr_for_primitivename->Format_doc.fprintfppf"The primitive [%s] is used in an invalid declaration.@ \
The declaration contains argument/return types with the@ \
wrong layout."namelet()=Location.register_error_of_exn(function|Error(loc,err)->Some(Location.error_of_printer~locreport_errorerr)|_->None)