Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file utils.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417(* -------------------------------------------------------------------- *)moduleMap=BatMapmoduleSet=BatSetmoduleHash=BatHashtblmoduleSint=Set.Make(BatInt)moduleMint=Map.Make(BatInt)(* -------------------------------------------------------------------- *)moduleSs=Set.Make(String)moduleMs=Map.Make(String)(* -------------------------------------------------------------------- *)moduleILoc=structopenLocationtypet=i_locletcomparexy=Stdlib.Int.comparex.uid_locy.uid_locletequalxy=Stdlib.Int.equalx.uid_locy.uid_loclethashx=x.uid_locendmoduleHiloc=Hash.Make(ILoc)moduleMiloc=Map.Make(ILoc)moduleSiloc=Set.Make(ILoc)(* -------------------------------------------------------------------- *)letidentityx=xlet(|-)gf=funx->g(fx)(* -------------------------------------------------------------------- *)type'atuple0=unittype'atuple1='atype'atuple2='a*'atype'atuple3='a*'a*'atype'apair='a*'a(* -------------------------------------------------------------------- *)letas_seq0=function[]->()|_->assertfalseletas_seq1=function[x]->x|_->assertfalseletas_seq2=function[x1;x2]->(x1,x2)|_->assertfalseletas_seq3=function[x1;x2;x3]->(x1,x2,x3)|_->assertfalse(* -------------------------------------------------------------------- *)moduleOption=BatOption(* -------------------------------------------------------------------- *)letoget?exn(x:'aoption)=matchx,exnwith|None,None->assertfalse|None,Someexn->raiseexn|Somex,_->x(* -------------------------------------------------------------------- *)moduleUniq=structletgen()=Oo.id(objectend)end(* -------------------------------------------------------------------- *)moduleISet=BatISet(* -------------------------------------------------------------------- *)moduleList=structincludeBatList(* ------------------------------------------------------------------ *)letopick=Exceptionless.find_map(* ------------------------------------------------------------------ *)moduleParallel=structletmap_fold2f=letrecdoitaxs1xs2 =matchxs1,xs2with|[],[]->(a,[])|x1::xs1,x2::xs2->let(a,x)=fax1x2inlet(a,xs)=doitaxs1xs2in(a,x::xs)|_,_->invalid_arg"List.map_fold2"infunaxs1xs2->doitaxs1xs2endincludeParallel(* ------------------------------------------------------------------ *)letlast(s:'alist)=matchExceptionless.lastswith|None->failwith"List.last"|Somex->xletrecfind_map_optf=function|[]->None|x::l->beginmatchfxwith|Some_asresult->result|None->find_map_optflendletrecpmap(f:'a->'boption)(xs:'alist)=matchxswith|[]->[]|x::xs->letv=fxinletbs=pmapfxsinmatchvwithSomeb->b::bs|None->bsletmapi_foldfaxs=leta=refainletxs=List.mapi(funib->let(a',b')=fi!abina:=a';b')xsin(!a,xs)letmap_foldfaxs=mapi_fold(fun(_:int)x->fx)axs(* ------------------------------------------------------------------ *)letmodify_lastfxs=modify_at(lengthxs-1)fxsend(* -------------------------------------------------------------------- *)moduleString=structincludeBatStringletdrop_endns=subs0(lengths-n)end(* -------------------------------------------------------------------- *)moduleIO=BatIO(* -------------------------------------------------------------------- *)moduleBuffer=BatBuffer(* -------------------------------------------------------------------- *)type'app=Format.formatter->'a->unitletrecpp_listsepppfmtxs=letpp_list=pp_listsepppinmatchxswith|[]->()|[x]->Format.fprintffmt"%a"ppx|x::xs->Format.fprintffmt"%a%(%)%a"ppxseppp_listxs(* -------------------------------------------------------------------- *)letpp_enclose~pre~postppfmtx=Format.fprintffmt"%(%)%a%(%)"preppxpost(* -------------------------------------------------------------------- *)letpp_parenppfmtx=pp_enclose~pre:"("~post:")"ppfmtx(* -------------------------------------------------------------------- *)letpp_stringfmts=Format.fprintffmt"%s"s(* -------------------------------------------------------------------- *)typearchitecture=|X86_64|ARM_M4|RISCV(* -------------------------------------------------------------------- *)typemodel=|ConstantTime|ConstantTimeGlobal|Normal(* -------------------------------------------------------------------- *)(* Functions used to add colors to errors and warnings. *)(* for locations *)letpp_print_boldpp=pp_enclose~pre:"@{<\027[1m>"~post:"@}"pp(* for error kind *)letpp_print_bold_redpp=pp_enclose~pre:"@{<\027[1;31m>"~post:"@}"pp(* for warning kind *)letpp_print_bold_magentapp=pp_enclose~pre:"@{<\027[1;35m>"~post:"@}"pp(* Enabling the interpretation of semantic tags for the error channel, so that
error and warning messages are printed with colors.
*)letenable_colors()=letmark_open_stags=matchswith|Format.String_tags->s|_->""inletmark_close_stag_="\027[m"inletstag_functions=Format.{mark_open_stag;mark_close_stag;print_open_stag=(fun_->());print_close_stag=(fun_->());}inFormat.pp_set_formatter_stag_functionsFormat.err_formatterstag_functions;Format.pp_set_mark_tagsFormat.err_formattertrue(* -------------------------------------------------------------------- *)(* An [error_loc] is either unknown, a single location or a pair of a location
and a list of locations (this list comes from the inlining pass).
We could probably just have an [i_loc], though, since we can simulate
the other cases with a dummy location and an empty list.
*)typeerror_loc=Lnone|LoneofLocation.t|LmoreofLocation.i_loctypehierror={err_msg:Format.formatter->unit;(* a printer of the main error message *)err_loc:error_loc;(* the location *)err_funname:stringoption;(* the name of the function, if any *)err_kind:string;(* kind of error (e.g. typing, compilation) *)err_sub_kind:stringoption;(* sub-kind (e.g. the name of the compilation pass) *)err_internal:bool;(* whether the error is unexpected *)}exceptionHiErrorofhierror(* We fetch from [i_loc] the locations coming from the inlining pass *)letadd_ilocei_loc=leterr_loc=matche.err_locwith|Lnone->Lmorei_loc|Loneloc->Lmore(Location.i_locloci_loc.stack_loc)|Lmore_aserr_loc->err_loc(* we already have a more precise location *)in{ewitherr_loc}letremove_dummy_locations=letopenLocationinfunction|Lnone->Lnone|Lonelwhenisdummyl->Lnone|Lone_asx->x|Lmore{base_loc;stack_loc;_}->matchList.filter(funx->not(isdummyx))(base_loc::stack_loc)with|[]->Lnone|[x]->Lonex|x::xs->Lmore(i_locxxs)letpp_hierrorfmte=letpp_locfmt=matchremove_dummy_locationse.err_locwith|Lnone->()|Lonel->Format.fprintffmt"%a:@ "(pp_print_boldLocation.pp_loc)l|Lmorei_loc->Format.fprintffmt"%a:@ "(pp_print_boldLocation.pp_iloc)i_locinletpp_kindfmt=letppfmt()=ife.err_internalthenFormat.fprintffmt"internal %s"e.err_kindelseFormat.fprintffmt"%s"e.err_kindinpp_print_bold_redppfmt()inletpp_funnamefmt=matche.err_funnamewith|Somefn->Format.fprintffmt" in function %s"fn|None->()in(* this function decides whether we open a new line *)letpp_other_linefmt=ife.err_internalthen(* if the error is internal, we go to a new line with an indent *)Format.fprintffmt"@;<1 2>"elseife.err_funname<>None||e.err_sub_kind<>Nonethen(* if there is at least a funname or a sub-kind, we go to a new line *)Format.fprintffmt"@ "else(* otherwise, we keep the same line *)Format.fprintffmt" "inletpp_errfmt=matche.err_sub_kindwith|Somes->Format.fprintffmt"%s: %t"se.err_msg|None->Format.fprintffmt"%t"e.err_msginletpp_postfmt=ife.err_internalthenFormat.fprintffmt"@ Please report at https://github.com/jasmin-lang/jasmin/issues"inFormat.fprintffmt"@[<v>%t%t%t:%t%t%t@]"pp_locpp_kindpp_funnamepp_other_linepp_errpp_post(* In general, we want a [loc], that's why it is not optional. If you really
don't want to give a [loc], pass [Lnone].
*)lethierror~loc?funname~kind?sub_kind?(internal=false)=Format.kdprintf(funpp->leterr={err_msg=pp;err_loc=loc;err_funname=funname;err_kind=kind;err_sub_kind=sub_kind;err_internal=internal;}inraise(HiErrorerr))(* -------------------------------------------------------------------- *)(** Splits a time in seconds into hours, minutes, seconds, and centiseconds.
Number of hours must be below one hundred. *)lethmscf=letopenFloatinletcutfn=letr=remfninto_intr,(f-.r)/.ninletc,f=modffinlets,f=cutf60.inletm,f=cutf60.inleth,f=cutf100.inassert(f=0.);h,m,s,to_int(100.*.c)letpp_now=letopenUnixinlettimestamp=ref(-1.)inletpp_elapsedfmtnow=letold=!timestampinifold>=0.thenbeginletdiff=now-.oldinleth,m,s,c=hmscdiffinFormat.fprintffmt"|";ifh>0thenFormat.fprintffmt"%2dh"helseFormat.fprintffmt" ";ifh>0||m>0thenFormat.fprintffmt"%2dm"melseFormat.fprintffmt" ";Format.fprintffmt"%2ds%02d"scend;timestamp:=nowinfunfmt->letnow=gettimeofday()inlet{tm_hour;tm_min;tm_sec;_}=localtimenowinFormat.fprintffmt"[%02d:%02d:%02d%a]"tm_hourtm_mintm_secpp_elapsednow(* -------------------------------------------------------------------- *)typewarning=|ExtraAssignment(* -wea *)|UseLea(* -wlea *)|IntroduceArrayCopy(* -winsertarraycopy *)|InlinedCallToExport|KeptRenaming|SimplifyVectorSuffix|DuplicateVar(* -wduplicatevar *)|UnusedVar(* -wunusedvar *)|SCTchecker|Linter|Deprecated|Experimental|Always|PedanticPretypingletdefault_warnings=[InlinedCallToExport;SimplifyVectorSuffix;DuplicateVar;UnusedVar;SCTchecker;Deprecated;Experimental;PedanticPretyping;]letall_warnings=Linter::ExtraAssignment::UseLea::IntroduceArrayCopy::KeptRenaming::default_warningsletwarns=refdefault_warningsletwarn_recoverable=reffalseletset_warn_recoverableb=warn_recoverable:=bletadd_warning(w:warning)()=letws=!warnsinifnot(List.memwws)thenwarns:=w::wsletremove_warning(w:warning)=letws=!warnsinifList.memwwsthenwarns:=List.removewswletset_all_warnings()=warns:=all_warningsletnowarning()=warns:=[]letto_warnw=w=Always||List.memw!warnsletwarning(w:warning)loc=Format.kdprintf(funpp->matchwwith|PedanticPretypingwhennot!warn_recoverable->hierror~loc:(Lmoreloc)~kind:"typing error""%t"pp|_->ifto_warnwthenletpp_warningfmt=pp_print_bold_magentapp_stringfmt"warning"inletpp_ilocfmtd=ifnot(Location.isdummyd.Location.base_loc)thenFormat.fprintffmt"%a@ "(pp_print_boldLocation.pp_iloc)dinFormat.eprintf"@[<v>%a%t: %t@]@."pp_iloclocpp_warningpp)