hlinterp.ml 95 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931
  1. (*
  2. * Copyright (C)2005-2017 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Unix
  23. open Hlcode
  24. type value =
  25. | VNull
  26. | VInt of int32
  27. | VInt64 of int64
  28. | VFloat of float
  29. | VBool of bool
  30. | VDyn of value * ttype
  31. | VObj of vobject
  32. | VClosure of vfunction * value option
  33. | VBytes of string
  34. | VArray of value array * ttype
  35. | VUndef
  36. | VType of ttype
  37. | VRef of ref_value * ttype
  38. | VVirtual of vvirtual
  39. | VDynObj of vdynobj
  40. | VEnum of enum_proto * int * value array
  41. | VAbstract of vabstract
  42. | VVarArgs of vfunction * value option
  43. and ref_value =
  44. | RStack of int
  45. | RValue of value ref
  46. | RArray of value array * int
  47. and vabstract =
  48. | AHashBytes of (string, value) Hashtbl.t
  49. | AHashInt of (int32, value) Hashtbl.t
  50. | AHashObject of (value * value) list ref
  51. | AReg of regexp
  52. | ARandom
  53. | APos of Globals.pos
  54. | ATDecl of Type.module_type
  55. | AUnsafe of Obj.t
  56. | ALazyType of ((unit -> Type.t) ref) * (unit -> value)
  57. and vfunction =
  58. | FFun of fundecl
  59. | FNativeFun of string * (value list -> value) * ttype
  60. and vobject = {
  61. oproto : vproto;
  62. ofields : value array;
  63. }
  64. and vproto = {
  65. pclass : class_proto;
  66. pmethods : vfunction array;
  67. }
  68. and vvirtual = {
  69. vtype : virtual_proto;
  70. mutable vindexes : vfield array;
  71. mutable vtable : value array;
  72. mutable vvalue : value;
  73. }
  74. and vdynobj = {
  75. dfields : (string, int) Hashtbl.t;
  76. mutable dtypes : ttype array;
  77. mutable dvalues : value array;
  78. mutable dvirtuals : vvirtual list;
  79. }
  80. and vfield =
  81. | VFNone
  82. | VFIndex of int
  83. and regexp = {
  84. r : Str.regexp;
  85. mutable r_string : string;
  86. mutable r_groups : (int * int) option array;
  87. }
  88. exception Return of value
  89. exception Runtime_error of string
  90. exception InterpThrow of value
  91. exception Sys_exit of int
  92. type context = {
  93. mutable t_globals : value array;
  94. mutable t_functions : vfunction array;
  95. mutable call_stack : (fundecl * int ref) list;
  96. mutable error_stack : (fundecl * int ref) list;
  97. mutable stack : value array;
  98. mutable stack_pos : int;
  99. mutable fcall : vfunction -> value list -> value;
  100. mutable code : code;
  101. mutable on_error : value -> (fundecl * int ref) list -> unit;
  102. mutable resolve_macro_api : string -> (value list -> value) option;
  103. checked : bool;
  104. cached_protos : (int, vproto * ttype array * (int * (value -> value)) list) Hashtbl.t;
  105. cached_strings : (int, string) Hashtbl.t;
  106. cached_hashes : (int32, string) Hashtbl.t;
  107. }
  108. let default t =
  109. match t with
  110. | HUI8 | HUI16 | HI32 -> VInt Int32.zero
  111. | HI64 -> VInt64 Int64.zero
  112. | HF32 | HF64 -> VFloat 0.
  113. | HBool -> VBool false
  114. | _ -> if is_nullable t then VNull else VUndef
  115. let get_type = function
  116. | VDyn (_,t) -> Some t
  117. | VObj o -> Some (HObj o.oproto.pclass)
  118. | VDynObj _ -> Some HDynObj
  119. | VVirtual v -> Some (HVirtual v.vtype)
  120. | VArray _ -> Some HArray
  121. | VClosure (f,None) -> Some (match f with FFun f -> f.ftype | FNativeFun (_,_,t) -> t)
  122. | VClosure (f,Some _) -> Some (match f with FFun { ftype = HFun(_::args,ret) } | FNativeFun (_,_,HFun(_::args,ret)) -> HFun (args,ret) | _ -> assert false)
  123. | VVarArgs _ -> Some (HFun ([],HDyn))
  124. | VEnum (e,_,_) -> Some (HEnum e)
  125. | _ -> None
  126. let v_dynamic = function
  127. | VNull | VDyn _ | VObj _ | VClosure _ | VArray _ | VVirtual _ | VDynObj _ | VVarArgs _ | VEnum _ -> true
  128. | _ -> false
  129. let rec is_compatible v t =
  130. match v, t with
  131. | VInt _, (HUI8 | HUI16 | HI32) -> true
  132. | VInt64 _, HI64 -> true
  133. | VFloat _, (HF32 | HF64) -> true
  134. | VBool _, HBool -> true
  135. | _, HVoid -> true
  136. | VNull, t -> is_nullable t
  137. | VObj o, HObj _ -> safe_cast (HObj o.oproto.pclass) t
  138. | VClosure _, HFun _ -> safe_cast (match get_type v with None -> assert false | Some t -> t) t
  139. | VBytes _, HBytes -> true
  140. | VDyn (_,t1), HNull t2 -> tsame t1 t2
  141. | v, HNull t -> is_compatible v t
  142. | v, HDyn -> v_dynamic v
  143. | VType _, HType -> true
  144. | VArray _, HArray -> true
  145. | VDynObj _, HDynObj -> true
  146. | VVirtual v, HVirtual _ -> safe_cast (HVirtual v.vtype) t
  147. | VRef (_,t1), HRef t2 -> tsame t1 t2
  148. | VAbstract _, HAbstract _ -> true
  149. | VEnum _, HEnum _ -> true
  150. | _ -> false
  151. type cast =
  152. | CNo
  153. | CDyn of ttype
  154. | CUnDyn of ttype
  155. | CCast of ttype * ttype
  156. let error msg = raise (Runtime_error msg)
  157. let get_function ctx f =
  158. ctx.t_functions.(f)
  159. let rec get_proto ctx p =
  160. try
  161. Hashtbl.find ctx.cached_protos p.pid
  162. with Not_found ->
  163. let fields, bindings = (match p.psuper with None -> [||],[] | Some p -> let _, fields, bindings = get_proto ctx p in fields, bindings) in
  164. let meths = Array.map (get_function ctx) p.pvirtuals in
  165. let fields = Array.append fields (Array.map (fun (_,_,t) -> t) p.pfields) in
  166. let bindings = List.fold_left (fun acc (fid,fidx) ->
  167. let f = get_function ctx fidx in
  168. let ft = (match f with FFun f -> f.ftype | FNativeFun _ -> assert false) in
  169. let need_closure = (match ft, fields.(fid) with HFun (args,_), HFun(args2,_) -> List.length args > List.length args2 | HFun _, HDyn -> false | _ -> assert false) in
  170. let acc = List.filter (fun (fid2,_) -> fid2 <> fid) acc in
  171. (fid, (fun v -> VClosure (f,if need_closure then Some v else None))) :: acc
  172. ) bindings p.pbindings in
  173. let proto = ({ pclass = p; pmethods = meths },fields,bindings) in
  174. Hashtbl.replace ctx.cached_protos p.pid proto;
  175. proto
  176. let alloc_obj ctx t =
  177. match t with
  178. | HDynObj ->
  179. VDynObj { dfields = Hashtbl.create 0; dvalues = [||]; dtypes = [||]; dvirtuals = []; }
  180. | HObj p ->
  181. let p, fields, bindings = get_proto ctx p in
  182. let ftable = Array.map default fields in
  183. let obj = VObj { oproto = p; ofields = ftable } in
  184. List.iter (fun (fid,mk) -> ftable.(fid) <- mk obj) bindings;
  185. obj
  186. | HVirtual v ->
  187. let o = {
  188. dfields = Hashtbl.create 0;
  189. dvalues = Array.map (fun (_,_,t) -> default t) v.vfields;
  190. dtypes = Array.map (fun (_,_,t) -> t) v.vfields;
  191. dvirtuals = [];
  192. } in
  193. Array.iteri (fun i (n,_,_) -> Hashtbl.add o.dfields n i) v.vfields;
  194. let v = { vtype = v; vvalue = VDynObj o; vtable = o.dvalues; vindexes = Array.mapi (fun i _ -> VFIndex i) v.vfields } in
  195. o.dvirtuals <- [v];
  196. VVirtual v
  197. | _ ->
  198. assert false
  199. let float_to_string f =
  200. let s = string_of_float f in
  201. let len = String.length s in
  202. if String.unsafe_get s (len - 1) = '.' then String.sub s 0 (len - 1) else s
  203. let rec get_method p name =
  204. let m = ref None in
  205. Array.iter (fun p -> if p.fname = name then m := Some p.fmethod) p.pproto;
  206. match !m , p.psuper with
  207. | Some i, _ -> Some i
  208. | None, Some s -> get_method s name
  209. | None, None -> None
  210. let get_to_string ctx p =
  211. match get_method p "__string" with
  212. | Some f ->
  213. (match get_function ctx f with
  214. | (FFun { ftype = HFun([_],HBytes) } as f) -> Some f
  215. | _ -> None)
  216. | None ->
  217. None
  218. let set_i32 b p v =
  219. try
  220. Bytes.set (Bytes.unsafe_of_string b) p (char_of_int ((Int32.to_int v) land 0xFF));
  221. Bytes.set (Bytes.unsafe_of_string b) (p+1) (char_of_int ((Int32.to_int (Int32.shift_right_logical v 8)) land 0xFF));
  222. Bytes.set (Bytes.unsafe_of_string b) (p+2) (char_of_int ((Int32.to_int (Int32.shift_right_logical v 16)) land 0xFF));
  223. Bytes.set (Bytes.unsafe_of_string b) (p+3) (char_of_int (Int32.to_int (Int32.shift_right_logical v 24)));
  224. with _ ->
  225. error "Set outside of bytes bounds"
  226. let set_i64 b p v =
  227. set_i32 b p (Int64.to_int32 v);
  228. set_i32 b (p + 4) (Int64.to_int32 (Int64.shift_right_logical v 32))
  229. let get_i32 b p =
  230. let i = int_of_char (String.get b p) in
  231. let j = int_of_char (String.get b (p + 1)) in
  232. let k = int_of_char (String.get b (p + 2)) in
  233. let l = int_of_char (String.get b (p + 3)) in
  234. Int32.logor (Int32.of_int (i lor (j lsl 8) lor (k lsl 16))) (Int32.shift_left (Int32.of_int l) 24)
  235. let get_i64 b p =
  236. let low = get_i32 b p in
  237. let high = get_i32 b (p + 4) in
  238. Int64.logor (Int64.logand (Int64.of_int32 low) 0xFFFFFFFFL) (Int64.shift_left (Int64.of_int32 high) 32)
  239. let make_dyn v t =
  240. if v = VNull || is_dynamic t then
  241. v
  242. else
  243. VDyn (v,t)
  244. let get_ref ctx = function
  245. | RStack i -> ctx.stack.(i)
  246. | RValue r -> !r
  247. | RArray (a,i) -> a.(i)
  248. let set_ref ctx r v =
  249. match r with
  250. | RStack i -> ctx.stack.(i) <- v
  251. | RValue r -> r := v
  252. | RArray (a,i) -> a.(i) <- v
  253. let fstr = function
  254. | FFun f -> "function@" ^ string_of_int f.findex
  255. | FNativeFun (s,_,_) -> "native[" ^ s ^ "]"
  256. let caml_to_hl str = utf8_to_utf16 str
  257. let hash ctx str =
  258. let h = hl_hash str in
  259. if not (Hashtbl.mem ctx.cached_hashes h) then Hashtbl.add ctx.cached_hashes h (String.sub str 0 (try String.index str '\000' with _ -> String.length str));
  260. h
  261. let utf16_iter f s =
  262. let get v = int_of_char s.[v] in
  263. let rec loop p =
  264. if p = String.length s then () else
  265. let c = (get p) lor ((get (p+1)) lsl 8) in
  266. if c >= 0xD800 && c <= 0xDFFF then begin
  267. let c = c - 0xD800 in
  268. let c2 = ((get (p+2)) lor ((get(p+3)) lsl 8)) - 0xDC00 in
  269. f ((c2 lor (c lsl 10)) + 0x10000);
  270. loop (p + 4);
  271. end else begin
  272. f c;
  273. loop (p + 2);
  274. end;
  275. in
  276. loop 0
  277. let utf16_char buf c =
  278. utf16_add buf (int_of_char c)
  279. let hl_to_caml str =
  280. let utf16_eof s =
  281. let get v = int_of_char s.[v] in
  282. let rec loop p =
  283. let c = (get p) lor ((get (p+1)) lsl 8) in
  284. if c = 0 then String.sub s 0 p else loop (p + 2);
  285. in
  286. loop 0
  287. in
  288. let b = UTF8.Buf.create (String.length str / 2) in
  289. utf16_iter (fun c -> UTF8.Buf.add_char b (UChar.chr c)) (utf16_eof str);
  290. UTF8.Buf.contents b
  291. let null_access() =
  292. error "Null value bypass null pointer check"
  293. let throw ctx v =
  294. ctx.error_stack <- [];
  295. raise (InterpThrow v)
  296. let throw_msg ctx msg =
  297. throw ctx (VDyn (VBytes (caml_to_hl msg),HBytes))
  298. let rec vstr_d ctx v =
  299. let vstr_d = vstr_d ctx in
  300. match v with
  301. | VNull -> "null"
  302. | VInt i -> Int32.to_string i ^ "i"
  303. | VInt64 i -> Int64.to_string i ^ "l"
  304. | VFloat f -> string_of_float f ^ "f"
  305. | VBool b -> if b then "true" else "false"
  306. | VDyn (v,t) -> "dyn(" ^ vstr_d v ^ ":" ^ tstr t ^ ")"
  307. | VObj o ->
  308. let p = "#" ^ o.oproto.pclass.pname in
  309. (match get_to_string ctx o.oproto.pclass with
  310. | Some f -> p ^ ":" ^ vstr_d (ctx.fcall f [v])
  311. | None -> p)
  312. | VBytes b -> "bytes(" ^ String.escaped b ^ ")"
  313. | VClosure (f,o) ->
  314. (match o with
  315. | None -> fstr f
  316. | Some v -> fstr f ^ "[" ^ vstr_d v ^ "]")
  317. | VArray (a,t) -> "array<" ^ tstr t ^ ">(" ^ String.concat "," (Array.to_list (Array.map vstr_d a)) ^ ")"
  318. | VUndef -> "undef"
  319. | VType t -> "type(" ^ tstr t ^ ")"
  320. | VRef (r,_) -> "ref(" ^ vstr_d (get_ref ctx r) ^ ")"
  321. | VVirtual v -> "virtual(" ^ vstr_d v.vvalue ^ ")"
  322. | VDynObj d -> "dynobj(" ^ String.concat "," (Hashtbl.fold (fun f i acc -> (f^":"^vstr_d d.dvalues.(i)) :: acc) d.dfields []) ^ ")"
  323. | VEnum (e,i,vals) -> let n, _, _ = e.efields.(i) in if Array.length vals = 0 then n else n ^ "(" ^ String.concat "," (Array.to_list (Array.map vstr_d vals)) ^ ")"
  324. | VAbstract _ -> "abstract"
  325. | VVarArgs _ -> "varargs"
  326. let rec to_virtual ctx v vp =
  327. match v with
  328. | VNull ->
  329. VNull
  330. | VObj o ->
  331. let indexes = Array.mapi (fun i (n,_,t) ->
  332. try
  333. let idx, ft = get_index n o.oproto.pclass in
  334. if idx < 0 || not (tsame t ft) then raise Not_found;
  335. VFIndex idx
  336. with Not_found ->
  337. VFNone (* most likely a method *)
  338. ) vp.vfields in
  339. let v = {
  340. vtype = vp;
  341. vindexes = indexes;
  342. vtable = o.ofields;
  343. vvalue = v;
  344. } in
  345. VVirtual v
  346. | VDynObj d ->
  347. (try
  348. VVirtual (List.find (fun v -> v.vtype == vp) d.dvirtuals)
  349. with Not_found ->
  350. let indexes = Array.mapi (fun i (n,_,t) ->
  351. try
  352. let idx = Hashtbl.find d.dfields n in
  353. if not (tsame t d.dtypes.(idx)) then raise Not_found;
  354. VFIndex idx
  355. with Not_found ->
  356. VFNone
  357. ) vp.vfields in
  358. let v = {
  359. vtype = vp;
  360. vindexes = indexes;
  361. vtable = d.dvalues;
  362. vvalue = v;
  363. } in
  364. d.dvirtuals <- v :: d.dvirtuals;
  365. VVirtual v
  366. )
  367. | VVirtual vd ->
  368. if vd.vtype == vp then
  369. v
  370. else if vd.vvalue = VNull then
  371. assert false
  372. else
  373. to_virtual ctx vd.vvalue vp
  374. | _ ->
  375. throw_msg ctx ("Invalid ToVirtual " ^ vstr_d ctx v ^ " : " ^ tstr (HVirtual vp))
  376. let rec dyn_cast ctx v t rt =
  377. let invalid() =
  378. throw_msg ctx ("Can't cast " ^ vstr_d ctx v ^ ":" ^ tstr t ^ " to " ^ tstr rt)
  379. in
  380. let default() =
  381. let v = default rt in
  382. if v = VUndef then invalid();
  383. v
  384. in
  385. if safe_cast t rt then
  386. v
  387. else if v = VNull then
  388. default()
  389. else match t, rt with
  390. | (HUI8|HUI16|HI32), (HF32|HF64) ->
  391. (match v with VInt i -> VFloat (Int32.to_float i) | _ -> assert false)
  392. | (HF32|HF64), (HUI8|HUI16|HI32) ->
  393. (match v with VFloat f -> VInt (Int32.of_float f) | _ -> assert false)
  394. | (HUI8|HUI16|HI32|HF32|HF64), HNull ((HUI8|HUI16|HI32|HF32|HF64) as rt) ->
  395. let v = dyn_cast ctx v t rt in
  396. VDyn (v,rt)
  397. | HBool, HNull HBool ->
  398. VDyn (v,HBool)
  399. | _, HDyn ->
  400. make_dyn v t
  401. | _, HRef t2 when t = t2 ->
  402. VRef (RValue (ref v),t)
  403. | HFun (args1,t1), HFun (args2,t2) when List.length args1 = List.length args2 ->
  404. (match v with
  405. | VClosure (fn,farg) ->
  406. let get_conv t1 t2 =
  407. if safe_cast t1 t2 || (t2 = HDyn && is_dynamic t1) then CNo
  408. else if t2 = HDyn then CDyn t1
  409. else if t1 = HDyn then CUnDyn t2
  410. else CCast (t1,t2)
  411. in
  412. let conv = List.map2 get_conv args2 args1 in
  413. let rconv = get_conv t1 t2 in
  414. let convert v c =
  415. match c with
  416. | CNo -> v
  417. | CDyn t -> make_dyn v t
  418. | CUnDyn t -> dyn_cast ctx v HDyn t
  419. | CCast (t1,t2) -> dyn_cast ctx v t1 t2
  420. in
  421. VClosure (FNativeFun ("~convert",(fun args ->
  422. let args = List.map2 convert args conv in
  423. let ret = ctx.fcall fn (match farg with None -> args | Some a -> a :: args) in
  424. convert ret rconv
  425. ),rt),None)
  426. | _ ->
  427. assert false)
  428. | HDyn, HFun (targs,tret) when (match v with VVarArgs _ -> true | _ -> false) ->
  429. VClosure (FNativeFun ("~varargs",(fun args ->
  430. dyn_call ctx v (List.map2 (fun v t -> (v,t)) args targs) tret
  431. ),rt),None)
  432. | HDyn, _ ->
  433. (match get_type v with
  434. | None -> assert false
  435. | Some t -> dyn_cast ctx (match v with VDyn (v,_) -> v | _ -> v) t rt)
  436. | HNull t, _ ->
  437. (match v with
  438. | VDyn (v,t) -> dyn_cast ctx v t rt
  439. | _ -> assert false)
  440. | HObj _, HObj b when safe_cast rt t && (match get_type v with Some t -> safe_cast t rt | None -> assert false) ->
  441. (* downcast *)
  442. v
  443. | (HObj _ | HDynObj | HVirtual _), HVirtual vp ->
  444. to_virtual ctx v vp
  445. | HVirtual _, _ ->
  446. (match v with
  447. | VVirtual v -> dyn_cast ctx v.vvalue (match get_type v.vvalue with None -> assert false | Some t -> t) rt
  448. | _ -> assert false)
  449. | HObj p, _ ->
  450. (match get_method p "__cast" with
  451. | None -> invalid()
  452. | Some f ->
  453. if v = VNull then VNull else
  454. let ret = ctx.fcall (get_function ctx f) [v;VType rt] in
  455. if ret <> VNull && (match get_type ret with None -> assert false | Some vt -> safe_cast vt rt) then ret else invalid())
  456. | _ ->
  457. invalid()
  458. and dyn_call ctx v args tret =
  459. match v with
  460. | VClosure (f,a) ->
  461. let ft = (match f with FFun f -> f.ftype | FNativeFun (_,_,t) -> t) in
  462. let fargs, fret = (match ft with HFun (a,t) -> a, t | _ -> assert false) in
  463. let full_args = args and full_fargs = (match a with None -> fargs | Some _ -> List.tl fargs) in
  464. let rec loop args fargs =
  465. match args, fargs with
  466. | [], [] -> []
  467. | _, [] -> throw_msg ctx (Printf.sprintf "Too many arguments (%s) != (%s)" (String.concat "," (List.map (fun (v,_) -> vstr_d ctx v) full_args)) (String.concat "," (List.map tstr full_fargs)))
  468. | (v,t) :: args, ft :: fargs -> dyn_cast ctx v t ft :: loop args fargs
  469. | [], _ :: fargs -> default ft :: loop args fargs
  470. in
  471. let vargs = loop args full_fargs in
  472. let v = ctx.fcall f (match a with None -> vargs | Some a -> a :: vargs) in
  473. dyn_cast ctx v fret tret
  474. | VNull ->
  475. null_access()
  476. | VVarArgs (f,a) ->
  477. let arr = VArray (Array.of_list (List.map (fun (v,t) -> make_dyn v t) args),HDyn) in
  478. dyn_call ctx (VClosure (f,a)) [arr,HArray] tret
  479. | _ ->
  480. throw_msg ctx (vstr_d ctx v ^ " cannot be called")
  481. let invalid_comparison = 255
  482. let rec dyn_compare ctx a at b bt =
  483. if a == b && (match at with HF32 | HF64 -> false | _ -> true) then 0 else
  484. let fcompare (a:float) (b:float) = if a = b then 0 else if a > b then 1 else if a < b then -1 else invalid_comparison in
  485. match a, b with
  486. | VInt a, VInt b -> Int32.compare a b
  487. | VInt a, VFloat b -> fcompare (Int32.to_float a) b
  488. | VFloat a, VInt b -> fcompare a (Int32.to_float b)
  489. | VFloat a, VFloat b -> fcompare a b
  490. | VBool a, VBool b -> compare a b
  491. | VNull, VNull -> 0
  492. | VType t1, VType t2 -> if tsame t1 t2 then 0 else 1
  493. | VNull, _ -> 1
  494. | _, VNull -> -1
  495. | VObj oa, VObj ob ->
  496. if oa == ob then 0 else
  497. (match get_method oa.oproto.pclass "__compare" with
  498. | None -> invalid_comparison
  499. | Some f -> (match ctx.fcall (get_function ctx f) [a;b] with VInt i -> Int32.to_int i | _ -> assert false));
  500. | VDyn (v,t), _ ->
  501. dyn_compare ctx v t b bt
  502. | _, VDyn (v,t) ->
  503. dyn_compare ctx a at v t
  504. | VVirtual v, _ ->
  505. dyn_compare ctx v.vvalue HDyn b bt
  506. | _, VVirtual v ->
  507. dyn_compare ctx a at v.vvalue HDyn
  508. | _ ->
  509. invalid_comparison
  510. let rec dyn_get_field ctx obj field rt =
  511. let get_with v t = dyn_cast ctx v t rt in
  512. match obj with
  513. | VDynObj d ->
  514. (try
  515. let idx = Hashtbl.find d.dfields field in
  516. get_with d.dvalues.(idx) d.dtypes.(idx)
  517. with Not_found ->
  518. default rt)
  519. | VObj o ->
  520. let default rt =
  521. match get_method o.oproto.pclass "__get_field" with
  522. | None -> default rt
  523. | Some f ->
  524. get_with (ctx.fcall (get_function ctx f) [obj; VInt (hash ctx field)]) HDyn
  525. in
  526. let rec loop p =
  527. try
  528. let fid = PMap.find field p.pfunctions in
  529. (match get_function ctx fid with
  530. | FFun fd as f -> get_with (VClosure (f,Some obj)) (match fd.ftype with HFun (_::args,t) -> HFun(args,t) | _ -> assert false)
  531. | FNativeFun _ -> assert false)
  532. with Not_found ->
  533. match p.psuper with
  534. | None -> default rt
  535. | Some p -> loop p
  536. in
  537. (try
  538. let idx, t = get_index field o.oproto.pclass in
  539. if idx < 0 then raise Not_found;
  540. get_with o.ofields.(idx) t
  541. with Not_found ->
  542. loop o.oproto.pclass)
  543. | VVirtual vp ->
  544. (match vp.vvalue with
  545. | VNull ->
  546. (try
  547. let idx = PMap.find field vp.vtype.vindex in
  548. match vp.vindexes.(idx) with
  549. | VFNone -> VNull
  550. | VFIndex i -> vp.vtable.(i)
  551. with Not_found ->
  552. VNull)
  553. | v -> dyn_get_field ctx v field rt)
  554. | VNull ->
  555. null_access()
  556. | _ ->
  557. throw_msg ctx "Invalid object access"
  558. let rebuild_virtuals ctx d =
  559. let old = d.dvirtuals in
  560. d.dvirtuals <- [];
  561. List.iter (fun v ->
  562. let v2 = (match to_virtual ctx (VDynObj d) v.vtype with VVirtual v -> v | _ -> assert false) in
  563. v.vindexes <- v2.vindexes;
  564. v.vtable <- d.dvalues;
  565. ) old;
  566. d.dvirtuals <- old
  567. let rec dyn_set_field ctx obj field v vt =
  568. let v, vt = (match vt with
  569. | HDyn ->
  570. (match get_type v with
  571. | None -> if v = VNull then VNull, HDyn else assert false
  572. | Some t -> (match v with VDyn (v,_) -> v | _ -> v), t)
  573. | t -> v, t
  574. ) in
  575. match obj with
  576. | VDynObj d ->
  577. (try
  578. let idx = Hashtbl.find d.dfields field in
  579. d.dvalues.(idx) <- v;
  580. if not (tsame d.dtypes.(idx) vt) then begin
  581. d.dtypes.(idx) <- vt;
  582. rebuild_virtuals ctx d;
  583. end;
  584. with Not_found ->
  585. let idx = Array.length d.dvalues in
  586. Hashtbl.add d.dfields field idx;
  587. let vals2 = Array.make (idx + 1) VNull in
  588. let types2 = Array.make (idx + 1) HVoid in
  589. Array.blit d.dvalues 0 vals2 0 idx;
  590. Array.blit d.dtypes 0 types2 0 idx;
  591. vals2.(idx) <- v;
  592. types2.(idx) <- vt;
  593. d.dvalues <- vals2;
  594. d.dtypes <- types2;
  595. rebuild_virtuals ctx d;
  596. )
  597. | VObj o ->
  598. (try
  599. let idx, t = get_index field o.oproto.pclass in
  600. if idx < 0 then raise Not_found;
  601. o.ofields.(idx) <- dyn_cast ctx v vt t
  602. with Not_found ->
  603. throw_msg ctx (o.oproto.pclass.pname ^ " has no field " ^ field))
  604. | VVirtual vp ->
  605. dyn_set_field ctx vp.vvalue field v vt
  606. | VNull ->
  607. null_access()
  608. | _ ->
  609. throw_msg ctx "Invalid object access"
  610. let make_stack ctx (f,pos) =
  611. let pos = !pos - 1 in
  612. try let fid, line = f.debug.(pos) in ctx.code.debugfiles.(fid), line with _ -> "???", 0
  613. let stack_frame ctx (f,pos) =
  614. let file, line = make_stack ctx (f,pos) in
  615. Printf.sprintf "%s:%d: Called from fun@%d @x%X" file line f.findex (!pos - 1)
  616. let virt_make_val v =
  617. let hfields = Hashtbl.create 0 in
  618. let ftypes = DynArray.create() in
  619. let values = DynArray.create() in
  620. Array.iteri (fun i idx ->
  621. match idx with
  622. | VFNone -> ()
  623. | VFIndex k ->
  624. let n, _, t = v.vtype.vfields.(i) in
  625. Hashtbl.add hfields n (DynArray.length values);
  626. DynArray.add values v.vtable.(k);
  627. DynArray.add ftypes t;
  628. ) v.vindexes;
  629. VDynObj {
  630. dfields = hfields;
  631. dtypes = DynArray.to_array ftypes;
  632. dvalues = DynArray.to_array values;
  633. dvirtuals = [v];
  634. }
  635. let rec vstr ctx v t =
  636. let vstr = vstr ctx in
  637. match v with
  638. | VNull -> "null"
  639. | VInt i -> Int32.to_string i
  640. | VInt64 i -> Int64.to_string i
  641. | VFloat f -> float_to_string f
  642. | VBool b -> if b then "true" else "false"
  643. | VDyn (v,t) ->
  644. vstr v t
  645. | VObj o ->
  646. (match get_to_string ctx o.oproto.pclass with
  647. | None -> "#" ^ o.oproto.pclass.pname
  648. | Some f -> vstr (ctx.fcall f [v]) HBytes)
  649. | VBytes b -> (try hl_to_caml b with _ -> "?" ^ String.escaped b)
  650. | VClosure (f,_) -> fstr f
  651. | VArray (a,t) -> "[" ^ String.concat ", " (Array.to_list (Array.map (fun v -> vstr v t) a)) ^ "]"
  652. | VUndef -> "undef"
  653. | VType t -> tstr t
  654. | VRef (r,t) -> "*" ^ (vstr (get_ref ctx r) t)
  655. | VVirtual v ->
  656. (match v.vvalue with
  657. | VNull ->
  658. vstr (virt_make_val v) HDyn
  659. | _ ->
  660. vstr v.vvalue HDyn)
  661. | VDynObj d ->
  662. (try
  663. let fid = Hashtbl.find d.dfields "__string" in
  664. (match d.dtypes.(fid) with HFun ([],HBytes) -> () | _ -> raise Not_found);
  665. vstr (dyn_call ctx d.dvalues.(fid) [] HBytes) HBytes
  666. with Not_found ->
  667. "{" ^ String.concat ", " (Hashtbl.fold (fun f i acc -> (f^":"^vstr d.dvalues.(i) d.dtypes.(i)) :: acc) d.dfields []) ^ "}")
  668. | VAbstract _ -> "abstract"
  669. | VEnum (e,i,vals) ->
  670. let n, _, pl = e.efields.(i) in
  671. if Array.length pl = 0 then
  672. n
  673. else
  674. let rec loop i =
  675. if i = Array.length pl then []
  676. else let v = vals.(i) in vstr v pl.(i) :: loop (i + 1)
  677. in
  678. n ^ "(" ^ String.concat "," (loop 0) ^ ")"
  679. | VVarArgs _ -> "varargs"
  680. let interp ctx f args =
  681. let func = get_function ctx in
  682. let spos = ctx.stack_pos in
  683. if spos + Array.length f.regs > Array.length ctx.stack then begin
  684. let nsize = spos + Array.length f.regs + 256 in
  685. let nstack = Array.make nsize VUndef in
  686. Array.blit ctx.stack 0 nstack 0 ctx.stack_pos;
  687. ctx.stack <- nstack;
  688. end;
  689. if ctx.checked then for i = 0 to Array.length f.regs - 1 do ctx.stack.(i + spos) <- VUndef; done;
  690. ctx.stack_pos <- spos + Array.length f.regs;
  691. let pos = ref 1 in
  692. ctx.call_stack <- (f,pos) :: ctx.call_stack;
  693. let fret = (match f.ftype with
  694. | HFun (fargs,fret) ->
  695. if ctx.checked && List.length fargs <> List.length args then error (Printf.sprintf "Invalid args: (%s) should be (%s)" (String.concat "," (List.map (vstr_d ctx) args)) (String.concat "," (List.map tstr fargs)));
  696. fret
  697. | _ -> assert false
  698. ) in
  699. let fcall = ctx.fcall in
  700. let rtype i = Array.unsafe_get f.regs i in
  701. let check v t id =
  702. if ctx.checked && not (is_compatible v t) then error (Printf.sprintf "Can't set %s(%s) with %s" (id()) (tstr t) (vstr_d ctx v))
  703. in
  704. let cached_string idx =
  705. try
  706. Hashtbl.find ctx.cached_strings idx
  707. with Not_found ->
  708. let s = caml_to_hl ctx.code.strings.(idx) in
  709. Hashtbl.add ctx.cached_strings idx s;
  710. s
  711. in
  712. let check_obj v o fid =
  713. if ctx.checked then match o with
  714. | VObj o ->
  715. let _, fields, _ = get_proto ctx o.oproto.pclass in
  716. check v fields.(fid) (fun() -> "obj field")
  717. | VVirtual vp ->
  718. let _,_, t = vp.vtype.vfields.(fid) in
  719. check v t (fun() -> "virtual field")
  720. | _ ->
  721. ()
  722. in
  723. let set r v =
  724. check v (rtype r) (fun() -> "register " ^ string_of_int r);
  725. Array.unsafe_set ctx.stack (r + spos) v
  726. in
  727. list_iteri set args;
  728. let get r = Array.unsafe_get ctx.stack (r + spos) in
  729. let global g = Array.unsafe_get ctx.t_globals g in
  730. let traps = ref [] in
  731. let numop iop fop a b =
  732. match rtype a with
  733. (* todo : sign-extend and mask after result for HUI8/16 *)
  734. | HUI8 | HUI16 | HI32 ->
  735. (match get a, get b with
  736. | VInt a, VInt b -> VInt (iop a b)
  737. | _ -> assert false)
  738. | HF32 | HF64 ->
  739. (match get a, get b with
  740. | VFloat a, VFloat b -> VFloat (fop a b)
  741. | _ -> assert false)
  742. | _ ->
  743. assert false
  744. in
  745. let iop f a b =
  746. match rtype a with
  747. (* todo : sign-extend and mask after result for HUI8/16 *)
  748. | HUI8 | HUI16 | HI32 ->
  749. (match get a, get b with
  750. | VInt a, VInt b -> VInt (f a b)
  751. | _ -> assert false)
  752. | _ ->
  753. assert false
  754. in
  755. let iunop iop r =
  756. match rtype r with
  757. | HUI8 | HUI16 | HI32 ->
  758. (match get r with
  759. | VInt a -> VInt (iop a)
  760. | _ -> assert false)
  761. | _ ->
  762. assert false
  763. in
  764. let ucompare a b =
  765. match a, b with
  766. | VInt a, VInt b ->
  767. let d = Int32.sub (Int32.shift_right_logical a 16) (Int32.shift_right_logical b 16) in
  768. Int32.to_int (if d = 0l then Int32.sub (Int32.logand a 0xFFFFl) (Int32.logand b 0xFFFFl) else d)
  769. | _ -> assert false
  770. in
  771. let vcompare ra rb op =
  772. let a = get ra in
  773. let b = get rb in
  774. let t = rtype ra in
  775. let r = dyn_compare ctx a t b t in
  776. if r = invalid_comparison then false else op r 0
  777. in
  778. let ufloat v =
  779. if v < 0l then Int32.to_float v +. 4294967296. else Int32.to_float v
  780. in
  781. let rec loop() =
  782. let op = Array.unsafe_get f.code (!pos) in
  783. incr pos;
  784. (match op with
  785. | OMov (a,b) -> set a (get b)
  786. | OInt (r,i) -> set r (VInt ctx.code.ints.(i))
  787. | OFloat (r,i) -> set r (VFloat (Array.unsafe_get ctx.code.floats i))
  788. | OString (r,s) -> set r (VBytes (cached_string s))
  789. | OBytes (r,s) -> set r (VBytes (ctx.code.strings.(s) ^ "\x00"))
  790. | OBool (r,b) -> set r (VBool b)
  791. | ONull r -> set r VNull
  792. | OAdd (r,a,b) -> set r (numop Int32.add ( +. ) a b)
  793. | OSub (r,a,b) -> set r (numop Int32.sub ( -. ) a b)
  794. | OMul (r,a,b) -> set r (numop Int32.mul ( *. ) a b)
  795. | OSDiv (r,a,b) -> set r (numop (fun a b -> if b = 0l then 0l else Int32.div a b) ( /. ) a b)
  796. | OUDiv (r,a,b) -> set r (iop (fun a b -> if b = 0l then 0l else Int32.of_float ((ufloat a) /. (ufloat b))) a b)
  797. | OSMod (r,a,b) -> set r (numop (fun a b -> if b = 0l then 0l else Int32.rem a b) mod_float a b)
  798. | OUMod (r,a,b) -> set r (iop (fun a b -> if b = 0l then 0l else Int32.of_float (mod_float (ufloat a) (ufloat b))) a b)
  799. | OShl (r,a,b) -> set r (iop (fun a b -> Int32.shift_left a (Int32.to_int b)) a b)
  800. | OSShr (r,a,b) -> set r (iop (fun a b -> Int32.shift_right a (Int32.to_int b)) a b)
  801. | OUShr (r,a,b) -> set r (iop (fun a b -> Int32.shift_right_logical a (Int32.to_int b)) a b)
  802. | OAnd (r,a,b) -> set r (iop Int32.logand a b)
  803. | OOr (r,a,b) -> set r (iop Int32.logor a b)
  804. | OXor (r,a,b) -> set r (iop Int32.logxor a b)
  805. | ONeg (r,v) -> set r (match get v with VInt v -> VInt (Int32.neg v) | VFloat f -> VFloat (-. f) | _ -> assert false)
  806. | ONot (r,v) -> set r (match get v with VBool b -> VBool (not b) | _ -> assert false)
  807. | OIncr r -> set r (iunop (fun i -> Int32.add i 1l) r)
  808. | ODecr r -> set r (iunop (fun i -> Int32.sub i 1l) r)
  809. | OCall0 (r,f) -> set r (fcall (func f) [])
  810. | OCall1 (r,f,r1) -> set r (fcall (func f) [get r1])
  811. | OCall2 (r,f,r1,r2) -> set r (fcall (func f) [get r1;get r2])
  812. | OCall3 (r,f,r1,r2,r3) -> set r (fcall (func f) [get r1;get r2;get r3])
  813. | OCall4 (r,f,r1,r2,r3,r4) -> set r (fcall (func f) [get r1;get r2;get r3;get r4])
  814. | OCallN (r,f,rl) -> set r (fcall (func f) (List.map get rl))
  815. | OGetGlobal (r,g) -> set r (global g)
  816. | OSetGlobal (g,r) ->
  817. let v = get r in
  818. check v ctx.code.globals.(g) (fun() -> "global " ^ string_of_int g);
  819. Array.unsafe_set ctx.t_globals g v
  820. | OJTrue (r,i) -> if get r = VBool true then pos := !pos + i
  821. | OJFalse (r,i) -> if get r = VBool false then pos := !pos + i
  822. | ORet r -> raise (Return (get r))
  823. | OJNull (r,i) -> if get r == VNull then pos := !pos + i
  824. | OJNotNull (r,i) -> if get r != VNull then pos := !pos + i
  825. | OJSLt (a,b,i) -> if vcompare a b (<) then pos := !pos + i
  826. | OJSGte (a,b,i) -> if vcompare a b (>=) then pos := !pos + i
  827. | OJSGt (a,b,i) -> if vcompare a b (>) then pos := !pos + i
  828. | OJSLte (a,b,i) -> if vcompare a b (<=) then pos := !pos + i
  829. | OJULt (a,b,i) -> if ucompare (get a) (get b) < 0 then pos := !pos + i
  830. | OJUGte (a,b,i) -> if ucompare (get a) (get b) >= 0 then pos := !pos + i
  831. | OJNotLt (a,b,i) -> if not (vcompare a b (<)) then pos := !pos + i
  832. | OJNotGte (a,b,i) -> if not (vcompare a b (>=)) then pos := !pos + i
  833. | OJEq (a,b,i) -> if vcompare a b (=) then pos := !pos + i
  834. | OJNotEq (a,b,i) -> if not (vcompare a b (=)) then pos := !pos + i
  835. | OJAlways i -> pos := !pos + i
  836. | OToDyn (r,a) -> set r (make_dyn (get a) f.regs.(a))
  837. | OToSFloat (r,a) -> set r (match get a with VInt v -> VFloat (Int32.to_float v) | VFloat _ as v -> v | _ -> assert false)
  838. | OToUFloat (r,a) -> set r (match get a with VInt v -> VFloat (ufloat v) | VFloat _ as v -> v | _ -> assert false)
  839. | OToInt (r,a) -> set r (match get a with VFloat v -> VInt (Int32.of_float v) | VInt i when rtype r = HI64 -> VInt64 (Int64.of_int32 i) | VInt _ as v -> v | _ -> assert false)
  840. | OLabel _ -> ()
  841. | ONew r ->
  842. set r (alloc_obj ctx (rtype r))
  843. | OField (r,o,fid) ->
  844. set r (match get o with
  845. | VObj v -> v.ofields.(fid)
  846. | VVirtual v as obj ->
  847. (match v.vindexes.(fid) with
  848. | VFNone -> dyn_get_field ctx obj (let n,_,_ = v.vtype.vfields.(fid) in n) (rtype r)
  849. | VFIndex i -> v.vtable.(i))
  850. | VNull -> null_access()
  851. | _ -> assert false)
  852. | OSetField (o,fid,r) ->
  853. let rv = get r in
  854. let o = get o in
  855. (match o with
  856. | VObj v ->
  857. check_obj rv o fid;
  858. v.ofields.(fid) <- rv
  859. | VVirtual v ->
  860. (match v.vindexes.(fid) with
  861. | VFNone ->
  862. dyn_set_field ctx o (let n,_,_ = v.vtype.vfields.(fid) in n) rv (rtype r)
  863. | VFIndex i ->
  864. check_obj rv o fid;
  865. v.vtable.(i) <- rv)
  866. | VNull -> null_access()
  867. | _ -> assert false)
  868. | OGetThis (r, fid) ->
  869. set r (match get 0 with VObj v -> v.ofields.(fid) | _ -> assert false)
  870. | OSetThis (fid, r) ->
  871. (match get 0 with
  872. | VObj v as o ->
  873. let rv = get r in
  874. check_obj rv o fid;
  875. v.ofields.(fid) <- rv
  876. | _ -> assert false)
  877. | OCallMethod (r,m,rl) ->
  878. (match get (List.hd rl) with
  879. | VObj v -> set r (fcall v.oproto.pmethods.(m) (List.map get rl))
  880. | VVirtual v ->
  881. let name, _, _ = v.vtype.vfields.(m) in
  882. (match v.vvalue with
  883. | VObj o as obj ->
  884. (try
  885. let m = PMap.find name o.oproto.pclass.pfunctions in
  886. set r (dyn_call ctx (VClosure (get_function ctx m,Some obj)) (List.map (fun r -> get r, rtype r) (List.tl rl)) (rtype r))
  887. with Not_found ->
  888. assert false)
  889. | VDynObj _ ->
  890. set r (dyn_call ctx v.vvalue (List.map (fun r -> get r, rtype r) (List.tl rl)) (rtype r))
  891. | _ ->
  892. assert false)
  893. | VNull -> null_access()
  894. | _ -> assert false)
  895. | OCallThis (r,m,rl) ->
  896. (match get 0 with
  897. | VObj v as o -> set r (fcall v.oproto.pmethods.(m) (o :: List.map get rl))
  898. | _ -> assert false)
  899. | OCallClosure (r,v,rl) ->
  900. if rtype v = HDyn then
  901. set r (dyn_call ctx (get v) (List.map (fun r -> get r, rtype r) rl) (rtype r))
  902. else (match get v with
  903. | VClosure (f,None) -> set r (fcall f (List.map get rl))
  904. | VClosure (f,Some arg) -> set r (fcall f (arg :: List.map get rl))
  905. | VNull -> null_access()
  906. | _ -> throw_msg ctx (vstr_d ctx (get v)))
  907. | OStaticClosure (r, fid) ->
  908. let f = get_function ctx fid in
  909. set r (VClosure (f,None))
  910. | OInstanceClosure (r, fid, v) ->
  911. let f = get_function ctx fid in
  912. set r (VClosure (f,Some (get v)))
  913. | OVirtualClosure (r, o, m) ->
  914. let m = (match get o with
  915. | VObj v as obj -> VClosure (v.oproto.pmethods.(m), Some obj)
  916. | VNull -> null_access()
  917. | VVirtual v ->
  918. let name, _, _ = v.vtype.vfields.(m) in
  919. (match v.vvalue with
  920. | VObj o as obj ->
  921. (try
  922. let m = PMap.find name o.oproto.pclass.pfunctions in
  923. VClosure (get_function ctx m, Some obj)
  924. with Not_found ->
  925. VNull)
  926. | _ -> assert false)
  927. | _ -> assert false
  928. ) in
  929. set r (if m = VNull then m else dyn_cast ctx m (match get_type m with None -> assert false | Some v -> v) (rtype r))
  930. | OThrow r ->
  931. throw ctx (get r)
  932. | ORethrow r ->
  933. ctx.call_stack <- List.rev ctx.error_stack @ ctx.call_stack;
  934. throw ctx (get r)
  935. | OGetUI8 (r,b,p) ->
  936. (match get b, get p with
  937. | VBytes b, VInt p -> set r (VInt (Int32.of_int (int_of_char (String.get b (Int32.to_int p)))))
  938. | _ -> assert false)
  939. | OGetUI16 (r,b,p) ->
  940. (match get b, get p with
  941. | VBytes b, VInt p ->
  942. let a = int_of_char (String.get b (Int32.to_int p)) in
  943. let b = int_of_char (String.get b (Int32.to_int p + 1)) in
  944. set r (VInt (Int32.of_int (a lor (b lsl 8))))
  945. | _ -> assert false)
  946. | OGetMem (r,b,p) ->
  947. (match get b, get p with
  948. | VBytes b, VInt p ->
  949. let p = Int32.to_int p in
  950. set r (match rtype r with
  951. | HI32 -> VInt (get_i32 b p)
  952. | HI64 -> VInt64 (get_i64 b p)
  953. | HF32 -> VFloat (Int32.float_of_bits (get_i32 b p))
  954. | HF64 -> VFloat (Int64.float_of_bits (get_i64 b p))
  955. | _ -> assert false)
  956. | _ ->
  957. assert false)
  958. | OGetArray (r,a,i) ->
  959. (match get a, get i with
  960. | VArray (a,_), VInt i -> set r a.(Int32.to_int i)
  961. | _ -> assert false);
  962. | OSetUI8 (r,p,v) ->
  963. (match get r, get p, get v with
  964. | VBytes b, VInt p, VInt v -> Bytes.set (Bytes.unsafe_of_string b) (Int32.to_int p) (char_of_int ((Int32.to_int v) land 0xFF))
  965. | _ -> assert false)
  966. | OSetUI16 (r,p,v) ->
  967. (match get r, get p, get v with
  968. | VBytes b, VInt p, VInt v ->
  969. Bytes.set (Bytes.unsafe_of_string b) (Int32.to_int p) (char_of_int ((Int32.to_int v) land 0xFF));
  970. Bytes.set (Bytes.unsafe_of_string b) (Int32.to_int p + 1) (char_of_int (((Int32.to_int v) lsr 8) land 0xFF))
  971. | _ -> assert false)
  972. | OSetMem (r,p,v) ->
  973. (match get r, get p with
  974. | VBytes b, VInt p ->
  975. let p = Int32.to_int p in
  976. (match rtype v, get v with
  977. | HI32, VInt v -> set_i32 b p v
  978. | HI64, VInt64 v -> set_i64 b p v
  979. | HF32, VFloat f -> set_i32 b p (Int32.bits_of_float f)
  980. | HF64, VFloat f -> set_i64 b p (Int64.bits_of_float f)
  981. | _ -> assert false)
  982. | _ ->
  983. assert false)
  984. | OSetArray (a,i,v) ->
  985. (match get a, get i with
  986. | VArray (a,t), VInt i ->
  987. let v = get v in
  988. check v t (fun() -> "array");
  989. let idx = Int32.to_int i in
  990. if ctx.checked && (idx < 0 || idx >= Array.length a) then error (Printf.sprintf "Can't set array index %d with %s" idx (vstr_d ctx v));
  991. a.(Int32.to_int i) <- v
  992. | _ -> assert false);
  993. | OSafeCast (r, v) ->
  994. set r (dyn_cast ctx (get v) (rtype v) (rtype r))
  995. | OUnsafeCast (r,v) ->
  996. set r (get v)
  997. | OArraySize (r,a) ->
  998. (match get a with
  999. | VArray (a,_) -> set r (VInt (Int32.of_int (Array.length a)));
  1000. | _ -> assert false)
  1001. | OType (r,t) ->
  1002. set r (VType t)
  1003. | OGetType (r,v) ->
  1004. let v = get v in
  1005. let v = (match v with VVirtual { vvalue = VNull } -> assert false | VVirtual v -> v.vvalue | _ -> v) in
  1006. set r (VType (if v = VNull then HVoid else match get_type v with None -> assert false | Some t -> t));
  1007. | OGetTID (r,v) ->
  1008. set r (match get v with
  1009. | VType t ->
  1010. (VInt (Int32.of_int (match t with
  1011. | HVoid -> 0
  1012. | HUI8 -> 1
  1013. | HUI16 -> 2
  1014. | HI32 -> 3
  1015. | HI64 -> 4
  1016. | HF32 -> 5
  1017. | HF64 -> 6
  1018. | HBool -> 7
  1019. | HBytes -> 8
  1020. | HDyn -> 9
  1021. | HFun _ -> 10
  1022. | HObj _ -> 11
  1023. | HArray -> 12
  1024. | HType -> 13
  1025. | HRef _ -> 14
  1026. | HVirtual _ -> 15
  1027. | HDynObj -> 16
  1028. | HAbstract _ -> 17
  1029. | HEnum _ -> 18
  1030. | HNull _ -> 19)))
  1031. | _ -> assert false);
  1032. | ORef (r,v) ->
  1033. set r (VRef (RStack (v + spos),rtype v))
  1034. | OUnref (v,r) ->
  1035. set v (match get r with
  1036. | VRef (r,_) -> get_ref ctx r
  1037. | _ -> assert false)
  1038. | OSetref (r,v) ->
  1039. (match get r with
  1040. | VRef (r,t) ->
  1041. let v = get v in
  1042. check v t (fun() -> "ref");
  1043. set_ref ctx r v
  1044. | _ -> assert false)
  1045. | OToVirtual (r,rv) ->
  1046. set r (to_virtual ctx (get rv) (match rtype r with HVirtual vp -> vp | _ -> assert false))
  1047. | ODynGet (r,o,f) ->
  1048. set r (dyn_get_field ctx (get o) ctx.code.strings.(f) (rtype r))
  1049. | ODynSet (o,fid,vr) ->
  1050. dyn_set_field ctx (get o) ctx.code.strings.(fid) (get vr) (rtype vr)
  1051. | OMakeEnum (r,e,pl) ->
  1052. set r (VEnum ((match rtype r with HEnum e -> e | _ -> assert false),e,Array.map get (Array.of_list pl)))
  1053. | OEnumAlloc (r,f) ->
  1054. (match rtype r with
  1055. | HEnum e ->
  1056. let _, _, fl = e.efields.(f) in
  1057. let vl = Array.create (Array.length fl) VUndef in
  1058. set r (VEnum (e, f, vl))
  1059. | _ -> assert false
  1060. )
  1061. | OEnumIndex (r,v) ->
  1062. (match get v with
  1063. | VEnum (_,i,_) -> set r (VInt (Int32.of_int i))
  1064. | _ -> assert false)
  1065. | OEnumField (r, v, _, i) ->
  1066. (match get v with
  1067. | VEnum (_,_,vl) -> set r vl.(i)
  1068. | _ -> assert false)
  1069. | OSetEnumField (v, i, r) ->
  1070. (match get v, rtype v with
  1071. | VEnum (_,id,vl), HEnum e ->
  1072. let rv = get r in
  1073. let _, _, fields = e.efields.(id) in
  1074. check rv fields.(i) (fun() -> "enumfield");
  1075. vl.(i) <- rv
  1076. | _ -> assert false)
  1077. | OSwitch (r, indexes, _) ->
  1078. (match get r with
  1079. | VInt i ->
  1080. let i = Int32.to_int i in
  1081. if i >= 0 && i < Array.length indexes then pos := !pos + indexes.(i)
  1082. | _ -> assert false)
  1083. | ONullCheck r ->
  1084. if get r = VNull then throw_msg ctx "Null access"
  1085. | OTrap (r,j) ->
  1086. let target = !pos + j in
  1087. traps := (r,target) :: !traps
  1088. | OEndTrap _ ->
  1089. traps := List.tl !traps
  1090. | OAssert _ ->
  1091. throw_msg ctx "Assert"
  1092. | ORefData (r,d) ->
  1093. (match get d with
  1094. | VArray (a,t) -> set r (VRef (RArray (a,0),t))
  1095. | _ -> assert false)
  1096. | ORefOffset (r,r2,off) ->
  1097. (match get r2, get off with
  1098. | VRef (RArray (a,pos),t), VInt i -> set r (VRef (RArray (a,pos + Int32.to_int i),t))
  1099. | _ -> assert false)
  1100. | ONop _ ->
  1101. ()
  1102. );
  1103. loop()
  1104. in
  1105. let rec exec() =
  1106. try
  1107. loop()
  1108. with
  1109. | Return v ->
  1110. check v fret (fun() -> "return value");
  1111. ctx.call_stack <- List.tl ctx.call_stack;
  1112. ctx.stack_pos <- spos;
  1113. v
  1114. | InterpThrow v ->
  1115. match !traps with
  1116. | [] ->
  1117. ctx.error_stack <- List.hd ctx.call_stack :: ctx.error_stack;
  1118. ctx.call_stack <- List.tl ctx.call_stack;
  1119. raise (InterpThrow v)
  1120. | (r,target) :: tl ->
  1121. traps := tl;
  1122. ctx.error_stack <- (f,ref !pos) :: ctx.error_stack;
  1123. pos := target;
  1124. ctx.stack_pos <- spos + Array.length f.regs;
  1125. set r v;
  1126. exec()
  1127. in
  1128. pos := 0;
  1129. exec()
  1130. let call_fun ctx f args =
  1131. match f with
  1132. | FFun f -> interp ctx f args
  1133. | FNativeFun (_,f,_) ->
  1134. try
  1135. f args
  1136. with InterpThrow v ->
  1137. raise (InterpThrow v)
  1138. | Failure msg ->
  1139. throw_msg ctx msg
  1140. | Sys_exit _ as exc ->
  1141. raise exc
  1142. | e ->
  1143. throw_msg ctx (Printexc.to_string e)
  1144. let call_wrap ?(final=(fun()->())) ctx f args =
  1145. let old_st = ctx.call_stack in
  1146. let old_pos = ctx.stack_pos in
  1147. let restore() =
  1148. ctx.call_stack <- old_st;
  1149. ctx.stack_pos <- old_pos;
  1150. in
  1151. try
  1152. let v = call_fun ctx f args in
  1153. final();
  1154. v
  1155. with
  1156. | InterpThrow v ->
  1157. restore();
  1158. final();
  1159. ctx.on_error v (List.rev ctx.error_stack);
  1160. VNull
  1161. | Runtime_error msg ->
  1162. let stack = ctx.call_stack in
  1163. restore();
  1164. final();
  1165. ctx.on_error (VBytes (caml_to_hl ("HL Interp error " ^ msg))) stack;
  1166. VNull
  1167. (* ------------------------------- HL RUNTIME ---------------------------------------------- *)
  1168. let load_native ctx lib name t =
  1169. let unresolved() = (fun args -> error ("Unresolved native " ^ lib ^ "@" ^ name)) in
  1170. let int = Int32.to_int in
  1171. let to_int i = VInt (Int32.of_int i) in
  1172. let date d =
  1173. Unix.localtime (Int32.to_float d)
  1174. in
  1175. let to_date d =
  1176. let t, _ = Unix.mktime d in
  1177. VInt (Int32.of_float t)
  1178. in
  1179. let hl_to_caml_sub str pos len =
  1180. hl_to_caml (String.sub str pos len ^ "\x00\x00")
  1181. in
  1182. let no_virtual v =
  1183. match v with
  1184. | VVirtual v when v.vvalue <> VNull -> v.vvalue
  1185. | _ -> v
  1186. in
  1187. let set_ref = set_ref ctx in
  1188. let f = (match lib with
  1189. | "std" ->
  1190. (match name with
  1191. | "alloc_bytes" ->
  1192. (function
  1193. | [VInt i] -> VBytes (Bytes.unsafe_to_string (Bytes.create (int i)))
  1194. | _ -> assert false)
  1195. | "alloc_array" ->
  1196. (function
  1197. | [VType t;VInt i] -> VArray (Array.create (int i) (default t),t)
  1198. | _ -> assert false)
  1199. | "alloc_obj" ->
  1200. (function
  1201. | [VType t] -> alloc_obj ctx t
  1202. | _ -> assert false)
  1203. | "alloc_enum_dyn" ->
  1204. (function
  1205. | [VType (HEnum e); VInt idx; VArray (vl,vt); VInt len] ->
  1206. let idx = int idx in
  1207. let len = int len in
  1208. let _, _, args = e.efields.(idx) in
  1209. if Array.length args <> len then
  1210. VNull
  1211. else
  1212. VEnum (e,idx,Array.mapi (fun i v -> dyn_cast ctx v vt args.(i)) (Array.sub vl 0 len))
  1213. | vl ->
  1214. assert false)
  1215. | "array_blit" ->
  1216. (function
  1217. | [VArray (dst,_); VInt dp; VArray (src,_); VInt sp; VInt len] ->
  1218. Array.blit src (int sp) dst (int dp) (int len);
  1219. VUndef
  1220. | _ -> assert false)
  1221. | "bytes_blit" ->
  1222. (function
  1223. | [VBytes dst; VInt dp; VBytes src; VInt sp; VInt len] ->
  1224. String.blit src (int sp) (Bytes.unsafe_of_string dst) (int dp) (int len);
  1225. VUndef
  1226. | [(VBytes _ | VNull); VInt _; (VBytes _ | VNull); VInt _; VInt len] ->
  1227. if len = 0l then VUndef else error "bytes_blit to NULL bytes";
  1228. | _ -> assert false)
  1229. | "bsort_i32" ->
  1230. (function
  1231. | [VBytes b; VInt pos; VInt len; VClosure (f,c)] ->
  1232. let pos = int pos and len = int len in
  1233. let a = Array.init len (fun i -> get_i32 b (pos + i * 4)) in
  1234. Array.stable_sort (fun a b ->
  1235. match ctx.fcall f (match c with None -> [VInt a;VInt b] | Some v -> [v;VInt a;VInt b]) with
  1236. | VInt i -> int i
  1237. | _ -> assert false
  1238. ) a;
  1239. Array.iteri (fun i v -> set_i32 b (pos + i * 4) v) a;
  1240. VUndef;
  1241. | _ ->
  1242. assert false)
  1243. | "bsort_f64" ->
  1244. (function
  1245. | [VBytes b; VInt pos; VInt len; VClosure _] ->
  1246. assert false
  1247. | _ ->
  1248. assert false)
  1249. | "itos" ->
  1250. (function
  1251. | [VInt v; VRef (r,_)] ->
  1252. let str = Int32.to_string v in
  1253. set_ref r (to_int (String.length str));
  1254. VBytes (caml_to_hl str)
  1255. | _ -> assert false);
  1256. | "ftos" ->
  1257. (function
  1258. | [VFloat f; VRef (r,_)] ->
  1259. let str = float_to_string f in
  1260. set_ref r (to_int (String.length str));
  1261. VBytes (caml_to_hl str)
  1262. | _ -> assert false);
  1263. | "value_to_string" ->
  1264. (function
  1265. | [v; VRef (r,_)] ->
  1266. let str = caml_to_hl (vstr ctx v HDyn) in
  1267. set_ref r (to_int ((String.length str) lsr 1 - 1));
  1268. VBytes str
  1269. | _ -> assert false);
  1270. | "math_isnan" -> (function [VFloat f] -> VBool (classify_float f = FP_nan) | _ -> assert false)
  1271. | "math_isfinite" -> (function [VFloat f] -> VBool (match classify_float f with FP_infinite | FP_nan -> false | _ -> true) | _ -> assert false)
  1272. | "math_round" -> (function [VFloat f] -> VInt (Int32.of_float (floor (f +. 0.5))) | _ -> assert false)
  1273. | "math_floor" -> (function [VFloat f] -> VInt (Int32.of_float (floor f)) | _ -> assert false)
  1274. | "math_ceil" -> (function [VFloat f] -> VInt (Int32.of_float (ceil f)) | _ -> assert false)
  1275. | "math_ffloor" -> (function [VFloat f] -> VFloat (floor f) | _ -> assert false)
  1276. | "math_fceil" -> (function [VFloat f] -> VFloat (ceil f) | _ -> assert false)
  1277. | "math_fround" -> (function [VFloat f] -> VFloat (floor (f +. 0.5)) | _ -> assert false)
  1278. | "math_abs" -> (function [VFloat f] -> VFloat (abs_float f) | _ -> assert false)
  1279. | "math_sqrt" -> (function [VFloat f] -> VFloat (if f < 0. then nan else sqrt f) | _ -> assert false)
  1280. | "math_cos" -> (function [VFloat f] -> VFloat (cos f) | _ -> assert false)
  1281. | "math_sin" -> (function [VFloat f] -> VFloat (sin f) | _ -> assert false)
  1282. | "math_tan" -> (function [VFloat f] -> VFloat (tan f) | _ -> assert false)
  1283. | "math_acos" -> (function [VFloat f] -> VFloat (acos f) | _ -> assert false)
  1284. | "math_asin" -> (function [VFloat f] -> VFloat (asin f) | _ -> assert false)
  1285. | "math_atan" -> (function [VFloat f] -> VFloat (atan f) | _ -> assert false)
  1286. | "math_atan2" -> (function [VFloat a; VFloat b] -> VFloat (atan2 a b) | _ -> assert false)
  1287. | "math_log" -> (function [VFloat f] -> VFloat (Pervasives.log f) | _ -> assert false)
  1288. | "math_exp" -> (function [VFloat f] -> VFloat (exp f) | _ -> assert false)
  1289. | "math_pow" -> (function [VFloat a; VFloat b] -> VFloat (a ** b) | _ -> assert false)
  1290. | "parse_int" ->
  1291. (function
  1292. | [VBytes str; VInt pos; VInt len] ->
  1293. (try
  1294. let i = (match Interp.parse_int (hl_to_caml_sub str (int pos) (int len)) with
  1295. | Interp.VInt v -> Int32.of_int v
  1296. | Interp.VInt32 v -> v
  1297. | _ -> assert false
  1298. ) in
  1299. VDyn (VInt i,HI32)
  1300. with _ ->
  1301. VNull)
  1302. | l -> assert false)
  1303. | "parse_float" ->
  1304. (function
  1305. | [VBytes str; VInt pos; VInt len] -> (try VFloat (Interp.parse_float (hl_to_caml_sub str (int pos) (int len))) with _ -> VFloat nan)
  1306. | _ -> assert false)
  1307. | "dyn_compare" ->
  1308. (function
  1309. | [a;b] -> to_int (dyn_compare ctx a HDyn b HDyn)
  1310. | _ -> assert false)
  1311. | "fun_compare" ->
  1312. let ocompare o1 o2 =
  1313. match o1, o2 with
  1314. | None, None -> true
  1315. | Some o1, Some o2 -> o1 == o2
  1316. | _ -> false
  1317. in
  1318. (function
  1319. | [VClosure (FFun f1,o1);VClosure (FFun f2,o2)] -> VBool (f1 == f2 && ocompare o1 o2)
  1320. | [VClosure (FNativeFun (f1,_,_),o1);VClosure (FNativeFun (f2,_,_),o2)] -> VBool (f1 = f2 && ocompare o1 o2)
  1321. | _ -> VBool false)
  1322. | "array_type" ->
  1323. (function
  1324. | [VArray (_,t)] -> VType t
  1325. | _ -> assert false)
  1326. | "value_cast" ->
  1327. (function
  1328. | [v;VType t] -> if is_compatible v t then v else throw_msg ctx ("Cannot cast " ^ vstr_d ctx v ^ " to " ^ tstr t);
  1329. | _ -> assert false)
  1330. | "hballoc" ->
  1331. (function
  1332. | [] -> VAbstract (AHashBytes (Hashtbl.create 0))
  1333. | _ -> assert false)
  1334. | "hbset" ->
  1335. (function
  1336. | [VAbstract (AHashBytes h);VBytes b;v] ->
  1337. Hashtbl.replace h (hl_to_caml b) v;
  1338. VUndef
  1339. | _ -> assert false)
  1340. | "hbget" ->
  1341. (function
  1342. | [VAbstract (AHashBytes h);VBytes b] ->
  1343. (try Hashtbl.find h (hl_to_caml b) with Not_found -> VNull)
  1344. | _ -> assert false)
  1345. | "hbvalues" ->
  1346. (function
  1347. | [VAbstract (AHashBytes h)] ->
  1348. let values = Hashtbl.fold (fun _ v acc -> v :: acc) h [] in
  1349. VArray (Array.of_list values, HDyn)
  1350. | _ -> assert false)
  1351. | "hbkeys" ->
  1352. (function
  1353. | [VAbstract (AHashBytes h)] ->
  1354. let keys = Hashtbl.fold (fun s _ acc -> VBytes (caml_to_hl s) :: acc) h [] in
  1355. VArray (Array.of_list keys, HBytes)
  1356. | _ -> assert false)
  1357. | "hbexists" ->
  1358. (function
  1359. | [VAbstract (AHashBytes h);VBytes b] -> VBool (Hashtbl.mem h (hl_to_caml b))
  1360. | _ -> assert false)
  1361. | "hbremove" ->
  1362. (function
  1363. | [VAbstract (AHashBytes h);VBytes b] ->
  1364. let m = Hashtbl.mem h (hl_to_caml b) in
  1365. if m then Hashtbl.remove h (hl_to_caml b);
  1366. VBool m
  1367. | _ -> assert false)
  1368. | "hialloc" ->
  1369. (function
  1370. | [] -> VAbstract (AHashInt (Hashtbl.create 0))
  1371. | _ -> assert false)
  1372. | "hiset" ->
  1373. (function
  1374. | [VAbstract (AHashInt h);VInt i;v] ->
  1375. Hashtbl.replace h i v;
  1376. VUndef
  1377. | _ -> assert false)
  1378. | "higet" ->
  1379. (function
  1380. | [VAbstract (AHashInt h);VInt i] ->
  1381. (try Hashtbl.find h i with Not_found -> VNull)
  1382. | _ -> assert false)
  1383. | "hivalues" ->
  1384. (function
  1385. | [VAbstract (AHashInt h)] ->
  1386. let values = Hashtbl.fold (fun _ v acc -> v :: acc) h [] in
  1387. VArray (Array.of_list values, HDyn)
  1388. | _ -> assert false)
  1389. | "hikeys" ->
  1390. (function
  1391. | [VAbstract (AHashInt h)] ->
  1392. let keys = Hashtbl.fold (fun i _ acc -> VInt i :: acc) h [] in
  1393. VArray (Array.of_list keys, HI32)
  1394. | _ -> assert false)
  1395. | "hiexists" ->
  1396. (function
  1397. | [VAbstract (AHashInt h);VInt i] -> VBool (Hashtbl.mem h i)
  1398. | _ -> assert false)
  1399. | "hiremove" ->
  1400. (function
  1401. | [VAbstract (AHashInt h);VInt i] ->
  1402. let m = Hashtbl.mem h i in
  1403. if m then Hashtbl.remove h i;
  1404. VBool m
  1405. | _ -> assert false)
  1406. | "hoalloc" ->
  1407. (function
  1408. | [] -> VAbstract (AHashObject (ref []))
  1409. | _ -> assert false)
  1410. | "hoset" ->
  1411. (function
  1412. | [VAbstract (AHashObject l);o;v] ->
  1413. let o = no_virtual o in
  1414. let rec replace l =
  1415. match l with
  1416. | [] -> [o,v]
  1417. | (o2,_) :: l when o == o2 -> (o,v) :: l
  1418. | p :: l -> p :: replace l
  1419. in
  1420. l := replace !l;
  1421. VUndef
  1422. | _ -> assert false)
  1423. | "hoget" ->
  1424. (function
  1425. | [VAbstract (AHashObject l);o] ->
  1426. (try List.assq (no_virtual o) !l with Not_found -> VNull)
  1427. | _ -> assert false)
  1428. | "hovalues" ->
  1429. (function
  1430. | [VAbstract (AHashObject l)] ->
  1431. VArray (Array.of_list (List.map snd !l), HDyn)
  1432. | _ -> assert false)
  1433. | "hokeys" ->
  1434. (function
  1435. | [VAbstract (AHashObject l)] ->
  1436. VArray (Array.of_list (List.map fst !l), HDyn)
  1437. | _ -> assert false)
  1438. | "hoexists" ->
  1439. (function
  1440. | [VAbstract (AHashObject l);o] -> VBool (List.mem_assq (no_virtual o) !l)
  1441. | _ -> assert false)
  1442. | "horemove" ->
  1443. (function
  1444. | [VAbstract (AHashObject rl);o] ->
  1445. let rec loop acc = function
  1446. | [] -> false
  1447. | (o2,_) :: l when o == o2 ->
  1448. rl := (List.rev acc) @ l;
  1449. true
  1450. | p :: l -> loop (p :: acc) l
  1451. in
  1452. VBool (loop [] !rl)
  1453. | _ -> assert false)
  1454. | "sys_print" ->
  1455. (function
  1456. | [VBytes str] -> print_string (hl_to_caml str); VUndef
  1457. | _ -> assert false)
  1458. | "sys_time" ->
  1459. (function
  1460. | [] -> VFloat (Unix.gettimeofday())
  1461. | _ -> assert false)
  1462. | "sys_exit" ->
  1463. (function
  1464. | [VInt code] -> raise (Sys_exit (Int32.to_int code))
  1465. | _ -> assert false)
  1466. | "sys_utf8_path" ->
  1467. (function
  1468. | [] -> VBool true
  1469. | _ -> assert false)
  1470. | "sys_string" ->
  1471. let cached_sys_name = ref None in
  1472. (function
  1473. | [] ->
  1474. VBytes (caml_to_hl (match Sys.os_type with
  1475. | "Unix" ->
  1476. (match !cached_sys_name with
  1477. | Some n -> n
  1478. | None ->
  1479. let ic = Unix.open_process_in "uname" in
  1480. let uname = (match input_line ic with
  1481. | "Darwin" -> "Mac"
  1482. | n -> n
  1483. ) in
  1484. close_in ic;
  1485. cached_sys_name := Some uname;
  1486. uname)
  1487. | "Win32" | "Cygwin" -> "Windows"
  1488. | s -> s))
  1489. | _ ->
  1490. assert false)
  1491. | "sys_is64" ->
  1492. (function
  1493. | [] -> VBool (Sys.word_size = 64)
  1494. | _ -> assert false)
  1495. | "hash" ->
  1496. (function
  1497. | [VBytes str] -> VInt (hash ctx (hl_to_caml str))
  1498. | _ -> assert false)
  1499. | "type_safe_cast" ->
  1500. (function
  1501. | [VType a; VType b] -> VBool (safe_cast a b)
  1502. | _ -> assert false)
  1503. | "type_super" ->
  1504. (function
  1505. | [VType t] -> VType (match t with HObj { psuper = Some o } -> HObj o | _ -> HVoid)
  1506. | _ -> assert false)
  1507. | "type_args_count" ->
  1508. (function
  1509. | [VType t] -> to_int (match t with HFun (args,_) -> List.length args | _ -> 0)
  1510. | _ -> assert false)
  1511. | "type_get_global" ->
  1512. (function
  1513. | [VType t] ->
  1514. (match t with
  1515. | HObj c -> (match c.pclassglobal with None -> VNull | Some g -> ctx.t_globals.(g))
  1516. | HEnum e -> (match e.eglobal with None -> VNull | Some g -> ctx.t_globals.(g))
  1517. | _ -> VNull)
  1518. | _ -> assert false)
  1519. | "type_set_global" ->
  1520. (function
  1521. | [VType t; v] ->
  1522. VBool (match t with
  1523. | HObj c -> (match c.pclassglobal with None -> false | Some g -> ctx.t_globals.(g) <- v; true)
  1524. | HEnum e -> (match e.eglobal with None -> false | Some g -> ctx.t_globals.(g) <- v; true)
  1525. | _ -> false)
  1526. | _ -> assert false)
  1527. | "type_name" ->
  1528. (function
  1529. | [VType t] ->
  1530. VBytes (caml_to_hl (match t with
  1531. | HObj o -> o.pname
  1532. | HEnum e -> e.ename
  1533. | _ -> assert false))
  1534. | _ -> assert false)
  1535. | "obj_fields" ->
  1536. let rec get_fields v isRec =
  1537. match v with
  1538. | VDynObj o ->
  1539. VArray (Array.of_list (Hashtbl.fold (fun n _ acc -> VBytes (caml_to_hl n) :: acc) o.dfields []), HBytes)
  1540. | VObj o ->
  1541. let rec loop p =
  1542. let fields = Array.map (fun (n,_,_) -> VBytes (caml_to_hl n)) p.pfields in
  1543. match p.psuper with Some p when isRec -> fields :: loop p | _ -> [fields]
  1544. in
  1545. VArray (Array.concat (loop o.oproto.pclass), HBytes)
  1546. | VVirtual v ->
  1547. get_fields v.vvalue isRec
  1548. | _ ->
  1549. VNull
  1550. in
  1551. (function
  1552. | [v] -> get_fields v true
  1553. | _ -> assert false)
  1554. | "obj_copy" ->
  1555. (function
  1556. | [VDynObj d | VVirtual { vvalue = VDynObj d }] ->
  1557. VDynObj { dfields = Hashtbl.copy d.dfields; dvalues = Array.copy d.dvalues; dtypes = Array.copy d.dtypes; dvirtuals = [] }
  1558. | [_] -> VNull
  1559. | _ -> assert false)
  1560. | "enum_parameters" ->
  1561. (function
  1562. | [VEnum (e,idx,pl)] ->
  1563. let _,_, ptypes = e.efields.(idx) in
  1564. VArray (Array.mapi (fun i v -> make_dyn v ptypes.(i)) pl,HDyn)
  1565. | _ ->
  1566. assert false)
  1567. | "type_instance_fields" ->
  1568. (function
  1569. | [VType t] ->
  1570. (match t with
  1571. | HObj o ->
  1572. let rec fields o =
  1573. let sup = (match o.psuper with None -> [||] | Some o -> fields o) in
  1574. Array.concat [
  1575. sup;
  1576. Array.map (fun (s,_,_) -> VBytes (caml_to_hl s)) o.pfields;
  1577. Array.of_list (Array.fold_left (fun acc f ->
  1578. let is_override = (match o.psuper with None -> false | Some p -> try ignore(get_index f.fname p); true with Not_found -> false) in
  1579. if is_override then acc else VBytes (caml_to_hl f.fname) :: acc
  1580. ) [] o.pproto)
  1581. ]
  1582. in
  1583. VArray (fields o,HBytes)
  1584. | _ -> VNull)
  1585. | _ -> assert false)
  1586. | "type_enum_fields" ->
  1587. (function
  1588. | [VType t] ->
  1589. (match t with
  1590. | HEnum e -> VArray (Array.map (fun (f,_,_) -> VBytes (caml_to_hl f)) e.efields,HBytes)
  1591. | _ -> VNull)
  1592. | _ -> assert false)
  1593. | "type_enum_values" ->
  1594. (function
  1595. | [VType (HEnum e)] ->
  1596. VArray (Array.mapi (fun i (_,_,args) -> if Array.length args <> 0 then VNull else VEnum (e,i,[||])) e.efields,HDyn)
  1597. | _ -> assert false)
  1598. | "type_enum_eq" ->
  1599. (function
  1600. | [VEnum _; VNull] | [VNull; VEnum _] -> VBool false
  1601. | [VNull; VNull] -> VBool true
  1602. | [VEnum (e1,_,_) as v1; VEnum (e2,_,_) as v2] ->
  1603. let rec loop v1 v2 e =
  1604. match v1, v2 with
  1605. | VEnum (_,t1,_), VEnum (_,t2,_) when t1 <> t2 -> false
  1606. | VEnum (_,t,vl1), VEnum (_,_,vl2) ->
  1607. let _, _, pl = e.efields.(t) in
  1608. let rec chk i =
  1609. if i = Array.length pl then true
  1610. else
  1611. (match pl.(i) with
  1612. | HEnum e -> loop vl1.(i) vl2.(i) e
  1613. | t -> dyn_compare ctx vl1.(i) t vl2.(i) t = 0) && chk (i + 1)
  1614. in
  1615. chk 0
  1616. | _ -> assert false
  1617. in
  1618. VBool (if e1 != e2 then false else loop v1 v2 e1)
  1619. | _ -> assert false)
  1620. | "obj_get_field" ->
  1621. (function
  1622. | [o;VInt hash] ->
  1623. let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in
  1624. (match o with
  1625. | VObj _ | VDynObj _ | VVirtual _ -> dyn_get_field ctx o f HDyn
  1626. | _ -> VNull)
  1627. | _ -> assert false)
  1628. | "obj_set_field" ->
  1629. (function
  1630. | [o;VInt hash;v] ->
  1631. let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in
  1632. dyn_set_field ctx o f v HDyn;
  1633. VUndef
  1634. | _ -> assert false)
  1635. | "obj_has_field" ->
  1636. (function
  1637. | [o;VInt hash] ->
  1638. let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in
  1639. let rec loop o =
  1640. match o with
  1641. | VDynObj d -> Hashtbl.mem d.dfields f
  1642. | VObj o ->
  1643. let rec loop p =
  1644. if PMap.mem f p.pindex then let idx, _ = PMap.find f p.pindex in idx >= 0 else match p.psuper with None -> false | Some p -> loop p
  1645. in
  1646. loop o.oproto.pclass
  1647. | VVirtual v -> loop v.vvalue
  1648. | _ -> false
  1649. in
  1650. VBool (loop o)
  1651. | _ -> assert false)
  1652. | "obj_delete_field" ->
  1653. (function
  1654. | [o;VInt hash] ->
  1655. let f = (try Hashtbl.find ctx.cached_hashes hash with Not_found -> assert false) in
  1656. let rec loop o =
  1657. match o with
  1658. | VDynObj d when Hashtbl.mem d.dfields f ->
  1659. let idx = Hashtbl.find d.dfields f in
  1660. let count = Array.length d.dvalues in
  1661. Hashtbl.remove d.dfields f;
  1662. let fields = Hashtbl.fold (fun name i acc -> (name,if i < idx then i else i - 1) :: acc) d.dfields [] in
  1663. Hashtbl.clear d.dfields;
  1664. List.iter (fun (n,i) -> Hashtbl.add d.dfields n i) fields;
  1665. let vals2 = Array.make (count - 1) VNull in
  1666. let types2 = Array.make (count - 1) HVoid in
  1667. let len = count - idx - 1 in
  1668. Array.blit d.dvalues 0 vals2 0 idx;
  1669. Array.blit d.dvalues (idx + 1) vals2 idx len;
  1670. Array.blit d.dtypes 0 types2 0 idx;
  1671. Array.blit d.dtypes (idx + 1) types2 idx len;
  1672. d.dvalues <- vals2;
  1673. d.dtypes <- types2;
  1674. rebuild_virtuals ctx d;
  1675. true
  1676. | VVirtual v -> loop v.vvalue
  1677. | _ -> false
  1678. in
  1679. VBool (loop o)
  1680. | _ -> assert false)
  1681. | "get_virtual_value" ->
  1682. (function
  1683. | [VVirtual v] -> v.vvalue
  1684. | _ -> assert false)
  1685. | "ucs2length" ->
  1686. (function
  1687. | [VBytes s; VInt pos] ->
  1688. let delta = int pos in
  1689. let rec loop p =
  1690. let c = int_of_char s.[p+delta] lor ((int_of_char s.[p+delta+1]) lsl 8) in
  1691. if c = 0 then p lsr 1 else loop (p + 2)
  1692. in
  1693. to_int (loop 0)
  1694. | _ -> assert false)
  1695. | "utf8_to_utf16" ->
  1696. (function
  1697. | [VBytes s; VInt pos; VRef (r,HI32)] ->
  1698. let s = String.sub s (int pos) (String.length s - (int pos)) in
  1699. let u16 = caml_to_hl (try String.sub s 0 (String.index s '\000') with Not_found -> assert false) in
  1700. set_ref r (to_int (String.length u16 - 2));
  1701. VBytes u16
  1702. | _ -> assert false)
  1703. | "utf16_to_utf8" ->
  1704. (function
  1705. | [VBytes s; VInt pos; VRef (r,HI32)] ->
  1706. let s = String.sub s (int pos) (String.length s - (int pos)) in
  1707. let u8 = hl_to_caml s in
  1708. set_ref r (to_int (String.length u8));
  1709. VBytes (u8 ^ "\x00")
  1710. | _ -> assert false)
  1711. | "ucs2_upper" ->
  1712. (function
  1713. | [VBytes s; VInt pos; VInt len] ->
  1714. let buf = Buffer.create 0 in
  1715. utf16_iter (fun c ->
  1716. let c =
  1717. if c >= int_of_char 'a' && c <= int_of_char 'z' then c + int_of_char 'A' - int_of_char 'a'
  1718. else c
  1719. in
  1720. utf16_add buf c
  1721. ) (String.sub s (int pos) ((int len) lsl 1));
  1722. utf16_add buf 0;
  1723. VBytes (Buffer.contents buf)
  1724. | _ -> assert false)
  1725. | "ucs2_lower" ->
  1726. (function
  1727. | [VBytes s; VInt pos; VInt len] ->
  1728. let buf = Buffer.create 0 in
  1729. utf16_iter (fun c ->
  1730. let c =
  1731. if c >= int_of_char 'A' && c <= int_of_char 'Z' then c + int_of_char 'a' - int_of_char 'A'
  1732. else c
  1733. in
  1734. utf16_add buf c
  1735. ) (String.sub s (int pos) ((int len) lsl 1));
  1736. utf16_add buf 0;
  1737. VBytes (Buffer.contents buf)
  1738. | _ -> assert false)
  1739. | "url_encode" ->
  1740. (function
  1741. | [VBytes s; VRef (r, HI32)] ->
  1742. let s = hl_to_caml s in
  1743. let buf = Buffer.create 0 in
  1744. let hex = "0123456789ABCDEF" in
  1745. for i = 0 to String.length s - 1 do
  1746. let c = String.unsafe_get s i in
  1747. match c with
  1748. | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' | '-' | '.' ->
  1749. utf16_char buf c
  1750. | _ ->
  1751. utf16_char buf '%';
  1752. utf16_char buf (String.unsafe_get hex (int_of_char c lsr 4));
  1753. utf16_char buf (String.unsafe_get hex (int_of_char c land 0xF));
  1754. done;
  1755. utf16_add buf 0;
  1756. let str = Buffer.contents buf in
  1757. set_ref r (to_int (String.length str lsr 1 - 1));
  1758. VBytes str
  1759. | _ -> assert false)
  1760. | "url_decode" ->
  1761. (function
  1762. | [VBytes s; VRef (r, HI32)] ->
  1763. let s = hl_to_caml s in
  1764. let b = Buffer.create 0 in
  1765. let len = String.length s in
  1766. let decode c =
  1767. match c with
  1768. | '0'..'9' -> Some (int_of_char c - int_of_char '0')
  1769. | 'a'..'f' -> Some (int_of_char c - int_of_char 'a' + 10)
  1770. | 'A'..'F' -> Some (int_of_char c - int_of_char 'A' + 10)
  1771. | _ -> None
  1772. in
  1773. let rec loop i =
  1774. if i = len then () else
  1775. let c = String.unsafe_get s i in
  1776. match c with
  1777. | '%' ->
  1778. let p1 = (try decode (String.get s (i + 1)) with _ -> None) in
  1779. let p2 = (try decode (String.get s (i + 2)) with _ -> None) in
  1780. (match p1, p2 with
  1781. | Some c1, Some c2 ->
  1782. Buffer.add_char b (char_of_int ((c1 lsl 4) lor c2));
  1783. loop (i + 3)
  1784. | _ ->
  1785. loop (i + 1));
  1786. | '+' ->
  1787. Buffer.add_char b ' ';
  1788. loop (i + 1)
  1789. | c ->
  1790. Buffer.add_char b c;
  1791. loop (i + 1)
  1792. in
  1793. loop 0;
  1794. let str = Buffer.contents b in
  1795. set_ref r (to_int (UTF8.length str));
  1796. VBytes (caml_to_hl str)
  1797. | _ -> assert false)
  1798. | "call_method" ->
  1799. (function
  1800. | [f;VArray (args,HDyn)] -> dyn_call ctx f (List.map (fun v -> v,HDyn) (Array.to_list args)) HDyn
  1801. | _ -> assert false)
  1802. | "no_closure" ->
  1803. (function
  1804. | [VClosure (f,_)] -> VClosure (f,None)
  1805. | _ -> assert false)
  1806. | "get_closure_value" ->
  1807. (function
  1808. | [VClosure (_,None)] -> VNull
  1809. | [VClosure (_,Some v)] -> v
  1810. | _ -> assert false)
  1811. | "make_var_args" ->
  1812. (function
  1813. | [VClosure (f,arg)] -> VVarArgs (f,arg)
  1814. | _ -> assert false)
  1815. | "bytes_find" ->
  1816. (function
  1817. | [VBytes src; VInt pos; VInt len; VBytes chk; VInt cpos; VInt clen; ] ->
  1818. to_int (try int pos + ExtString.String.find (String.sub src (int pos) (int len)) (String.sub chk (int cpos) (int clen)) with ExtString.Invalid_string -> -1)
  1819. | _ -> assert false)
  1820. | "bytes_compare" ->
  1821. (function
  1822. | [VBytes a; VInt apos; VBytes b; VInt bpos; VInt len] -> to_int (String.compare (String.sub a (int apos) (int len)) (String.sub b (int bpos) (int len)))
  1823. | _ -> assert false)
  1824. | "string_compare" ->
  1825. (function
  1826. | [VBytes a; VBytes b; VInt len] -> to_int (String.compare (String.sub a 0 ((int len) * 2)) (String.sub b 0 ((int len)*2)))
  1827. | _ -> assert false)
  1828. | "bytes_fill" ->
  1829. (function
  1830. | [VBytes a; VInt pos; VInt len; VInt v] ->
  1831. Bytes.fill (Bytes.unsafe_of_string a) (int pos) (int len) (char_of_int ((int v) land 0xFF));
  1832. VUndef
  1833. | _ -> assert false)
  1834. | "exception_stack" ->
  1835. (function
  1836. | [] -> VArray (Array.map (fun e -> VBytes (caml_to_hl (stack_frame ctx e))) (Array.of_list (List.rev ctx.error_stack)),HBytes)
  1837. | _ -> assert false)
  1838. | "date_new" ->
  1839. (function
  1840. | [VInt y; VInt mo; VInt d; VInt h; VInt m; VInt s] ->
  1841. let t = Unix.localtime (Unix.time()) in
  1842. let t = { t with
  1843. tm_year = int y - 1900;
  1844. tm_mon = int mo;
  1845. tm_mday = int d;
  1846. tm_hour = int h;
  1847. tm_min = int m;
  1848. tm_sec = int s;
  1849. } in
  1850. to_date t
  1851. | _ ->
  1852. assert false)
  1853. | "date_now" ->
  1854. (function
  1855. | [] -> to_date (Unix.localtime (Unix.time()))
  1856. | _ -> assert false)
  1857. | "date_get_time" ->
  1858. (function
  1859. | [VInt v] -> VFloat (fst (Unix.mktime (date v)) *. 1000.)
  1860. | _ -> assert false)
  1861. | "date_from_time" ->
  1862. (function
  1863. | [VFloat f] -> to_date (Unix.localtime (f /. 1000.))
  1864. | _ -> assert false)
  1865. | "date_get_inf" ->
  1866. (function
  1867. | [VInt d;year;month;day;hours;minutes;seconds;wday] ->
  1868. let d = date d in
  1869. let set r v =
  1870. match r with
  1871. | VNull -> ()
  1872. | VRef (r,HI32) -> set_ref r (to_int v)
  1873. | _ -> assert false
  1874. in
  1875. set year (d.tm_year + 1900);
  1876. set month d.tm_mon;
  1877. set day d.tm_mday;
  1878. set hours d.tm_hour;
  1879. set minutes d.tm_min;
  1880. set seconds d.tm_sec;
  1881. set wday d.tm_wday;
  1882. VUndef
  1883. | _ -> assert false)
  1884. | "date_to_string" ->
  1885. (function
  1886. | [VInt d; VRef (r,HI32)] ->
  1887. let t = date d in
  1888. let str = Printf.sprintf "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" (t.tm_year + 1900) (t.tm_mon + 1) t.tm_mday t.tm_hour t.tm_min t.tm_sec in
  1889. set_ref r (to_int (String.length str));
  1890. VBytes (caml_to_hl str)
  1891. | _ -> assert false)
  1892. | "rnd_init_system" ->
  1893. (function
  1894. | [] -> Random.self_init(); VAbstract ARandom
  1895. | _ -> assert false)
  1896. | "rnd_int" ->
  1897. (function
  1898. | [VAbstract ARandom] -> VInt (Int32.of_int (Random.bits()))
  1899. | _ -> assert false)
  1900. | "rnd_float" ->
  1901. (function
  1902. | [VAbstract ARandom] -> VFloat (Random.float 1.)
  1903. | _ -> assert false)
  1904. | "regexp_new_options" ->
  1905. (function
  1906. | [VBytes str; VBytes opt] ->
  1907. let case_sensitive = ref true in
  1908. List.iter (function
  1909. | 'm' -> () (* always ON ? *)
  1910. | 'i' -> case_sensitive := false
  1911. | c -> failwith ("Unsupported regexp option '" ^ String.make 1 c ^ "'")
  1912. ) (ExtString.String.explode (hl_to_caml opt));
  1913. let buf = Buffer.create 0 in
  1914. let rec loop prev esc = function
  1915. | [] -> ()
  1916. | c :: l when esc ->
  1917. (match c with
  1918. | 'n' -> Buffer.add_char buf '\n'
  1919. | 'r' -> Buffer.add_char buf '\r'
  1920. | 't' -> Buffer.add_char buf '\t'
  1921. | 's' -> Buffer.add_string buf "[ \t\r\n]"
  1922. | 'd' -> Buffer.add_string buf "[0-9]"
  1923. | '\\' -> Buffer.add_string buf "\\\\"
  1924. | '(' | ')' | '{' | '}' -> Buffer.add_char buf c
  1925. | '1'..'9' | '+' | '$' | '^' | '*' | '?' | '.' | '[' | ']' ->
  1926. Buffer.add_char buf '\\';
  1927. Buffer.add_char buf c;
  1928. | _ ->
  1929. Buffer.add_char buf c);
  1930. loop c false l
  1931. | c :: l ->
  1932. match c with
  1933. | '\\' -> loop prev true l
  1934. | '(' | '|' | ')' ->
  1935. Buffer.add_char buf '\\';
  1936. Buffer.add_char buf c;
  1937. loop c false l
  1938. | '?' when prev = '(' && (match l with ':' :: _ -> true | _ -> false) ->
  1939. failwith "Non capturing groups '(?:' are not supported in macros"
  1940. | '?' when prev = '*' ->
  1941. failwith "Ungreedy *? are not supported in macros"
  1942. | _ ->
  1943. Buffer.add_char buf c;
  1944. loop c false l
  1945. in
  1946. loop '\000' false (ExtString.String.explode (hl_to_caml str));
  1947. let str = Buffer.contents buf in
  1948. let r = {
  1949. r = if !case_sensitive then Str.regexp str else Str.regexp_case_fold str;
  1950. r_string = "";
  1951. r_groups = [||];
  1952. } in
  1953. VAbstract (AReg r)
  1954. | _ ->
  1955. assert false);
  1956. | "regexp_match" ->
  1957. (function
  1958. | [VAbstract (AReg r);VBytes str;VInt pos;VInt len] ->
  1959. let str = hl_to_caml str and pos = int pos and len = int len in
  1960. let nstr, npos, delta = (if len = String.length str - pos then str, pos, 0 else String.sub str pos len, 0, pos) in
  1961. (try
  1962. ignore(Str.search_forward r.r nstr npos);
  1963. let rec loop n =
  1964. if n = 9 then
  1965. []
  1966. else try
  1967. (Some (Str.group_beginning n + delta, Str.group_end n + delta)) :: loop (n + 1)
  1968. with Not_found ->
  1969. None :: loop (n + 1)
  1970. | Invalid_argument _ ->
  1971. []
  1972. in
  1973. r.r_string <- str;
  1974. r.r_groups <- Array.of_list (loop 0);
  1975. VBool true;
  1976. with Not_found ->
  1977. VBool false)
  1978. | _ -> assert false);
  1979. | "regexp_matched_pos" ->
  1980. (function
  1981. | [VAbstract (AReg r); VInt n; VRef (rr,HI32)] ->
  1982. let n = int n in
  1983. (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with
  1984. | None -> to_int (-1)
  1985. | Some (pos,pend) -> set_ref rr (to_int (pend - pos)); to_int pos)
  1986. | [VAbstract (AReg r); VInt n; VNull] ->
  1987. let n = int n in
  1988. (match (try r.r_groups.(n) with _ -> failwith ("Invalid group " ^ string_of_int n)) with
  1989. | None -> to_int (-1)
  1990. | Some (pos,pend) -> to_int pos)
  1991. | _ -> assert false)
  1992. | "make_macro_pos" ->
  1993. (function
  1994. | [VBytes file;VInt min;VInt max] ->
  1995. VAbstract (APos { Globals.pfile = String.sub file 0 (String.length file - 1); pmin = Int32.to_int min; pmax = Int32.to_int max })
  1996. | _ -> assert false)
  1997. | "dyn_op" ->
  1998. let op_names = [|"+";"-";"*";"%";"/";"<<";">>";">>>";"&";"|";"^"|] in
  1999. (function
  2000. | [VInt op; a; b] ->
  2001. let op = Int32.to_int op in
  2002. let is_number v =
  2003. match v with
  2004. | VNull -> true
  2005. | VDyn (_,t) -> is_number t
  2006. | _ -> false
  2007. in
  2008. let error() =
  2009. failwith ("Can't perform dyn op " ^ vstr ctx a HDyn ^ " " ^ op_names.(op) ^ " " ^ vstr ctx b HDyn)
  2010. in
  2011. let fop op =
  2012. if is_number a && is_number b then begin
  2013. let a = dyn_cast ctx a HDyn HF64 in
  2014. let b = dyn_cast ctx b HDyn HF64 in
  2015. match a, b with
  2016. | VFloat a, VFloat b -> VDyn (VFloat (op a b),HF64)
  2017. | _ -> assert false
  2018. end else
  2019. error();
  2020. in
  2021. let iop op =
  2022. if is_number a && is_number b then begin
  2023. let a = dyn_cast ctx a HDyn HI32 in
  2024. let b = dyn_cast ctx b HDyn HI32 in
  2025. match a, b with
  2026. | VInt a, VInt b -> VDyn (VInt (op a b),HI32)
  2027. | _ -> assert false
  2028. end else
  2029. error();
  2030. in
  2031. (match op with
  2032. | 0 -> fop ( +. )
  2033. | 1 -> fop ( -. )
  2034. | 2 -> fop ( *. )
  2035. | 3 -> fop mod_float
  2036. | 4 -> fop ( /. )
  2037. | 5 -> iop (fun a b -> Int32.shift_left a (Int32.to_int b))
  2038. | 6 -> iop (fun a b -> Int32.shift_right a (Int32.to_int b))
  2039. | 7 -> iop (fun a b -> Int32.shift_right_logical a (Int32.to_int b))
  2040. | 8 -> iop Int32.logand
  2041. | 9 -> iop Int32.logor
  2042. | 10 -> iop Int32.logxor
  2043. | _ -> assert false)
  2044. | _ -> assert false)
  2045. | _ ->
  2046. unresolved())
  2047. | "macro" ->
  2048. (match ctx.resolve_macro_api name with
  2049. | None -> unresolved()
  2050. | Some f -> f)
  2051. | _ ->
  2052. unresolved()
  2053. ) in
  2054. FNativeFun (lib ^ "@" ^ name, f, t)
  2055. let create checked =
  2056. let ctx = {
  2057. t_globals = [||];
  2058. t_functions = [||];
  2059. call_stack = [];
  2060. error_stack = [];
  2061. stack = [||];
  2062. stack_pos = 0;
  2063. cached_protos = Hashtbl.create 0;
  2064. cached_strings = Hashtbl.create 0;
  2065. cached_hashes = Hashtbl.create 0;
  2066. code = {
  2067. functions = [||];
  2068. globals = [||];
  2069. natives = [||];
  2070. strings = [||];
  2071. ints = [||];
  2072. debugfiles = [||];
  2073. floats = [||];
  2074. entrypoint = 0;
  2075. version = 0;
  2076. };
  2077. checked = checked;
  2078. fcall = (fun _ _ -> assert false);
  2079. on_error = (fun _ _ -> assert false);
  2080. resolve_macro_api = (fun _ -> None);
  2081. } in
  2082. ctx.on_error <- (fun msg stack -> failwith (vstr ctx msg HDyn ^ "\n" ^ String.concat "\n" (List.map (stack_frame ctx) stack)));
  2083. ctx.fcall <- call_fun ctx;
  2084. ctx
  2085. let set_error_handler ctx e =
  2086. ctx.on_error <- e
  2087. let set_macro_api ctx f =
  2088. ctx.resolve_macro_api <- f
  2089. let add_code ctx code =
  2090. (* expand global table *)
  2091. let globals = Array.map default code.globals in
  2092. Array.blit ctx.t_globals 0 globals 0 (Array.length ctx.t_globals);
  2093. ctx.t_globals <- globals;
  2094. (* expand function table *)
  2095. let nfunctions = Array.length code.functions + Array.length code.natives in
  2096. let functions = Array.create nfunctions (FNativeFun ("",(fun _ -> assert false),HDyn)) in
  2097. Array.blit ctx.t_functions 0 functions 0 (Array.length ctx.t_functions);
  2098. let rec loop i =
  2099. if i = Array.length code.natives then () else
  2100. let lib, name, t, idx = code.natives.(i) in
  2101. functions.(idx) <- load_native ctx code.strings.(lib) code.strings.(name) t;
  2102. loop (i + 1)
  2103. in
  2104. loop (Array.length ctx.code.natives);
  2105. let rec loop i =
  2106. if i = Array.length code.functions then () else
  2107. let fd = code.functions.(i) in
  2108. functions.(fd.findex) <- FFun fd;
  2109. loop (i + 1)
  2110. in
  2111. loop (Array.length ctx.code.functions);
  2112. ctx.t_functions <- functions;
  2113. ctx.code <- code;
  2114. (* call entrypoint *)
  2115. ignore(call_wrap ctx functions.(code.entrypoint) [])
  2116. (* ------------------------------- CHECK ---------------------------------------------- *)
  2117. let check code macros =
  2118. let ftypes = Array.create (Array.length code.natives + Array.length code.functions) HVoid in
  2119. let is_native_fun = Hashtbl.create 0 in
  2120. let check_fun f =
  2121. let pos = ref 0 in
  2122. let error msg =
  2123. let dfile, dline = f.debug.(!pos) in
  2124. let file = code.debugfiles.(dfile) in
  2125. let msg = Printf.sprintf "Check failure at fun@%d @%X - %s" f.findex (!pos) msg in
  2126. if macros then begin
  2127. let low = dline land 0xFFFFF in
  2128. let pos = {
  2129. Globals.pfile = file;
  2130. Globals.pmin = low;
  2131. Globals.pmax = low + (dline lsr 20);
  2132. } in
  2133. Common.abort msg pos
  2134. end else
  2135. failwith (Printf.sprintf "\n%s:%d: %s" file dline msg)
  2136. in
  2137. let targs, tret = (match f.ftype with HFun (args,ret) -> args, ret | _ -> assert false) in
  2138. let rtype i = try f.regs.(i) with _ -> HObj { null_proto with pname = "OUT_OF_BOUNDS:" ^ string_of_int i } in
  2139. let check t1 t2 =
  2140. if not (safe_cast t1 t2) then error (tstr t1 ^ " should be " ^ tstr t2)
  2141. in
  2142. let reg_inf r =
  2143. "Register " ^ string_of_int r ^ "(" ^ tstr (rtype r) ^ ")"
  2144. in
  2145. let reg r t =
  2146. if not (safe_cast (rtype r) t) then error (reg_inf r ^ " should be " ^ tstr t ^ " and not " ^ tstr (rtype r))
  2147. in
  2148. let numeric r =
  2149. match rtype r with
  2150. | HUI8 | HUI16 | HI32 | HI64 | HF32 | HF64 -> ()
  2151. | _ -> error (reg_inf r ^ " should be numeric")
  2152. in
  2153. let int r =
  2154. match rtype r with
  2155. | HUI8 | HUI16 | HI32 | HI64 -> ()
  2156. | _ -> error (reg_inf r ^ " should be integral")
  2157. in
  2158. let float r =
  2159. match rtype r with
  2160. | HF32 | HF64 -> ()
  2161. | _ -> error (reg_inf r ^ " should be float")
  2162. in
  2163. let call f args r =
  2164. match ftypes.(f) with
  2165. | HFun (targs, tret) ->
  2166. if List.length args <> List.length targs then error (tstr (HFun (List.map rtype args, rtype r)) ^ " should be " ^ tstr ftypes.(f));
  2167. List.iter2 reg args targs;
  2168. check tret (rtype r)
  2169. | _ -> assert false
  2170. in
  2171. let can_jump delta =
  2172. if !pos + 1 + delta < 0 || !pos + 1 + delta >= Array.length f.code then error "Jump outside function bounds";
  2173. if delta < 0 && Array.get f.code (!pos + 1 + delta) <> OLabel 0 then error "Jump back without Label";
  2174. in
  2175. let is_obj r =
  2176. match rtype r with
  2177. | HObj _ -> ()
  2178. | _ -> error (reg_inf r ^ " should be object")
  2179. in
  2180. let is_enum r =
  2181. match rtype r with
  2182. | HEnum _ -> ()
  2183. | _ -> error (reg_inf r ^ " should be enum")
  2184. in
  2185. let is_dyn r =
  2186. if not (is_dynamic (rtype r)) then error (reg_inf r ^ " should be castable to dynamic")
  2187. in
  2188. let tfield o fid proto =
  2189. if fid < 0 then error (reg_inf o ^ " does not have " ^ (if proto then "proto " else "") ^ "field " ^ string_of_int fid);
  2190. match rtype o with
  2191. | HObj p ->
  2192. if proto then ftypes.(p.pvirtuals.(fid)) else (try snd (resolve_field p fid) with Not_found -> error (reg_inf o ^ " does not have field " ^ string_of_int fid))
  2193. | HVirtual v when not proto ->
  2194. let _,_, t = v.vfields.(fid) in
  2195. t
  2196. | _ ->
  2197. is_obj o;
  2198. HVoid
  2199. in
  2200. list_iteri reg targs;
  2201. Array.iteri (fun i op ->
  2202. pos := i;
  2203. match op with
  2204. | OMov (a,b) ->
  2205. reg b (rtype a)
  2206. | OInt (r,i) ->
  2207. ignore(code.ints.(i));
  2208. int r
  2209. | OFloat (r,i) ->
  2210. if rtype r <> HF32 then reg r HF64;
  2211. if i < 0 || i >= Array.length code.floats then error "float outside range";
  2212. | OBool (r,_) ->
  2213. reg r HBool
  2214. | OString (r,i) | OBytes (r,i) ->
  2215. reg r HBytes;
  2216. if i < 0 || i >= Array.length code.strings then error "string outside range";
  2217. | ONull r ->
  2218. let t = rtype r in
  2219. if not (is_nullable t) then error (tstr t ^ " is not nullable")
  2220. | OAdd (r,a,b) | OSub (r,a,b) | OMul (r,a,b) | OSDiv (r,a,b) | OUDiv (r,a,b) | OSMod (r,a,b) | OUMod(r,a,b) ->
  2221. numeric r;
  2222. reg a (rtype r);
  2223. reg b (rtype r);
  2224. | ONeg (r,a) ->
  2225. numeric r;
  2226. reg a (rtype r);
  2227. | OShl (r,a,b) | OSShr (r,a,b) | OUShr (r,a,b) | OAnd (r,a,b) | OOr (r,a,b) | OXor (r,a,b) ->
  2228. int r;
  2229. reg a (rtype r);
  2230. reg b (rtype r);
  2231. | OIncr r ->
  2232. int r
  2233. | ODecr r ->
  2234. int r
  2235. | ONot (a,b) ->
  2236. reg a HBool;
  2237. reg b HBool;
  2238. | OCall0 (r,f) ->
  2239. call f [] r
  2240. | OCall1 (r, f, a) ->
  2241. call f [a] r
  2242. | OCall2 (r, f, a, b) ->
  2243. call f [a;b] r
  2244. | OCall3 (r, f, a, b, c) ->
  2245. call f [a;b;c] r
  2246. | OCall4 (r, f, a, b, c, d) ->
  2247. call f [a;b;c;d] r
  2248. | OCallN (r,f,rl) ->
  2249. call f rl r
  2250. | OCallThis (r, m, rl) ->
  2251. (match tfield 0 m true with
  2252. | HFun (tobj :: targs, tret) when List.length targs = List.length rl -> reg 0 tobj; List.iter2 reg rl targs; check tret (rtype r)
  2253. | t -> check t (HFun (rtype 0 :: List.map rtype rl, rtype r)));
  2254. | OCallMethod (r, m, rl) ->
  2255. (match rl with
  2256. | [] -> assert false
  2257. | obj :: rl2 ->
  2258. let t, rl = (match rtype obj with
  2259. | HVirtual v ->
  2260. let _, _, t = v.vfields.(m) in
  2261. t, rl2
  2262. | _ ->
  2263. tfield obj m true, rl
  2264. ) in
  2265. match t with
  2266. | HFun (targs, tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r)
  2267. | t -> check t (HFun (List.map rtype rl, rtype r)))
  2268. | OCallClosure (r,f,rl) ->
  2269. (match rtype f with
  2270. | HFun (targs,tret) when List.length targs = List.length rl -> List.iter2 reg rl targs; check tret (rtype r)
  2271. | HDyn -> List.iter (fun r -> ignore(rtype r)) rl;
  2272. | _ -> reg f (HFun(List.map rtype rl,rtype r)))
  2273. | OGetGlobal (r,g) ->
  2274. if not (safe_cast code.globals.(g) (rtype r)) then reg r code.globals.(g)
  2275. | OSetGlobal (g,r) ->
  2276. reg r code.globals.(g)
  2277. | ORet r ->
  2278. reg r tret
  2279. | OJTrue (r,delta) | OJFalse (r,delta) ->
  2280. reg r HBool;
  2281. can_jump delta
  2282. | OJNull (r,delta) | OJNotNull (r,delta) ->
  2283. ignore(rtype r);
  2284. can_jump delta
  2285. | OJUGte (a,b,delta) | OJULt (a,b,delta) | OJSGte (a,b,delta) | OJSLt (a,b,delta) | OJSGt (a,b,delta) | OJSLte (a,b,delta) | OJNotLt (a,b,delta) | OJNotGte (a,b,delta) ->
  2286. if not (safe_cast (rtype a) (rtype b)) then reg b (rtype a);
  2287. can_jump delta
  2288. | OJEq (a,b,delta) | OJNotEq (a,b,delta) ->
  2289. (match rtype a, rtype b with
  2290. | (HObj _ | HVirtual _), (HObj _ | HVirtual _) -> ()
  2291. | ta, tb when safe_cast tb ta -> ()
  2292. | _ -> reg a (rtype b));
  2293. can_jump delta
  2294. | OJAlways d ->
  2295. can_jump d
  2296. | OToDyn (r,a) ->
  2297. (* we can still use OToDyn on nullable if we want to turn them into dynamic *)
  2298. if is_dynamic (rtype a) then reg a HI32; (* don't wrap as dynamic types that can safely be cast to it *)
  2299. if rtype r <> HDyn then reg r (HNull (rtype a))
  2300. | OToSFloat (a,b) | OToUFloat (a,b) ->
  2301. float a;
  2302. (match rtype b with HF32 | HF64 -> () | _ -> int b);
  2303. | OToInt (a,b) ->
  2304. int a;
  2305. (match rtype b with HF32 | HF64 -> () | _ -> int b);
  2306. | OLabel _ ->
  2307. ()
  2308. | ONew r ->
  2309. (match rtype r with
  2310. | HDynObj | HVirtual _ -> ()
  2311. | _ -> is_obj r)
  2312. | OField (r,o,fid) ->
  2313. check (tfield o fid false) (rtype r)
  2314. | OSetField (o,fid,r) ->
  2315. reg r (tfield o fid false)
  2316. | OGetThis (r,fid) ->
  2317. check (tfield 0 fid false) (rtype r)
  2318. | OSetThis(fid,r) ->
  2319. reg r (tfield 0 fid false)
  2320. | OStaticClosure (r,f) ->
  2321. reg r ftypes.(f)
  2322. | OVirtualClosure (r,o,fid) ->
  2323. (match rtype o with
  2324. | HObj _ ->
  2325. (match tfield o fid true with
  2326. | HFun (t :: tl, tret) ->
  2327. reg o t;
  2328. reg r (HFun (tl,tret));
  2329. | _ ->
  2330. assert false)
  2331. | HVirtual v ->
  2332. let _,_, t = v.vfields.(fid) in
  2333. reg r t;
  2334. | _ ->
  2335. is_obj o)
  2336. | OInstanceClosure (r,f,arg) ->
  2337. (match ftypes.(f) with
  2338. | HFun (t :: tl, tret) ->
  2339. reg arg t;
  2340. if not (is_nullable t) then error (reg_inf r ^ " should be nullable");
  2341. reg r (HFun (tl,tret));
  2342. | _ -> assert false);
  2343. | OThrow r ->
  2344. reg r HDyn
  2345. | ORethrow r ->
  2346. reg r HDyn
  2347. | OGetArray (v,a,i) ->
  2348. reg a HArray;
  2349. reg i HI32;
  2350. ignore(rtype v);
  2351. | OGetUI8 (r,b,p) | OGetUI16(r,b,p) ->
  2352. reg r HI32;
  2353. reg b HBytes;
  2354. reg p HI32;
  2355. | OGetMem (r,b,p) ->
  2356. (match rtype r with HI32 | HI64 | HF32 | HF64 -> () | _ -> error (reg_inf r ^ " should be numeric"));
  2357. reg b HBytes;
  2358. reg p HI32;
  2359. | OSetUI8 (r,p,v) | OSetUI16 (r,p,v) ->
  2360. reg r HBytes;
  2361. reg p HI32;
  2362. reg v HI32;
  2363. | OSetMem (r,p,v) ->
  2364. reg r HBytes;
  2365. reg p HI32;
  2366. (match rtype v with HI32 | HI64 | HF32 | HF64 -> () | _ -> error (reg_inf r ^ " should be numeric"));
  2367. | OSetArray (a,i,v) ->
  2368. reg a HArray;
  2369. reg i HI32;
  2370. ignore(rtype v);
  2371. | OUnsafeCast (a,b) ->
  2372. is_dyn a;
  2373. is_dyn b;
  2374. | OSafeCast (a,b) ->
  2375. ignore(rtype a);
  2376. ignore(rtype b);
  2377. | OArraySize (r,a) ->
  2378. reg a HArray;
  2379. reg r HI32
  2380. | OType (r,_) ->
  2381. reg r HType
  2382. | OGetType (r,v) ->
  2383. reg r HType;
  2384. is_dyn v;
  2385. | OGetTID (r,v) ->
  2386. reg r HI32;
  2387. reg v HType;
  2388. | OUnref (v,r) ->
  2389. (match rtype r with
  2390. | HRef t -> check t (rtype v)
  2391. | _ -> reg r (HRef (rtype v)))
  2392. | ORef (r,v)
  2393. | OSetref (r,v) ->
  2394. (match rtype r with HRef t -> reg v t | _ -> reg r (HRef (rtype v)))
  2395. | OToVirtual (r,v) ->
  2396. (match rtype r with
  2397. | HVirtual _ -> ()
  2398. | _ -> reg r (HVirtual {vfields=[||];vindex=PMap.empty;}));
  2399. (match rtype v with
  2400. | HObj _ | HDynObj | HDyn | HVirtual _ -> ()
  2401. | _ -> reg v HDynObj)
  2402. | ODynGet (v,r,f) | ODynSet (r,f,v) ->
  2403. ignore(code.strings.(f));
  2404. ignore(rtype v);
  2405. (match rtype r with
  2406. | HObj _ | HDyn | HDynObj | HVirtual _ -> ()
  2407. | _ -> reg r HDynObj)
  2408. | OMakeEnum (r,index,pl) ->
  2409. (match rtype r with
  2410. | HEnum e ->
  2411. let _,_, fl = e.efields.(index) in
  2412. if Array.length fl <> List.length pl then error ("MakeEnum has " ^ (string_of_int (List.length pl)) ^ " params while " ^ (string_of_int (Array.length fl)) ^ " are required");
  2413. List.iter2 (fun r t -> reg r t) pl (Array.to_list fl)
  2414. | _ ->
  2415. is_enum r)
  2416. | OEnumAlloc (r,index) ->
  2417. (match rtype r with
  2418. | HEnum e ->
  2419. ignore(e.efields.(index))
  2420. | _ ->
  2421. is_enum r)
  2422. | OEnumIndex (r,v) ->
  2423. if rtype v <> HDyn then is_enum v;
  2424. reg r HI32;
  2425. | OEnumField (r,e,f,i) ->
  2426. (match rtype e with
  2427. | HEnum e ->
  2428. let _, _, tl = e.efields.(f) in
  2429. check tl.(i) (rtype r)
  2430. | _ -> is_enum e)
  2431. | OSetEnumField (e,i,r) ->
  2432. (match rtype e with
  2433. | HEnum e ->
  2434. let _, _, tl = e.efields.(0) in
  2435. check (rtype r) tl.(i)
  2436. | _ -> is_enum e)
  2437. | OSwitch (r,idx,eend) ->
  2438. reg r HI32;
  2439. Array.iter can_jump idx;
  2440. if eend + 1 + i <> Array.length f.code then can_jump eend
  2441. | ONullCheck r ->
  2442. ignore(rtype r)
  2443. | OTrap (r, idx) ->
  2444. reg r HDyn;
  2445. can_jump idx
  2446. | OEndTrap _ ->
  2447. ()
  2448. | OAssert _ ->
  2449. ()
  2450. | ORefData (r,d) ->
  2451. reg d HArray;
  2452. (match rtype r with HRef _ -> () | _ -> reg r (HRef HDyn))
  2453. | ORefOffset (r,r2,off) ->
  2454. (match rtype r2 with HRef _ -> () | _ -> reg r2 (HRef HDyn));
  2455. reg r (rtype r2);
  2456. reg off HI32;
  2457. | ONop _ ->
  2458. ()
  2459. ) f.code
  2460. (* TODO : check that all path correctly initialize NULL values and reach a return *)
  2461. in
  2462. Array.iter (fun fd ->
  2463. if fd.findex >= Array.length ftypes then failwith ("Invalid function index " ^ string_of_int fd.findex);
  2464. if ftypes.(fd.findex) <> HVoid then failwith ("Duplicate function bind " ^ string_of_int fd.findex ^ " " ^ fundecl_name fd);
  2465. ftypes.(fd.findex) <- fd.ftype;
  2466. ) code.functions;
  2467. Array.iter (fun (lib,name,t,idx) ->
  2468. if idx >= Array.length ftypes then failwith ("Invalid native function index " ^ string_of_int idx ^ " for "^ code.strings.(lib) ^ "@" ^ code.strings.(name));
  2469. if ftypes.(idx) <> HVoid then failwith ("Duplicate native function bind " ^ string_of_int idx);
  2470. Hashtbl.add is_native_fun idx true;
  2471. ftypes.(idx) <- t
  2472. ) code.natives;
  2473. (* TODO : check that no object type has a virtual native in his proto *)
  2474. Array.iter check_fun code.functions
  2475. (* ------------------------------- SPEC ---------------------------------------------- *)
  2476. (*
  2477. open Hlopt
  2478. type svalue =
  2479. | SUndef
  2480. | SArg of int
  2481. | SInt of int32
  2482. | SFloat of float
  2483. | SString of string
  2484. | SBool of bool
  2485. | SNull
  2486. | SType of ttype
  2487. | SOp of string * svalue * svalue
  2488. | SUnop of string * svalue
  2489. | SResult of string
  2490. | SFun of int * svalue option
  2491. | SMeth of svalue * int
  2492. | SGlobal of int
  2493. | SField of svalue * int
  2494. | SDField of svalue * string
  2495. | SConv of string * svalue
  2496. | SCast of svalue * ttype
  2497. | SMem of svalue * svalue * ttype
  2498. | SEnum of int * svalue list
  2499. | SEnumField of svalue * int * int
  2500. | SUnion of svalue list
  2501. | SRef of int
  2502. | SRefResult of string
  2503. | SUnreach
  2504. | SExc
  2505. | SDelayed of string * svalue list option ref
  2506. type call_spec =
  2507. | SFid of int
  2508. | SMethod of int
  2509. | SClosure of svalue
  2510. type spec =
  2511. | SCall of call_spec * svalue list
  2512. | SGlobalSet of int * svalue
  2513. | SFieldSet of svalue * int * svalue
  2514. | SFieldDSet of svalue * string * svalue
  2515. | SJEq of string * svalue
  2516. | SJComp of string * svalue * svalue
  2517. | SJump
  2518. | SRet of svalue
  2519. | SNullCheck of svalue
  2520. | SThrow of svalue
  2521. | SSwitch of svalue
  2522. | SWriteMem of svalue * svalue * svalue * ttype
  2523. | SSetRef of svalue * svalue
  2524. | SSetEnumField of svalue * int * svalue
  2525. | SStoreResult of string * spec
  2526. | SNew of ttype * int
  2527. | SVal of svalue
  2528. let rec svalue_string v =
  2529. let sval = svalue_string in
  2530. match v with
  2531. | SUndef -> "undef"
  2532. | SArg i -> "arg" ^ string_of_int i
  2533. | SInt i -> Int32.to_string i
  2534. | SFloat f -> string_of_float f
  2535. | SString s -> "\"" ^ s ^ "\""
  2536. | SBool b -> if b then "true" else "false"
  2537. | SNull -> "null"
  2538. | SRef _ -> "ref"
  2539. | SRefResult s -> Printf.sprintf "refresult(%s)" s
  2540. | SType t -> tstr t
  2541. | SOp (op,a,b) -> Printf.sprintf "(%s %s %s)" (sval a) op (sval b)
  2542. | SUnop (op,v) -> op ^ sval v
  2543. | SResult i -> i
  2544. | SFun (i,None) -> "fun" ^ string_of_int i
  2545. | SFun (i,Some v) -> Printf.sprintf "fun%d(%s)" i (sval v)
  2546. | SMeth (v,i) -> Printf.sprintf "meth%d(%s)" i (sval v)
  2547. | SGlobal g -> Printf.sprintf "G[%d]" g
  2548. | SField (o,i) -> Printf.sprintf "%s[%d]" (sval o) i
  2549. | SDField (o,f) -> Printf.sprintf "%s.%s" (sval o) f
  2550. | SConv (f,v) -> Printf.sprintf "%s(%s)" f (sval v)
  2551. | SCast (v,t) -> Printf.sprintf "cast(%s,%s)" (sval v) (tstr t)
  2552. | SMem (m,idx,t) -> Printf.sprintf "(%s*)%s[%s]" (tstr t) (sval m) (sval idx)
  2553. | SEnum (i,vl) -> Printf.sprintf "enum%d(%s)" i (String.concat "," (List.map sval vl))
  2554. | SEnumField (v,k,i) -> Printf.sprintf "%s[%d:%d]" (sval v) k i
  2555. | SUnion vl -> Printf.sprintf "union(%s)" (String.concat " | " (List.map sval vl))
  2556. | SUnreach -> "unreach"
  2557. | SExc -> "exc"
  2558. | SDelayed (str,_) -> str
  2559. let svalue_iter f = function
  2560. | SUndef | SArg _ | SInt _ | SFloat _ | SString _ | SBool _ | SNull | SType _ | SResult _
  2561. | SFun (_,None) | SGlobal _ | SRef _ | SRefResult _ | SUnreach | SExc | SDelayed _ ->
  2562. ()
  2563. | SOp (_,a,b) | SMem (a,b,_) -> f a; f b
  2564. | SUnop (_,a) | SFun (_,Some a) | SMeth (a,_) | SField (a,_) | SDField (a,_) | SConv (_,a) | SCast (a,_) | SEnumField (a,_,_) -> f a
  2565. | SUnion vl | SEnum (_,vl) -> List.iter f vl
  2566. let spec_iter fs fv = function
  2567. | SCall (c,vl) ->
  2568. (match c with SClosure v -> fv v | _ -> ());
  2569. List.iter fv vl
  2570. | SVal v
  2571. | SJEq (_,v)
  2572. | SRet v
  2573. | SNullCheck v
  2574. | SThrow v
  2575. | SSwitch v
  2576. | SGlobalSet (_,v) -> fv v
  2577. | SJComp (_,a,b)
  2578. | SSetRef (a,b)
  2579. | SSetEnumField (a,_,b)
  2580. | SFieldDSet (a,_,b) | SFieldSet (a,_,b) -> fv a; fv b
  2581. | SJump ->
  2582. ()
  2583. | SWriteMem (m,a,b,_) ->
  2584. fv m; fv a; fv b
  2585. | SStoreResult (_,s) ->
  2586. fs s
  2587. | SNew _ ->
  2588. ()
  2589. let rec svalue_same a b =
  2590. let vsame = svalue_same in
  2591. match a, b with
  2592. | SType t1, SType t2 -> tsame t1 t2
  2593. | SOp (op1,a1,b1), SOp (op2,a2,b2) -> op1 = op2 && vsame a1 a2 && vsame b1 b2
  2594. | SUnop (op1,v1), SUnop (op2,v2) -> op1 = op2 && vsame v1 v2
  2595. | SFun (f1,Some v1), SFun (f2,Some v2) -> f1 = f2 && vsame v1 v2
  2596. | SMeth (v1,m1), SMeth (v2,m2) -> vsame v1 v2 && m1 = m2
  2597. | SField (v1,f1), SField (v2,f2) -> vsame v1 v2 && f1 = f2
  2598. | SDField (v1,f1), SDField (v2,f2) -> vsame v1 v2 && f1 = f2
  2599. | SConv (op1,v1), SConv (op2,v2) -> op1 = op2 && vsame v1 v2
  2600. | SCast (v1,t1), SCast (v2,t2) -> vsame v1 v2 && tsame t1 t2
  2601. | SMem (m1,i1,t1), SMem (m2,i2,t2) -> vsame m1 m2 && vsame i1 i2 && tsame t1 t2
  2602. | SEnum (i1,vl1), SEnum (i2,vl2) -> i1 = i2 && List.length vl1 = List.length vl2 && List.for_all2 vsame vl1 vl2
  2603. | SEnumField (v1,c1,i1), SEnumField (v2,c2,i2) -> vsame v1 v2 && c1 = c2 && i1 = i2
  2604. | SUnion vl1, SUnion vl2 -> List.length vl1 = List.length vl2 && List.for_all2 vsame vl1 vl2
  2605. | SDelayed (id1,_), SDelayed (id2,_) -> id1 = id2
  2606. | _ -> a = b
  2607. let rec spec_string s =
  2608. let sval = svalue_string in
  2609. match s with
  2610. | SCall (c,vl) ->
  2611. let cstr = (match c with
  2612. | SFid i -> Printf.sprintf "fun%d" i
  2613. | SMethod i -> Printf.sprintf "meth%d" i
  2614. | SClosure v -> Printf.sprintf "closure(%s)" (sval v)
  2615. ) in
  2616. Printf.sprintf "%s(%s)" cstr (String.concat "," (List.map sval vl))
  2617. | SGlobalSet (i,v) ->
  2618. Printf.sprintf "G[%d] = %s" i (sval v)
  2619. | SFieldSet (o,fid,v) | SSetEnumField (o,fid,v) ->
  2620. Printf.sprintf "%s[%d] = %s" (sval o) fid (sval v)
  2621. | SFieldDSet (o,f,v) ->
  2622. Printf.sprintf "%s.%s = %s" (sval o) f (sval v)
  2623. | SJEq (s,v) ->
  2624. Printf.sprintf "j%s(%s)" s (sval v)
  2625. | SJComp (s,a,b) ->
  2626. Printf.sprintf "jump(%s %s %s)" (sval a) s (sval b)
  2627. | SJump ->
  2628. "jump"
  2629. | SRet v ->
  2630. "ret " ^ sval v
  2631. | SNullCheck v ->
  2632. "nullcheck " ^ sval v
  2633. | SThrow v ->
  2634. "throw " ^ sval v
  2635. | SSwitch v ->
  2636. "switch " ^ sval v
  2637. | SWriteMem (m,idx,v,t) ->
  2638. Printf.sprintf "(%s*)%s[%s] = %s" (tstr t) (sval m) (sval idx) (sval v)
  2639. | SSetRef (r,v) ->
  2640. Printf.sprintf "*%s = %s" (sval r) (sval v)
  2641. | SStoreResult (r,s) ->
  2642. r ^ " <- " ^ spec_string s
  2643. | SNew (t,idx) ->
  2644. Printf.sprintf "new %s(%d)" (tstr t) idx
  2645. | SVal v ->
  2646. sval v
  2647. let make_spec (code:code) (f:fundecl) =
  2648. let op = Array.get f.code in
  2649. let out_spec = ref [] in
  2650. let alloc_count = ref (-1) in
  2651. let digest str =
  2652. let d = Digest.to_hex (Digest.string str) in
  2653. String.sub d 0 4
  2654. in
  2655. let rec semit s =
  2656. let rec loop_spec s =
  2657. spec_iter loop_spec loop_val s
  2658. and loop_val v =
  2659. match v with
  2660. | SDelayed (r,used) ->
  2661. (match !used with
  2662. | None -> ()
  2663. | Some vl -> used := None; semit (SStoreResult (r,SVal (SUnion vl))))
  2664. | _ ->
  2665. svalue_iter loop_val v
  2666. in
  2667. loop_spec s;
  2668. out_spec := s :: !out_spec
  2669. in
  2670. let emit (s:spec) =
  2671. let d = digest (spec_string s) in
  2672. semit (SStoreResult (d,s));
  2673. SResult d
  2674. in
  2675. let big_unions = Hashtbl.create 0 in
  2676. let block_args = Hashtbl.create 0 in
  2677. let rec get_args b =
  2678. try
  2679. Hashtbl.find block_args b.bstart
  2680. with Not_found ->
  2681. assert false
  2682. and calc_spec b =
  2683. let bprev = List.filter (fun b2 -> b2.bstart < b.bstart) b.bprev in
  2684. let args = (match bprev with
  2685. | [] ->
  2686. let args = Array.make (Array.length f.regs) SUndef in
  2687. (match f.ftype with
  2688. | HFun (tl,_) -> list_iteri (fun i _ -> args.(i) <- SArg i) tl
  2689. | _ -> assert false);
  2690. args
  2691. | b2 :: l ->
  2692. let args = Array.copy (get_args b2) in
  2693. List.iter (fun b2 ->
  2694. let args2 = get_args b2 in
  2695. for i = 0 to Array.length args - 1 do
  2696. if not (svalue_same args.(i) args2.(i)) then begin
  2697. let l1 = (match args.(i) with SUnion l -> l | v -> [v]) in
  2698. let l2 = (match args2.(i) with SUnion l -> l | v -> [v]) in
  2699. let l = l1 @ List.filter (fun v -> not (List.exists (svalue_same v) l1)) l2 in
  2700. if List.length l > 10 then begin
  2701. (try
  2702. let ident, used = Hashtbl.find big_unions l in
  2703. args.(i) <- SDelayed (ident, used);
  2704. with Not_found ->
  2705. let ident = digest (String.concat "," (List.map svalue_string l)) in
  2706. let used = ref (Some l) in
  2707. Hashtbl.replace big_unions l (ident,used);
  2708. args.(i) <- SDelayed (ident, used))
  2709. end else
  2710. args.(i) <- SUnion l;
  2711. end
  2712. done;
  2713. ) l;
  2714. if l = [] then (match op b2.bend with OTrap (r,_) -> args.(r) <- SExc | _ -> ());
  2715. args
  2716. ) in
  2717. let make_call c vl =
  2718. let r = emit (SCall (c,vl)) in
  2719. (match r with
  2720. | SResult result -> List.iter (fun v -> match v with SRef r -> args.(r) <- SRefResult result | _ -> ()) vl
  2721. | _ -> assert false);
  2722. r
  2723. in
  2724. for i = b.bstart to b.bend do
  2725. match op i with
  2726. | OMov (d,r) -> args.(d) <- args.(r)
  2727. | OInt (d,i) -> args.(d) <- SInt code.ints.(i)
  2728. | OFloat (d,f) -> args.(d) <- SFloat code.floats.(f)
  2729. | OBool (d,b) -> args.(d) <- SBool b
  2730. | OBytes (d,s) | OString (d,s) -> args.(d) <- SString code.strings.(s)
  2731. | ONull d -> args.(d) <- SNull
  2732. | OAdd (d,a,b) -> args.(d) <- SOp ("+",args.(a),args.(b))
  2733. | OSub (d,a,b) -> args.(d) <- SOp ("-",args.(a),args.(b))
  2734. | OMul (d,a,b) -> args.(d) <- SOp ("*",args.(a),args.(b))
  2735. | OSDiv (d,a,b) -> args.(d) <- SOp ("/",args.(a),args.(b))
  2736. | OUDiv (d,a,b) -> args.(d) <- SOp ("//",args.(a),args.(b))
  2737. | OSMod (d,a,b) -> args.(d) <- SOp ("%",args.(a),args.(b))
  2738. | OUMod (d,a,b) -> args.(d) <- SOp ("%%",args.(a),args.(b))
  2739. | OShl (d,a,b) -> args.(d) <- SOp ("<<",args.(a),args.(b))
  2740. | OSShr (d,a,b) -> args.(d) <- SOp (">>",args.(a),args.(b))
  2741. | OUShr (d,a,b) -> args.(d) <- SOp (">>>",args.(a),args.(b))
  2742. | OAnd (d,a,b) -> args.(d) <- SOp ("&",args.(a),args.(b))
  2743. | OOr (d,a,b) -> args.(d) <- SOp ("|",args.(a),args.(b))
  2744. | OXor (d,a,b) -> args.(d) <- SOp ("^",args.(a),args.(b))
  2745. | ONeg (d,r) -> args.(d) <- SUnop ("-",args.(r))
  2746. | ONot (d,r) -> args.(d) <- SUnop ("!",args.(r))
  2747. | OIncr r -> args.(r) <- SUnop ("++",args.(r))
  2748. | ODecr r -> args.(r) <- SUnop ("++",args.(r))
  2749. | OCall0 (d,f) -> args.(d) <- make_call (SFid f) []
  2750. | OCall1 (d,f,a) -> args.(d) <- make_call (SFid f) [args.(a)]
  2751. | OCall2 (d,f,a,b) -> args.(d) <- make_call (SFid f) [args.(a);args.(b)]
  2752. | OCall3 (d,f,a,b,c) -> args.(d) <- make_call (SFid f) [args.(a);args.(b);args.(c)]
  2753. | OCall4 (d,f,a,b,c,k) -> args.(d) <- make_call (SFid f) [args.(a);args.(b);args.(c);args.(k)]
  2754. | OCallN (d,f,rl) -> args.(d) <- make_call (SFid f) (List.map (fun r -> args.(r)) rl)
  2755. | OCallMethod (d,fid,rl) -> args.(d) <- make_call (SMethod fid) (List.map (fun r -> args.(r)) rl)
  2756. | OCallThis (d,fid,rl) -> args.(d) <- make_call (SMethod fid) (List.map (fun r -> args.(r)) (0 :: rl))
  2757. | OCallClosure (d,r,rl) -> args.(d) <- make_call (SClosure args.(r)) (List.map (fun r -> args.(r)) rl)
  2758. | OStaticClosure (d,fid) -> args.(d) <- SFun (fid,None)
  2759. | OInstanceClosure (d,fid,r) -> args.(d) <- SFun (fid,Some args.(r))
  2760. | OVirtualClosure (d,r,index) -> args.(d) <- SMeth (args.(r),index)
  2761. | OGetGlobal (d,g) -> args.(d) <- SGlobal g
  2762. | OSetGlobal (g,r) -> semit (SGlobalSet (g,args.(r)))
  2763. | OField (d,r,f) -> args.(d) <- SField (args.(r),f)
  2764. | OSetField (o,f,r) -> semit (SFieldSet (args.(o),f,args.(r)))
  2765. | OGetThis (d,fid) -> args.(d) <- SField (args.(0),fid)
  2766. | OSetThis (f,r) -> semit (SFieldSet (args.(0),f,args.(r)))
  2767. | ODynGet (d,o,f) -> args.(d) <- SDField (args.(o),code.strings.(f))
  2768. | ODynSet (o,f,v) -> semit (SFieldDSet (args.(o),code.strings.(f),args.(v)))
  2769. | OJTrue (r,_) -> semit (SJEq ("true",args.(r)))
  2770. | OJFalse (r,_) -> semit (SJEq ("false",args.(r)))
  2771. | OJNull (r,_) -> semit (SJEq ("null",args.(r)))
  2772. | OJNotNull (r,_) -> semit (SJEq ("not null",args.(r)))
  2773. | OJSLt (a,b,_) -> semit (SJComp ("<",args.(a),args.(b)))
  2774. | OJSGte (a,b,_) -> semit (SJComp (">=",args.(a),args.(b)))
  2775. | OJSGt (a,b,_) -> semit (SJComp (">",args.(a),args.(b)))
  2776. | OJSLte (a,b,_) -> semit (SJComp ("<=",args.(a),args.(b)))
  2777. | OJULt (a,b,_) -> semit (SJComp ("<U",args.(a),args.(b)))
  2778. | OJUGte (a,b,_) -> semit (SJComp (">=U",args.(a),args.(b)))
  2779. | OJNotLt (a,b,_) -> semit (SJComp ("not<",args.(a),args.(b)))
  2780. | OJNotGte (a,b,_) -> semit (SJComp ("not>=",args.(a),args.(b)))
  2781. | OJEq (a,b,_) -> semit (SJComp ("==",args.(a),args.(b)))
  2782. | OJNotEq (a,b,_) -> semit (SJComp ("!=",args.(a),args.(b)))
  2783. | OJAlways _ -> semit SJump
  2784. | OToDyn (d,r) -> args.(d) <- SConv ("dyn",args.(r))
  2785. | OToSFloat (d,r) -> args.(d) <- SConv ("sfloat",args.(r))
  2786. | OToUFloat (d,r) -> args.(d) <- SConv ("ufloat",args.(r))
  2787. | OToInt (d,r) -> args.(d) <- SConv ("int",args.(r))
  2788. | OSafeCast (d,r) -> args.(d) <- SCast (args.(r),f.regs.(d))
  2789. | OUnsafeCast (d,r) -> args.(d) <- SConv ("cast", args.(r))
  2790. | OToVirtual (d,r) -> args.(d) <- SConv ("virtual",args.(r))
  2791. | OLabel _ -> ()
  2792. | ORet r ->
  2793. semit (SRet (if f.regs.(r) = HVoid then SUndef else args.(r)));
  2794. if i < b.bend then for i = 0 to Array.length args - 1 do args.(i) <- SUnreach done
  2795. | OThrow r | ORethrow r ->
  2796. semit (SThrow args.(r));
  2797. if i < b.bend then for i = 0 to Array.length args - 1 do args.(i) <- SUnreach done
  2798. | OSwitch (r,_,_) -> semit (SSwitch args.(r))
  2799. | ONullCheck r -> semit (SNullCheck args.(r))
  2800. | OTrap _ | OEndTrap _ -> ()
  2801. | OGetUI8 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HUI8)
  2802. | OGetUI16 (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HUI16)
  2803. | OGetMem (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),f.regs.(d))
  2804. | OGetArray (d,b,i) -> args.(d) <- SMem (args.(b),args.(i),HArray)
  2805. | OSetUI8 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HUI8))
  2806. | OSetUI16 (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HUI16))
  2807. | OSetMem (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),f.regs.(v)))
  2808. | OSetArray (b,i,v) -> semit (SWriteMem (args.(b),args.(i),args.(v),HArray))
  2809. | ONew d ->
  2810. incr alloc_count;
  2811. args.(d) <- emit (SNew (f.regs.(d),!alloc_count))
  2812. | OArraySize (d,r) -> args.(d) <- SConv ("size",args.(r))
  2813. | OType (d,t) -> args.(d) <- SType t
  2814. | OGetType (d,r) -> args.(d) <- SConv ("type",args.(r))
  2815. | OGetTID (d,r) -> args.(d) <- SConv ("tid",args.(r))
  2816. | ORef (d,r) -> args.(d) <- SRef r
  2817. | OUnref (d,r) ->
  2818. (match args.(r) with
  2819. | SRef r -> args.(d) <- args.(r)
  2820. | _ -> args.(d) <- SConv ("unref",args.(r)))
  2821. | OSetref (r,v) ->
  2822. (match args.(r) with
  2823. | SRef r -> args.(r) <- args.(v)
  2824. | _ -> ());
  2825. semit (SSetRef (args.(r),args.(v)))
  2826. | OMakeEnum (d,fid,rl) -> args.(d) <- SEnum (fid, List.map (fun r -> args.(r)) rl)
  2827. | OEnumAlloc (d,fid) -> args.(d) <- SEnum (fid, [])
  2828. | OEnumIndex (d,r) -> args.(d) <- SConv ("index",args.(r))
  2829. | OEnumField (d,r,fid,cid) -> args.(d) <- SEnumField (args.(r),fid,cid)
  2830. | OSetEnumField (e,fid,r) -> semit (SSetEnumField (args.(e),fid,args.(r)))
  2831. | OAssert _ -> ()
  2832. | ONop _ -> ()
  2833. done;
  2834. Hashtbl.add block_args b.bstart args
  2835. in
  2836. let all_blocks, _ = Hlopt.code_graph f in
  2837. let rec loop i =
  2838. if i = Array.length f.code then () else
  2839. if not (Hashtbl.mem all_blocks i) then loop (i + 1) else (* unreachable code *)
  2840. let b = try Hashtbl.find all_blocks i with Not_found -> failwith (Printf.sprintf "Missing block %s(%d)" (fundecl_name f) i) in
  2841. calc_spec b;
  2842. loop (b.bend + 1)
  2843. in
  2844. loop 0;
  2845. List.rev !out_spec
  2846. *)