123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2013 Hugo Heuzard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)open!StdlibmoduleFlag=structletoptims=ref[]letavailable()=List.map~f:fst!optimsleto~name~default=letstate=matchList.string_assocname!optimswith|Somex->x|None->letstate=refdefaultinoptims:=(name,state)::!optims;stateinfun()->!stateletfinds=matchList.string_assocs!optimswith|Somex->!x|None->failwith(Printf.sprintf"The option named %S doesn't exist"s)letsetsb=matchList.string_assocs!optimswith|Somes->s:=b|None->failwith(Printf.sprintf"The option named %S doesn't exist"s)letdisables=matchList.string_assocs!optimswith|Somes->s:=false|None->failwith(Printf.sprintf"The option named %S doesn't exist"s)letenables=matchList.string_assocs!optimswith|Somes->s:=true|None->failwith(Printf.sprintf"The option named %S doesn't exist"s)letpretty=o~name:"pretty"~default:falseletstable_var=o~name:"stable_var"~default:falseletdebuginfo=o~name:"debuginfo"~default:falseletdeadcode=o~name:"deadcode"~default:trueletglobaldeadcode=o~name:"globaldeadcode"~default:trueletshortvar=o~name:"shortvar"~default:trueletcompact=o~name:"compact"~default:trueletoptcall=o~name:"optcall"~default:trueletinline=o~name:"inline"~default:trueleteffects=o~name:"effects"~default:falseletstaticeval=o~name:"staticeval"~default:trueletshare_constant=o~name:"share"~default:trueletstrictmode=o~name:"strict"~default:trueletdebugger=o~name:"debugger"~default:trueletgenprim=o~name:"genprim"~default:trueletexcwrap=o~name:"excwrap"~default:trueletimproved_stacktrace=o~name:"with-js-error"~default:falseletinline_callgen=o~name:"callgen"~default:falseletsafe_string=o~name:"safestring"~default:trueletuse_js_string=o~name:"use-js-string"~default:trueletcheck_magic=o~name:"check-magic-number"~default:trueletcompact_vardecl=o~name:"vardecl"~default:falseletheader=o~name:"header"~default:trueletauto_link=o~name:"auto-link"~default:trueletes6=o~name:"es6"~default:falseletload_shapes_auto=o~name:"load-shapes-auto"~default:falseendmoduleParam=structletintdefault=(default,int_of_string,funs->tryignore(int_of_strings:int);Ok()with_->Error"expecting an integer")letenum:(string*'a)list->_=function|(_,v)::_asl->(v,(funx->matchList.string_assocxlwith|Somex->x|None->assertfalse),funx->ifList.exists~f:(fun(y,_)->String.equalxy)lthenOk()elseError(Printf.sprintf"expecting one of %s"(String.concat~sep:", "(List.mapl~f:fst))))|_->assertfalseletparams:(string*_)listref=ref[]letp~name~desc(default,convert,valid)=assert(Option.is_none(List.string_assocname!params));letstate=refdefaultinletset:string->unit=funv->trystate:=convertvwith_->failwith(Printf.sprintf"malformed option %s=%s."namev)inparams:=(name,(set,desc,valid))::!params;fun()->!stateletsetsv=matchList.string_assocs!paramswith|Some(f,_,_)->fv|None->failwith(Printf.sprintf"The option named %S doesn't exist"s)letall()=List.map!params~f:(fun(n,(_,d,valid))->n,d,valid)(* V8 "optimize" switches with less than 128 case.
60 seams to perform well. *)letswitch_max_case=p~name:"switch_size"~desc:"set the maximum number of case in a switch"(int60)letinlining_limit=p~name:"inlining-limit"~desc:"set the size limit for inlining"(int150)lettailcall_max_depth=p~name:"tc_depth"~desc:"set the maximum number of recursive tailcalls defore returning a trampoline"(int50)letconstant_max_depth=p~name:"cst_depth"~desc:"set the maximum depth of generated literal JavaScript values"(int10)typetc=|TcNone|TcTrampolinelettc_equal(a:tc)b=Poly.equalab(* | TcWhile *)lettc_default=TcTrampolinelet_tc_all=tc_default::List.filter[TcNone;TcTrampoline]~f:(funx->not(tc_equaltc_defaultx))lettailcall_optim=p~name:"tc"~desc:"Set tailcall optimisation"(enum["trampoline",TcTrampoline(* default *);"none",TcNone])letlambda_lifting_threshold=(* When we reach this depth, we start looking for functions to be lifted *)p~name:"lifting-threshold"~desc:"Set threshold for lifting deeply nested functions"(int50)letlambda_lifting_baseline=(* Level at which functions are lifted *)p~name:"lifting-baseline"~desc:"Set baseline for lifting deeply nested functions"(int1)end(****)lettarget_:[`JavaScript|`Wasm|`None]ref=ref`Nonelettarget()=match!target_with|`None->failwith"target was not set"|(`JavaScript|`Wasm)ast->tletset_target(t:[`JavaScript|`Wasm])=(matchtwith|`JavaScript->Targetint.set_num_bits32|`Wasm->Targetint.set_num_bits31);target_:=(t:>[`JavaScript|`Wasm|`None])typeeffects_backend=[`Disabled|`Cps|`Double_translation|`Jspi]leteffects_:[<`None|effects_backend]ref=ref`Noneleteffects()=match!effects_with|`None->failwith"effects was not set"|(`Jspi|`Cps|`Disabled|`Double_translation)asb->bletset_effects_backend(backend:effects_backend)=effects_:=(backend:>[`None|effects_backend])