123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189(**************************************************************************)(* *)(* SPDX-License-Identifier LGPL-2.1 *)(* Copyright (C) *)(* CEA (Commissariat à l'énergie atomique et aux énergies alternatives) *)(* *)(**************************************************************************)(** Plug-in states and options. *)includePlugin.Register(structletname="ACSL importer"letshortname="acsl-import"lethelp="external ACSL files importer"end)letdkey=register_category"trace-options"(** {1 Messages and warning categories} *)letannot_error?sourcefmt=Kernel.warning~wkey:Kernel.wkey_annot_error?sourcefmtletannot_warning?source~raisingfmt=Kernel.logwith(fun_->raising())~wkey:Kernel.wkey_annot_error?sourcefmtletwkey_integer_cast=register_warn_category"annot:integer-cast"(** {1 Plug-in options.} *)moduleTypeOnly=False(structletoption_name="-acsl-import-type-only"lethelp="parses and types the ACSL files without imports"end)letcontinue_after_typing()=not(TypeOnly.get())moduleParseOnly=False(structletoption_name="-acsl-import-parse-only"lethelp="parses the ACSL files without typing nor imports"end)letcontinue_after_parsing()=not(ParseOnly.get())moduleImport=String_list(structletoption_name="-acsl-import"letarg_name="f1,...,fn"lethelp="ACSL files to import"end)moduleKeepUnusedSymbols=False(structletoption_name="-acsl-import-keep-unused-symbols"lethelp="keeps unused C symbols"end)let()=KeepUnusedSymbols.add_update_hook(fun_v->Rmtmps.keepUnused:=v)moduleAddonEnsuresAndExits=False(structletoption_name="-acsl-import-addon-ensures-and-exits"lethelp="adds ensures_and_exits extension clause"end)moduleIdirs=String_list(structletoption_name="-acsl-import-include-dirs"letarg_name="d1,...,dn"lethelp="directories for searching ACSL files to include"end)moduleAddonIntegerCast=False(structletoption_name="-acsl-import-addon-integer-cast"lethelp="elucidates implicit and explicit casts from integers to C integral \
types"end)moduleRun=True(structletoption_name="-acsl-import-run"lethelp="runs the plugin (other options just configure its parameters)"end)moduleUnroolLoopCondition=False(structletoption_name="-acsl-import-unroll-loop-conditions"lethelp="unrolls statements related to loop conditions"end)letis_unroll_loop_condition_on=UnroolLoopCondition.getletsplit_values=letcompletely="completely"inletrx2=Str.regexp"@"inletb,s=match(tryStr.bounded_split_delimrx2s3with_->failwith"cannot split from separator '@'")with|["";""]->failwith"no directive"|[total;n]whentotal=completely->true,n|[total]whentotal=completely->true,""|[n]->false,n|[]->failwith"empty string"|_->failwith"too much directive separator '@'"inb,ifs=""then-1else(tryint_of_stringswith_->failwith("invalid unrolling number:"^s))moduleUnroolLoopFunctionLevel=String_map(structincludeDatatype.Pair(Datatype.Bool)(Datatype.Int)letof_strings=trydebug~level:2~dkey"Parsing value for \"-acsl-import-ulevel-spec=%s\""s;let(b,n)asv=split_valuesindebug~level:2~dkey"-> unencoded value: %b, %d."bn;vwith|Failurewhy->raise(Cannot_build(why))letto_string=function|(false,n)->string_of_intn|(true,n)->"completely@"^string_of_intnend)(structletoption_name="-acsl-import-ulevel-spec"letarg_name="spec1,...,specs"lethelp="an unrolling specification <m@f:tag@n> adds a 'loop unfold \"tag\", <n>;' to the loop of the function <f> of occurrence <m>.\n \
An unrolling specification <c@f:tag@n> adds a 'loop unfold \"tag\", <n>;' to all loops of category <c> of the function <f> where allowed loop categories are: 'while', 'for' and 'do-while'.\n \
The specification is considered as a set of elementary specifications: spec1,...,specs.\n \
Categories, function names and loop occurrence numbers can be omitted. \
The priority ordering used for choosing the (\"tag\", unrolling value <n>) pair is: m@f:tag@n > c@f:tag@n > f:tag@n > c:tag@n > :tag@n.\n \
The default value for optional tags is the empty string which leads to add a loop pragmas without tags.\n \
Nothing is done for loops having already a clause 'loop unfold ...'."letdefault=Datatype.String.Map.emptyend)letis_unroll_loop_pragma_on=UnroolLoopFunctionLevel.is_emptyletfind_ulevel_specloop_categoryloop_numfct_name=debug~level:2~dkey"Find -acsl-import-ulevel-spec for %S loop #%d of function %S."loop_categoryloop_numfct_name;let(_,times)asspec=lettotal=reffalseandtimes=ref(-1)in(tryList.iter(funf->(tryletb,n=letkey=f()indebug~level:2~dkey"-> keys=%S."key;UnroolLoopFunctionLevel.findkeyindebug~level:2~dkey"-> found %b, %d."bn;ifbthentotal:=true;if!times<0thentimes:=n;withNot_found->());if!total&&!times>=0thenraiseNot_found)[(fun()->(string_of_intloop_num)^"@"^fct_name);(fun()->loop_category^"@"^fct_name);(fun()->fct_name);(fun()->loop_category);(fun()->"")];withNot_found->());debug~level:2~dkey"Found finally %b, %d."!total!times;!total,!timesiniftimes<0thenraiseNot_found;specletis_importation_on()=(not(Import.is_empty())&&Run.get())letset_importation_off()=Import.set[]letemitter=Emitter.create"ACSL Importer"[Emitter.Global_annot;Emitter.Code_annot]~correctness:[]~tuning:[]letmain_import=File.register_code_transformation_category"acsl importer"letaux_import=File.register_code_transformation_category"acsl importer transform"