123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Reflection;
- using System.Reflection.Emit;
- using System.Text;
- using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
- using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
- using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
- using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
- using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
- using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
- /**
- * Contains classes that disassemble or decompile an yobj file.
- * See xmrengcomp.cx utility program.
- */
- namespace OpenSim.Region.ScriptEngine.Yengine
- {
- /*
- * Encapsulate object code for a method.
- */
- public abstract class ObjectTokens
- {
- public ScriptObjCode scriptObjCode;
- public ObjectTokens(ScriptObjCode scriptObjCode)
- {
- this.scriptObjCode = scriptObjCode;
- }
- public abstract void Close();
- public abstract void BegMethod(DynamicMethod method);
- public abstract void EndMethod();
- public abstract void DefineLabel(int number, string name);
- public abstract void DefineLocal(int number, string name, string type, Type syType);
- public abstract void DefineMethod(string methName, Type retType, Type[] argTypes, string[] argNames);
- public abstract void MarkLabel(int offset, int number);
- public abstract void BegExcBlk(int offset);
- public abstract void BegCatBlk(int offset, Type excType);
- public abstract void BegFinBlk(int offset);
- public abstract void EndExcBlk(int offset);
- public abstract void EmitNull(int offset, OpCode opCode);
- public abstract void EmitField(int offset, OpCode opCode, FieldInfo field);
- public abstract void EmitLocal(int offset, OpCode opCode, int number);
- public abstract void EmitType(int offset, OpCode opCode, Type type);
- public abstract void EmitLabel(int offset, OpCode opCode, int number);
- public abstract void EmitLabels(int offset, OpCode opCode, int[] numbers);
- public abstract void EmitMethod(int offset, OpCode opCode, MethodInfo method);
- public abstract void EmitCtor(int offset, OpCode opCode, ConstructorInfo ctor);
- public abstract void EmitDouble(int offset, OpCode opCode, double value);
- public abstract void EmitFloat(int offset, OpCode opCode, float value);
- public abstract void EmitInteger(int offset, OpCode opCode, int value);
- public abstract void EmitString(int offset, OpCode opCode, string value);
- }
- /******************\
- * DISASSEMBLER *
- \******************/
- public class OTDisassemble: ObjectTokens
- {
- private static readonly int OPCSTRWIDTH = 12;
- private Dictionary<int, string> labelNames;
- private Dictionary<int, string> localNames;
- private StringBuilder lbuf = new StringBuilder();
- private TextWriter twout;
- public OTDisassemble(ScriptObjCode scriptObjCode, TextWriter twout) : base(scriptObjCode)
- {
- this.twout = twout;
- }
- public override void Close()
- {
- twout.WriteLine("TheEnd.");
- }
- /**
- * About to generate object code for this method.
- */
- public override void BegMethod(DynamicMethod method)
- {
- labelNames = new Dictionary<int, string>();
- localNames = new Dictionary<int, string>();
- twout.WriteLine("");
- lbuf.Append(method.ReturnType.Name);
- lbuf.Append(' ');
- lbuf.Append(method.Name);
- ParameterInfo[] parms = method.GetParameters();
- int nArgs = parms.Length;
- lbuf.Append(" (");
- for(int i = 0; i < nArgs; i++)
- {
- if(i > 0)
- lbuf.Append(", ");
- lbuf.Append(parms[i].ParameterType.Name);
- }
- lbuf.Append(')');
- FlushLine();
- lbuf.Append('{');
- FlushLine();
- }
- /**
- * Dump out reconstructed source for this method.
- */
- public override void EndMethod()
- {
- lbuf.Append('}');
- FlushLine();
- }
- /**
- * Add instructions to stream.
- */
- public override void DefineLabel(int number, string name)
- {
- labelNames[number] = name + "$" + number;
- }
- public override void DefineLocal(int number, string name, string type, Type syType)
- {
- localNames[number] = name + "$" + number;
- lbuf.Append(" ");
- lbuf.Append(type.PadRight(OPCSTRWIDTH - 1));
- lbuf.Append(' ');
- lbuf.Append(localNames[number]);
- FlushLine();
- }
- public override void DefineMethod(string methName, Type retType, Type[] argTypes, string[] argNames)
- {
- }
- public override void MarkLabel(int offset, int number)
- {
- LinePrefix(offset);
- lbuf.Append(labelNames[number]);
- lbuf.Append(":");
- FlushLine();
- }
- public override void BegExcBlk(int offset)
- {
- LinePrefix(offset);
- lbuf.Append(" BeginExceptionBlock");
- FlushLine();
- }
- public override void BegCatBlk(int offset, Type excType)
- {
- LinePrefix(offset);
- lbuf.Append(" BeginCatchBlock ");
- lbuf.Append(excType.Name);
- FlushLine();
- }
- public override void BegFinBlk(int offset)
- {
- LinePrefix(offset);
- lbuf.Append(" BeginFinallyBlock");
- FlushLine();
- }
- public override void EndExcBlk(int offset)
- {
- LinePrefix(offset);
- lbuf.Append(" EndExceptionBlock");
- FlushLine();
- }
- public override void EmitNull(int offset, OpCode opCode)
- {
- LinePrefix(offset, opCode);
- FlushLine();
- }
- public override void EmitField(int offset, OpCode opCode, FieldInfo field)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(field.DeclaringType.Name);
- lbuf.Append(':');
- lbuf.Append(field.Name);
- lbuf.Append(" -> ");
- lbuf.Append(field.FieldType.Name);
- lbuf.Append(" (field)");
- FlushLine();
- }
- public override void EmitLocal(int offset, OpCode opCode, int number)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(localNames[number]);
- lbuf.Append(" (local)");
- FlushLine();
- }
- public override void EmitType(int offset, OpCode opCode, Type type)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(type.Name);
- lbuf.Append(" (type)");
- FlushLine();
- }
- public override void EmitLabel(int offset, OpCode opCode, int number)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(labelNames[number]);
- lbuf.Append(" (label)");
- FlushLine();
- }
- public override void EmitLabels(int offset, OpCode opCode, int[] numbers)
- {
- LinePrefix(offset, opCode);
- int lineLen = lbuf.Length;
- int nLabels = numbers.Length;
- for(int i = 0; i < nLabels; i++)
- {
- if(i > 0)
- {
- lbuf.AppendLine();
- lbuf.Append(",".PadLeft(lineLen));
- }
- lbuf.Append(labelNames[numbers[i]]);
- }
- FlushLine();
- }
- public override void EmitMethod(int offset, OpCode opCode, MethodInfo method)
- {
- LinePrefix(offset, opCode);
- ParameterInfo[] parms = method.GetParameters();
- int nArgs = parms.Length;
- if(method.DeclaringType != null)
- {
- lbuf.Append(method.DeclaringType.Name);
- lbuf.Append(':');
- }
- lbuf.Append(method.Name);
- lbuf.Append('(');
- for(int i = 0; i < nArgs; i++)
- {
- if(i > 0)
- lbuf.Append(",");
- lbuf.Append(parms[i].ParameterType.Name);
- }
- lbuf.Append(") -> ");
- lbuf.Append(method.ReturnType.Name);
- FlushLine();
- }
- public override void EmitCtor(int offset, OpCode opCode, ConstructorInfo ctor)
- {
- LinePrefix(offset, opCode);
- ParameterInfo[] parms = ctor.GetParameters();
- int nArgs = parms.Length;
- lbuf.Append(ctor.DeclaringType.Name);
- lbuf.Append(":(");
- for(int i = 0; i < nArgs; i++)
- {
- if(i > 0)
- lbuf.Append(",");
- lbuf.Append(parms[i].ParameterType.Name);
- }
- lbuf.Append(")");
- FlushLine();
- }
- public override void EmitDouble(int offset, OpCode opCode, double value)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(value.ToString());
- lbuf.Append(" (double)");
- FlushLine();
- }
- public override void EmitFloat(int offset, OpCode opCode, float value)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(value.ToString());
- lbuf.Append(" (float)");
- FlushLine();
- }
- public override void EmitInteger(int offset, OpCode opCode, int value)
- {
- LinePrefix(offset, opCode);
- lbuf.Append(value.ToString());
- lbuf.Append(" (int)");
- FlushLine();
- }
- public override void EmitString(int offset, OpCode opCode, string value)
- {
- LinePrefix(offset, opCode);
- lbuf.Append("\"");
- lbuf.Append(value);
- lbuf.Append("\" (string)");
- FlushLine();
- }
- /**
- * Put offset and opcode at beginning of line.
- */
- private void LinePrefix(int offset, OpCode opCode)
- {
- LinePrefix(offset);
- lbuf.Append(" ");
- lbuf.Append(opCode.ToString().PadRight(OPCSTRWIDTH - 1));
- lbuf.Append(' ');
- }
- private void LinePrefix(int offset)
- {
- lbuf.Append(" ");
- lbuf.Append(offset.ToString("X4"));
- lbuf.Append(" ");
- }
- /**
- * Flush line buffer to output file.
- */
- private void FlushLine()
- {
- if(lbuf.Length > 0)
- {
- twout.WriteLine(lbuf.ToString());
- lbuf.Remove(0, lbuf.Length);
- }
- }
- }
- /****************\
- * DECOMPILER *
- \****************/
- /**
- * Note: The decompiler does not handle any xmroption extensions
- * such as &&&, |||, ? operators and switch statements, as
- * they do branches with a non-empty stack, which is way
- * beyond this code's ability to analyze.
- */
- public class OTDecompile: ObjectTokens
- {
- public const string _mainCallNo = "__mainCallNo$";
- public const string _callLabel = "__call_";
- public const string _callMode = "callMode";
- public const string _checkRunQuick = "CheckRunQuick";
- public const string _checkRunStack = "CheckRunStack";
- public const string _cmRestore = "__cmRestore";
- public const string _doBreak = "dobreak_";
- public const string _doCont = "docont_";
- public const string _doGblInit = "doGblInit";
- public const string _doLoop = "doloop_";
- public const string _ehArgs = "ehArgs";
- public const string _forBreak = "forbreak_";
- public const string _forCont = "forcont_";
- public const string _forLoop = "forloop_";
- public const string _globalvarinit = "$globalvarinit()";
- public const string _heapTrackerPop = "Pop";
- public const string _heapTrackerPush = "Push";
- public const string _ifDone = "ifdone_";
- public const string _ifElse = "ifelse_";
- public const string _llAbstemp = "llAbstemp";
- public const string _retlbl = "__retlbl";
- public const string _retval = "__retval$";
- public const string _whileBreak = "whilebreak_";
- public const string _whileCont = "whilecont_";
- public const string _whileLoop = "whileloop_";
- public const string _xmrinst = "__xmrinst";
- public const string _xmrinstlocal = "__xmrinst$";
- private const string INDENT = " ";
- private const string LABELINDENT = " ";
- private static Dictionary<string, string> typeTranslator = InitTypeTranslator();
- private static Dictionary<string, string> InitTypeTranslator()
- {
- Dictionary<string, string> d = new Dictionary<string, string>();
- d["Boolean"] = "integer";
- d["bool"] = "integer";
- d["Double"] = "float";
- d["double"] = "float";
- d["Int32"] = "integer";
- d["int"] = "integer";
- d["htlist"] = "list";
- d["htobject"] = "object";
- d["htstring"] = "string";
- d["lslfloat"] = "float";
- d["lslint"] = "integer";
- d["lsllist"] = "list";
- d["lslrot"] = "rotation";
- d["lslstr"] = "string";
- d["lslvec"] = "vector";
- d["Quaternion"] = "rotation";
- d["String"] = "string";
- d["Vector3"] = "vector";
- return d;
- }
- private Dictionary<int, OTLocal> eharglist;
- private Dictionary<int, OTLabel> labels;
- private Dictionary<int, OTLocal> locals;
- private Dictionary<string, string[]> methargnames;
- private LinkedList<OTCilInstr> cilinstrs;
- private OTStmtBlock topBlock;
- private Stack<OTOpnd> opstack;
- private Stack<OTStmtBegExcBlk> trystack;
- private Stack<OTStmtBlock> blockstack;
- private int dupNo;
- private DynamicMethod method;
- private string laststate;
- private TextWriter twout;
- public OTDecompile(ScriptObjCode scriptObjCode, TextWriter twout) : base(scriptObjCode)
- {
- this.twout = twout;
- twout.Write("xmroption dollarsigns;");
- methargnames = new Dictionary<string, string[]>();
- }
- public override void Close()
- {
- if(laststate != null)
- {
- twout.Write("\n}");
- laststate = null;
- }
- twout.Write('\n');
- }
- /**
- * About to generate object code for this method.
- */
- public override void BegMethod(DynamicMethod method)
- {
- this.method = method;
- eharglist = new Dictionary<int, OTLocal>();
- labels = new Dictionary<int, OTLabel>();
- locals = new Dictionary<int, OTLocal>();
- cilinstrs = new LinkedList<OTCilInstr>();
- opstack = new Stack<OTOpnd>();
- trystack = new Stack<OTStmtBegExcBlk>();
- blockstack = new Stack<OTStmtBlock>();
- dupNo = 0;
- }
- /**
- * Dump out reconstructed source for this method.
- */
- public override void EndMethod()
- {
- // Convert CIL code to primitive statements.
- // There are a bunch of labels and internal code such as call stack save restore.
- topBlock = new OTStmtBlock();
- blockstack.Push(topBlock);
- for(LinkedListNode<OTCilInstr> link = cilinstrs.First; link != null; link = link.Next)
- {
- link.Value.BuildStatements(this, link);
- }
- // Strip out stuff we don't want, such as references to callMode.
- // This strips out stack frame capture and restore code.
- topBlock.StripStuff(null);
- // including a possible final return statement
- // - delete if void return value
- // - delete if returning __retval cuz we converted all __retval assignments to return statements
- if((topBlock.blkstmts.Last != null) && (topBlock.blkstmts.Last.Value is OTStmtRet))
- {
- OTStmtRet finalret = (OTStmtRet)topBlock.blkstmts.Last.Value;
- if((finalret.value == null) ||
- ((finalret.value is OTOpndLocal) &&
- ((OTOpndLocal)finalret.value).local.name.StartsWith(_retval)))
- {
- topBlock.blkstmts.RemoveLast();
- }
- }
- // At this point, all behind-the-scenes references are removed except
- // that the do/for/if/while blocks are represented by OTStmtCont-style
- // if/jumps. So try to convert them to the higher-level structures.
- topBlock.DetectDoForIfWhile(null);
- // Final strip to get rid of unneeded @forbreak_<suffix>; labels and the like.
- topBlock.StripStuff(null);
- // Build reference counts so we don't output unneeded declarations,
- // especially temps and internal variables.
- foreach(OTLocal local in locals.Values)
- {
- local.nlclreads = 0;
- local.nlclwrites = 0;
- }
- topBlock.CountRefs();
- for(IEnumerator<int> localenum = locals.Keys.GetEnumerator(); localenum.MoveNext();)
- {
- OTLocal local = locals[localenum.Current];
- if(((local.nlclreads | local.nlclwrites) == 0) || local.name.StartsWith(_xmrinstlocal))
- {
- locals.Remove(localenum.Current);
- localenum = locals.Keys.GetEnumerator();
- }
- }
- // Strip the $n off of local vars that are not ambiguous.
- // Make sure they don't mask globals and arguments as well.
- Dictionary<string, int> namecounts = new Dictionary<string, int>();
- foreach(Dictionary<int, string> varnames in scriptObjCode.globalVarNames.Values)
- {
- foreach(string varname in varnames.Values)
- {
- int count;
- if(!namecounts.TryGetValue(varname, out count))
- count = 0;
- namecounts[varname] = count + 1;
- }
- }
- if(methargnames.ContainsKey(method.Name))
- {
- foreach(string argname in methargnames[method.Name])
- {
- int count;
- if(!namecounts.TryGetValue(argname, out count))
- count = 0;
- namecounts[argname] = count + 1;
- }
- }
- foreach(OTLocal local in locals.Values)
- {
- int i = local.name.LastIndexOf('$');
- string name = local.name.Substring(0, i);
- int count;
- if(!namecounts.TryGetValue(name, out count))
- count = 0;
- namecounts[name] = count + 1;
- }
- foreach(OTLocal local in locals.Values)
- {
- int i = local.name.LastIndexOf('$');
- string name = local.name.Substring(0, i);
- int count = namecounts[name];
- if(count == 1)
- local.name = name;
- }
- // Print out result.
- if(method.Name == _globalvarinit)
- {
- GlobalsDump();
- }
- else
- {
- MethodDump();
- }
- }
- /**
- * Add instructions to stream.
- */
- public override void DefineLabel(int number, string name)
- {
- labels.Add(number, new OTLabel(number, name));
- }
- public override void DefineLocal(int number, string name, string type, Type syType)
- {
- locals.Add(number, new OTLocal(number, name, type));
- }
- public override void DefineMethod(string methName, Type retType, Type[] argTypes, string[] argNames)
- {
- methargnames[methName] = argNames;
- }
- public override void MarkLabel(int offset, int number)
- {
- OTCilInstr label = labels[number];
- label.offset = offset;
- cilinstrs.AddLast(label);
- }
- public override void BegExcBlk(int offset)
- {
- cilinstrs.AddLast(new OTCilBegExcBlk(offset));
- }
- public override void BegCatBlk(int offset, Type excType)
- {
- cilinstrs.AddLast(new OTCilBegCatBlk(offset, excType));
- }
- public override void BegFinBlk(int offset)
- {
- cilinstrs.AddLast(new OTCilBegFinBlk(offset));
- }
- public override void EndExcBlk(int offset)
- {
- cilinstrs.AddLast(new OTCilEndExcBlk(offset));
- }
- public override void EmitNull(int offset, OpCode opCode)
- {
- cilinstrs.AddLast(new OTCilNull(offset, opCode));
- }
- public override void EmitField(int offset, OpCode opCode, FieldInfo field)
- {
- cilinstrs.AddLast(new OTCilField(offset, opCode, field));
- }
- public override void EmitLocal(int offset, OpCode opCode, int number)
- {
- cilinstrs.AddLast(new OTCilLocal(offset, opCode, locals[number]));
- }
- public override void EmitType(int offset, OpCode opCode, Type type)
- {
- cilinstrs.AddLast(new OTCilType(offset, opCode, type));
- }
- public override void EmitLabel(int offset, OpCode opCode, int number)
- {
- cilinstrs.AddLast(new OTCilLabel(offset, opCode, labels[number]));
- }
- public override void EmitLabels(int offset, OpCode opCode, int[] numbers)
- {
- OTLabel[] labelarray = new OTLabel[numbers.Length];
- for(int i = 0; i < numbers.Length; i++)
- {
- labelarray[i] = labels[numbers[i]];
- }
- cilinstrs.AddLast(new OTCilLabels(offset, opCode, labelarray));
- }
- public override void EmitMethod(int offset, OpCode opCode, MethodInfo method)
- {
- cilinstrs.AddLast(new OTCilMethod(offset, opCode, method));
- }
- public override void EmitCtor(int offset, OpCode opCode, ConstructorInfo ctor)
- {
- cilinstrs.AddLast(new OTCilCtor(offset, opCode, ctor));
- }
- public override void EmitDouble(int offset, OpCode opCode, double value)
- {
- cilinstrs.AddLast(new OTCilDouble(offset, opCode, value));
- }
- public override void EmitFloat(int offset, OpCode opCode, float value)
- {
- cilinstrs.AddLast(new OTCilFloat(offset, opCode, value));
- }
- public override void EmitInteger(int offset, OpCode opCode, int value)
- {
- cilinstrs.AddLast(new OTCilInteger(offset, opCode, value));
- }
- public override void EmitString(int offset, OpCode opCode, string value)
- {
- cilinstrs.AddLast(new OTCilString(offset, opCode, value));
- }
- /**
- * Add the given statement to the end of the currently open block.
- */
- public void AddLastStmt(OTStmt stmt)
- {
- blockstack.Peek().blkstmts.AddLast(stmt);
- }
- /**
- * Generate output for $globalvarinit() function.
- * Also outputs declarations for global variables.
- */
- private void GlobalsDump()
- {
- // Scan $globalvarinit(). It should only have global var assignments in it.
- // Also gather up list of variables it initializes.
- bool badinit = false;
- Dictionary<string, string> inittypes = new Dictionary<string, string>();
- foreach(OTStmt stmt in topBlock.blkstmts)
- {
- if(!(stmt is OTStmtStore))
- {
- badinit = true;
- break;
- }
- OTStmtStore store = (OTStmtStore)stmt;
- if(!(store.varwr is OTOpndGlobal))
- {
- badinit = true;
- break;
- }
- OTOpndGlobal globalop = (OTOpndGlobal)store.varwr;
- inittypes[globalop.PrintableString] = "";
- }
- // Scan through list of all global variables in the script.
- // Output declarations for those what don't have any init statement for them.
- // Save the type for those that do have init statements.
- bool first = true;
- foreach(string iartypename in scriptObjCode.globalVarNames.Keys)
- {
- Dictionary<int, string> varnames = scriptObjCode.globalVarNames[iartypename];
- string typename = iartypename.ToLowerInvariant();
- if(typename.StartsWith("iar"))
- typename = typename.Substring(3);
- if(typename.EndsWith("s"))
- typename = typename.Substring(0, typename.Length - 1);
- foreach(string varname in varnames.Values)
- {
- if(!badinit && inittypes.ContainsKey(varname))
- {
- inittypes[varname] = typename;
- }
- else
- {
- if(first)
- twout.Write('\n');
- twout.Write('\n' + typename + ' ' + varname + ';');
- first = false;
- }
- }
- }
- // If $globalvarinit() has anything bad in it, output it as a function.
- // Otherwise, output it as a series of global declarations with init values.
- if(badinit)
- {
- MethodDump();
- }
- else
- {
- foreach(OTStmt stmt in topBlock.blkstmts)
- {
- OTStmtStore store = (OTStmtStore)stmt;
- OTOpndGlobal globalop = (OTOpndGlobal)store.varwr;
- string name = globalop.PrintableString;
- if(first)
- twout.Write('\n');
- twout.Write('\n' + inittypes[name] + ' ');
- store.PrintStmt(twout, "");
- first = false;
- }
- }
- }
- /**
- * Generate output for other functions.
- */
- private void MethodDump()
- {
- string indent;
- // Event handlers don't have an argument list as such in the original
- // code. Instead they have a series of assignments from ehargs[] to
- // local variables. So make those local variables look like they are
- // an argument list.
- int i = method.Name.IndexOf(' ');
- if(i >= 0)
- {
- // Maybe we have to output the state name.
- string statename = method.Name.Substring(0, i);
- string eventname = method.Name.Substring(++i);
- if(laststate != statename)
- {
- if(laststate != null)
- twout.Write("\n}");
- if(statename == "default")
- {
- twout.Write("\n\ndefault {");
- }
- else
- {
- twout.Write("\n\nstate " + statename + " {");
- }
- laststate = statename;
- }
- else
- {
- twout.Write('\n');
- }
- // Output event name and argument list.
- // Remove from locals list so they don't print below.
- twout.Write('\n' + INDENT + eventname + " (");
- MethodInfo meth = typeof(IEventHandlers).GetMethod(eventname);
- i = 0;
- foreach(ParameterInfo pi in meth.GetParameters())
- {
- // skip the first param cuz it's the XMRInstance arg
- if(i > 0)
- twout.Write(", ");
- OTLocal local;
- if(eharglist.TryGetValue(i, out local) && locals.ContainsKey(local.number))
- {
- twout.Write(local.DumpString());
- locals.Remove(local.number);
- }
- else
- {
- // maybe the assignment was removed
- // eg, because the local was write-only (not referenced)
- // so substitute in placeholder that won't be referenced
- twout.Write(AbbrType(pi.ParameterType) + " arg$" + (i + 1));
- }
- i++;
- }
- twout.Write(')');
- // Indent method body by 4 spaces.
- indent = INDENT;
- }
- else
- {
- // Maybe need to close out previous state.
- if(laststate != null)
- {
- twout.Write("\n}");
- laststate = null;
- }
- // Output blank line and return type (if any).
- twout.Write("\n\n");
- if(method.ReturnType != typeof(void))
- {
- twout.Write(AbbrType(method.ReturnType) + ' ');
- }
- // Output method name and argument list.
- int j = method.Name.IndexOf('(');
- if(j < 0)
- {
- twout.Write(method.Name);
- }
- else
- {
- twout.Write(method.Name.Substring(0, j) + " (");
- bool first = true;
- j = 0;
- foreach(ParameterInfo pi in method.GetParameters())
- {
- if(j > 0)
- { // skip the XMRInstance arg$0 parameter
- if(!first)
- twout.Write(", ");
- twout.Write(AbbrType(pi.ParameterType) + ' ' + MethArgName(j));
- first = false;
- }
- j++;
- }
- twout.Write(')');
- }
- // Don't indent method body at all.
- indent = "";
- }
- // Output local variable declarations.
- twout.Write('\n' + indent + '{');
- bool didOne = false;
- foreach(OTLocal local in locals.Values)
- {
- twout.Write('\n' + indent + INDENT + local.DumpString() + "; // r:" + local.nlclreads + " w:" + local.nlclwrites);
- didOne = true;
- }
- if(didOne)
- twout.Write('\n');
- // Output statements.
- if(topBlock.blkstmts.Count == 0)
- {
- twout.Write(" }");
- }
- else
- {
- topBlock.PrintBodyAndEnd(twout, indent);
- }
- }
- /**
- * Get abbreviated type string.
- */
- public static string AbbrType(Type type)
- {
- if(type == null)
- return "null";
- return AbbrType(type.Name);
- }
- public static string AbbrType(string type)
- {
- if(type.StartsWith("OpenSim.Region.ScriptEngine.YEngine."))
- {
- type = type.Substring(38);
- int i = type.IndexOf(',');
- if(i > 0)
- type = type.Substring(0, i);
- }
- if(typeTranslator.ContainsKey(type))
- {
- type = typeTranslator[type];
- }
- return type;
- }
- /**
- * Get current method's argument name.
- */
- public string MethArgName(int index)
- {
- string[] argnames;
- if(methargnames.TryGetValue(method.Name, out argnames) && (index < argnames.Length))
- {
- return argnames[index];
- }
- return "arg$" + index;
- }
- /**
- * Strip svperflvovs (float) cast from rotation/vector values.
- */
- public static OTOpnd StripFloatCast(OTOpnd op)
- {
- if(op is OTOpndCast)
- {
- OTOpndCast opcast = (OTOpndCast)op;
- if((opcast.type == typeof(double)) && (opcast.value is OTOpndInt))
- {
- return opcast.value;
- }
- }
- return op;
- }
- /**
- * Strip svperflvovs Brtrues so we don't end up with stuff like 'if (!! someint) ...'.
- */
- public static OTOpnd StripBrtrue(OTOpnd op)
- {
- if(op is OTOpndUnOp)
- {
- OTOpndUnOp opunop = (OTOpndUnOp)op;
- if(opunop.opCode == MyOp.Brtrue)
- return opunop.value;
- }
- return op;
- }
- /*
- * Local variable declaration.
- */
- private class OTLocal
- {
- public int number;
- public string name;
- public string type;
- public int nlclreads;
- public int nlclwrites;
- public OTLocal(int number, string name, string type)
- {
- this.number = number;
- this.name = name.StartsWith("tmp$") ? name : name + "$" + number;
- this.type = type;
- }
- public string DumpString()
- {
- return AbbrType(type) + ' ' + name;
- }
- }
- /***********************************************\
- * Tokens that are one-for-one with CIL code *
- \***********************************************/
- /*
- * Part of instruction stream.
- */
- public abstract class OTCilInstr
- {
- public int offset; // cil offset
- public OTCilInstr(int offset)
- {
- this.offset = offset;
- }
- public abstract string DumpString();
- public abstract void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link);
- protected void CheckEmptyStack(OTDecompile decompile, string opMnemonic)
- {
- if(decompile.opstack.Count > 0)
- {
- Console.Error.WriteLine("CheckEmptyStack: " + decompile.method.Name + " 0x" + offset.ToString("X") + ": " +
- opMnemonic + " stack depth " + decompile.opstack.Count);
- }
- }
- }
- /*
- * Label mark point.
- */
- private class OTLabel: OTCilInstr
- {
- public int number;
- public string name;
- public int lbljumps;
- public OTLabel(int number, string name) : base(-1)
- {
- this.number = number;
- this.name = name;
- }
- public string PrintableName
- {
- get
- {
- if(name.StartsWith(_doBreak))
- return _doBreak + "$" + number;
- if(name.StartsWith(_doCont))
- return _doCont + "$" + number;
- if(name.StartsWith(_forBreak))
- return _forBreak + "$" + number;
- if(name.StartsWith(_forCont))
- return _forCont + "$" + number;
- if(name.StartsWith(_whileBreak))
- return _whileBreak + "$" + number;
- if(name.StartsWith(_whileCont))
- return _whileCont + "$" + number;
- return name;
- }
- }
- public override string DumpString()
- {
- return name + ":";
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- OTStmtLabel.AddLast(decompile, this);
- }
- }
- /*
- * 'try {'
- */
- private class OTCilBegExcBlk: OTCilInstr
- {
- public LinkedList<OTCilBegCatBlk> catches = new LinkedList<OTCilBegCatBlk>();
- public OTCilBegExcBlk(int offset) : base(offset)
- {
- }
- public override string DumpString()
- {
- return "try {";
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- CheckEmptyStack(decompile, "try");
- // link the try itself onto outer block
- OTStmtBegExcBlk trystmt = new OTStmtBegExcBlk();
- decompile.AddLastStmt(trystmt);
- // subsequent statements go to the try block
- trystmt.tryblock = new OTStmtBlock();
- decompile.trystack.Push(trystmt);
- decompile.blockstack.Push(trystmt.tryblock);
- }
- }
- /*
- * '} catch (...) {'
- */
- private class OTCilBegCatBlk: OTCilInstr
- {
- public Type excType;
- public OTCilBegCatBlk(int offset, Type excType) : base(offset)
- {
- this.excType = excType;
- }
- public override string DumpString()
- {
- return "} catch (" + AbbrType(excType) + ") {";
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- CheckEmptyStack(decompile, "catch");
- // link the catch itself onto the try statement
- OTStmtBegExcBlk trystmt = decompile.trystack.Peek();
- OTStmtBegCatBlk catstmt = new OTStmtBegCatBlk(excType);
- trystmt.catches.AddLast(catstmt);
- // start capturing statements into the catch block
- catstmt.tryblock = trystmt;
- catstmt.catchblock = new OTStmtBlock();
- decompile.blockstack.Pop();
- decompile.blockstack.Push(catstmt.catchblock);
- // fill the stack slot with something for the exception argument
- OTOpndDup dup = new OTOpndDup(++decompile.dupNo);
- decompile.opstack.Push(dup);
- }
- }
- /*
- * '} finally {'
- */
- private class OTCilBegFinBlk: OTCilInstr
- {
- public OTCilBegFinBlk(int offset) : base(offset)
- {
- }
- public override string DumpString()
- {
- return "} finally {";
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- CheckEmptyStack(decompile, "finally");
- // link the finally itself to the try statement
- OTStmtBegExcBlk trystmt = decompile.trystack.Peek();
- OTStmtBegFinBlk finstmt = new OTStmtBegFinBlk();
- trystmt.finblock = finstmt;
- // start capturing statements into the finally block
- finstmt.tryblock = trystmt;
- finstmt.finblock = new OTStmtBlock();
- decompile.blockstack.Pop();
- decompile.blockstack.Push(finstmt.finblock);
- }
- }
- /*
- * '}' end of try
- */
- private class OTCilEndExcBlk: OTCilInstr
- {
- public OTCilEndExcBlk(int offset) : base(offset)
- {
- }
- public override string DumpString()
- {
- return "} // end try";
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- CheckEmptyStack(decompile, "endtry");
- // pop the try/catch/finally blocks from stacks
- decompile.blockstack.Pop();
- decompile.trystack.Pop();
- // subsequent statements collect following the try
- }
- }
- /*
- * Actual opcodes (instructions).
- */
- private class OTCilNull: OTCilInstr
- {
- public MyOp opCode;
- public OTCilNull(int offset, OpCode opCode) : base(offset)
- {
- this.opCode = MyOp.GetByName(opCode.Name);
- }
- public override string DumpString()
- {
- return opCode.ToString();
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "conv.i1":
- case "conv.i2":
- case "conv.i4":
- case "conv.i8":
- {
- OTOpnd value = decompile.opstack.Pop();
- decompile.opstack.Push(new OTOpndCast(typeof(int), value));
- break;
- }
- case "conv.r4":
- case "conv.r8":
- {
- OTOpnd value = decompile.opstack.Pop();
- decompile.opstack.Push(new OTOpndCast(typeof(double), value));
- break;
- }
- case "dup":
- {
- OTOpnd value = decompile.opstack.Pop();
- if(!(value is OTOpndDup))
- {
- OTOpndDup dup = new OTOpndDup(++decompile.dupNo);
- OTStmtStore.AddLast(decompile, dup, value);
- value = dup;
- }
- decompile.opstack.Push(value);
- decompile.opstack.Push(value);
- break;
- }
- case "endfinally":
- break;
- case "ldarg.0":
- {
- decompile.opstack.Push(new OTOpndArg(0, false, decompile));
- break;
- }
- case "ldarg.1":
- {
- decompile.opstack.Push(new OTOpndArg(1, false, decompile));
- break;
- }
- case "ldarg.2":
- {
- decompile.opstack.Push(new OTOpndArg(2, false, decompile));
- break;
- }
- case "ldarg.3":
- {
- decompile.opstack.Push(new OTOpndArg(3, false, decompile));
- break;
- }
- case "ldc.i4.0":
- {
- decompile.opstack.Push(new OTOpndInt(0));
- break;
- }
- case "ldc.i4.1":
- {
- decompile.opstack.Push(new OTOpndInt(1));
- break;
- }
- case "ldc.i4.2":
- {
- decompile.opstack.Push(new OTOpndInt(2));
- break;
- }
- case "ldc.i4.3":
- {
- decompile.opstack.Push(new OTOpndInt(3));
- break;
- }
- case "ldc.i4.4":
- {
- decompile.opstack.Push(new OTOpndInt(4));
- break;
- }
- case "ldc.i4.5":
- {
- decompile.opstack.Push(new OTOpndInt(5));
- break;
- }
- case "ldc.i4.6":
- {
- decompile.opstack.Push(new OTOpndInt(6));
- break;
- }
- case "ldc.i4.7":
- {
- decompile.opstack.Push(new OTOpndInt(7));
- break;
- }
- case "ldc.i4.8":
- {
- decompile.opstack.Push(new OTOpndInt(8));
- break;
- }
- case "ldc.i4.m1":
- {
- decompile.opstack.Push(new OTOpndInt(-1));
- break;
- }
- case "ldelem.i4":
- case "ldelem.r4":
- case "ldelem.r8":
- case "ldelem.ref":
- {
- OTOpnd index = decompile.opstack.Pop();
- OTOpnd array = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndArrayElem.Make(array, index, false, decompile));
- break;
- }
- case "ldnull":
- {
- decompile.opstack.Push(new OTOpndNull());
- break;
- }
- case "neg":
- case "not":
- {
- OTOpnd value = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndUnOp.Make(opCode, value));
- break;
- }
- case "pop":
- {
- OTStmtVoid.AddLast(decompile, decompile.opstack.Pop());
- break;
- }
- case "ret":
- {
- OTOpnd value = null;
- if(decompile.method.ReturnType != typeof(void))
- {
- value = decompile.opstack.Pop();
- }
- CheckEmptyStack(decompile);
- decompile.AddLastStmt(new OTStmtRet(value));
- break;
- }
- case "stelem.i4":
- case "stelem.r8":
- case "stelem.ref":
- {
- OTOpnd value = decompile.opstack.Pop();
- OTOpnd index = decompile.opstack.Pop();
- OTOpnd array = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, OTOpndArrayElem.Make(array, index, false, decompile), value);
- break;
- }
- case "throw":
- {
- OTOpnd value = decompile.opstack.Pop();
- CheckEmptyStack(decompile);
- decompile.AddLastStmt(new OTStmtThrow(value, decompile));
- break;
- }
- case "add":
- case "and":
- case "ceq":
- case "cgt":
- case "cgt.un":
- case "clt":
- case "clt.un":
- case "div":
- case "div.un":
- case "mul":
- case "or":
- case "rem":
- case "rem.un":
- case "shl":
- case "shr":
- case "shr.un":
- case "sub":
- case "xor":
- {
- OTOpnd rite = decompile.opstack.Pop();
- OTOpnd left = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndBinOp.Make(left, opCode, rite));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- protected void CheckEmptyStack(OTDecompile decompile)
- {
- CheckEmptyStack(decompile, opCode.ToString());
- }
- }
- private class OTCilField: OTCilNull
- {
- public FieldInfo field;
- public OTCilField(int offset, OpCode opCode, FieldInfo field) : base(offset, opCode)
- {
- this.field = field;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + field.Name;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldfld":
- {
- OTOpnd obj = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndField.Make(obj, field));
- break;
- }
- case "ldsfld":
- {
- decompile.opstack.Push(new OTOpndSField(field));
- break;
- }
- case "stfld":
- {
- OTOpnd val = decompile.opstack.Pop();
- OTOpnd obj = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, OTOpndField.Make(obj, field), val);
- break;
- }
- case "stsfld":
- {
- OTOpnd val = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, new OTOpndSField(field), val);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilLocal: OTCilNull
- {
- public OTLocal local;
- public OTCilLocal(int offset, OpCode opCode, OTLocal local) : base(offset, opCode)
- {
- this.local = local;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + local.name;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldloc":
- {
- decompile.opstack.Push(new OTOpndLocal(local));
- break;
- }
- case "ldloca":
- {
- decompile.opstack.Push(new OTOpndLocalRef(local));
- break;
- }
- case "stloc":
- {
- OTOpnd val = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, new OTOpndLocal(local), val);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilType: OTCilNull
- {
- public Type type;
- public OTCilType(int offset, OpCode opCode, Type type) : base(offset, opCode)
- {
- this.type = type;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + AbbrType(type);
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "box":
- {
- break;
- }
- case "castclass":
- case "unbox.any":
- {
- OTOpnd value = decompile.opstack.Pop();
- decompile.opstack.Push(new OTOpndCast(type, value));
- break;
- }
- case "ldelem":
- {
- OTOpnd index = decompile.opstack.Pop();
- OTOpnd array = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndArrayElem.Make(array, index, false, decompile));
- break;
- }
- case "ldelema":
- {
- OTOpnd index = decompile.opstack.Pop();
- OTOpnd array = decompile.opstack.Pop();
- decompile.opstack.Push(OTOpndArrayElem.Make(array, index, true, decompile));
- break;
- }
- case "newarr":
- {
- OTOpnd index = decompile.opstack.Pop();
- decompile.opstack.Push(new OTOpndNewarr(type, index));
- break;
- }
- case "stelem":
- {
- OTOpnd value = decompile.opstack.Pop();
- OTOpnd index = decompile.opstack.Pop();
- OTOpnd array = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, OTOpndArrayElem.Make(array, index, false, decompile), value);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilLabel: OTCilNull
- {
- public OTLabel label;
- public OTCilLabel(int offset, OpCode opCode, OTLabel label) : base(offset, opCode)
- {
- this.label = label;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + label.name;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- // We don't handle non-empty stack at branch points.
- //
- // So handle this case specially:
- //
- // dup
- // ldc.i4.0
- // bge.s llAbstemp << we are here
- // neg
- // llAbstemp:
- //
- // becomes:
- //
- // call llAbs
- case "bge.s":
- {
- OTOpnd rite = decompile.opstack.Pop(); // alleged zero
- OTOpnd left = decompile.opstack.Pop(); // alleged dup
- if((label.name == _llAbstemp) && (decompile.opstack.Count > 0))
- {
- LinkedListNode<OTCilInstr> linkneg = link.Next;
- if((left is OTOpndDup) && (rite is OTOpndInt) &&
- (linkneg != null) && (linkneg.Value is OTCilNull) &&
- (((OTCilNull)linkneg.Value).opCode == MyOp.Neg))
- {
- OTOpndInt riteint = (OTOpndInt)rite;
- LinkedListNode<OTCilInstr> linklbl = linkneg.Next;
- if((riteint.value == 0) && (linklbl != null) && (linklbl.Value is OTLabel) &&
- (((OTLabel)linklbl.Value) == label))
- {
- linkneg.List.Remove(linkneg);
- linklbl.List.Remove(linklbl);
- MethodInfo method = typeof(ScriptBaseClass).GetMethod("llAbs");
- OTOpnd[] args = new OTOpnd[] { new OTOpndNull(), decompile.opstack.Pop() };
- OTOpndCall.AddLast(decompile, method, args);
- break;
- }
- }
- }
- CheckEmptyStack(decompile);
- OTOpnd valu = OTOpndBinOp.Make(left, opCode, rite);
- OTStmt jump = OTStmtJump.Make(label);
- decompile.AddLastStmt(new OTStmtCond(valu, jump));
- break;
- }
- case "beq":
- case "bge":
- case "bgt":
- case "ble":
- case "blt":
- case "bne.un":
- case "beq.s":
- case "bgt.s":
- case "ble.s":
- case "blt.s":
- case "bne.un.s":
- {
- OTOpnd rite = decompile.opstack.Pop();
- OTOpnd left = decompile.opstack.Pop();
- CheckEmptyStack(decompile);
- OTOpnd valu = OTOpndBinOp.Make(left, opCode, rite);
- OTStmt jump = OTStmtJump.Make(label);
- decompile.AddLastStmt(new OTStmtCond(valu, jump));
- break;
- }
- case "brfalse":
- case "brfalse.s":
- case "brtrue":
- case "brtrue.s":
- {
- OTOpnd value = decompile.opstack.Pop();
- CheckEmptyStack(decompile);
- OTOpnd valu = OTOpndUnOp.Make(opCode, value);
- OTStmt jump = OTStmtJump.Make(label);
- decompile.AddLastStmt(new OTStmtCond(valu, jump));
- break;
- }
- case "br":
- case "br.s":
- case "leave":
- {
- CheckEmptyStack(decompile);
- OTStmt jump = OTStmtJump.Make(label);
- decompile.AddLastStmt(jump);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilLabels: OTCilNull
- {
- public OTLabel[] labels;
- public OTCilLabels(int offset, OpCode opCode, OTLabel[] labels) : base(offset, opCode)
- {
- this.labels = labels;
- }
- public override string DumpString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(opCode.ToString());
- foreach(OTLabel label in labels)
- {
- sb.Append(' ');
- sb.Append(label.name);
- }
- return sb.ToString();
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "switch":
- {
- OTOpnd value = decompile.opstack.Pop();
- CheckEmptyStack(decompile);
- decompile.AddLastStmt(new OTStmtSwitch(value, labels));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilMethod: OTCilNull
- {
- public MethodInfo method;
- public OTCilMethod(int offset, OpCode opCode, MethodInfo method) : base(offset, opCode)
- {
- this.method = method;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + method.Name;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "call":
- case "callvirt":
- {
- int nargs = method.GetParameters().Length;
- if(!method.IsStatic)
- nargs++;
- OTOpnd[] args = new OTOpnd[nargs];
- for(int i = nargs; --i >= 0;)
- {
- args[i] = decompile.opstack.Pop();
- }
- OTOpndCall.AddLast(decompile, method, args);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilCtor: OTCilNull
- {
- public ConstructorInfo ctor;
- public OTCilCtor(int offset, OpCode opCode, ConstructorInfo ctor) : base(offset, opCode)
- {
- this.ctor = ctor;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + AbbrType(ctor.DeclaringType);
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "newobj":
- {
- int nargs = ctor.GetParameters().Length;
- OTOpnd[] args = new OTOpnd[nargs];
- for(int i = nargs; --i >= 0;)
- {
- args[i] = decompile.opstack.Pop();
- }
- decompile.opstack.Push(OTOpndNewobj.Make(ctor, args));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilDouble: OTCilNull
- {
- public double value;
- public OTCilDouble(int offset, OpCode opCode, double value) : base(offset, opCode)
- {
- this.value = value;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + value;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldc.r8":
- {
- decompile.opstack.Push(new OTOpndDouble(value));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilFloat: OTCilNull
- {
- public float value;
- public OTCilFloat(int offset, OpCode opCode, float value) : base(offset, opCode)
- {
- this.value = value;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + value;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldc.r4":
- {
- decompile.opstack.Push(new OTOpndFloat(value));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilInteger: OTCilNull
- {
- public int value;
- public OTCilInteger(int offset, OpCode opCode, int value) : base(offset, opCode)
- {
- this.value = value;
- }
- public override string DumpString()
- {
- return opCode.ToString() + ' ' + value;
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldarg":
- case "ldarg.s":
- {
- decompile.opstack.Push(new OTOpndArg(value, false, decompile));
- break;
- }
- case "ldarga":
- case "ldarga.s":
- {
- decompile.opstack.Push(new OTOpndArg(value, true, decompile));
- break;
- }
- case "ldc.i4":
- case "ldc.i4.s":
- {
- decompile.opstack.Push(new OTOpndInt(value));
- break;
- }
- case "starg":
- {
- OTOpnd val = decompile.opstack.Pop();
- OTStmtStore.AddLast(decompile, new OTOpndArg(value, false, decompile), val);
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- private class OTCilString: OTCilNull
- {
- public string value;
- public OTCilString(int offset, OpCode opCode, string value) : base(offset, opCode)
- {
- this.value = value;
- }
- public override string DumpString()
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(opCode.ToString());
- sb.Append(' ');
- TokenDeclInline.PrintParamString(sb, value);
- return sb.ToString();
- }
- public override void BuildStatements(OTDecompile decompile, LinkedListNode<OTCilInstr> link)
- {
- switch(opCode.ToString())
- {
- case "ldstr":
- {
- decompile.opstack.Push(new OTOpndString(value));
- break;
- }
- default:
- throw new Exception("unknown opcode " + opCode.ToString());
- }
- }
- }
- /***************************************\
- * Tokens what are on operand stack. *
- \***************************************/
- public abstract class OTOpnd
- {
- /**
- * See if it possibly has any side effects.
- */
- public abstract bool HasSideEffects
- {
- get;
- }
- /**
- * Increment reference counts.
- */
- public virtual void CountRefs(bool writing)
- {
- }
- /**
- * If this operand is a 'by reference' operand,
- * return the corresponding 'by value' operand.
- */
- public virtual OTOpnd GetNonByRefOpnd()
- {
- return this;
- }
- /**
- * If this operand is same as oldopnd, replace it with newopnd.
- *
- * This default just does a shallow search which is ok if this operand does not have any sub-operands.
- * But it must be overridden for a deep search if this operand has any sub-operands.
- */
- public virtual OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- return this;
- }
- /**
- * See if the two operands are the same value.
- * Note that calls might have side-effects so are never the same.
- */
- public abstract bool SameAs(OTOpnd other);
- /**
- * Get a printable string representation of the operand.
- */
- public abstract string PrintableString
- {
- get;
- }
- }
- /**
- * Argument variable.
- */
- private class OTOpndArg: OTOpnd
- {
- public int index;
- public bool byref;
- private OTDecompile decompile;
- public OTOpndArg(int index, bool byref, OTDecompile decompile)
- {
- this.index = index;
- this.byref = byref;
- this.decompile = decompile;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override OTOpnd GetNonByRefOpnd()
- {
- if(!byref)
- return this;
- return new OTOpndArg(index, false, decompile);
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndArg))
- return false;
- return (((OTOpndArg)other).byref == byref) && (((OTOpndArg)other).index == index);
- }
- public override string PrintableString
- {
- get
- {
- string argname = decompile.MethArgName(index);
- return byref ? ("ref " + argname) : argname;
- }
- }
- }
- /**
- * Element of an array.
- */
- private class OTOpndArrayElem: OTOpnd
- {
- public bool byref;
- public OTOpnd array;
- public OTOpnd index;
- public static OTOpnd Make(OTOpnd array, OTOpnd index, bool byref, OTDecompile decompile)
- {
- // arg$0.glblVars.iar<type>[<intconst>] is a reference to a global variable
- // likewise so is __xmrinst.glblVars.iar<type>[<intconst>]
- if((array is OTOpndField) && (index is OTOpndInt))
- {
- // arrayfield = (arg$0.glblVars).iar<type>
- // arrayfieldobj = arg$0.glblVars
- // iartypename = iar<type>
- OTOpndField arrayfield = (OTOpndField)array;
- OTOpnd arrayfieldobj = arrayfield.obj;
- string iartypename = arrayfield.field.Name;
- // See if they are what they are supposed to be.
- if((arrayfieldobj is OTOpndField) && iartypename.StartsWith("iar"))
- {
- // arrayfieldobjfield = arg$0.glblVars
- OTOpndField arrayfieldobjfield = (OTOpndField)arrayfieldobj;
- // See if the parts are what they are supposed to be.
- if(IsArg0OrXMRInst(arrayfieldobjfield.obj) && (arrayfieldobjfield.field.Name == "glblVars"))
- {
- // Everything matches up, make a global variable instead of an array reference.
- return new OTOpndGlobal(iartypename, ((OTOpndInt)index).value, byref, decompile.scriptObjCode);
- }
- }
- }
- // Other array reference.
- OTOpndArrayElem it = new OTOpndArrayElem();
- it.array = array;
- it.index = index;
- it.byref = byref;
- return it;
- }
- private OTOpndArrayElem()
- {
- }
- public override bool HasSideEffects
- {
- get
- {
- return array.HasSideEffects || index.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- array.CountRefs(false);
- index.CountRefs(false);
- }
- public override OTOpnd GetNonByRefOpnd()
- {
- if(!byref)
- return this;
- OTOpndArrayElem it = new OTOpndArrayElem();
- it.array = array;
- it.index = index;
- return it;
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- array = array.ReplaceOperand(oldopnd, newopnd, ref rc);
- index = index.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndArrayElem))
- return false;
- OTOpndArrayElem otherae = (OTOpndArrayElem)other;
- return array.SameAs(otherae.array) && index.SameAs(otherae.index);
- }
- public override string PrintableString
- {
- get
- {
- return (byref ? "ref " : "") + array.PrintableString + "[" + index.PrintableString + "]";
- }
- }
- /**
- * See if the argument is a reference to arg$0 or __xmrinst
- */
- public static bool IsArg0OrXMRInst(OTOpnd obj)
- {
- if(obj is OTOpndArg)
- {
- OTOpndArg objarg = (OTOpndArg)obj;
- return objarg.index == 0;
- }
- if(obj is OTOpndLocal)
- {
- OTOpndLocal objlcl = (OTOpndLocal)obj;
- return objlcl.local.name.StartsWith(_xmrinstlocal);
- }
- return false;
- }
- }
- /**
- * Binary operator.
- */
- private class OTOpndBinOp: OTOpnd
- {
- public OTOpnd left;
- public MyOp opCode;
- public OTOpnd rite;
- private static Dictionary<string, string> xor1ops = InitXor1Ops();
- private static Dictionary<string, string> InitXor1Ops()
- {
- Dictionary<string, string> d = new Dictionary<string, string>();
- d["ceq"] = "cne";
- d["cge"] = "clt";
- d["cgt"] = "cle";
- d["cle"] = "cgt";
- d["clt"] = "cge";
- d["cne"] = "ceq";
- return d;
- }
- public static OTOpnd Make(OTOpnd left, MyOp opCode, OTOpnd rite)
- {
- // ((x clt y) xor 1) => (x cge y) etc
- string xor1op;
- if((left is OTOpndBinOp) && xor1ops.TryGetValue(((OTOpndBinOp)left).opCode.name, out xor1op) &&
- (opCode == MyOp.Xor) &&
- (rite is OTOpndInt) && (((OTOpndInt)rite).value == 1))
- {
- opCode = MyOp.GetByName(xor1op);
- }
- // handle strcmp() cases (see OTOpndStrCmp)
- if(left is OTOpndStrCmp)
- {
- OTOpnd strcmp = ((OTOpndStrCmp)left).MakeBinOp(opCode, rite);
- if(strcmp != null)
- return strcmp;
- }
- // nothing special, make as is
- OTOpndBinOp it = new OTOpndBinOp();
- it.left = left;
- it.opCode = opCode;
- it.rite = rite;
- return it;
- }
- private OTOpndBinOp()
- {
- }
- public override bool HasSideEffects
- {
- get
- {
- return left.HasSideEffects || rite.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- left.CountRefs(false);
- rite.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- left = left.ReplaceOperand(oldopnd, newopnd, ref rc);
- rite = rite.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndBinOp))
- return false;
- OTOpndBinOp otherbo = (OTOpndBinOp)other;
- return left.SameAs(otherbo.left) && (opCode.ToString() == otherbo.opCode.ToString()) && rite.SameAs(otherbo.rite);
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- bool leftneedsparen = ItNeedsParentheses(left, true);
- if(leftneedsparen)
- sb.Append('(');
- sb.Append(left.PrintableString);
- if(leftneedsparen)
- sb.Append(')');
- sb.Append(' ');
- sb.Append(opCode.source);
- sb.Append(' ');
- bool riteneedsparen = ItNeedsParentheses(rite, false);
- if(riteneedsparen)
- sb.Append('(');
- sb.Append(rite.PrintableString);
- if(riteneedsparen)
- sb.Append(')');
- return sb.ToString();
- }
- }
- /**
- * See if source code representation requires parentheses around the given operand.
- * @param it = the other operand to decide about
- * @param itleft = true: 'it' is on the left of this operand (A $ B) # C
- * false: 'it' is on the right of this operand A $ (B # C)
- */
- private bool ItNeedsParentheses(OTOpnd it, bool itleft)
- {
- if(!(it is OTOpndBinOp))
- return false;
- string itop = ((OTOpndBinOp)it).opCode.source;
- string myop = opCode.source;
- // find them in table. higher number is for *, lower is for +.
- int itpi, mypi;
- if(!precedence.TryGetValue(itop, out itpi))
- return true;
- if(!precedence.TryGetValue(myop, out mypi))
- return true;
- int itpiabs = Math.Abs(itpi);
- int mypiabs = Math.Abs(mypi);
- // if its precedence is lower (eg +) than my precedence (eg *), it needs parentheses
- if(itpiabs < mypiabs)
- return true;
- // if its precedence is higher (eg *) than my precedence (eg +), it doesn't needs parentheses
- if(itpiabs > mypiabs)
- return false;
- // if (A $ B) # C, we can safely go without the parentheses
- if(itleft)
- return false;
- // my it
- // A $ (B # C) only works without parentheses for commutative $
- // A - (B + C) and A - (B - C) require parentheses
- // A + (B - C) does not
- return mypi < 0; // neg: things like -, /, etc require parentheses
- // pos: things like +, *, etc do not need parens
- }
- // see MMRScriptReduce.PrecedenceInit()
- private static Dictionary<string, int> precedence = InitPrecedence();
- private static Dictionary<string, int> InitPrecedence()
- {
- Dictionary<string, int> d = new Dictionary<string, int>();
- d["|"] = 140;
- d["^"] = 160;
- d["&"] = 180;
- d["<<"] = -260;
- d[">>"] = -260;
- d["+"] = 280;
- d["-"] = -280;
- d["*"] = 320;
- d["/"] = -320;
- d["%"] = -320;
- return d;
- }
- }
- /**
- * Call with or without return value.
- */
- private class OTOpndCall: OTOpnd
- {
- private static Dictionary<string, MethodInfo> mathmeths = InitMathMeths();
- private static Dictionary<string, MethodInfo> InitMathMeths()
- {
- Dictionary<string, MethodInfo> d = new Dictionary<string, MethodInfo>();
- d["Acos"] = typeof(ScriptBaseClass).GetMethod("llAcos");
- d["Asin"] = typeof(ScriptBaseClass).GetMethod("llAsin");
- d["Atan"] = typeof(ScriptBaseClass).GetMethod("llAtan");
- d["Cos"] = typeof(ScriptBaseClass).GetMethod("llCos");
- d["Abs"] = typeof(ScriptBaseClass).GetMethod("llFabs");
- d["Log"] = typeof(ScriptBaseClass).GetMethod("llLog");
- d["Log10"] = typeof(ScriptBaseClass).GetMethod("llLog10");
- d["Round"] = typeof(ScriptBaseClass).GetMethod("llRound");
- d["Sin"] = typeof(ScriptBaseClass).GetMethod("llSin");
- d["Sqrt"] = typeof(ScriptBaseClass).GetMethod("llSqrt");
- d["Tan"] = typeof(ScriptBaseClass).GetMethod("llTan");
- return d;
- }
- public MethodInfo method;
- public OTOpnd[] args;
- // pushes on stack for return-value functions
- // pushes to end of instruction stream for return-void functions
- public static void AddLast(OTDecompile decompile, MethodInfo method, OTOpnd[] args)
- {
- int nargs = args.Length;
- // heap tracker push is just the single arg value as far as we're concerned
- if((nargs == 1) && (method.Name == _heapTrackerPush) && method.DeclaringType.Name.StartsWith("HeapTracker"))
- {
- decompile.opstack.Push(args[0]);
- return;
- }
- // heap tracker pop is just a store as far as we're concerned
- if((nargs == 2) && (method.Name == _heapTrackerPop) && method.DeclaringType.Name.StartsWith("HeapTracker"))
- {
- OTStmtStore.AddLast(decompile, args[0], args[1]);
- return;
- }
- // string.Compare() is its own thing cuz it has to decompile many ways
- if((nargs == 2) && (method.DeclaringType == typeof(string)) && (method.Name == "Compare"))
- {
- decompile.opstack.Push(new OTOpndStrCmp(args[0], args[1]));
- return;
- }
- // ObjectToString, etc, should appear as casts
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToBool"))
- {
- MethodInfo meth = typeof(XMRInstAbstract).GetMethod("xmr" + method.Name);
- AddLast(decompile, meth, new OTOpnd[] { new OTOpndNull(), args[0] });
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToFloat"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(double), args[0]));
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToInteger"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(int), args[0]));
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToList"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(LSL_List), args[0]));
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToRotation"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(LSL_Rotation), args[0]));
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToString"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(string), args[0]));
- return;
- }
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.EndsWith("ToVector"))
- {
- decompile.opstack.Push(new OTOpndCast(typeof(LSL_Vector), args[0]));
- return;
- }
- if((method.DeclaringType == typeof(XMRInstAbstract)) && (method.Name == "xmrHeapLeft"))
- {
- AddLast(decompile, typeof(ScriptBaseClass).GetMethod("llGetFreeMemory"), new OTOpnd[] { new OTOpndNull() });
- return;
- }
- // pop to entry in the list/object/string array
- if(PopToGlobalArray(decompile, method, args))
- return;
- // strip off event handler argument unwrapper calls
- if((nargs == 1) && (method.DeclaringType == typeof(TypeCast)) && method.Name.StartsWith("EHArgUnwrap"))
- {
- decompile.opstack.Push(args[0]);
- return;
- }
- // translate Math method to ll method
- MethodInfo mathmeth;
- if((method.DeclaringType == typeof(Math)) && mathmeths.TryGetValue(method.Name, out mathmeth))
- {
- AddLast(decompile, mathmeth, new OTOpnd[] { new OTOpndNull(), args[0] });
- return;
- }
- if((method.DeclaringType == typeof(Math)) && (method.Name == "Atan2"))
- {
- AddLast(decompile, typeof(ScriptBaseClass).GetMethod("llAtan2"), new OTOpnd[] { new OTOpndNull(), args[0], args[1] });
- return;
- }
- if((method.DeclaringType == typeof(Math)) && (method.Name == "Pow"))
- {
- AddLast(decompile, typeof(ScriptBaseClass).GetMethod("llPow"), new OTOpnd[] { new OTOpndNull(), args[0], args[1] });
- return;
- }
- // string concat should be a bunch of adds
- if((method.Name == "Concat") && (method.DeclaringType == typeof(string)))
- {
- int k = args.Length;
- while(k > 1)
- {
- int j = 0;
- int i;
- for(i = 0; i + 2 <= k; i += 2)
- {
- args[j++] = OTOpndBinOp.Make(args[i + 0], MyOp.Add, args[i + 1]);
- }
- while(i < k)
- args[j++] = args[i++];
- k = j;
- }
- if(k > 0)
- decompile.opstack.Push(args[0]);
- return;
- }
- // bunch of calls for rotation and vector arithmetic
- if((method.DeclaringType == typeof(BinOpStr)) && BinOpStrCall(decompile, method, args))
- return;
- if((method.DeclaringType == typeof(ScriptCodeGen)) && (method.Name == "LSLRotationNegate"))
- {
- decompile.opstack.Push(OTOpndUnOp.Make(MyOp.Neg, args[0]));
- return;
- }
- if((method.DeclaringType == typeof(ScriptCodeGen)) && (method.Name == "LSLVectorNegate"))
- {
- decompile.opstack.Push(OTOpndUnOp.Make(MyOp.Neg, args[0]));
- return;
- }
- // otherwise process it as a call
- OTOpndCall call = new OTOpndCall();
- call.method = method;
- call.args = args;
- if(method.ReturnType == typeof(void))
- {
- OTStmtVoid.AddLast(decompile, call);
- }
- else
- {
- decompile.opstack.Push(call);
- }
- }
- public override bool HasSideEffects
- {
- get
- {
- return true;
- }
- }
- /**
- * Handle a call to XMRInstArrays.Pop<List,Object,String>
- * by converting it to a store directly into the array.
- */
- private static bool PopToGlobalArray(OTDecompile decompile, MethodInfo method, OTOpnd[] args)
- {
- if(method.DeclaringType != typeof(XMRInstArrays))
- return false;
- if(args.Length != 3)
- return false;
- string array = null;
- if(method.Name == "PopList")
- array = "iarLists";
- if(method.Name == "PopObject")
- array = "iarObjects";
- if(method.Name == "PopString")
- array = "iarStrings";
- if(array == null)
- return false;
- // make token that points to the iar<whatever> array
- FieldInfo field = typeof(XMRInstArrays).GetField(array);
- OTOpnd arrayfield = OTOpndField.Make(args[0], field);
- // make token that points to the element to be popped to
- OTOpnd element = OTOpndArrayElem.Make(arrayfield, args[1], false, decompile);
- // make a statement to store value in that element
- OTStmtStore.AddLast(decompile, element, args[2]);
- return true;
- }
- /**
- * BinOpStr has a bunch of calls to do funky arithmetic.
- * Instead of generating a call, put back the original source.
- */
- private static bool BinOpStrCall(OTDecompile decompile, MethodInfo method, OTOpnd[] args)
- {
- switch(method.Name)
- {
- case "MethFloatAddList":
- case "MethIntAddList":
- case "MethKeyAddList":
- case "MethListAddFloat":
- case "MethListAddInt":
- case "MethListAddKey":
- case "MethListAddList":
- case "MethListAddObj":
- case "MethListAddRot":
- case "MethListAddStr":
- case "MethListAddVec":
- case "MethObjAddList":
- case "MethRotAddList":
- case "MethRotAddRot":
- case "MethStrAddList":
- case "MethVecAddList":
- case "MethVecAddVec":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Add, args[1]));
- return true;
- }
- case "MethListEqList":
- case "MethRotEqRot":
- case "MethVecEqVec":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Ceq, args[1]));
- return true;
- }
- case "MethListNeList":
- case "MethRotNeRot":
- case "MethVecNeVec":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Cne, args[1]));
- return true;
- }
- case "MethRotSubRot":
- case "MethVecSubVec":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Sub, args[1]));
- return true;
- }
- case "MethFloatMulVec":
- case "MethIntMulVec":
- case "MethRotMulRot":
- case "MethVecMulFloat":
- case "MethVecMulInt":
- case "MethVecMulRot":
- case "MethVecMulVec":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Mul, args[1]));
- return true;
- }
- case "MethRotDivRot":
- case "MethVecDivFloat":
- case "MethVecDivInt":
- case "MethVecDivRot":
- {
- decompile.opstack.Push(OTOpndBinOp.Make(args[0], MyOp.Div, args[1]));
- return true;
- }
- default:
- return false;
- }
- }
- private OTOpndCall()
- {
- }
- public override void CountRefs(bool writing)
- {
- foreach(OTOpnd arg in args)
- {
- arg.CountRefs(false);
- }
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- for(int i = 0; i < args.Length; i++)
- {
- args[i] = args[i].ReplaceOperand(oldopnd, newopnd, ref rc);
- }
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- return false;
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- // GetByKey(a,i) => a[i]
- if((method.DeclaringType == typeof(XMR_Array)) && (method.Name == "GetByKey") && (args.Length == 2))
- {
- sb.Append(args[0].PrintableString);
- sb.Append('[');
- sb.Append(args[1].PrintableString);
- sb.Append(']');
- return sb.ToString();
- }
- // SetByKey(a,i,v) => a[i] = v
- if((method.DeclaringType == typeof(XMR_Array)) && (method.Name == "SetByKey") && (args.Length == 3))
- {
- sb.Append(args[0].PrintableString);
- sb.Append('[');
- sb.Append(args[1].PrintableString);
- sb.Append("] = ");
- sb.Append(args[2].PrintableString);
- return sb.ToString();
- }
- // CompValuListEl.GetElementFromList accesses list elements like an array.
- if((method.DeclaringType == typeof(CompValuListEl)) && (method.Name == "GetElementFromList"))
- {
- sb.Append(args[0].PrintableString);
- sb.Append('[');
- sb.Append(args[1].PrintableString);
- sb.Append(']');
- return sb.ToString();
- }
- // methods that are part of ScriptBaseClass are LSL functions such as llSay()
- // so we want to skip outputting "arg$0," as it is the hidden "this" argument.
- // and there are also XMRInstAbstract functions such as xmrEventDequeue().
- int starti = 0;
- if((method.DeclaringType == typeof(ScriptBaseClass)) && !method.IsStatic)
- starti = 1;
- if((method.DeclaringType == typeof(XMRInstAbstract)) && !method.IsStatic)
- starti = 1;
- // likewise, method that have null as the declaring type are script-defined
- // dynamic methods which have a hidden "this" argument passed as "arg$0".
- if(method.DeclaringType == null)
- starti = 1;
- // all others we want to show the type name (such as Math.Abs, String.Compare, etc)
- if(starti == 0)
- {
- sb.Append(AbbrType(method.DeclaringType));
- sb.Append('.');
- }
- // script-defined functions have the param types as part of their name
- // so strip them off here so they don't clutter things up
- int i = method.Name.IndexOf('(');
- if(i < 0)
- sb.Append(method.Name);
- else
- sb.Append(method.Name.Substring(0, i));
- // now add the call arguments
- sb.Append(" (");
- bool first = true;
- foreach(OTOpnd arg in args)
- {
- if(--starti < 0)
- {
- if(!first)
- sb.Append(", ");
- sb.Append(arg.PrintableString);
- first = false;
- }
- }
- sb.Append(')');
- return sb.ToString();
- }
- }
- }
- /**
- * Cast value to the given type.
- */
- private class OTOpndCast: OTOpnd
- {
- public Type type;
- public OTOpnd value;
- public OTOpndCast(Type type, OTOpnd value)
- {
- this.type = type;
- this.value = value;
- }
- public override bool HasSideEffects
- {
- get
- {
- return value.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- value.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndCast))
- return false;
- OTOpndCast othercast = (OTOpndCast)other;
- return (type == othercast.type) && value.SameAs(othercast.value);
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- sb.Append('(');
- sb.Append(AbbrType(type));
- sb.Append(") ");
- if(value is OTOpndBinOp)
- sb.Append('(');
- sb.Append(value.PrintableString);
- if(value is OTOpndBinOp)
- sb.Append(')');
- return sb.ToString();
- }
- }
- }
- /**
- * Duplicate stack value without re-performing computation.
- * Semantics just like local var except it doesn't have a declaration.
- */
- private class OTOpndDup: OTOpnd
- {
- public int index;
- public int ndupreads;
- public OTOpndDup(int index)
- {
- this.index = index;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override void CountRefs(bool writing)
- {
- if(!writing)
- ndupreads++;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndDup))
- return false;
- return ((OTOpndDup)other).index == index;
- }
- public override string PrintableString
- {
- get
- {
- return "dup$" + index;
- }
- }
- }
- /**
- * Field of an object.
- */
- private class OTOpndField: OTOpnd
- {
- public OTOpnd obj;
- public FieldInfo field;
- public static OTOpnd Make(OTOpnd obj, FieldInfo field)
- {
- // LSL_Float.value => the object itself
- if((field.DeclaringType == typeof(LSL_Float)) && (field.Name == "value"))
- {
- return obj;
- }
- // LSL_Integer.value => the object itself
- if((field.DeclaringType == typeof(LSL_Integer)) && (field.Name == "value"))
- {
- return obj;
- }
- // LSL_String.m_string => the object itself
- if((field.DeclaringType == typeof(LSL_String)) && (field.Name == "m_string"))
- {
- return obj;
- }
- // some other field, output code to access it
- // sometimes the object comes as by reference (value types), so we might need to deref it first
- OTOpndField it = new OTOpndField();
- it.obj = obj.GetNonByRefOpnd();
- it.field = field;
- return it;
- }
- private OTOpndField()
- {
- }
- public override bool HasSideEffects
- {
- get
- {
- return obj.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- // the field may be getting written to, but the object is being read
- obj.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- obj = obj.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndField))
- return false;
- OTOpndField otherfield = (OTOpndField)other;
- return (field.Name == otherfield.field.Name) && obj.SameAs(otherfield.obj);
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- if(obj is OTOpndBinOp)
- sb.Append('(');
- sb.Append(obj.PrintableString);
- if(obj is OTOpndBinOp)
- sb.Append(')');
- sb.Append('.');
- sb.Append(field.Name);
- return sb.ToString();
- }
- }
- }
- /**
- * Script-level global variable.
- */
- private class OTOpndGlobal: OTOpnd
- {
- public string iartypename;
- public int iararrayidx;
- public bool byref;
- public ScriptObjCode scriptObjCode;
- public OTOpndGlobal(string iartypename, int iararrayidx, bool byref, ScriptObjCode scriptObjCode)
- {
- this.iartypename = iartypename;
- this.iararrayidx = iararrayidx;
- this.byref = byref;
- this.scriptObjCode = scriptObjCode;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override OTOpnd GetNonByRefOpnd()
- {
- if(!byref)
- return this;
- return new OTOpndGlobal(iartypename, iararrayidx, false, scriptObjCode);
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndGlobal))
- return false;
- OTOpndGlobal otherglobal = (OTOpndGlobal)other;
- return (iartypename == otherglobal.iartypename) && (iararrayidx == otherglobal.iararrayidx);
- }
- public override string PrintableString
- {
- get
- {
- return (byref ? "ref " : "") + scriptObjCode.globalVarNames[iartypename][iararrayidx];
- }
- }
- }
- /**
- * List initialization.
- */
- private class OTOpndListIni: OTOpnd
- {
- public OTOpnd[] values;
- /**
- * Try to detect list initialization building idiom:
- * dup$<n> = newarr object[<m>] << link points here
- * dup$<n>[0] = bla
- * dup$<n>[1] = bla
- * ...
- * ... newobj list (dup$<n>) ...
- */
- public static bool Detect(LinkedListNode<OTStmt> link)
- {
- if(link == null)
- return false;
- /*
- * Check for 'dup$<n> = newarr object[<m>]' and get listsize from <m>.
- */
- OTStmtStore store = (OTStmtStore)link.Value;
- if(!(store.varwr is OTOpndDup))
- return false;
- if(!(store.value is OTOpndNewarr))
- return false;
- OTOpndDup storevar = (OTOpndDup)store.varwr;
- OTOpndNewarr storeval = (OTOpndNewarr)store.value;
- if(storeval.type != typeof(object))
- return false;
- if(!(storeval.index is OTOpndInt))
- return false;
- int listsize = ((OTOpndInt)storeval.index).value;
- // Good chance of having list initializer, malloc an object to hold it.
- OTOpndListIni it = new OTOpndListIni();
- it.values = new OTOpnd[listsize];
- // There should be exactly listsize statements following that of the form:
- // dup$<n>[<i>] = bla
- // If so, save the bla values in the values[] array.
- LinkedListNode<OTStmt> vallink = link;
- for(int i = 0; i < listsize; i++)
- {
- vallink = vallink.Next;
- if(vallink == null)
- return false;
- if(!(vallink.Value is OTStmtStore))
- return false;
- OTStmtStore valstore = (OTStmtStore)vallink.Value;
- if(!(valstore.varwr is OTOpndArrayElem))
- return false;
- OTOpndArrayElem varelem = (OTOpndArrayElem)valstore.varwr;
- if(varelem.array != storevar)
- return false;
- if(!(varelem.index is OTOpndInt))
- return false;
- if(((OTOpndInt)varelem.index).value != i)
- return false;
- it.values[i] = valstore.value;
- }
- // The next statement should have a 'newobj list (dup$<n>)' in it somewhere
- // that we want to replace with 'it'.
- ConstructorInfo protoctor = typeof(LSL_List).GetConstructor(new Type[] { typeof(object[]) });
- OTOpnd[] protoargs = new OTOpnd[] { storevar };
- OTOpnd proto = OTOpndNewobj.Make(protoctor, protoargs);
- vallink = vallink.Next;
- bool rc = vallink.Value.ReplaceOperand(proto, it);
- // If successful, delete 'dup$n =' and all 'dup$n[i] =' statements.
- if(rc)
- {
- do
- {
- LinkedListNode<OTStmt> nextlink = link.Next;
- link.List.Remove(link);
- link = nextlink;
- } while(link != vallink);
- }
- return rc;
- }
- public override bool HasSideEffects
- {
- get
- {
- foreach(OTOpnd value in values)
- {
- if(value.HasSideEffects)
- return true;
- }
- return false;
- }
- }
- public override void CountRefs(bool writing)
- {
- foreach(OTOpnd value in values)
- {
- value.CountRefs(false);
- }
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- for(int i = 0; i < values.Length; i++)
- {
- values[i] = values[i].ReplaceOperand(oldopnd, newopnd, ref rc);
- }
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndListIni))
- return false;
- OTOpndListIni otherli = (OTOpndListIni)other;
- if(otherli.values.Length != values.Length)
- return false;
- for(int i = 0; i < values.Length; i++)
- {
- if(!values[i].SameAs(otherli.values[i]))
- return false;
- }
- return true;
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- sb.Append('[');
- for(int i = 0; i < values.Length; i++)
- {
- if(i > 0)
- sb.Append(',');
- sb.Append(' ');
- sb.Append(values[i].PrintableString);
- }
- sb.Append(" ]");
- return sb.ToString();
- }
- }
- }
- /**
- * Local variable.
- */
- private class OTOpndLocal: OTOpnd
- {
- public OTLocal local;
- public OTOpndLocal(OTLocal local)
- {
- this.local = local;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override void CountRefs(bool writing)
- {
- if(writing)
- local.nlclwrites++;
- else
- local.nlclreads++;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndLocal))
- return false;
- OTOpndLocal otherlocal = (OTOpndLocal)other;
- return local == otherlocal.local;
- }
- public override string PrintableString
- {
- get
- {
- return local.name;
- }
- }
- }
- private class OTOpndLocalRef: OTOpnd
- {
- public OTLocal local;
- public OTOpndLocalRef(OTLocal local)
- {
- this.local = local;
- }
- public override bool HasSideEffects
- {
- get
- {
- return true;
- }
- }
- public override void CountRefs(bool writing)
- {
- local.nlclreads++;
- local.nlclwrites++;
- }
- public override OTOpnd GetNonByRefOpnd()
- {
- return new OTOpndLocal(local);
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndLocal))
- return false;
- OTOpndLocal otherlocal = (OTOpndLocal)other;
- return local == otherlocal.local;
- }
- public override string PrintableString
- {
- get
- {
- return "ref " + local.name;
- }
- }
- }
- /**
- * New C#-level array.
- */
- private class OTOpndNewarr: OTOpnd
- {
- public Type type;
- public OTOpnd index;
- public OTOpndNewarr(Type type, OTOpnd index)
- {
- this.type = type;
- this.index = index;
- }
- public override bool HasSideEffects
- {
- get
- {
- return index.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- index.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- index = index.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- return false;
- }
- public override string PrintableString
- {
- get
- {
- return "newarr " + type.Name + "[" + index.PrintableString + "]";
- }
- }
- }
- /**
- * New C#-level object.
- */
- private class OTOpndNewobj: OTOpnd
- {
- public ConstructorInfo ctor;
- public OTOpnd[] args;
- public static OTOpnd Make(ConstructorInfo ctor, OTOpnd[] args)
- {
- // newobj LSL_Float (x) => x
- if((ctor.DeclaringType == typeof(LSL_Float)) && (args.Length == 1))
- {
- Type ptype = ctor.GetParameters()[0].ParameterType;
- if(ptype == typeof(string))
- {
- return new OTOpndCast(typeof(double), args[0]);
- }
- return args[0];
- }
- // newobj LSL_Integer (x) => x
- if((ctor.DeclaringType == typeof(LSL_Integer)) && (args.Length == 1))
- {
- Type ptype = ctor.GetParameters()[0].ParameterType;
- if(ptype == typeof(string))
- {
- return new OTOpndCast(typeof(int), args[0]);
- }
- return args[0];
- }
- // newobj LSL_String (x) => x
- if((ctor.DeclaringType == typeof(LSL_String)) && (args.Length == 1))
- {
- return args[0];
- }
- // newobj LSL_Rotation (x, y, z, w) => <x, y, z, w>
- if((ctor.DeclaringType == typeof(LSL_Rotation)) && (args.Length == 4))
- {
- return new OTOpndRot(args[0], args[1], args[2], args[3]);
- }
- // newobj LSL_Vector (x, y, z) => <x, y, z>
- if((ctor.DeclaringType == typeof(LSL_Vector)) && (args.Length == 3))
- {
- return new OTOpndVec(args[0], args[1], args[2]);
- }
- // newobj LSL_Rotation (string) => (rotation) string
- if((ctor.DeclaringType == typeof(LSL_Rotation)) && (args.Length == 1))
- {
- return new OTOpndCast(typeof(LSL_Rotation), args[0]);
- }
- // newobj LSL_Vector (string) => (rotation) string
- if((ctor.DeclaringType == typeof(LSL_Vector)) && (args.Length == 1))
- {
- return new OTOpndCast(typeof(LSL_Vector), args[0]);
- }
- // newobj LSL_List (newarr object[0]) => [ ]
- if((ctor.DeclaringType == typeof(LSL_List)) && (args.Length == 1) && (args[0] is OTOpndNewarr))
- {
- OTOpndNewarr arg0 = (OTOpndNewarr)args[0];
- if((arg0.type == typeof(object)) && (arg0.index is OTOpndInt) && (((OTOpndInt)arg0.index).value == 0))
- {
- OTOpndListIni listini = new OTOpndListIni();
- listini.values = new OTOpnd[0];
- return listini;
- }
- }
- // something else, output as is
- OTOpndNewobj it = new OTOpndNewobj();
- it.ctor = ctor;
- it.args = args;
- return it;
- }
- private OTOpndNewobj()
- {
- }
- public override bool HasSideEffects
- {
- get
- {
- foreach(OTOpnd arg in args)
- {
- if(arg.HasSideEffects)
- return true;
- }
- return false;
- }
- }
- public override void CountRefs(bool writing)
- {
- foreach(OTOpnd arg in args)
- {
- arg.CountRefs(false);
- }
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- for(int i = 0; i < args.Length; i++)
- {
- args[i] = args[i].ReplaceOperand(oldopnd, newopnd, ref rc);
- }
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndNewobj))
- return false;
- OTOpndNewobj otherno = (OTOpndNewobj)other;
- if(otherno.ctor.DeclaringType != ctor.DeclaringType)
- return false;
- if(otherno.args.Length != args.Length)
- return false;
- for(int i = 0; i < args.Length; i++)
- {
- if(!args[i].SameAs(otherno.args[i]))
- return false;
- }
- return true;
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("newobj ");
- sb.Append(ctor.DeclaringType.Name);
- sb.Append(" (");
- bool first = true;
- foreach(OTOpnd arg in args)
- {
- if(!first)
- sb.Append(", ");
- sb.Append(arg.PrintableString);
- first = false;
- }
- sb.Append(')');
- return sb.ToString();
- }
- }
- }
- /**
- * Rotation value.
- */
- private class OTOpndRot: OTOpnd
- {
- private OTOpnd x, y, z, w;
- public OTOpndRot(OTOpnd x, OTOpnd y, OTOpnd z, OTOpnd w)
- {
- this.x = StripFloatCast(x);
- this.y = StripFloatCast(y);
- this.z = StripFloatCast(z);
- this.w = StripFloatCast(w);
- }
- public override bool HasSideEffects
- {
- get
- {
- return x.HasSideEffects || y.HasSideEffects || z.HasSideEffects || w.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- x.CountRefs(false);
- y.CountRefs(false);
- z.CountRefs(false);
- w.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- x = x.ReplaceOperand(oldopnd, newopnd, ref rc);
- y = y.ReplaceOperand(oldopnd, newopnd, ref rc);
- z = z.ReplaceOperand(oldopnd, newopnd, ref rc);
- w = w.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndRot))
- return false;
- OTOpndRot otherv = (OTOpndRot)other;
- return otherv.x.SameAs(x) && otherv.y.SameAs(y) && otherv.z.SameAs(z) && otherv.w.SameAs(w);
- }
- public override string PrintableString
- {
- get
- {
- return "<" + x.PrintableString + ", " + y.PrintableString + ", " + z.PrintableString + ", " + w.PrintableString + ">";
- }
- }
- }
- /**
- * Static field.
- */
- private class OTOpndSField: OTOpnd
- {
- private FieldInfo field;
- public OTOpndSField(FieldInfo field)
- {
- this.field = field;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndSField))
- return false;
- OTOpndSField othersfield = (OTOpndSField)other;
- return (field.Name == othersfield.field.Name) && (field.DeclaringType == othersfield.field.DeclaringType);
- }
- public override string PrintableString
- {
- get
- {
- if(field.DeclaringType == typeof(ScriptBaseClass))
- return field.Name;
- return field.DeclaringType.Name + "." + field.Name;
- }
- }
- }
- /**
- * Call to string.Compare().
- * See use cases in BinOpStr:
- * strcmp (a, b) ceq 0
- * (strcmp (a, b) ceq 0) xor 1 => we translate to: strcmp (a, b) cne 0
- * strcmp (a, b) clt 0
- * strcmp (a, b) clt 1 // <=
- * strcmp (a, b) cgt 0
- * strcmp (a, b) cgt -1 // >=
- * ...but then optimized by ScriptCollector if followed by br{false,true}:
- * ceq + xor 1 + brtrue => bne.un
- * ceq + xor 1 + brfalse => beq
- * ceq + brtrue => beq
- * ceq + brfalse => bne.un
- * cgt + brtrue => bgt
- * cgt + brfalse => ble
- * clt + brtrue => blt
- * clt + brfalse => bge
- * So we end up with these cases:
- * strcmp (a, b) ceq 0
- * strcmp (a, b) cne 0
- * strcmp (a, b) clt 0
- * strcmp (a, b) clt 1
- * strcmp (a, b) cgt 0
- * strcmp (a, b) cgt -1
- * strcmp (a, b) beq 0
- * strcmp (a, b) bne.un 0
- * strcmp (a, b) bgt 0
- * strcmp (a, b) ble 0
- * strcmp (a, b) bgt -1
- * strcmp (a, b) ble -1
- * strcmp (a, b) blt 0
- * strcmp (a, b) bge 0
- * strcmp (a, b) blt 1
- * strcmp (a, b) bge 1
- * ... so we pretty them up in OTOpndBinOp
- */
- private class OTOpndStrCmp: OTOpnd
- {
- private static Dictionary<string, string> binops = InitBinops();
- private static Dictionary<string, string> InitBinops()
- {
- Dictionary<string, string> d = new Dictionary<string, string>();
- d["ceq 0"] = "ceq";
- d["cne 0"] = "cne";
- d["clt 0"] = "clt";
- d["clt 1"] = "cle";
- d["cgt 0"] = "cgt";
- d["cgt -1"] = "cge";
- d["beq 0"] = "ceq";
- d["bne.un 0"] = "cne";
- d["bgt 0"] = "cgt";
- d["ble 0"] = "cle";
- d["bgt -1"] = "cge";
- d["ble -1"] = "clt";
- d["blt 0"] = "clt";
- d["bge 0"] = "cge";
- d["blt 1"] = "cle";
- d["bge 1"] = "cgt";
- return d;
- }
- private OTOpnd arg0;
- private OTOpnd arg1;
- public OTOpndStrCmp(OTOpnd arg0, OTOpnd arg1)
- {
- this.arg0 = arg0;
- this.arg1 = arg1;
- }
- /**
- * Try to make something a script writer would recognize.
- * If we can't, then we leave it as a call to xmrStringCompare().
- * this = some strcmp(a,b)
- * opCode = hopefully some cxx or bxx from above table
- * rite = hopefully some constant from above table
- */
- public OTOpnd MakeBinOp(MyOp opCode, OTOpnd rite)
- {
- if(!(rite is OTOpndInt))
- return null;
- int riteint = ((OTOpndInt)rite).value;
- string key = opCode.name + ' ' + riteint;
- string cxxopname;
- if(!binops.TryGetValue(key, out cxxopname))
- return null;
- return OTOpndBinOp.Make(arg0, MyOp.GetByName(cxxopname), arg1);
- }
- public OTOpnd MakeUnOp(MyOp opCode)
- {
- if(opCode == MyOp.Brfalse)
- return OTOpndBinOp.Make(arg0, MyOp.Ceq, arg1);
- if(opCode == MyOp.Brtrue)
- return OTOpndBinOp.Make(arg0, MyOp.Cne, arg1);
- return null;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override void CountRefs(bool writing)
- {
- arg0.CountRefs(writing);
- arg1.CountRefs(writing);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- arg0 = arg0.ReplaceOperand(oldopnd, newopnd, ref rc);
- arg1 = arg1.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndStrCmp))
- return false;
- return arg0.SameAs(((OTOpndStrCmp)other).arg0) && arg1.SameAs(((OTOpndStrCmp)other).arg1);
- }
- public override string PrintableString
- {
- get
- {
- return "xmrStringCompare (" + arg0.PrintableString + ", " + arg1.PrintableString + ")";
- }
- }
- }
- /**
- * Unary operator.
- */
- private class OTOpndUnOp: OTOpnd
- {
- public MyOp opCode;
- public OTOpnd value;
- private static Dictionary<string, string> brfops = InitBrfOps();
- private static Dictionary<string, string> InitBrfOps()
- {
- Dictionary<string, string> d = new Dictionary<string, string>();
- d["beq"] = "cne";
- d["bge"] = "clt";
- d["bgt"] = "cle";
- d["ble"] = "cgt";
- d["blt"] = "cge";
- d["bne.un"] = "ceq";
- d["ceq"] = "cne";
- d["cge"] = "clt";
- d["cgt"] = "cle";
- d["cle"] = "cgt";
- d["clt"] = "cge";
- d["cne"] = "ceq";
- return d;
- }
- public static OTOpnd Make(MyOp opCode, OTOpnd value)
- {
- // (brfalse (brfalse (x))) => (brtrue (x))
- if((opCode == MyOp.Brfalse) && (value is OTOpndUnOp) && (((OTOpndUnOp)value).opCode == MyOp.Brfalse))
- {
- ((OTOpndUnOp)value).opCode = MyOp.Brtrue;
- return value;
- }
- // (brfalse (brtrue (x))) => (brfalse (x))
- if((opCode == MyOp.Brfalse) && (value is OTOpndUnOp) && (((OTOpndUnOp)value).opCode == MyOp.Brtrue))
- {
- ((OTOpndUnOp)value).opCode = MyOp.Brfalse;
- return value;
- }
- // (brtrue (brfalse (x))) => (brfalse (x))
- if((opCode == MyOp.Brtrue) && (value is OTOpndUnOp) && (((OTOpndUnOp)value).opCode == MyOp.Brfalse))
- {
- return value;
- }
- // (brtrue (brtrue (x))) => (brtrue (x))
- if((opCode == MyOp.Brtrue) && (value is OTOpndUnOp) && (((OTOpndUnOp)value).opCode == MyOp.Brtrue))
- {
- return value;
- }
- // (brfalse (x beq y)) => (x bne y) etc
- string brfop;
- if((opCode == MyOp.Brfalse) && (value is OTOpndBinOp) && brfops.TryGetValue(((OTOpndBinOp)value).opCode.name, out brfop))
- {
- ((OTOpndBinOp)value).opCode = MyOp.GetByName(brfop);
- return value;
- }
- // (brtrue (x beq y)) => (x beq y) etc
- if((opCode == MyOp.Brtrue) && (value is OTOpndBinOp) && brfops.ContainsKey(((OTOpndBinOp)value).opCode.name))
- {
- return value;
- }
- // strcmp() can be a special case
- if(value is OTOpndStrCmp)
- {
- OTOpnd strcmp = ((OTOpndStrCmp)value).MakeUnOp(opCode);
- if(strcmp != null)
- return strcmp;
- }
- // nothing special, save opcode and value
- OTOpndUnOp it = new OTOpndUnOp();
- it.opCode = opCode;
- it.value = value;
- return it;
- }
- private OTOpndUnOp()
- {
- }
- public override bool HasSideEffects
- {
- get
- {
- return value.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- value.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndUnOp))
- return false;
- OTOpndUnOp otherop = (OTOpndUnOp)other;
- return (opCode.ToString() == otherop.opCode.ToString()) && value.SameAs(otherop.value);
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- sb.Append(opCode.source);
- sb.Append(' ');
- if(value is OTOpndBinOp)
- sb.Append('(');
- sb.Append(value.PrintableString);
- if(value is OTOpndBinOp)
- sb.Append(')');
- return sb.ToString();
- }
- }
- }
- /**
- * Vector value.
- */
- private class OTOpndVec: OTOpnd
- {
- private OTOpnd x, y, z;
- public OTOpndVec(OTOpnd x, OTOpnd y, OTOpnd z)
- {
- this.x = StripFloatCast(x);
- this.y = StripFloatCast(y);
- this.z = StripFloatCast(z);
- }
- public override bool HasSideEffects
- {
- get
- {
- return x.HasSideEffects || y.HasSideEffects || z.HasSideEffects;
- }
- }
- public override void CountRefs(bool writing)
- {
- x.CountRefs(false);
- y.CountRefs(false);
- z.CountRefs(false);
- }
- public override OTOpnd ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd, ref bool rc)
- {
- if(SameAs(oldopnd))
- {
- rc = true;
- return newopnd;
- }
- x = x.ReplaceOperand(oldopnd, newopnd, ref rc);
- y = y.ReplaceOperand(oldopnd, newopnd, ref rc);
- z = z.ReplaceOperand(oldopnd, newopnd, ref rc);
- return this;
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndVec))
- return false;
- OTOpndVec otherv = (OTOpndVec)other;
- return otherv.x.SameAs(x) && otherv.y.SameAs(y) && otherv.z.SameAs(z);
- }
- public override string PrintableString
- {
- get
- {
- return "<" + x.PrintableString + ", " + y.PrintableString + ", " + z.PrintableString + ">";
- }
- }
- }
- /**
- * Constants.
- */
- private class OTOpndDouble: OTOpnd
- {
- public double value;
- public OTOpndDouble(double value)
- {
- this.value = value;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndDouble))
- return false;
- return ((OTOpndDouble)other).value == value;
- }
- public override string PrintableString
- {
- get
- {
- string s = value.ToString();
- long i;
- if(long.TryParse(s, out i))
- {
- s += ".0";
- }
- return s;
- }
- }
- }
- private class OTOpndFloat: OTOpnd
- {
- public float value;
- public OTOpndFloat(float value)
- {
- this.value = value;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndFloat))
- return false;
- return ((OTOpndFloat)other).value == value;
- }
- public override string PrintableString
- {
- get
- {
- string s = value.ToString();
- long i;
- if(long.TryParse(s, out i))
- {
- s += ".0";
- }
- return s;
- }
- }
- }
- private class OTOpndInt: OTOpnd
- {
- public int value;
- public OTOpndInt(int value)
- {
- this.value = value;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndInt))
- return false;
- return ((OTOpndInt)other).value == value;
- }
- public override string PrintableString
- {
- get
- {
- return value.ToString();
- }
- }
- }
- private class OTOpndNull: OTOpnd
- {
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- return other is OTOpndNull;
- }
- public override string PrintableString
- {
- get
- {
- return "undef";
- }
- }
- }
- private class OTOpndString: OTOpnd
- {
- public string value;
- public OTOpndString(string value)
- {
- this.value = value;
- }
- public override bool HasSideEffects
- {
- get
- {
- return false;
- }
- }
- public override bool SameAs(OTOpnd other)
- {
- if(!(other is OTOpndString))
- return false;
- return ((OTOpndString)other).value == value;
- }
- public override string PrintableString
- {
- get
- {
- StringBuilder sb = new StringBuilder();
- TokenDeclInline.PrintParamString(sb, value);
- return sb.ToString();
- }
- }
- }
- /****************************************\
- * Tokens what are in statement list. *
- \****************************************/
- public abstract class OTStmt
- {
- /**
- * Increment reference counts.
- */
- public abstract void CountRefs();
- /**
- * Strip out any of the behind-the-scenes code such as stack capture/restore.
- * By default, there is no change.
- */
- public virtual bool StripStuff(LinkedListNode<OTStmt> link)
- {
- return false;
- }
- /**
- * Replace the oldopnd operand with the newopnd operand if it is present.
- * Return whether or not it was found and replaced.
- */
- public abstract bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd);
- /**
- * Detect and modify for do/for/if/while structures.
- */
- public virtual bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return false;
- }
- /**
- * If this statement is the old statement, replace it with the given new statement.
- * Also search any sub-ordinate statements.
- * **NOTE**: minimally implemented to replace a Jump with a Break or Continue
- */
- public abstract OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt);
- /**
- * Print the statement out on the given printer with the given indenting.
- * The first line is already indented, subsequent lines must be indented as given.
- * This method should leave the printer at the end of the line.
- */
- public abstract void PrintStmt(TextWriter twout, string indent);
- /**
- * Strip all statements following this statement
- * because this statement jumps somewhere.
- */
- protected bool StripStuffForTerminal(LinkedListNode<OTStmt> link)
- {
- // strip all statements following jump until seeing some label
- bool rc = false;
- if(link != null)
- {
- LinkedListNode<OTStmt> nextlink;
- while((nextlink = link.Next) != null)
- {
- if(nextlink.Value is OTStmtLabel)
- break;
- nextlink.List.Remove(nextlink);
- rc = true;
- }
- }
- return rc;
- }
- }
- /**************************\
- * Primitive statements *
- \**************************/
- /**
- * Begin catch block (catch).
- */
- private class OTStmtBegCatBlk: OTStmt
- {
- public OTStmtBegExcBlk tryblock;
- public OTStmtBlock catchblock;
- private Type excType;
- public OTStmtBegCatBlk(Type excType)
- {
- this.excType = excType;
- }
- public override void CountRefs()
- {
- catchblock.CountRefs();
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- return catchblock.StripStuff(null);
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return catchblock.ReplaceOperand(oldopnd, newopnd);
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return catchblock.DetectDoForIfWhile(link);
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- catchblock = (OTStmtBlock)catchblock.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- /**
- * Print out the catch block including its enclosed statements.
- */
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("catch (" + excType.Name + ") ");
- catchblock.PrintStmt(twout, indent);
- }
- }
- /**
- * Begin exception block (try).
- */
- private class OTStmtBegExcBlk: OTStmt
- {
- // statements within the try { } not including any catch or finally
- public OTStmtBlock tryblock;
- // list of all catch { } blocks associated with this try { }
- public LinkedList<OTStmtBegCatBlk> catches = new LinkedList<OTStmtBegCatBlk>();
- // possible single finally { } associated with this try
- public OTStmtBegFinBlk finblock; // might be null
- public override void CountRefs()
- {
- tryblock.CountRefs();
- foreach(OTStmtBegCatBlk catblock in catches)
- {
- catblock.CountRefs();
- }
- if(finblock != null)
- finblock.CountRefs();
- }
- /**
- * Strip behind-the-scenes info from all the sub-blocks.
- */
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // strip behind-the-scenes info from all the sub-blocks.
- bool rc = tryblock.StripStuff(null);
- foreach(OTStmtBegCatBlk catblk in catches)
- {
- rc |= catblk.StripStuff(null);
- }
- if(finblock != null)
- rc |= finblock.StripStuff(null);
- if(rc)
- return true;
- // change:
- // try {
- // ...
- // }
- // to:
- // {
- // ...
- // }
- // note that an empty catch () { } has meaning so can't be stripped
- // empty finally { } blocks strips itself from the try
- if((catches.Count == 0) && (finblock == null) && (link != null))
- {
- link.List.AddAfter(link, tryblock);
- tryblock = null;
- link.List.Remove(link);
- return true;
- }
- return false;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = tryblock.ReplaceOperand(oldopnd, newopnd);
- foreach(OTStmtBegCatBlk catblk in catches)
- {
- rc |= catblk.ReplaceOperand(oldopnd, newopnd);
- }
- if(finblock != null)
- rc |= finblock.ReplaceOperand(oldopnd, newopnd);
- return rc;
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- bool rc = tryblock.DetectDoForIfWhile(link);
- foreach(OTStmtBegCatBlk catblk in catches)
- {
- rc |= catblk.DetectDoForIfWhile(link);
- }
- if(finblock != null)
- rc |= finblock.DetectDoForIfWhile(link);
- return rc;
- }
- /**
- * Assume we will never try to replace the try block itself.
- * But go through all our sub-ordinates statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- tryblock = (OTStmtBlock)tryblock.ReplaceStatement(oldstmt, newstmt);
- for(LinkedListNode<OTStmtBegCatBlk> catlink = catches.First; catlink != null; catlink = catlink.Next)
- {
- catlink.Value = (OTStmtBegCatBlk)catlink.Value.ReplaceStatement(oldstmt, newstmt);
- }
- if(finblock != null)
- finblock = (OTStmtBegFinBlk)finblock.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- /**
- * Print out the try block including its enclosed statements.
- * And since the try is the only thing pushed to the outer block,
- * we also print out all the catch and finally blocks.
- */
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("try ");
- tryblock.PrintStmt(twout, indent);
- foreach(OTStmtBegCatBlk catblk in catches)
- {
- twout.Write(' ');
- catblk.PrintStmt(twout, indent);
- }
- if(finblock != null)
- {
- twout.Write(' ');
- finblock.PrintStmt(twout, indent);
- }
- }
- }
- /**
- * Begin finally block (finally).
- */
- private class OTStmtBegFinBlk: OTStmt
- {
- public OTStmtBegExcBlk tryblock;
- public OTStmtBlock finblock;
- public override void CountRefs()
- {
- finblock.CountRefs();
- }
- /**
- * Strip behind-the-scene parts from the finally block.
- */
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // strip behind-the-scenes parts from finally block itself
- if(finblock.StripStuff(null))
- return true;
- // if finblock is empty, delete the finally from the try
- if(finblock.blkstmts.Count == 0)
- {
- tryblock.finblock = null;
- return true;
- }
- return false;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return finblock.ReplaceOperand(oldopnd, newopnd);
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return finblock.DetectDoForIfWhile(link);
- }
- /**
- * Assume we will never try to replace the finally block itself.
- * But go through all our sub-ordinates statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- finblock = (OTStmtBlock)finblock.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- /**
- * Print out the finally block including its enclosed statements.
- */
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("finally ");
- finblock.PrintStmt(twout, indent);
- }
- }
- /**
- * Simple if jump/break/continue statement.
- */
- private class OTStmtCond: OTStmt
- {
- public OTOpnd valu;
- public OTStmt stmt; // jump, break, continue only
- public OTStmtCond(OTOpnd valu, OTStmt stmt)
- {
- this.valu = valu;
- this.stmt = stmt;
- }
- public override void CountRefs()
- {
- valu.CountRefs(false);
- stmt.CountRefs();
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // we assume that callMode is always CallMode_NORMAL, ie, not doing a stack capture or restore
- // so the 'if (arg$0.callMode bne.un 0) ...' is deleted
- // and the 'if (arg$0.callMode bne.un 1) ...' becomes unconditional
- // it can also be __xmrinst.callMode instead of arg$0
- if(valu is OTOpndBinOp)
- {
- OTOpndBinOp binop = (OTOpndBinOp)valu;
- if((binop.left is OTOpndField) && (binop.opCode.ToString() == "bne.un") && (binop.rite is OTOpndInt))
- {
- OTOpndField leftfield = (OTOpndField)binop.left;
- if(leftfield.field.Name == _callMode)
- {
- bool ok = false;
- if(leftfield.obj is OTOpndArg)
- {
- ok = ((OTOpndArg)leftfield.obj).index == 0;
- }
- if(leftfield.obj is OTOpndLocal)
- {
- ok = ((OTOpndLocal)leftfield.obj).local.name.StartsWith(_xmrinstlocal);
- }
- if(ok)
- {
- OTOpndInt riteint = (OTOpndInt)binop.rite;
- // delete 'if ((arg$0).callMode bne.un 0) ...'
- if(riteint.value == XMRInstAbstract.CallMode_NORMAL)
- {
- link.List.Remove(link);
- return true;
- }
- // make 'if ((arg$0).callMode bne.un 1) ...' unconditional
- if(riteint.value == XMRInstAbstract.CallMode_SAVE)
- {
- link.Value = stmt;
- return true;
- }
- }
- }
- }
- }
- // similarly we assume that doGblInit is always 0 to eliminate the code at beginning of default state_entry()
- // so the 'if (brfalse __xmrinst.doGblInit) ...' is made unconditional
- if(valu is OTOpndUnOp)
- {
- OTOpndUnOp unop = (OTOpndUnOp)valu;
- if((unop.opCode == MyOp.Brfalse) && (unop.value is OTOpndField))
- {
- OTOpndField valuefield = (OTOpndField)unop.value;
- if(valuefield.field.Name == _doGblInit)
- {
- bool ok = false;
- if(valuefield.obj is OTOpndLocal)
- {
- ok = ((OTOpndLocal)valuefield.obj).local.name.StartsWith(_xmrinstlocal);
- }
- if(ok)
- {
- // make 'if (brfalse __xmrinst.doGblInit) ...' unconditional
- link.Value = stmt;
- return true;
- }
- }
- }
- }
- return false;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = stmt.ReplaceOperand(oldopnd, newopnd);
- valu = valu.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- /**
- * Maybe this simple if statement is part of a script-level if/then/else statement.
- */
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return OTStmtIf.Detect(link);
- }
- /**
- * Assume we won't replace the if statement itself.
- * But search all our sub-ordinate statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- stmt = stmt.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("if (" + StripBrtrue(valu).PrintableString + ") ");
- stmt.PrintStmt(twout, indent);
- }
- /**
- * Scan forward for a given label definition.
- * Put intervening statements in a statement block.
- * @param link = start scanning after this statement
- * @param label = look for this label definition
- * @param block = where to return intervening statement block
- * @returns null: label definition not found
- * else: label definition statement
- */
- private static LinkedListNode<OTStmt> ScanForLabel(LinkedListNode<OTStmt> link,
- OTLabel label, out OTStmtBlock block)
- {
- block = new OTStmtBlock();
- while((link = link.Next) != null)
- {
- if(link.Value is OTStmtLabel)
- {
- if(((OTStmtLabel)link.Value).label == label)
- break;
- }
- block.blkstmts.AddLast(link.Value);
- }
- return link;
- }
- /**
- * Strip statements after link up to and including donelink.
- */
- private static void StripInterveningStatements(LinkedListNode<OTStmt> link, LinkedListNode<OTStmt> donelink)
- {
- LinkedListNode<OTStmt> striplink;
- do
- {
- striplink = link.Next;
- striplink.List.Remove(striplink);
- } while(striplink != donelink);
- }
- }
- /**
- * Jump to a label.
- */
- private class OTStmtJump: OTStmt
- {
- public OTLabel label;
- public static OTStmt Make(OTLabel label)
- {
- // jumps to __retlbl are return statements
- // note that is is safe to say it is a valueless return because
- // valued returns are done with this construct:
- // __retval = ....;
- // jump __retlbl;
- // and those __retval = statements have been changed to return statements already
- if(label.name.StartsWith(_retlbl))
- return new OTStmtRet(null);
- // other jumps are really jumps
- OTStmtJump it = new OTStmtJump();
- it.label = label;
- return it;
- }
- private OTStmtJump()
- {
- }
- public override void CountRefs()
- {
- label.lbljumps++;
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- if(link == null)
- return false;
- // strip statements following unconditional jump until next label
- bool rc = StripStuffForTerminal(link);
- // if we (now) have:
- // jump label;
- // @label;
- // ... delete this jump
- if(link.Next != null)
- {
- OTStmtLabel nextlabel = (OTStmtLabel)link.Next.Value;
- if(nextlabel.label == label)
- {
- link.List.Remove(link);
- rc = true;
- }
- }
- return rc;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return false;
- }
- /**
- * This is actually what ReplaceStatement() is currently used for.
- * It replaces a jump with a break or a continue.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- if((oldstmt is OTStmtJump) && (((OTStmtJump)oldstmt).label == label))
- return newstmt;
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("jump " + label.PrintableName + ';');
- }
- }
- /**
- * Label definition point.
- */
- private class OTStmtLabel: OTStmt
- {
- public OTLabel label;
- private OTDecompile decompile;
- public static void AddLast(OTDecompile decompile, OTLabel label)
- {
- OTStmtLabel it = new OTStmtLabel();
- it.label = label;
- it.decompile = decompile;
- decompile.AddLastStmt(it);
- }
- private OTStmtLabel()
- {
- }
- public override void CountRefs()
- {
- // don't increment label.lbljumps
- // cuz we don't want the positioning
- // to count as a reference, only jumps
- // to the label should count
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // if label has nothing jumping to it, remove the label
- if(link != null)
- {
- label.lbljumps = 0;
- decompile.topBlock.CountRefs();
- if(label.lbljumps == 0)
- {
- link.List.Remove(link);
- return true;
- }
- }
- return false;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return false;
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- if(OTStmtDo.Detect(link))
- return true;
- if(OTStmtFor.Detect(link, true))
- return true;
- if(OTStmtFor.Detect(link, false))
- return true;
- return false;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("@" + label.PrintableName + ';');
- }
- }
- /**
- * Return with or without value.
- */
- private class OTStmtRet: OTStmt
- {
- public OTOpnd value; // might be null
- public OTStmtRet(OTOpnd value)
- {
- this.value = value;
- }
- public override void CountRefs()
- {
- if(value != null)
- value.CountRefs(false);
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- return StripStuffForTerminal(link);
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- if(value != null)
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- if(value == null)
- {
- twout.Write("return;");
- }
- else
- {
- twout.Write("return " + value.PrintableString + ';');
- }
- }
- }
- /**
- * Store value in variable.
- */
- private class OTStmtStore: OTStmt
- {
- public OTOpnd varwr;
- public OTOpnd value;
- private OTDecompile decompile;
- public static void AddLast(OTDecompile decompile, OTOpnd varwr, OTOpnd value)
- {
- OTStmtStore it = new OTStmtStore(varwr, value, decompile);
- decompile.AddLastStmt(it);
- }
- public OTStmtStore(OTOpnd varwr, OTOpnd value, OTDecompile decompile)
- {
- this.varwr = varwr;
- this.value = value;
- this.decompile = decompile;
- }
- public override void CountRefs()
- {
- varwr.CountRefs(true);
- value.CountRefs(false);
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // strip out stores to __mainCallNo
- if(varwr is OTOpndLocal)
- {
- OTOpndLocal local = (OTOpndLocal)varwr;
- if(local.local.name.StartsWith(_mainCallNo))
- {
- link.List.Remove(link);
- return true;
- }
- }
- // strip out stores to local vars where the var is not read
- // but convert the value to an OTStmtVoid in case it is a call
- if(varwr is OTOpndLocal)
- {
- OTOpndLocal local = (OTOpndLocal)varwr;
- local.local.nlclreads = 0;
- decompile.topBlock.CountRefs();
- if(local.local.nlclreads == 0)
- {
- OTStmt voidstmt = OTStmtVoid.Make(value);
- if(voidstmt == null)
- link.List.Remove(link);
- else
- link.Value = voidstmt;
- return true;
- }
- }
- // strip out bla = newobj HeapTrackerList (...);
- if(value is OTOpndNewobj)
- {
- OTOpndNewobj valueno = (OTOpndNewobj)value;
- if(valueno.ctor.DeclaringType == typeof(HeapTrackerList))
- {
- link.List.Remove(link);
- return true;
- }
- }
- // strip out bla = newobj HeapTrackerObject (...);
- if(value is OTOpndNewobj)
- {
- OTOpndNewobj valueno = (OTOpndNewobj)value;
- if(valueno.ctor.DeclaringType == typeof(HeapTrackerObject))
- {
- link.List.Remove(link);
- return true;
- }
- }
- // strip out bla = newobj HeapTrackerString (...);
- if(value is OTOpndNewobj)
- {
- OTOpndNewobj valueno = (OTOpndNewobj)value;
- if(valueno.ctor.DeclaringType == typeof(HeapTrackerString))
- {
- link.List.Remove(link);
- return true;
- }
- }
- // convert tmp$n = bla bla;
- // .... tmp$n ....;
- // to
- // .... bla bla ....;
- // gets rid of vast majority of temps
- if(varwr is OTOpndLocal)
- {
- OTOpndLocal temp = (OTOpndLocal)varwr;
- if(temp.local.name.StartsWith("tmp$"))
- {
- temp.local.nlclreads = 0;
- temp.local.nlclwrites = 0;
- decompile.topBlock.CountRefs();
- if((temp.local.nlclreads == 1) && (temp.local.nlclwrites == 1) && (link.Next != null))
- {
- OTStmt nextstmt = link.Next.Value;
- if(!(nextstmt is OTStmtBlock))
- {
- if(nextstmt.ReplaceOperand(varwr, value))
- {
- link.List.Remove(link);
- return true;
- }
- }
- }
- // also try to convert:
- // tmp$n = ... asdf ... << we are here (link)
- // lcl = tmp$n; << nextstore
- // ... qwer tmp$n ...
- // ... no further references to tmp$n
- // to:
- // lcl = ... asdf ...
- // ... qwer lcl ...
- if((temp.local.nlclreads == 2) && (temp.local.nlclwrites == 1) &&
- (link.Next != null) && (link.Next.Value is OTStmtStore))
- {
- OTStmtStore nextstore = (OTStmtStore)link.Next.Value;
- if((nextstore.varwr is OTOpndLocal) && (nextstore.value is OTOpndLocal) && (link.Next.Next != null))
- {
- OTOpndLocal localopnd = (OTOpndLocal)nextstore.varwr;
- OTOpndLocal tempopnd = (OTOpndLocal)nextstore.value;
- if(tempopnd.local == temp.local)
- {
- OTStmt finalstmt = link.Next.Next.Value;
- if(finalstmt.ReplaceOperand(tempopnd, localopnd))
- {
- nextstore.value = value;
- link.List.Remove(link);
- return true;
- }
- }
- }
- }
- }
- }
- // convert:
- // dup$n = ... asdf ... << we are here
- // lcl = dup$n;
- // ... qwer dup$n ...
- // ... no further references to dup$n
- // to:
- // lcl = ... asdf ...
- // ... qwer lcl ...
- if((varwr is OTOpndDup) && (link != null))
- {
- OTOpndDup vardup = (OTOpndDup)varwr;
- LinkedListNode<OTStmt> nextlink = link.Next;
- vardup.ndupreads = 0;
- decompile.topBlock.CountRefs();
- if((vardup.ndupreads == 2) && (nextlink != null) && (nextlink.Value is OTStmtStore))
- {
- // point to the supposed lcl = dup$n statement
- OTStmtStore nextstore = (OTStmtStore)nextlink.Value;
- LinkedListNode<OTStmt> nextlink2 = nextlink.Next;
- if((nextstore.varwr is OTOpndLocal) && (nextstore.value == vardup) && (nextlink2 != null))
- {
- // get the local var being written and point to the ... qwer dup$n ... statement
- OTOpndLocal varlcl = (OTOpndLocal)nextstore.varwr;
- OTStmt nextstmt2 = nextlink2.Value;
- // try to replace dup$n in qwer with lcl
- if(nextstmt2.ReplaceOperand(vardup, varlcl))
- {
- // successful, replace dup$n in asdf with lcl
- // and delete the lcl = dup$n statement
- varwr = varlcl;
- nextlink.List.Remove(nextlink);
- return true;
- }
- }
- }
- }
- // convert:
- // dup$n = ... asdf ... << we are here
- // ... qwer dup$n ...
- // ... no further references to dup$n
- // to:
- // ... qwer ... asdf ... ...
- if((varwr is OTOpndDup) && (link != null))
- {
- OTOpndDup vardup = (OTOpndDup)varwr;
- LinkedListNode<OTStmt> nextlink = link.Next;
- vardup.ndupreads = 0;
- decompile.topBlock.CountRefs();
- if((vardup.ndupreads == 1) && (nextlink != null))
- {
- // point to the ... qwer dup$n ... statement
- OTStmt nextstmt = nextlink.Value;
- // try to replace dup$n in qwer with ... asdf ...
- if(nextstmt.ReplaceOperand(vardup, value))
- {
- // successful, delete the dup$n = ... asdf ... statement
- link.List.Remove(link);
- return true;
- }
- }
- }
- // look for list initialization [ ... ]
- if(OTOpndListIni.Detect(link))
- return true;
- // __xmrinst = (XMRInstAbstract) arg$0 indicates this is an event handler
- // so strip it out and set the flag
- if((varwr is OTOpndLocal) && (value is OTOpndCast))
- {
- OTOpndLocal lcl = (OTOpndLocal)varwr;
- OTOpndCast cast = (OTOpndCast)value;
- if(lcl.local.name.StartsWith(_xmrinstlocal) && (cast.value is OTOpndArg))
- {
- link.List.Remove(link);
- return true;
- }
- }
- // local = [ (optional cast) ] __xmrinst.ehArgs[n] is a definition of event handler arg #n
- // if found, make it event handler arg list definition
- OTOpnd valuenocast = value;
- if(valuenocast is OTOpndCast)
- valuenocast = ((OTOpndCast)value).value;
- if((varwr is OTOpndLocal) && (valuenocast is OTOpndArrayElem))
- {
- OTOpndArrayElem array = (OTOpndArrayElem)valuenocast;
- if((array.array is OTOpndField) && (array.index is OTOpndInt))
- {
- OTOpndField arrayfield = (OTOpndField)array.array;
- if((arrayfield.obj is OTOpndLocal) &&
- ((OTOpndLocal)arrayfield.obj).local.name.StartsWith(_xmrinstlocal) &&
- (arrayfield.field.Name == _ehArgs))
- {
- int index = ((OTOpndInt)array.index).value;
- decompile.eharglist[index] = ((OTOpndLocal)varwr).local;
- link.List.Remove(link);
- return true;
- }
- }
- }
- // __retval$n = ...; => return ...;
- if(varwr is OTOpndLocal)
- {
- OTOpndLocal lcl = (OTOpndLocal)varwr;
- if(lcl.local.name.StartsWith(_retval))
- {
- link.Value = new OTStmtRet(value);
- return true;
- }
- }
- return false;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- if(value != null)
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- // print x = x + 1 as x += 1, but don't print x = x < 3 as x <= 3
- if(value is OTOpndBinOp)
- {
- OTOpndBinOp valuebo = (OTOpndBinOp)value;
- if(varwr.SameAs(valuebo.left) && " add and div mul or rem shl shr sub xor ".Contains(' ' + valuebo.opCode.name + ' '))
- {
- twout.Write(varwr.PrintableString + ' ' + valuebo.opCode.source + "= " + valuebo.rite.PrintableString + ';');
- return;
- }
- }
- twout.Write(varwr.PrintableString + " = " + value.PrintableString + ';');
- }
- }
- /**
- * Dispatch to a table of labels.
- */
- private class OTStmtSwitch: OTStmt
- {
- private OTOpnd index;
- private OTLabel[] labels;
- public OTStmtSwitch(OTOpnd index, OTLabel[] labels)
- {
- this.index = index;
- this.labels = labels;
- }
- public override void CountRefs()
- {
- index.CountRefs(false);
- foreach(OTLabel label in labels)
- {
- label.lbljumps++;
- }
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- if(index != null)
- index = index.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("switch (" + index.PrintableString + ") {\n");
- for(int i = 0; i < labels.Length; i++)
- {
- twout.Write(indent + INDENT + "case " + i + ": jump " + labels[i].name + ";\n");
- }
- twout.Write(indent + '}');
- }
- }
- /**
- * Throw an exception.
- */
- private class OTStmtThrow: OTStmt
- {
- private OTOpnd value;
- private OTDecompile decompile;
- public OTStmtThrow(OTOpnd value, OTDecompile decompile)
- {
- this.value = value;
- this.decompile = decompile;
- }
- public override void CountRefs()
- {
- value.CountRefs(false);
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- return StripStuffForTerminal(link);
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- if(value != null)
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- // throw newobj ScriptUndefinedStateException ("x") => state x
- if(value is OTOpndNewobj)
- {
- OTOpndNewobj valueno = (OTOpndNewobj)value;
- if((valueno.ctor.DeclaringType == typeof(ScriptUndefinedStateException)) &&
- (valueno.args.Length == 1) && (valueno.args[0] is OTOpndString))
- {
- OTOpndString arg0 = (OTOpndString)valueno.args[0];
- twout.Write("state " + arg0.value + "; /* throws undefined state exception */");
- return;
- }
- }
- // throw newobj ScriptChangeStateException (n) => state n
- if(value is OTOpndNewobj)
- {
- OTOpndNewobj valueno = (OTOpndNewobj)value;
- if((valueno.ctor.DeclaringType == typeof(ScriptChangeStateException)) &&
- (valueno.args.Length == 1) && (valueno.args[0] is OTOpndInt))
- {
- OTOpndInt arg0 = (OTOpndInt)valueno.args[0];
- twout.Write("state " + decompile.scriptObjCode.stateNames[arg0.value] + ';');
- return;
- }
- }
- // throwing something else, output as is
- twout.Write("throw " + value.PrintableString + ';');
- }
- }
- /**
- * Call with void return, or really anything that we discard the value of after computing it.
- */
- private class OTStmtVoid: OTStmt
- {
- private OTOpnd value;
- public static void AddLast(OTDecompile decompile, OTOpnd value)
- {
- OTStmt it = OTStmtVoid.Make(value);
- if(it != null)
- decompile.AddLastStmt(it);
- }
- public static OTStmt Make(OTOpnd value)
- {
- if(!value.HasSideEffects)
- return null;
- OTStmtVoid it = new OTStmtVoid();
- it.value = value;
- return it;
- }
- private OTStmtVoid()
- {
- }
- public override void CountRefs()
- {
- value.CountRefs(false);
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- value = value.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // strip out calls to CheckRunQuick() and CheckRunStack()
- if(value is OTOpndCall)
- {
- OTOpndCall call = (OTOpndCall)value;
- MethodInfo method = call.method;
- if((method.Name == _checkRunQuick) || (method.Name == _checkRunStack))
- {
- link.List.Remove(link);
- return true;
- }
- }
- return false;
- }
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write(value.PrintableString + ';');
- }
- }
- /***************************\
- * Structured statements *
- \***************************/
- /**
- * Block of statements.
- */
- private class OTStmtBlock: OTStmt
- {
- public LinkedList<OTStmt> blkstmts = new LinkedList<OTStmt>();
- public override void CountRefs()
- {
- foreach(OTStmt stmt in blkstmts)
- {
- stmt.CountRefs();
- }
- }
- /**
- * Scrub out all references to behind-the-scenes parts and simplify.
- */
- public override bool StripStuff(LinkedListNode<OTStmt> link)
- {
- // loop through all sub-statements to strip out behind-the-scenes references
- bool rc = false;
- loop:
- for(LinkedListNode<OTStmt> stmtlink = blkstmts.First; stmtlink != null; stmtlink = stmtlink.Next)
- {
- if(stmtlink.Value.StripStuff(stmtlink))
- {
- rc = true;
- goto loop;
- }
- }
- if(rc)
- return true;
- // try to merge this block into outer block
- // change:
- // {
- // ...
- // { << link points here
- // ...
- // }
- // ...
- // }
- // to:
- // {
- // ...
- // ...
- // ...
- // }
- if(link != null)
- {
- LinkedListNode<OTStmt> nextlink;
- while((nextlink = blkstmts.Last) != null)
- {
- nextlink.List.Remove(nextlink);
- link.List.AddAfter(link, nextlink);
- }
- link.List.Remove(link);
- return true;
- }
- return rc;
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = false;
- foreach(OTStmt stmt in blkstmts)
- {
- rc |= stmt.ReplaceOperand(oldopnd, newopnd);
- }
- return rc;
- }
- /**
- * Check each statement in the block to see if it starts a do/for/if/while statement.
- */
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- bool rc = false;
- loop:
- for(link = blkstmts.First; link != null; link = link.Next)
- {
- if(link.Value.DetectDoForIfWhile(link))
- {
- rc = true;
- goto loop;
- }
- }
- return rc;
- }
- /**
- * Assume we will never try to replace the block itself.
- * But go through all our sub-ordinates statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- for(LinkedListNode<OTStmt> childlink = blkstmts.First; childlink != null; childlink = childlink.Next)
- {
- childlink.Value = childlink.Value.ReplaceStatement(oldstmt, newstmt);
- }
- return this;
- }
- /**
- * Print out the block including its enclosed statements.
- */
- public override void PrintStmt(TextWriter twout, string indent)
- {
- switch(blkstmts.Count)
- {
- case 0:
- {
- twout.Write("{ }");
- break;
- }
- ////case 1: {
- //// blkstmts.First.Value.PrintStmt (twout, indent);
- //// break;
- ////}
- default:
- {
- twout.Write('{');
- PrintBodyAndEnd(twout, indent);
- break;
- }
- }
- }
- public void PrintBodyAndEnd(TextWriter twout, string indent)
- {
- string newindent = indent + INDENT;
- foreach(OTStmt stmt in blkstmts)
- {
- twout.Write('\n' + indent);
- if(!(stmt is OTStmtLabel))
- twout.Write(INDENT);
- else
- twout.Write(LABELINDENT);
- stmt.PrintStmt(twout, newindent);
- }
- twout.Write('\n' + indent + '}');
- }
- }
- /**
- * 'do' statement.
- */
- private class OTStmtDo: OTStmt
- {
- private OTOpnd dotest;
- private OTStmtBlock dobody;
- /**
- * See if we have a do loop...
- * @doloop_<suffix>; << link points here
- * ... <dobody> ...
- * [ if (dotest) ] jump doloop_<suffix>;
- */
- public static bool Detect(LinkedListNode<OTStmt> link)
- {
- // see if we have label starting with 'doloop_'
- OTLabel looplabel = ((OTStmtLabel)link.Value).label;
- if(!looplabel.name.StartsWith(_doLoop))
- return false;
- // good chance we have a do loop
- OTStmtDo it = new OTStmtDo();
- // scan ahead looking for the terminating cond/jump loop
- // also gather up the statements for the do body block
- it.dobody = new OTStmtBlock();
- LinkedListNode<OTStmt> nextlink;
- for(nextlink = link.Next; nextlink != null; nextlink = nextlink.Next)
- {
- OTStmt nextstmt = nextlink.Value;
- // add statement to do body
- it.dobody.blkstmts.AddLast(nextlink.Value);
- // check for something what jumps to loop label
- // that gives us the end of the loop
- OTStmt maybejump = nextstmt;
- if(nextstmt is OTStmtCond)
- {
- maybejump = ((OTStmtCond)nextstmt).stmt;
- }
- if((maybejump is OTStmtJump) && (((OTStmtJump)maybejump).label == looplabel))
- {
- break;
- }
- }
- // make sure we found the jump back to the loop label
- if(nextlink == null)
- return false;
- // remove all statements from caller's block including the continue label if any
- // but leave the break label alone it will be removed later if unreferenced
- // and leave the initial loop label intact for now
- for(LinkedListNode<OTStmt> remlink = null; (remlink = link.Next) != null;)
- {
- link.List.Remove(remlink);
- if(remlink == nextlink)
- break;
- }
- // take test condition from last statement of body
- // it should be an cond/jump or just a jump to the loop label
- LinkedListNode<OTStmt> lastlink = it.dobody.blkstmts.Last;
- OTStmt laststmt = lastlink.Value;
- if(laststmt is OTStmtCond)
- {
- it.dotest = ((OTStmtCond)laststmt).valu;
- }
- else
- {
- it.dotest = new OTOpndInt(1);
- }
- lastlink.List.Remove(lastlink);
- // finally replace the loop label with the whole do statement
- link.Value = it;
- // tell caller we made a change
- return true;
- }
- public override void CountRefs()
- {
- if(dotest != null)
- dotest.CountRefs(false);
- if(dobody != null)
- dobody.CountRefs();
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return dobody.ReplaceOperand(oldopnd, newopnd);
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return dobody.DetectDoForIfWhile(link);
- }
- /**
- * Assume we won't replace the do statement itself.
- * But search all our sub-ordinate statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- dobody = (OTStmtBlock)dobody.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- // output do body
- twout.Write("do ");
- dobody.PrintStmt(twout, indent);
- // output while part
- twout.Write(" while (" + StripBrtrue(dotest).PrintableString + ");");
- }
- }
- /**
- * 'for' or 'while' statement.
- */
- private class OTStmtFor: OTStmt
- {
- private bool iswhile;
- private OTOpnd fortest;
- private OTStmtBlock forbody;
- private OTStmt forinit;
- private OTStmt forstep;
- /**
- * See if we have a for or while loop...
- * <forinit>
- * @forloop_<suffix>; << link points here
- * [ if (<fortest>) jump forbreak_<suffix>; ]
- * ... <forbody> ...
- * jump forloop_<suffix>;
- * [ @forbreak_<suffix>; ]
- */
- public static bool Detect(LinkedListNode<OTStmt> link, bool iswhile)
- {
- string loopname = iswhile ? _whileLoop : _forLoop;
- string breakname = iswhile ? _whileBreak : _forBreak;
- // see if we have label starting with 'forloop_'
- OTLabel looplabel = ((OTStmtLabel)link.Value).label;
- if(!looplabel.name.StartsWith(loopname))
- return false;
- // good chance we have a for loop
- OTStmtFor it = new OTStmtFor();
- it.iswhile = iswhile;
- // all labels end with this suffix
- string suffix = looplabel.name.Substring(loopname.Length);
- // scan ahead looking for the 'jump forloop_<suffix>;' statement
- // also gather up the statements for the for body block
- it.forbody = new OTStmtBlock();
- LinkedListNode<OTStmt> lastlink;
- for(lastlink = link; (lastlink = lastlink.Next) != null;)
- {
- // check for jump forloop that tells us where loop ends
- if(lastlink.Value is OTStmtJump)
- {
- OTStmtJump lastjump = (OTStmtJump)lastlink.Value;
- if(lastjump.label == looplabel)
- break;
- }
- // add to body block
- it.forbody.blkstmts.AddLast(lastlink.Value);
- }
- // make sure we found the 'jump forloop' where the for loop ends
- if(lastlink == null)
- return false;
- // remove all statements from caller's block including final jump
- // but leave the loop label in place
- for(LinkedListNode<OTStmt> nextlink = null; (nextlink = link.Next) != null;)
- {
- link.List.Remove(nextlink);
- if(nextlink == lastlink)
- break;
- }
- // if statement before loop label is an assignment, use it for the init statement
- if(!iswhile && (link.Previous != null) && (link.Previous.Value is OTStmtStore))
- {
- it.forinit = link.Previous.Value;
- link.List.Remove(link.Previous);
- }
- // if first statement of for body is 'if (...) jump breaklabel' use it for the test value
- if((it.forbody.blkstmts.First != null) && (it.forbody.blkstmts.First.Value is OTStmtCond))
- {
- OTStmtCond condstmt = (OTStmtCond)it.forbody.blkstmts.First.Value;
- if((condstmt.stmt is OTStmtJump) && (((OTStmtJump)condstmt.stmt).label.name == breakname + suffix))
- {
- it.fortest = OTOpndUnOp.Make(MyOp.Brfalse, condstmt.valu);
- it.forbody.blkstmts.RemoveFirst();
- }
- }
- // if last statement of body is an assigment,
- // use the assignment as the step statement
- if(!iswhile && (it.forbody.blkstmts.Last != null) &&
- (it.forbody.blkstmts.Last.Value is OTStmtStore))
- {
- LinkedListNode<OTStmt> storelink = it.forbody.blkstmts.Last;
- storelink.List.Remove(storelink);
- it.forstep = storelink.Value;
- }
- // finally replace the loop label with the whole for statement
- link.Value = it;
- // tell caller we made a change
- return true;
- }
- public override void CountRefs()
- {
- if(fortest != null)
- fortest.CountRefs(false);
- if(forbody != null)
- forbody.CountRefs();
- if(forinit != null)
- forinit.CountRefs();
- if(forstep != null)
- forstep.CountRefs();
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- return forbody.ReplaceOperand(oldopnd, newopnd) |
- ((forinit != null) && forinit.ReplaceOperand(oldopnd, newopnd)) |
- ((forstep != null) && forstep.ReplaceOperand(oldopnd, newopnd));
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return forbody.DetectDoForIfWhile(link) |
- ((forinit != null) && forinit.DetectDoForIfWhile(link)) |
- ((forstep != null) && forstep.DetectDoForIfWhile(link));
- }
- /**
- * Assume we won't replace the for statement itself.
- * But search all our sub-ordinate statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- forbody = (OTStmtBlock)forbody.ReplaceStatement(oldstmt, newstmt);
- if(forinit != null)
- forinit = forinit.ReplaceStatement(oldstmt, newstmt);
- if(forstep != null)
- forstep = forstep.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- if(iswhile)
- {
- twout.Write("while (");
- if(fortest == null)
- {
- twout.Write("TRUE");
- }
- else
- {
- twout.Write(StripBrtrue(fortest).PrintableString);
- }
- }
- else
- {
- twout.Write("for (");
- if(forinit != null)
- {
- forinit.PrintStmt(twout, indent + INDENT);
- }
- else
- {
- twout.Write(';');
- }
- if(fortest != null)
- {
- twout.Write(' ' + StripBrtrue(fortest).PrintableString);
- }
- twout.Write(';');
- if(forstep != null)
- {
- StringWriter sw = new StringWriter();
- sw.Write(' ');
- forstep.PrintStmt(sw, indent + INDENT);
- StringBuilder sb = sw.GetStringBuilder();
- int sl = sb.Length;
- if((sl > 0) && (sb[sl - 1] == ';'))
- sb.Remove(--sl, 1);
- twout.Write(sb.ToString());
- }
- }
- twout.Write(") ");
- forbody.PrintStmt(twout, indent);
- }
- }
- /**
- * if/then/else block.
- */
- private class OTStmtIf: OTStmt
- {
- private OTOpnd testvalu;
- private OTStmt thenstmt;
- private OTStmt elsestmt; // might be null
- /**
- * Try to detect a structured if statement.
- *
- * if (condition) jump ifdone_<suffix>; << link points here
- * ... then body ...
- * @ifdone_<suffix>;
- *
- * if (condition) jump ifelse_<suffix>;
- * ... then body ...
- * jump ifdone_<suffix>; << optional if true body doesn't fall through
- * @ifelse_<suffix>;
- * ... else body ...
- * @ifdone_<suffix>;
- */
- public static bool Detect(LinkedListNode<OTStmt> link)
- {
- OTStmtCond condstmt = (OTStmtCond)link.Value;
- if(!(condstmt.stmt is OTStmtJump))
- return false;
- OTStmtJump jumpstmt = (OTStmtJump)condstmt.stmt;
- if(jumpstmt.label.name.StartsWith(_ifDone))
- {
- // then-only if
- // skip forward to find the ifdone_<suffix> label
- // also save the intervening statements for the then body
- OTStmtBlock thenbody;
- LinkedListNode<OTStmt> donelink = ScanForLabel(link, jumpstmt.label, out thenbody);
- // make sure we found matching label
- if(donelink == null)
- return false;
- // replace the jump ifdone_<suffix> with the <then body>
- OTStmtIf it = new OTStmtIf();
- it.thenstmt = thenbody;
- // replace the test value with the opposite
- it.testvalu = OTOpndUnOp.Make(MyOp.Brfalse, condstmt.valu);
- condstmt.valu = null;
- // strip out the true body statements from the main code including the ifdone_<suffix> label
- StripInterveningStatements(link, donelink);
- // replace the simple conditional with the if/then/else block
- link.Value = it;
- // tell caller we changed something
- return true;
- }
- if(jumpstmt.label.name.StartsWith(_ifElse))
- {
- string suffix = jumpstmt.label.name.Substring(_ifElse.Length);
- // if/then/else
- OTStmtIf it = new OTStmtIf();
- // skip forward to find the ifelse_<suffix> label
- // also save the intervening statements for the true body
- OTStmtBlock thenbody;
- LinkedListNode<OTStmt> elselink = ScanForLabel(link, jumpstmt.label, out thenbody);
- // make sure we found matching label
- if(elselink != null)
- {
- // the last statement of the then body might be a jump ifdone_<suffix>
- LinkedListNode<OTStmt> lastthenlink = thenbody.blkstmts.Last;
- if((lastthenlink != null) && (lastthenlink.Value is OTStmtJump))
- {
- OTStmtJump jumpifdone = (OTStmtJump)lastthenlink.Value;
- if(jumpifdone.label.name == _ifDone + suffix)
- {
- lastthenlink.List.Remove(lastthenlink);
- // skip forward to find the ifdone_<suffix> label
- // also save the intervening statements for the else body
- OTStmtBlock elsebody;
- LinkedListNode<OTStmt> donelink = ScanForLabel(elselink, jumpifdone.label, out elsebody);
- if(donelink != null)
- {
- // replace the jump ifdone_<suffix> with the <true body>
- it.thenstmt = thenbody;
- // save the else body as well
- it.elsestmt = elsebody;
- // replace the test value with the opposite
- it.testvalu = OTOpndUnOp.Make(MyOp.Brfalse, condstmt.valu);
- condstmt.valu = null;
- // strip out the true and else body statements from the main code including the ifdone_<suffix> label
- StripInterveningStatements(link, donelink);
- // replace the simple conditional with the if/then/else block
- link.Value = it;
- // tell caller we changed something
- return true;
- }
- }
- }
- // missing the jump _ifDone_<suffix>, so make it a simple if/then
- // if (condition) jump ifelse_<suffix>; << link
- // ... then body ... << encapsulated in block thenbody
- // @ifelse_<suffix>; << elselink
- // ... else body ... << still inline and leave it there
- // @ifdone_<suffix>; << strip this out
- // replace the jump ifelse_<suffix> with the <true body>
- it.thenstmt = thenbody;
- // replace the test value with the opposite
- it.testvalu = OTOpndUnOp.Make(MyOp.Brfalse, condstmt.valu);
- condstmt.valu = null;
- // strip out the then body statements from the main code including the ifelse_<suffix> label
- StripInterveningStatements(link, elselink);
- // there's a dangling unused ifdone_<suffix> label ahead that has to be stripped
- for(LinkedListNode<OTStmt> donelink = link; (donelink = donelink.Next) != null;)
- {
- if((donelink.Value is OTStmtLabel) && (((OTStmtLabel)donelink.Value).label.name == _ifDone + suffix))
- {
- donelink.List.Remove(donelink);
- break;
- }
- }
- // replace the simple conditional with the if/then/else block
- link.Value = it;
- // tell caller we changed something
- return true;
- }
- }
- return false;
- }
- private OTStmtIf()
- {
- }
- public override void CountRefs()
- {
- if(testvalu != null)
- testvalu.CountRefs(false);
- if(thenstmt != null)
- thenstmt.CountRefs();
- if(elsestmt != null)
- elsestmt.CountRefs();
- }
- public override bool ReplaceOperand(OTOpnd oldopnd, OTOpnd newopnd)
- {
- bool rc = thenstmt.ReplaceOperand(oldopnd, newopnd);
- testvalu = testvalu.ReplaceOperand(oldopnd, newopnd, ref rc);
- return rc;
- }
- public override bool DetectDoForIfWhile(LinkedListNode<OTStmt> link)
- {
- return ((thenstmt != null) && thenstmt.DetectDoForIfWhile(link)) |
- ((elsestmt != null) && elsestmt.DetectDoForIfWhile(link));
- }
- /**
- * Assume we won't replace the if statement itself.
- * But search all our sub-ordinate statements.
- */
- public override OTStmt ReplaceStatement(OTStmt oldstmt, OTStmt newstmt)
- {
- thenstmt = thenstmt.ReplaceStatement(oldstmt, newstmt);
- if(elsestmt != null)
- elsestmt = elsestmt.ReplaceStatement(oldstmt, newstmt);
- return this;
- }
- public override void PrintStmt(TextWriter twout, string indent)
- {
- twout.Write("if (" + StripBrtrue(testvalu).PrintableString + ") ");
- OTStmt thenst = ReduceStmtBody(thenstmt, false);
- thenst.PrintStmt(twout, indent);
- if(elsestmt != null)
- {
- twout.Write('\n' + indent + "else ");
- OTStmt elsest = ReduceStmtBody(elsestmt, true);
- elsest.PrintStmt(twout, indent);
- }
- }
- // strip block off a single jump so it prints inline instead of with braces around it
- // also, if this is part of else, strip block for ifs to make else if statement
- private static OTStmt ReduceStmtBody(OTStmt statement, bool stripif)
- {
- OTStmt onestmt = statement;
- if((onestmt is OTStmtBlock) && (((OTStmtBlock)onestmt).blkstmts.Count == 1))
- {
- onestmt = ((OTStmtBlock)onestmt).blkstmts.First.Value;
- if((onestmt is OTStmtJump) || (stripif && (onestmt is OTStmtIf)))
- {
- return onestmt;
- }
- }
- return statement;
- }
- /**
- * Scan forward for a given label definition.
- * Put intervening statements in a statement block.
- * @param link = start scanning after this statement
- * @param label = look for this label definition
- * @param block = where to return intervening statement block
- * @returns null: label definition not found
- * else: label definition statement
- */
- private static LinkedListNode<OTStmt> ScanForLabel(LinkedListNode<OTStmt> link,
- OTLabel label, out OTStmtBlock block)
- {
- block = new OTStmtBlock();
- while((link = link.Next) != null)
- {
- if(link.Value is OTStmtLabel)
- {
- if(((OTStmtLabel)link.Value).label == label)
- break;
- }
- block.blkstmts.AddLast(link.Value);
- }
- return link;
- }
- /**
- * Strip statements after link up to and including donelink.
- */
- private static void StripInterveningStatements(LinkedListNode<OTStmt> link, LinkedListNode<OTStmt> donelink)
- {
- LinkedListNode<OTStmt> striplink;
- do
- {
- striplink = link.Next;
- striplink.List.Remove(striplink);
- } while(striplink != donelink);
- }
- }
- private class MyOp
- {
- public int index;
- public OpCode sysop;
- public string name;
- public string source;
- private static Dictionary<string, MyOp> myopsbyname = new Dictionary<string, MyOp>();
- private static int nextindex = 0;
- public MyOp(OpCode sysop)
- {
- this.index = nextindex++;
- this.sysop = sysop;
- this.name = sysop.Name;
- myopsbyname.Add(name, this);
- }
- public MyOp(OpCode sysop, string source)
- {
- this.index = nextindex++;
- this.sysop = sysop;
- this.name = sysop.Name;
- this.source = source;
- myopsbyname.Add(name, this);
- }
- public MyOp(string name)
- {
- this.index = nextindex++;
- this.name = name;
- myopsbyname.Add(name, this);
- }
- public MyOp(string name, string source)
- {
- this.index = nextindex++;
- this.name = name;
- this.source = source;
- myopsbyname.Add(name, this);
- }
- public static MyOp GetByName(string name)
- {
- return myopsbyname[name];
- }
- public override string ToString()
- {
- return name;
- }
- // these copied from OpCodes.cs
- public static readonly MyOp Nop = new MyOp(OpCodes.Nop);
- public static readonly MyOp Break = new MyOp(OpCodes.Break);
- public static readonly MyOp Ldarg_0 = new MyOp(OpCodes.Ldarg_0);
- public static readonly MyOp Ldarg_1 = new MyOp(OpCodes.Ldarg_1);
- public static readonly MyOp Ldarg_2 = new MyOp(OpCodes.Ldarg_2);
- public static readonly MyOp Ldarg_3 = new MyOp(OpCodes.Ldarg_3);
- public static readonly MyOp Ldloc_0 = new MyOp(OpCodes.Ldloc_0);
- public static readonly MyOp Ldloc_1 = new MyOp(OpCodes.Ldloc_1);
- public static readonly MyOp Ldloc_2 = new MyOp(OpCodes.Ldloc_2);
- public static readonly MyOp Ldloc_3 = new MyOp(OpCodes.Ldloc_3);
- public static readonly MyOp Stloc_0 = new MyOp(OpCodes.Stloc_0);
- public static readonly MyOp Stloc_1 = new MyOp(OpCodes.Stloc_1);
- public static readonly MyOp Stloc_2 = new MyOp(OpCodes.Stloc_2);
- public static readonly MyOp Stloc_3 = new MyOp(OpCodes.Stloc_3);
- public static readonly MyOp Ldarg_S = new MyOp(OpCodes.Ldarg_S);
- public static readonly MyOp Ldarga_S = new MyOp(OpCodes.Ldarga_S);
- public static readonly MyOp Starg_S = new MyOp(OpCodes.Starg_S);
- public static readonly MyOp Ldloc_S = new MyOp(OpCodes.Ldloc_S);
- public static readonly MyOp Ldloca_S = new MyOp(OpCodes.Ldloca_S);
- public static readonly MyOp Stloc_S = new MyOp(OpCodes.Stloc_S);
- public static readonly MyOp Ldnull = new MyOp(OpCodes.Ldnull);
- public static readonly MyOp Ldc_I4_M1 = new MyOp(OpCodes.Ldc_I4_M1);
- public static readonly MyOp Ldc_I4_0 = new MyOp(OpCodes.Ldc_I4_0);
- public static readonly MyOp Ldc_I4_1 = new MyOp(OpCodes.Ldc_I4_1);
- public static readonly MyOp Ldc_I4_2 = new MyOp(OpCodes.Ldc_I4_2);
- public static readonly MyOp Ldc_I4_3 = new MyOp(OpCodes.Ldc_I4_3);
- public static readonly MyOp Ldc_I4_4 = new MyOp(OpCodes.Ldc_I4_4);
- public static readonly MyOp Ldc_I4_5 = new MyOp(OpCodes.Ldc_I4_5);
- public static readonly MyOp Ldc_I4_6 = new MyOp(OpCodes.Ldc_I4_6);
- public static readonly MyOp Ldc_I4_7 = new MyOp(OpCodes.Ldc_I4_7);
- public static readonly MyOp Ldc_I4_8 = new MyOp(OpCodes.Ldc_I4_8);
- public static readonly MyOp Ldc_I4_S = new MyOp(OpCodes.Ldc_I4_S);
- public static readonly MyOp Ldc_I4 = new MyOp(OpCodes.Ldc_I4);
- public static readonly MyOp Ldc_I8 = new MyOp(OpCodes.Ldc_I8);
- public static readonly MyOp Ldc_R4 = new MyOp(OpCodes.Ldc_R4);
- public static readonly MyOp Ldc_R8 = new MyOp(OpCodes.Ldc_R8);
- public static readonly MyOp Dup = new MyOp(OpCodes.Dup);
- public static readonly MyOp Pop = new MyOp(OpCodes.Pop);
- public static readonly MyOp Jmp = new MyOp(OpCodes.Jmp);
- public static readonly MyOp Call = new MyOp(OpCodes.Call);
- public static readonly MyOp Calli = new MyOp(OpCodes.Calli);
- public static readonly MyOp Ret = new MyOp(OpCodes.Ret);
- public static readonly MyOp Br_S = new MyOp(OpCodes.Br_S);
- public static readonly MyOp Brfalse_S = new MyOp(OpCodes.Brfalse_S);
- public static readonly MyOp Brtrue_S = new MyOp(OpCodes.Brtrue_S);
- public static readonly MyOp Beq_S = new MyOp(OpCodes.Beq_S, "==");
- public static readonly MyOp Bge_S = new MyOp(OpCodes.Bge_S, ">=");
- public static readonly MyOp Bgt_S = new MyOp(OpCodes.Bgt_S, ">");
- public static readonly MyOp Ble_S = new MyOp(OpCodes.Ble_S, "<=");
- public static readonly MyOp Blt_S = new MyOp(OpCodes.Blt_S, "<");
- public static readonly MyOp Bne_Un_S = new MyOp(OpCodes.Bne_Un_S, "!=");
- public static readonly MyOp Bge_Un_S = new MyOp(OpCodes.Bge_Un_S);
- public static readonly MyOp Bgt_Un_S = new MyOp(OpCodes.Bgt_Un_S);
- public static readonly MyOp Ble_Un_S = new MyOp(OpCodes.Ble_Un_S);
- public static readonly MyOp Blt_Un_S = new MyOp(OpCodes.Blt_Un_S);
- public static readonly MyOp Br = new MyOp(OpCodes.Br);
- public static readonly MyOp Brfalse = new MyOp(OpCodes.Brfalse, "!");
- public static readonly MyOp Brtrue = new MyOp(OpCodes.Brtrue, "!!");
- public static readonly MyOp Beq = new MyOp(OpCodes.Beq, "==");
- public static readonly MyOp Bge = new MyOp(OpCodes.Bge, ">=");
- public static readonly MyOp Bgt = new MyOp(OpCodes.Bgt, ">");
- public static readonly MyOp Ble = new MyOp(OpCodes.Ble, "<=");
- public static readonly MyOp Blt = new MyOp(OpCodes.Blt, "<");
- public static readonly MyOp Bne_Un = new MyOp(OpCodes.Bne_Un, "!=");
- public static readonly MyOp Bge_Un = new MyOp(OpCodes.Bge_Un);
- public static readonly MyOp Bgt_Un = new MyOp(OpCodes.Bgt_Un);
- public static readonly MyOp Ble_Un = new MyOp(OpCodes.Ble_Un);
- public static readonly MyOp Blt_Un = new MyOp(OpCodes.Blt_Un);
- public static readonly MyOp Switch = new MyOp(OpCodes.Switch);
- public static readonly MyOp Ldind_I1 = new MyOp(OpCodes.Ldind_I1);
- public static readonly MyOp Ldind_U1 = new MyOp(OpCodes.Ldind_U1);
- public static readonly MyOp Ldind_I2 = new MyOp(OpCodes.Ldind_I2);
- public static readonly MyOp Ldind_U2 = new MyOp(OpCodes.Ldind_U2);
- public static readonly MyOp Ldind_I4 = new MyOp(OpCodes.Ldind_I4);
- public static readonly MyOp Ldind_U4 = new MyOp(OpCodes.Ldind_U4);
- public static readonly MyOp Ldind_I8 = new MyOp(OpCodes.Ldind_I8);
- public static readonly MyOp Ldind_I = new MyOp(OpCodes.Ldind_I);
- public static readonly MyOp Ldind_R4 = new MyOp(OpCodes.Ldind_R4);
- public static readonly MyOp Ldind_R8 = new MyOp(OpCodes.Ldind_R8);
- public static readonly MyOp Ldind_Ref = new MyOp(OpCodes.Ldind_Ref);
- public static readonly MyOp Stind_Ref = new MyOp(OpCodes.Stind_Ref);
- public static readonly MyOp Stind_I1 = new MyOp(OpCodes.Stind_I1);
- public static readonly MyOp Stind_I2 = new MyOp(OpCodes.Stind_I2);
- public static readonly MyOp Stind_I4 = new MyOp(OpCodes.Stind_I4);
- public static readonly MyOp Stind_I8 = new MyOp(OpCodes.Stind_I8);
- public static readonly MyOp Stind_R4 = new MyOp(OpCodes.Stind_R4);
- public static readonly MyOp Stind_R8 = new MyOp(OpCodes.Stind_R8);
- public static readonly MyOp Add = new MyOp(OpCodes.Add, "+");
- public static readonly MyOp Sub = new MyOp(OpCodes.Sub, "-");
- public static readonly MyOp Mul = new MyOp(OpCodes.Mul, "*");
- public static readonly MyOp Div = new MyOp(OpCodes.Div, "/");
- public static readonly MyOp Div_Un = new MyOp(OpCodes.Div_Un);
- public static readonly MyOp Rem = new MyOp(OpCodes.Rem, "%");
- public static readonly MyOp Rem_Un = new MyOp(OpCodes.Rem_Un);
- public static readonly MyOp And = new MyOp(OpCodes.And, "&");
- public static readonly MyOp Or = new MyOp(OpCodes.Or, "|");
- public static readonly MyOp Xor = new MyOp(OpCodes.Xor, "^");
- public static readonly MyOp Shl = new MyOp(OpCodes.Shl, "<<");
- public static readonly MyOp Shr = new MyOp(OpCodes.Shr, ">>");
- public static readonly MyOp Shr_Un = new MyOp(OpCodes.Shr_Un);
- public static readonly MyOp Neg = new MyOp(OpCodes.Neg, "-");
- public static readonly MyOp Not = new MyOp(OpCodes.Not, "~");
- public static readonly MyOp Conv_I1 = new MyOp(OpCodes.Conv_I1);
- public static readonly MyOp Conv_I2 = new MyOp(OpCodes.Conv_I2);
- public static readonly MyOp Conv_I4 = new MyOp(OpCodes.Conv_I4);
- public static readonly MyOp Conv_I8 = new MyOp(OpCodes.Conv_I8);
- public static readonly MyOp Conv_R4 = new MyOp(OpCodes.Conv_R4);
- public static readonly MyOp Conv_R8 = new MyOp(OpCodes.Conv_R8);
- public static readonly MyOp Conv_U4 = new MyOp(OpCodes.Conv_U4);
- public static readonly MyOp Conv_U8 = new MyOp(OpCodes.Conv_U8);
- public static readonly MyOp Callvirt = new MyOp(OpCodes.Callvirt);
- public static readonly MyOp Cpobj = new MyOp(OpCodes.Cpobj);
- public static readonly MyOp Ldobj = new MyOp(OpCodes.Ldobj);
- public static readonly MyOp Ldstr = new MyOp(OpCodes.Ldstr);
- public static readonly MyOp Newobj = new MyOp(OpCodes.Newobj);
- public static readonly MyOp Castclass = new MyOp(OpCodes.Castclass);
- public static readonly MyOp Isinst = new MyOp(OpCodes.Isinst);
- public static readonly MyOp Conv_R_Un = new MyOp(OpCodes.Conv_R_Un);
- public static readonly MyOp Unbox = new MyOp(OpCodes.Unbox);
- public static readonly MyOp Throw = new MyOp(OpCodes.Throw);
- public static readonly MyOp Ldfld = new MyOp(OpCodes.Ldfld);
- public static readonly MyOp Ldflda = new MyOp(OpCodes.Ldflda);
- public static readonly MyOp Stfld = new MyOp(OpCodes.Stfld);
- public static readonly MyOp Ldsfld = new MyOp(OpCodes.Ldsfld);
- public static readonly MyOp Ldsflda = new MyOp(OpCodes.Ldsflda);
- public static readonly MyOp Stsfld = new MyOp(OpCodes.Stsfld);
- public static readonly MyOp Stobj = new MyOp(OpCodes.Stobj);
- public static readonly MyOp Conv_Ovf_I1_Un = new MyOp(OpCodes.Conv_Ovf_I1_Un);
- public static readonly MyOp Conv_Ovf_I2_Un = new MyOp(OpCodes.Conv_Ovf_I2_Un);
- public static readonly MyOp Conv_Ovf_I4_Un = new MyOp(OpCodes.Conv_Ovf_I4_Un);
- public static readonly MyOp Conv_Ovf_I8_Un = new MyOp(OpCodes.Conv_Ovf_I8_Un);
- public static readonly MyOp Conv_Ovf_U1_Un = new MyOp(OpCodes.Conv_Ovf_U1_Un);
- public static readonly MyOp Conv_Ovf_U2_Un = new MyOp(OpCodes.Conv_Ovf_U2_Un);
- public static readonly MyOp Conv_Ovf_U4_Un = new MyOp(OpCodes.Conv_Ovf_U4_Un);
- public static readonly MyOp Conv_Ovf_U8_Un = new MyOp(OpCodes.Conv_Ovf_U8_Un);
- public static readonly MyOp Conv_Ovf_I_Un = new MyOp(OpCodes.Conv_Ovf_I_Un);
- public static readonly MyOp Conv_Ovf_U_Un = new MyOp(OpCodes.Conv_Ovf_U_Un);
- public static readonly MyOp Box = new MyOp(OpCodes.Box);
- public static readonly MyOp Newarr = new MyOp(OpCodes.Newarr);
- public static readonly MyOp Ldlen = new MyOp(OpCodes.Ldlen);
- public static readonly MyOp Ldelema = new MyOp(OpCodes.Ldelema);
- public static readonly MyOp Ldelem_I1 = new MyOp(OpCodes.Ldelem_I1);
- public static readonly MyOp Ldelem_U1 = new MyOp(OpCodes.Ldelem_U1);
- public static readonly MyOp Ldelem_I2 = new MyOp(OpCodes.Ldelem_I2);
- public static readonly MyOp Ldelem_U2 = new MyOp(OpCodes.Ldelem_U2);
- public static readonly MyOp Ldelem_I4 = new MyOp(OpCodes.Ldelem_I4);
- public static readonly MyOp Ldelem_U4 = new MyOp(OpCodes.Ldelem_U4);
- public static readonly MyOp Ldelem_I8 = new MyOp(OpCodes.Ldelem_I8);
- public static readonly MyOp Ldelem_I = new MyOp(OpCodes.Ldelem_I);
- public static readonly MyOp Ldelem_R4 = new MyOp(OpCodes.Ldelem_R4);
- public static readonly MyOp Ldelem_R8 = new MyOp(OpCodes.Ldelem_R8);
- public static readonly MyOp Ldelem_Ref = new MyOp(OpCodes.Ldelem_Ref);
- public static readonly MyOp Stelem_I = new MyOp(OpCodes.Stelem_I);
- public static readonly MyOp Stelem_I1 = new MyOp(OpCodes.Stelem_I1);
- public static readonly MyOp Stelem_I2 = new MyOp(OpCodes.Stelem_I2);
- public static readonly MyOp Stelem_I4 = new MyOp(OpCodes.Stelem_I4);
- public static readonly MyOp Stelem_I8 = new MyOp(OpCodes.Stelem_I8);
- public static readonly MyOp Stelem_R4 = new MyOp(OpCodes.Stelem_R4);
- public static readonly MyOp Stelem_R8 = new MyOp(OpCodes.Stelem_R8);
- public static readonly MyOp Stelem_Ref = new MyOp(OpCodes.Stelem_Ref);
- public static readonly MyOp Ldelem = new MyOp(OpCodes.Ldelem);
- public static readonly MyOp Stelem = new MyOp(OpCodes.Stelem);
- public static readonly MyOp Unbox_Any = new MyOp(OpCodes.Unbox_Any);
- public static readonly MyOp Conv_Ovf_I1 = new MyOp(OpCodes.Conv_Ovf_I1);
- public static readonly MyOp Conv_Ovf_U1 = new MyOp(OpCodes.Conv_Ovf_U1);
- public static readonly MyOp Conv_Ovf_I2 = new MyOp(OpCodes.Conv_Ovf_I2);
- public static readonly MyOp Conv_Ovf_U2 = new MyOp(OpCodes.Conv_Ovf_U2);
- public static readonly MyOp Conv_Ovf_I4 = new MyOp(OpCodes.Conv_Ovf_I4);
- public static readonly MyOp Conv_Ovf_U4 = new MyOp(OpCodes.Conv_Ovf_U4);
- public static readonly MyOp Conv_Ovf_I8 = new MyOp(OpCodes.Conv_Ovf_I8);
- public static readonly MyOp Conv_Ovf_U8 = new MyOp(OpCodes.Conv_Ovf_U8);
- public static readonly MyOp Refanyval = new MyOp(OpCodes.Refanyval);
- public static readonly MyOp Ckfinite = new MyOp(OpCodes.Ckfinite);
- public static readonly MyOp Mkrefany = new MyOp(OpCodes.Mkrefany);
- public static readonly MyOp Ldtoken = new MyOp(OpCodes.Ldtoken);
- public static readonly MyOp Conv_U2 = new MyOp(OpCodes.Conv_U2);
- public static readonly MyOp Conv_U1 = new MyOp(OpCodes.Conv_U1);
- public static readonly MyOp Conv_I = new MyOp(OpCodes.Conv_I);
- public static readonly MyOp Conv_Ovf_I = new MyOp(OpCodes.Conv_Ovf_I);
- public static readonly MyOp Conv_Ovf_U = new MyOp(OpCodes.Conv_Ovf_U);
- public static readonly MyOp Add_Ovf = new MyOp(OpCodes.Add_Ovf);
- public static readonly MyOp Add_Ovf_Un = new MyOp(OpCodes.Add_Ovf_Un);
- public static readonly MyOp Mul_Ovf = new MyOp(OpCodes.Mul_Ovf);
- public static readonly MyOp Mul_Ovf_Un = new MyOp(OpCodes.Mul_Ovf_Un);
- public static readonly MyOp Sub_Ovf = new MyOp(OpCodes.Sub_Ovf);
- public static readonly MyOp Sub_Ovf_Un = new MyOp(OpCodes.Sub_Ovf_Un);
- public static readonly MyOp Endfinally = new MyOp(OpCodes.Endfinally);
- public static readonly MyOp Leave = new MyOp(OpCodes.Leave);
- public static readonly MyOp Leave_S = new MyOp(OpCodes.Leave_S);
- public static readonly MyOp Stind_I = new MyOp(OpCodes.Stind_I);
- public static readonly MyOp Conv_U = new MyOp(OpCodes.Conv_U);
- public static readonly MyOp Prefix7 = new MyOp(OpCodes.Prefix7);
- public static readonly MyOp Prefix6 = new MyOp(OpCodes.Prefix6);
- public static readonly MyOp Prefix5 = new MyOp(OpCodes.Prefix5);
- public static readonly MyOp Prefix4 = new MyOp(OpCodes.Prefix4);
- public static readonly MyOp Prefix3 = new MyOp(OpCodes.Prefix3);
- public static readonly MyOp Prefix2 = new MyOp(OpCodes.Prefix2);
- public static readonly MyOp Prefix1 = new MyOp(OpCodes.Prefix1);
- public static readonly MyOp Prefixref = new MyOp(OpCodes.Prefixref);
- public static readonly MyOp Arglist = new MyOp(OpCodes.Arglist);
- public static readonly MyOp Ceq = new MyOp(OpCodes.Ceq, "==");
- public static readonly MyOp Cgt = new MyOp(OpCodes.Cgt, ">");
- public static readonly MyOp Cgt_Un = new MyOp(OpCodes.Cgt_Un);
- public static readonly MyOp Clt = new MyOp(OpCodes.Clt, "<");
- public static readonly MyOp Clt_Un = new MyOp(OpCodes.Clt_Un);
- public static readonly MyOp Ldftn = new MyOp(OpCodes.Ldftn);
- public static readonly MyOp Ldvirtftn = new MyOp(OpCodes.Ldvirtftn);
- public static readonly MyOp Ldarg = new MyOp(OpCodes.Ldarg);
- public static readonly MyOp Ldarga = new MyOp(OpCodes.Ldarga);
- public static readonly MyOp Starg = new MyOp(OpCodes.Starg);
- public static readonly MyOp Ldloc = new MyOp(OpCodes.Ldloc);
- public static readonly MyOp Ldloca = new MyOp(OpCodes.Ldloca);
- public static readonly MyOp Stloc = new MyOp(OpCodes.Stloc);
- public static readonly MyOp Localloc = new MyOp(OpCodes.Localloc);
- public static readonly MyOp Endfilter = new MyOp(OpCodes.Endfilter);
- public static readonly MyOp Unaligned = new MyOp(OpCodes.Unaligned);
- public static readonly MyOp Volatile = new MyOp(OpCodes.Volatile);
- public static readonly MyOp Tailcall = new MyOp(OpCodes.Tailcall);
- public static readonly MyOp Initobj = new MyOp(OpCodes.Initobj);
- public static readonly MyOp Constrained = new MyOp(OpCodes.Constrained);
- public static readonly MyOp Cpblk = new MyOp(OpCodes.Cpblk);
- public static readonly MyOp Initblk = new MyOp(OpCodes.Initblk);
- public static readonly MyOp Rethrow = new MyOp(OpCodes.Rethrow);
- public static readonly MyOp Sizeof = new MyOp(OpCodes.Sizeof);
- public static readonly MyOp Refanytype = new MyOp(OpCodes.Refanytype);
- public static readonly MyOp Readonly = new MyOp(OpCodes.Readonly);
- // used internally
- public static readonly MyOp Cge = new MyOp("cge", ">=");
- public static readonly MyOp Cle = new MyOp("cle", "<=");
- public static readonly MyOp Cne = new MyOp("cne", "!=");
- }
- }
- }
|