123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256openUtils(*--------------------------------------------------------------------- *)letversion_string="Jasmin Compiler 2025.06.2"(*--------------------------------------------------------------------- *)letoutfile=ref""letdwarf=reffalseletdebug=reffalselettimings=reffalseletprint_list=ref[]letprint_liveness=reffalseletslice=ref[]letcheck_safety=reffalseletsafety_param=refNoneletsafety_config=refNoneletstop_after=refNoneletsafety_makeconfigdoc=refNonelettrust_aligned=reffalselethelp_version=reffalselethelp_intrinsics=reffalsetypecolor=|Auto|Always|Neverletcolor=refAutoletlea=reffalseletset0=reffalseletprint_stack_alloc=reffalseletprint_export_info_json=reffalseletintroduce_array_copy=reftrueletintroduce_export_renaming=reftrueletprint_dependencies=reffalseletlazy_regalloc=reffalseletverbosity=ref1letlinting_level=ref1letset_linting_leveli=if0<=i&&i<=2thenbeginlinting_level:=i;ifi=0thenremove_warningLinterelseadd_warningLinter()endelsehierror~loc:Lnone~kind:"parsing arguments""unknown linting level (should be 0, 1, or 2)"letenable_all_warnings()=linting_level:=2;set_all_warnings()letstack_zero_strategy=refNoneletstack_zero_strategies=letopenStack_zero_strategyinletassoc=function|SZSloop->"loop"|SZSloopSCT->"loopSCT"|SZSunrolled->"unrolled"inList.map(funs->(assocs,s))stack_zero_strategy_listletset_stack_zero_strategys=stack_zero_strategy:=Some(List.assocsstack_zero_strategies)letstack_zero_size=refNoneletset_stack_zero_sizes=stack_zero_size:=Some(Annot.ws_of_strings)lettarget_arch=refX86_64letset_target_archa=leta'=matchawith|"x86-64"->X86_64|"arm-m4"->ARM_M4|"riscv"->RISCV|_->assertfalseintarget_arch:=a'typex86_assembly_style=[`ATT|`Intel]letassembly_style:x86_assembly_styleref=ref`ATTletset_syntaxstyle()=assembly_style:=styleletset_printingp()=print_list:=p::!print_listletset_stop_afterp()=stop_after:=Somepletset_all_print()=print_list:=Compiler.compiler_step_listletset_slicef=slice:=f::!sliceletset_checksafety()=check_safety:=trueletset_safetyparams=safety_param:=Somesletset_safetyconfigs=safety_config:=Somesletset_safety_makeconfigdocs=safety_makeconfigdoc:=Somesletset_colorc=letassoc=function|"auto"->Auto|"always"->Always|"never"->Never|_->assertfalseincolor:=assoccletidirs=ref[]letset_idirss=letcolons=String.count_chars':'inletequals=String.count_chars'='inletidir=match(equals,colons)with|1,0->String.split~by:"="s|0,1->warningDeprecatedLocation.i_dummy"Use of colon in path:ident is deprecated: use an equal sign instead";String.split~by:":"s|_,_->hierror~loc:Lnone~kind:"parsing arguments""bad format for -I : ident=path expected"inidirs:=idir::!idirstypecall_conv=Linux|Windowsletcall_conv=refLinux(* Default value is chosen on start-up in `main_compiler` *)letset_cccc=letcc=matchccwith|"windows"->Windows|"linux"->Linux|_->assertfalseincall_conv:=ccletprint_strings=function|Compiler.Typing->"typing","typing"|Compiler.ParamsExpansion->"cstexp","param expansion"|Compiler.InsertRenaming->"rename","add renaming assignments at export function boundaries"|Compiler.WintWord->"wintword","replace wint by word"|Compiler.ArrayCopy->"arraycopy","array copy"|Compiler.AddArrInit->"addarrinit","add array initialisation"|Compiler.LowerSpill->"lowerspill","lower spill/unspill instructions"|Compiler.Inlining->"inline","inlining"|Compiler.RemoveUnusedFunction->"rmfunc","remove unused function"|Compiler.Unrolling->"unroll","unrolling"|Compiler.Splitting->"splitting","liverange splitting"|Compiler.Renaming->"renaming","variable renaming to remove copies"|Compiler.RemovePhiNodes->"rmphi","remove phi nodes introduced by splitting"|Compiler.DeadCode_Renaming->"renamingd","dead code after variable renaming to remove copies"|Compiler.RemoveArrInit->"rmarrinit","remove array initialisation"|Compiler.RegArrayExpansion->"arrexp","expansion of register arrays"|Compiler.RemoveGlobal->"rmglobals","remove globals variables"|Compiler.MakeRefArguments->"makeref","add assignments before and after call to ensure that arguments and results are ref ptr"|Compiler.LoadConstantsInCond->"loadconst","introduce registers for constants appearing in conditions (RISC-V only)"|Compiler.LowerInstruction->"lowering","lowering of instructions"|Compiler.PropagateInline->"propagate","propagate inline variables"|Compiler.SLHLowering->"slhlowering","lowering of selective load hardening instructions"|Compiler.LowerAddressing->"loweraddr","lowering of complex addressing modes (RISC-V only)"|Compiler.StackAllocation->"stkalloc","stack allocation"|Compiler.RemoveReturn->"rmreturn","remove unused returned values"|Compiler.RegAllocation->"ralloc","register allocation"|Compiler.DeadCode_RegAllocation->"rallocd","dead code after register allocation"|Compiler.Linearization->"linear","linearization"|Compiler.StackZeroization->"stackzero","stack zeroization"|Compiler.Tunneling->"tunnel","tunneling"|Compiler.Assembly->"asm","generation of assembly"letcompiler_step_symbol=List.map(funs->fst(print_stringss))Compiler.compiler_step_listletsymbol2pass=lettbl=Hashtbl.create101inList.iter(funs->Hashtbl.addtbl(fst(print_stringss))s)Compiler.compiler_step_list;funs->Hashtbl.findtblsletprint_optionp=lets,msg=print_stringspin("-p"^s,Arg.Unit(set_printingp)," Print program after "^msg)letstop_after_optionp=lets,msg=print_stringspin("-until_"^s,Arg.Unit(set_stop_afterp)," Stop after "^msg)letoptions=["-version",Arg.Sethelp_version," Display version information about this compiler (and exit)";"-o",Arg.Set_stringoutfile,"[filename] Name of the output file";"-g",Arg.Setdwarf," Emit DWARF2 line number information";"-debug",Arg.Setdebug," Print debug information";"-timings",Arg.Settimings," Print a timestamp and elapsed time after each pass";"-I",Arg.Stringset_idirs,"[ident=path] Bind ident to path for from ident require ...";"-lea",Arg.Setlea," Use lea as much as possible (default is nolea)";"-nolea",Arg.Clearlea," Try to use add and mul instead of lea";"-set0",Arg.Setset0," Use [xor x x] to set x to 0 (default is not)";"-noset0",Arg.Clearset0," Do not use set0 option";"-slice",Arg.Stringset_slice,"[f] Keep function [f] and everything it needs";"-checksafety",Arg.Unitset_checksafety," Automatically check for safety";"-safetyparam",Arg.Stringset_safetyparam," Parameter for automatic safety verification:\n \
format: \"f_1>param_1|f_2>param_2|...\" \
where each param_i is of the form:\n \
pt_1,...,pt_n;len_1,...,len_k\n \
pt_1,...,pt_n: input pointers of f_i\n \
len_1,...,len_k: input lengths of f_i";"-safetyconfig",Arg.Stringset_safetyconfig,"[filename] Use filename (JSON) as configuration file for the safety checker";"-safetymakeconfigdoc",Arg.Stringset_safety_makeconfigdoc,"[dir] Make the safety checker configuration docs in [dir]";"-nocheckalignment",Arg.Settrust_aligned," Do not report alignment issue as safety violations";"-wlea",Arg.Unit(add_warningUseLea)," Print warning when lea is used";"-wea",Arg.Unit(add_warningExtraAssignment)," Print warning when extra assignment is introduced";"-winsertarraycopy",Arg.Unit(add_warningIntroduceArrayCopy)," Print warning when array copy is introduced";"-wduplicatevar",Arg.Unit(add_warningDuplicateVar)," Print warning when two variables share the same name";"-wunusedvar",Arg.Unit(add_warningUnusedVar)," Print warning when a variable is not used";"-noinsertarraycopy",Arg.Clearintroduce_array_copy," Do not automatically insert array copy";"-noinsertrenaming",Arg.Clearintroduce_export_renaming," Do not automatically insert renaming assignments at export function boundaries";"-wall",Arg.Unitenable_all_warnings," Enable all warnings";"-nowarning",Arg.Unit(nowarning)," Do no print warnings";"-linting-level",Arg.Intset_linting_level,"[n] Set linting level to n (defaults to 1; disable linting when set to 0)";"-color",Arg.Symbol(["auto";"always";"never"],set_color)," Print messages with color";"-help-intrinsics",Arg.Sethelp_intrinsics," List the set of intrinsic operators (and exit)";"-print-stack-alloc",Arg.Setprint_stack_alloc," Print the results of the stack allocation OCaml oracle";"-print-export-info-json",Arg.Setprint_export_info_json," Print information about exported functions in json";"-lazy-regalloc",Arg.Setlazy_regalloc," Allocate variables to registers in program order";"-pall",Arg.Unitset_all_print," Print program after each compilation steps";"-print-dependencies",Arg.Setprint_dependencies," Print dependencies and exit";"-intel",Arg.Unit(set_syntax`Intel)," Use intel syntax (default is AT&T)";"-ATT",Arg.Unit(set_syntax`ATT)," Use AT&T syntax (default is AT&T)";"-call-conv",Arg.Symbol(["windows";"linux"],set_cc)," Select calling convention (default depends on host architecture)";"-arch",Arg.Symbol(["x86-64";"arm-m4";"riscv"],set_target_arch)," Select target arch (default is x86-64)";"-stack-zero",Arg.Symbol(List.mapfststack_zero_strategies,set_stack_zero_strategy)," Select stack zeroization strategy for export functions";"-stack-zero-size",Arg.Symbol(List.mapfstAnnot.ws_strings,set_stack_zero_size)," Select stack zeroization size for export functions";"-pliveness",Arg.Setprint_liveness," Print liveness information during register allocation"]@List.mapprint_optionCompiler.compiler_step_list@List.mapstop_after_optionCompiler.compiler_step_listletusage_msg="Usage : jasminc [option] filename"(* -------------------------------------------------------------------- *)leteprintsteppp_progp=if!timingsthenFormat.eprintf"%t after %s@."pp_now(fst(print_stringsstep));ifList.memstep!print_listthenbeginlet(_,msg)=print_stringsstepinFormat.printf"/* -------------------------------------------------------------------- */@.";Format.printf"/* After %s */@.@."msg;Format.printf"%a@.@.@."pp_progpend;if!stop_after=Somestepthenexit0