123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251(**************************************************************************)(* *)(* 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 *)openMiscopenParsetreetypeboxed_integer=Pnativeint|Pint32|Pint64typenative_repr=|Same_as_ocaml_repr|Unboxed_float|Unboxed_integerofboxed_integer|Untagged_inttypedescription={prim_name:string;(* Name of primitive or C function *)prim_arity:int;(* Number of arguments *)prim_alloc:bool;(* Does it allocates or raise? *)prim_native_name:string;(* Name of C function for the nat. code gen. *)prim_native_repr_args:native_reprlist;prim_native_repr_res:native_repr}typeerror=|Old_style_float_with_native_repr_attribute|Old_style_noalloc_with_noalloc_attribute|No_native_primitive_with_repr_attributeexceptionErrorofLocation.t*errorletis_ocaml_repr=function|Same_as_ocaml_repr->true|Unboxed_float|Unboxed_integer_|Untagged_int->falseletis_unboxed=function|Same_as_ocaml_repr|Untagged_int->false|Unboxed_float|Unboxed_integer_->trueletis_untagged=function|Untagged_int->true|Same_as_ocaml_repr|Unboxed_float|Unboxed_integer_->falseletrecmake_native_repr_argsarityx=ifarity=0then[]elsex::make_native_repr_args(arity-1)xletsimple~name~arity~alloc={prim_name=name;prim_arity=arity;prim_alloc=alloc;prim_native_name="";prim_native_repr_args=make_native_repr_argsaritySame_as_ocaml_repr;prim_native_repr_res=Same_as_ocaml_repr}letmake~name~alloc~native_name~native_repr_args~native_repr_res={prim_name=name;prim_arity=List.lengthnative_repr_args;prim_alloc=alloc;prim_native_name=native_name;prim_native_repr_args=native_repr_args;prim_native_repr_res=native_repr_res}letparse_declarationvaldecl~native_repr_args~native_repr_res=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";"ocaml.noalloc"]valdecl.pval_attributesinifold_style_float&¬(List.for_allis_ocaml_reprnative_repr_args&&is_ocaml_reprnative_repr_res)thenraise(Error(valdecl.pval_loc,Old_style_float_with_native_repr_attribute));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=""&¬(List.for_allis_ocaml_reprnative_repr_args&&is_ocaml_reprnative_repr_res)thenraise(Error(valdecl.pval_loc,No_native_primitive_with_repr_attribute));letnoalloc=old_style_noalloc||noalloc_attributeinletnative_repr_args,native_repr_res=ifold_style_floatthen(make_native_repr_argsarityUnboxed_float,Unboxed_float)else(native_repr_args,native_repr_res)in{prim_name=name;prim_arity=arity;prim_alloc=notnoalloc;prim_native_name=native_name;prim_native_repr_args=native_repr_args;prim_native_repr_res=native_repr_res}openOutcometreeletrecadd_native_repr_attributestyattrs=matchty,attrswith|Otyp_arrow(label,a,b),attr_opt::rest->letb=add_native_repr_attributesbrestinleta=matchattr_optwith|None->a|Someattr->Otyp_attribute(a,attr)inOtyp_arrow(label,a,b)|_,[Someattr]->Otyp_attribute(ty,attr)|_->assert(List.for_all(funx->x=None)attrs);tyletoattr_unboxed={oattr_name="unboxed"}letoattr_untagged={oattr_name="untagged"}letoattr_noalloc={oattr_name="noalloc"}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_resinletall_unboxed=for_allis_unboxedinletall_untagged=for_allis_untaggedinletattrs=ifp.prim_allocthen[]else[oattr_noalloc]inletattrs=ifall_unboxedthenoattr_unboxed::attrselseifall_untaggedthenoattr_untagged::attrselseattrsinletattr_of_native_repr=function|Same_as_ocaml_repr->None|Unboxed_float|Unboxed_integer_->ifall_unboxedthenNoneelseSomeoattr_unboxed|Untagged_int->ifall_untaggedthenNoneelseSomeoattr_untaggedinlettype_attrs=List.mapattr_of_native_reprp.prim_native_repr_args@[attr_of_native_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_nameletequal_boxed_integerbi1bi2=matchbi1,bi2with|Pnativeint,Pnativeint|Pint32,Pint32|Pint64,Pint64->true|(Pnativeint|Pint32|Pint64),_->falseletequal_native_reprnr1nr2=matchnr1,nr2with|Same_as_ocaml_repr,Same_as_ocaml_repr->true|Same_as_ocaml_repr,(Unboxed_float|Unboxed_integer_|Untagged_int)->false|Unboxed_float,Unboxed_float->true|Unboxed_float,(Same_as_ocaml_repr|Unboxed_integer_|Untagged_int)->false|Unboxed_integerbi1,Unboxed_integerbi2->equal_boxed_integerbi1bi2|Unboxed_integer_,(Same_as_ocaml_repr|Unboxed_float|Untagged_int)->false|Untagged_int,Untagged_int->true|Untagged_int,(Same_as_ocaml_repr|Unboxed_float|Unboxed_integer_)->falseletnative_name_is_externalp=letnat_name=native_namepinnat_name<>""&&nat_name.[0]<>'%'letreport_errorppferr=matcherrwith|Old_style_float_with_native_repr_attribute->Format.fprintfppf"Cannot use \"float\" in conjunction with \
[%@unboxed]/[%@untagged]."|Old_style_noalloc_with_noalloc_attribute->Format.fprintfppf"Cannot use \"noalloc\" in conjunction with \
[%@%@noalloc]."|No_native_primitive_with_repr_attribute->Format.fprintfppf"[@The native code version of the primitive is mandatory@ \
when attributes [%@untagged] or [%@unboxed] are present.@]"let()=Location.register_error_of_exn(function|Error(loc,err)->Some(Location.error_of_printer~locreport_errorerr)|_->None)