TransformContext.cpp 142 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710
  1. #include "TransformContext.h"
  2. #include "metadata/GenericMetadata.h"
  3. #include "vm/Class.h"
  4. #include "vm/Exception.h"
  5. #include "vm/String.h"
  6. #include "vm/Field.h"
  7. #include "../metadata/MethodBodyCache.h"
  8. #include "../interpreter/InterpreterUtil.h"
  9. namespace hybridclr
  10. {
  11. namespace transform
  12. {
  13. constexpr int32_t MAX_STACK_SIZE = (2 << 16) - 1;
  14. constexpr int32_t MAX_VALUE_TYPE_SIZE = (2 << 16) - 1;
  15. template<typename T>
  16. void AllocResolvedData(il2cpp::utils::dynamic_array<uint64_t>& resolvedDatas, int32_t size, int32_t& index, T*& buf)
  17. {
  18. if (size > 0)
  19. {
  20. int32_t oldSize = index = (int32_t)resolvedDatas.size();
  21. resolvedDatas.resize_initialized(oldSize + size);
  22. buf = (T*)&resolvedDatas[oldSize];
  23. }
  24. else
  25. {
  26. index = 0;
  27. buf = nullptr;
  28. }
  29. }
  30. IRCommon* CreateInitLocals(TemporaryMemoryArena& pool, uint32_t size, int32_t offset)
  31. {
  32. if (offset == 0)
  33. {
  34. CreateIR(ir, InitLocals_n_4);
  35. ir->size = size;
  36. return ir;
  37. }
  38. else
  39. {
  40. CreateIR(ir, InitInlineLocals_n_4);
  41. ir->size = size;
  42. ir->offset = offset;
  43. return ir;
  44. }
  45. }
  46. IRCommon* CreateLoadExpandDataToStackVarVar(TemporaryMemoryArena& pool, int32_t dstOffset, int32_t srcOffset, const Il2CppType* type, int32_t size);
  47. IRCommon* CreateAssignVarVar(TemporaryMemoryArena& pool, int32_t dstOffset, int32_t srcOffset, int32_t size);
  48. interpreter::IRCommon* CreateClassLdfld(TemporaryMemoryArena& pool, int32_t dstIdx, int32_t objIdx, const FieldInfo* fieldInfo);
  49. interpreter::IRCommon* CreateValueTypeLdfld(TemporaryMemoryArena& pool, int32_t dstIdx, int32_t objIdx, const FieldInfo* fieldInfo);
  50. interpreter::IRCommon* CreateStfld(TemporaryMemoryArena& pool, int32_t objIdx, const FieldInfo* fieldInfo, int32_t dataIdx);
  51. interpreter::IRCommon* CreateLdsfld(TemporaryMemoryArena& pool, int32_t dstIdx, const FieldInfo* fieldInfo, uint32_t parent);
  52. interpreter::IRCommon* CreateStsfld(TemporaryMemoryArena& pool, const FieldInfo* fieldInfo, uint32_t parent, int32_t dataIdx);
  53. interpreter::IRCommon* CreateLdthreadlocal(TemporaryMemoryArena& pool, int32_t dstIdx, const FieldInfo* fieldInfo, uint32_t parent);
  54. interpreter::IRCommon* CreateStthreadlocal(TemporaryMemoryArena& pool, const FieldInfo* fieldInfo, uint32_t parent, int32_t dataIdx);
  55. EvalStackReduceDataType GetEvalStackReduceDataType(const Il2CppType* type)
  56. {
  57. if (type->byref)
  58. {
  59. return NATIVE_INT_REDUCE_TYPE;
  60. }
  61. switch (type->type)
  62. {
  63. case IL2CPP_TYPE_BOOLEAN:
  64. case IL2CPP_TYPE_I1:
  65. case IL2CPP_TYPE_U1:
  66. case IL2CPP_TYPE_CHAR:
  67. case IL2CPP_TYPE_I2:
  68. case IL2CPP_TYPE_U2:
  69. case IL2CPP_TYPE_I4:
  70. case IL2CPP_TYPE_U4:
  71. return EvalStackReduceDataType::I4;
  72. case IL2CPP_TYPE_R4:
  73. return EvalStackReduceDataType::R4;
  74. case IL2CPP_TYPE_I8:
  75. case IL2CPP_TYPE_U8:
  76. return EvalStackReduceDataType::I8;
  77. case IL2CPP_TYPE_R8:
  78. return EvalStackReduceDataType::R8;
  79. case IL2CPP_TYPE_I:
  80. case IL2CPP_TYPE_U:
  81. case IL2CPP_TYPE_FNPTR:
  82. case IL2CPP_TYPE_PTR:
  83. case IL2CPP_TYPE_BYREF:
  84. case IL2CPP_TYPE_STRING:
  85. case IL2CPP_TYPE_CLASS:
  86. case IL2CPP_TYPE_ARRAY:
  87. case IL2CPP_TYPE_SZARRAY:
  88. case IL2CPP_TYPE_OBJECT:
  89. return NATIVE_INT_REDUCE_TYPE;
  90. case IL2CPP_TYPE_TYPEDBYREF:
  91. return EvalStackReduceDataType::Other;
  92. case IL2CPP_TYPE_VALUETYPE:
  93. {
  94. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  95. return klass->enumtype ? GetEvalStackReduceDataType(&klass->element_class->byval_arg) : EvalStackReduceDataType::Other;
  96. }
  97. case IL2CPP_TYPE_GENERICINST:
  98. {
  99. Il2CppGenericClass* genericClass = type->data.generic_class;
  100. if (genericClass->type->type == IL2CPP_TYPE_CLASS)
  101. {
  102. return NATIVE_INT_REDUCE_TYPE;
  103. }
  104. else
  105. {
  106. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  107. return klass->enumtype ? GetEvalStackReduceDataType(&klass->element_class->byval_arg) : EvalStackReduceDataType::Other;
  108. }
  109. }
  110. default:
  111. {
  112. RaiseExecutionEngineException("GetEvalStackReduceDataType invalid type");
  113. return EvalStackReduceDataType::Other;
  114. }
  115. }
  116. }
  117. int32_t GetSizeByReduceType(EvalStackReduceDataType type)
  118. {
  119. switch (type)
  120. {
  121. case hybridclr::transform::EvalStackReduceDataType::I4:
  122. case hybridclr::transform::EvalStackReduceDataType::R4:
  123. return 4;
  124. case hybridclr::transform::EvalStackReduceDataType::I8:
  125. case hybridclr::transform::EvalStackReduceDataType::R8:
  126. return 8;
  127. default:
  128. {
  129. RaiseExecutionEngineException("GetSizeByReduceType not support type");
  130. return PTR_SIZE;
  131. }
  132. }
  133. }
  134. LocationDescInfo ComputValueTypeDescInfo(int32_t size, bool hasReference)
  135. {
  136. #if HYBRIDCLR_ENABLE_WRITE_BARRIERS
  137. if (hasReference)
  138. {
  139. return { LocationDescType::StructContainsRef, size };
  140. }
  141. #endif
  142. switch (size)
  143. {
  144. case 1: return { LocationDescType::U1, 0 };
  145. case 2: return { LocationDescType::U2, 0 };
  146. case 4: return { LocationDescType::I4, 0 };
  147. case 8: return { LocationDescType::I8, 0 };
  148. default: return { LocationDescType::S, size };
  149. }
  150. }
  151. LocationDescInfo ComputLocationDescInfo(const Il2CppType* type)
  152. {
  153. if (type->byref)
  154. {
  155. return { NATIVE_INT_DESC_TYPE, 0 };
  156. }
  157. switch (type->type)
  158. {
  159. case IL2CPP_TYPE_BOOLEAN:
  160. case IL2CPP_TYPE_U1:
  161. return{ LocationDescType::U1, 0 };
  162. case IL2CPP_TYPE_I1:
  163. return{ LocationDescType::I1, 0 };
  164. case IL2CPP_TYPE_I2:
  165. return{ LocationDescType::I2, 0 };
  166. case IL2CPP_TYPE_CHAR:
  167. case IL2CPP_TYPE_U2:
  168. return{ LocationDescType::U2, 0 };
  169. case IL2CPP_TYPE_I4:
  170. case IL2CPP_TYPE_U4:
  171. case IL2CPP_TYPE_R4:
  172. return{ LocationDescType::I4, 0 };
  173. case IL2CPP_TYPE_I8:
  174. case IL2CPP_TYPE_U8:
  175. case IL2CPP_TYPE_R8:
  176. return{ LocationDescType::I8, 0 };
  177. case IL2CPP_TYPE_I:
  178. case IL2CPP_TYPE_U:
  179. case IL2CPP_TYPE_FNPTR:
  180. case IL2CPP_TYPE_PTR:
  181. case IL2CPP_TYPE_BYREF:
  182. return{ NATIVE_INT_DESC_TYPE, 0 };
  183. case IL2CPP_TYPE_STRING:
  184. case IL2CPP_TYPE_ARRAY:
  185. case IL2CPP_TYPE_SZARRAY:
  186. case IL2CPP_TYPE_OBJECT:
  187. case IL2CPP_TYPE_CLASS:
  188. return{ LocationDescType::Ref, 0 };
  189. case IL2CPP_TYPE_TYPEDBYREF:
  190. return { LocationDescType::S, sizeof(Il2CppTypedRef) };
  191. case IL2CPP_TYPE_VALUETYPE:
  192. {
  193. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  194. IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
  195. if (klass->enumtype)
  196. {
  197. return ComputLocationDescInfo(&klass->castClass->byval_arg);
  198. }
  199. return ComputValueTypeDescInfo(il2cpp::vm::Class::GetValueSize(klass, nullptr), klass->has_references);
  200. }
  201. case IL2CPP_TYPE_GENERICINST:
  202. {
  203. Il2CppGenericClass* genericClass = type->data.generic_class;
  204. if (genericClass->type->type == IL2CPP_TYPE_CLASS)
  205. {
  206. IL2CPP_ASSERT(!IS_CLASS_VALUE_TYPE(il2cpp::vm::Class::FromIl2CppType(type)));
  207. return{ LocationDescType::Ref, 0 };
  208. }
  209. else
  210. {
  211. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  212. IL2CPP_ASSERT(IS_CLASS_VALUE_TYPE(klass));
  213. if (klass->enumtype)
  214. {
  215. return ComputLocationDescInfo(&klass->castClass->byval_arg);
  216. }
  217. return ComputValueTypeDescInfo(il2cpp::vm::Class::GetValueSize(klass, nullptr), klass->has_references);
  218. }
  219. }
  220. default:
  221. {
  222. RaiseExecutionEngineException("not support arg type");
  223. return{ NATIVE_INT_DESC_TYPE, 0 };
  224. }
  225. }
  226. }
  227. IRCommon* CreateLoadExpandDataToStackVarVar(TemporaryMemoryArena& pool, int32_t dstOffset, int32_t srcOffset, const Il2CppType* type, int32_t size)
  228. {
  229. if (type->byref)
  230. {
  231. CreateIR(ir, LdlocVarVar);
  232. ir->dst = dstOffset;
  233. ir->src = srcOffset;
  234. return ir;
  235. }
  236. switch (type->type)
  237. {
  238. case Il2CppTypeEnum::IL2CPP_TYPE_I1:
  239. {
  240. CreateIR(ir, LdlocExpandVarVar_i1);
  241. ir->dst = dstOffset;
  242. ir->src = srcOffset;
  243. return ir;
  244. }
  245. case Il2CppTypeEnum::IL2CPP_TYPE_BOOLEAN:
  246. case Il2CppTypeEnum::IL2CPP_TYPE_U1:
  247. {
  248. CreateIR(ir, LdlocExpandVarVar_u1);
  249. ir->dst = dstOffset;
  250. ir->src = srcOffset;
  251. return ir;
  252. }
  253. case Il2CppTypeEnum::IL2CPP_TYPE_I2:
  254. {
  255. CreateIR(ir, LdlocExpandVarVar_i2);
  256. ir->dst = dstOffset;
  257. ir->src = srcOffset;
  258. return ir;
  259. }
  260. case IL2CPP_TYPE_CHAR:
  261. case IL2CPP_TYPE_U2:
  262. {
  263. CreateIR(ir, LdlocExpandVarVar_u2);
  264. ir->dst = dstOffset;
  265. ir->src = srcOffset;
  266. return ir;
  267. }
  268. case IL2CPP_TYPE_VALUETYPE:
  269. {
  270. Il2CppClass* klass = il2cpp::vm::Class::FromIl2CppType(type);
  271. if (klass->enumtype)
  272. {
  273. return CreateLoadExpandDataToStackVarVar(pool, dstOffset, srcOffset, &klass->element_class->byval_arg, size);
  274. }
  275. break;
  276. }
  277. default: break;
  278. }
  279. if (size <= 8)
  280. {
  281. CreateIR(ir, LdlocVarVar);
  282. ir->dst = dstOffset;
  283. ir->src = srcOffset;
  284. return ir;
  285. }
  286. else
  287. {
  288. IL2CPP_ASSERT(size <= MAX_VALUE_TYPE_SIZE);
  289. CreateIR(ir, LdlocVarVarSize);
  290. ir->dst = dstOffset;
  291. ir->src = srcOffset;
  292. ir->size = size;
  293. return ir;
  294. }
  295. }
  296. IRCommon* CreateAssignVarVar(TemporaryMemoryArena& pool, int32_t dstOffset, int32_t srcOffset, int32_t size)
  297. {
  298. IL2CPP_ASSERT(dstOffset >= 0 && dstOffset < 0x10000);
  299. IL2CPP_ASSERT(srcOffset >= 0 && srcOffset < 0x10000);
  300. if (size <= 8)
  301. {
  302. CreateIR(ir, LdlocVarVar);
  303. ir->dst = dstOffset;
  304. ir->src = srcOffset;
  305. return ir;
  306. }
  307. else
  308. {
  309. IL2CPP_ASSERT(size <= MAX_VALUE_TYPE_SIZE);
  310. CreateIR(ir, LdlocVarVarSize);
  311. ir->dst = dstOffset;
  312. ir->src = srcOffset;
  313. ir->size = size;
  314. return ir;
  315. }
  316. }
  317. interpreter::IRCommon* CreateClassLdfld(TemporaryMemoryArena& pool, int32_t dstIdx, int32_t objIdx, const FieldInfo* fieldInfo)
  318. {
  319. uint16_t offset = (uint16_t)GetFieldOffset(fieldInfo);
  320. const Il2CppType* type = fieldInfo->type;
  321. LocationDescInfo desc = ComputLocationDescInfo(type);
  322. CreateIR(ir, LdfldVarVar_i1);
  323. ir->dst = dstIdx;
  324. ir->obj = objIdx;
  325. ir->offset = offset;
  326. switch (desc.type)
  327. {
  328. case LocationDescType::I1:
  329. {
  330. ir->type = HiOpcodeEnum::LdfldVarVar_i1;
  331. return ir;
  332. }
  333. case LocationDescType::U1:
  334. {
  335. ir->type = HiOpcodeEnum::LdfldVarVar_u1;
  336. return ir;
  337. }
  338. case LocationDescType::I2:
  339. {
  340. ir->type = HiOpcodeEnum::LdfldVarVar_i2;
  341. return ir;
  342. }
  343. case LocationDescType::U2:
  344. {
  345. ir->type = HiOpcodeEnum::LdfldVarVar_u2;
  346. return ir;
  347. }
  348. case LocationDescType::I4:
  349. {
  350. ir->type = HiOpcodeEnum::LdfldVarVar_i4;
  351. return ir;
  352. }
  353. case LocationDescType::I8:
  354. {
  355. ir->type = HiOpcodeEnum::LdfldVarVar_i8;
  356. return ir;
  357. }
  358. case LocationDescType::Ref:
  359. {
  360. ir->type = ARCH_ARGUMENT(HiOpcodeEnum::LdfldVarVar_i4, HiOpcodeEnum::LdfldVarVar_i8);
  361. return ir;
  362. }
  363. case LocationDescType::S:
  364. case LocationDescType::StructContainsRef:
  365. {
  366. switch (desc.size)
  367. {
  368. case 12:
  369. {
  370. ir->type = HiOpcodeEnum::LdfldVarVar_size_12;
  371. return ir;
  372. }
  373. case 16:
  374. {
  375. ir->type = HiOpcodeEnum::LdfldVarVar_size_16;
  376. return ir;
  377. }
  378. case 20:
  379. {
  380. ir->type = HiOpcodeEnum::LdfldVarVar_size_20;
  381. return ir;
  382. }
  383. case 24:
  384. {
  385. ir->type = HiOpcodeEnum::LdfldVarVar_size_24;
  386. return ir;
  387. }
  388. case 28:
  389. {
  390. ir->type = HiOpcodeEnum::LdfldVarVar_size_28;
  391. return ir;
  392. }
  393. case 32:
  394. {
  395. ir->type = HiOpcodeEnum::LdfldVarVar_size_32;
  396. return ir;
  397. }
  398. default:
  399. {
  400. CreateIR(irn, LdfldVarVar_n_4);
  401. irn->dst = dstIdx;
  402. irn->obj = objIdx;
  403. irn->offset = offset;
  404. irn->size = desc.size;
  405. return irn;
  406. }
  407. }
  408. }
  409. default:
  410. {
  411. RaiseExecutionEngineException("field");
  412. return ir;
  413. }
  414. }
  415. }
  416. interpreter::IRCommon* CreateValueTypeLdfld(TemporaryMemoryArena& pool, int32_t dstIdx, int32_t objIdx, const FieldInfo* fieldInfo)
  417. {
  418. uint16_t offset = (uint16_t)GetFieldOffset(fieldInfo);
  419. const Il2CppType* type = fieldInfo->type;
  420. LocationDescInfo desc = ComputLocationDescInfo(type);
  421. CreateIR(ir, LdfldValueTypeVarVar_i1);
  422. ir->dst = dstIdx;
  423. ir->obj = objIdx;
  424. ir->offset = offset;
  425. switch (desc.type)
  426. {
  427. case LocationDescType::I1:
  428. {
  429. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_i1;
  430. return ir;
  431. }
  432. case LocationDescType::U1:
  433. {
  434. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_u1;
  435. return ir;
  436. }
  437. case LocationDescType::I2:
  438. {
  439. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_i2;
  440. return ir;
  441. }
  442. case LocationDescType::U2:
  443. {
  444. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_u2;
  445. return ir;
  446. }
  447. case LocationDescType::I4:
  448. {
  449. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_i4;
  450. return ir;
  451. }
  452. case LocationDescType::I8:
  453. {
  454. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_i8;
  455. return ir;
  456. }
  457. case LocationDescType::Ref:
  458. {
  459. ir->type = ARCH_ARGUMENT(HiOpcodeEnum::LdfldValueTypeVarVar_i4, HiOpcodeEnum::LdfldValueTypeVarVar_i8);
  460. return ir;
  461. }
  462. case LocationDescType::S:
  463. case LocationDescType::StructContainsRef:
  464. {
  465. switch (desc.size)
  466. {
  467. case 12:
  468. {
  469. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_12;
  470. return ir;
  471. }
  472. case 16:
  473. {
  474. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_16;
  475. return ir;
  476. }
  477. case 20:
  478. {
  479. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_20;
  480. return ir;
  481. }
  482. case 24:
  483. {
  484. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_24;
  485. return ir;
  486. }
  487. case 28:
  488. {
  489. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_28;
  490. return ir;
  491. }
  492. case 32:
  493. {
  494. ir->type = HiOpcodeEnum::LdfldValueTypeVarVar_size_32;
  495. return ir;
  496. }
  497. default:
  498. {
  499. CreateIR(irn, LdfldValueTypeVarVar_n_4);
  500. irn->dst = dstIdx;
  501. irn->obj = objIdx;
  502. irn->offset = offset;
  503. irn->size = desc.size;
  504. return irn;
  505. }
  506. }
  507. }
  508. default:
  509. {
  510. RaiseExecutionEngineException("field");
  511. return ir;
  512. }
  513. }
  514. }
  515. interpreter::IRCommon* CreateStfld(TemporaryMemoryArena& pool, int32_t objIdx, const FieldInfo* fieldInfo, int32_t dataIdx)
  516. {
  517. uint16_t offset = (uint16_t)GetFieldOffset(fieldInfo);
  518. const Il2CppType* type = fieldInfo->type;
  519. LocationDescInfo desc = ComputLocationDescInfo(type);
  520. CreateIR(ir, StfldVarVar_i1);
  521. ir->data = dataIdx;
  522. ir->obj = objIdx;
  523. ir->offset = offset;
  524. switch (desc.type)
  525. {
  526. case LocationDescType::I1:
  527. {
  528. ir->type = HiOpcodeEnum::StfldVarVar_i1;
  529. return ir;
  530. }
  531. case LocationDescType::U1:
  532. {
  533. ir->type = HiOpcodeEnum::StfldVarVar_u1;
  534. return ir;
  535. }
  536. case LocationDescType::I2:
  537. {
  538. ir->type = HiOpcodeEnum::StfldVarVar_i2;
  539. return ir;
  540. }
  541. case LocationDescType::U2:
  542. {
  543. ir->type = HiOpcodeEnum::StfldVarVar_u2;
  544. return ir;
  545. }
  546. case LocationDescType::I4:
  547. {
  548. ir->type = HiOpcodeEnum::StfldVarVar_i4;
  549. return ir;
  550. }
  551. case LocationDescType::I8:
  552. {
  553. ir->type = HiOpcodeEnum::StfldVarVar_i8;
  554. return ir;
  555. }
  556. case LocationDescType::Ref:
  557. {
  558. ir->type = HiOpcodeEnum::StfldVarVar_ref;
  559. return ir;
  560. }
  561. case LocationDescType::S:
  562. {
  563. switch (desc.size)
  564. {
  565. case 12:
  566. {
  567. ir->type = HiOpcodeEnum::StfldVarVar_size_12;
  568. return ir;
  569. }
  570. case 16:
  571. {
  572. ir->type = HiOpcodeEnum::StfldVarVar_size_16;
  573. return ir;
  574. }
  575. case 20:
  576. {
  577. ir->type = HiOpcodeEnum::StfldVarVar_size_20;
  578. return ir;
  579. }
  580. case 24:
  581. {
  582. ir->type = HiOpcodeEnum::StfldVarVar_size_24;
  583. return ir;
  584. }
  585. case 28:
  586. {
  587. ir->type = HiOpcodeEnum::StfldVarVar_size_28;
  588. return ir;
  589. }
  590. case 32:
  591. {
  592. ir->type = HiOpcodeEnum::StfldVarVar_size_32;
  593. return ir;
  594. }
  595. default:
  596. {
  597. CreateIR(irn, StfldVarVar_n_4);
  598. irn->data = dataIdx;
  599. irn->obj = objIdx;
  600. irn->offset = offset;
  601. irn->size = desc.size;
  602. return irn;
  603. }
  604. }
  605. }
  606. case LocationDescType::StructContainsRef:
  607. {
  608. CreateIR(irn, StfldVarVar_WriteBarrier_n_4);
  609. irn->data = dataIdx;
  610. irn->obj = objIdx;
  611. irn->offset = offset;
  612. irn->size = desc.size;
  613. return irn;
  614. }
  615. default:
  616. {
  617. RaiseExecutionEngineException("field");
  618. return ir;
  619. }
  620. }
  621. }
  622. interpreter::IRCommon* CreateLdsfld(TemporaryMemoryArena& pool, int32_t dstIdx, const FieldInfo* fieldInfo, uint32_t parent)
  623. {
  624. IL2CPP_ASSERT(fieldInfo->offset < (1 << 16));
  625. uint16_t offset = (uint16_t)fieldInfo->offset;
  626. const Il2CppType* type = fieldInfo->type;
  627. LocationDescInfo desc = ComputLocationDescInfo(type);
  628. CreateIR(ir, LdsfldVarVar_i1);
  629. ir->dst = dstIdx;
  630. ir->klass = parent;
  631. ir->offset = offset;
  632. switch (desc.type)
  633. {
  634. case LocationDescType::I1:
  635. {
  636. ir->type = HiOpcodeEnum::LdsfldVarVar_i1;
  637. return ir;
  638. }
  639. case LocationDescType::U1:
  640. {
  641. ir->type = HiOpcodeEnum::LdsfldVarVar_u1;
  642. return ir;
  643. }
  644. case LocationDescType::I2:
  645. {
  646. ir->type = HiOpcodeEnum::LdsfldVarVar_i2;
  647. return ir;
  648. }
  649. case LocationDescType::U2:
  650. {
  651. ir->type = HiOpcodeEnum::LdsfldVarVar_u2;
  652. return ir;
  653. }
  654. case LocationDescType::I4:
  655. {
  656. ir->type = HiOpcodeEnum::LdsfldVarVar_i4;
  657. return ir;
  658. }
  659. case LocationDescType::I8:
  660. {
  661. ir->type = HiOpcodeEnum::LdsfldVarVar_i8;
  662. return ir;
  663. }
  664. case LocationDescType::Ref:
  665. {
  666. ir->type = ARCH_ARGUMENT(HiOpcodeEnum::LdsfldVarVar_i4, HiOpcodeEnum::LdsfldVarVar_i8);
  667. return ir;
  668. }
  669. case LocationDescType::S:
  670. case LocationDescType::StructContainsRef:
  671. {
  672. switch (desc.size)
  673. {
  674. case 12:
  675. {
  676. ir->type = HiOpcodeEnum::LdsfldVarVar_size_12;
  677. return ir;
  678. }
  679. case 16:
  680. {
  681. ir->type = HiOpcodeEnum::LdsfldVarVar_size_16;
  682. return ir;
  683. }
  684. case 20:
  685. {
  686. ir->type = HiOpcodeEnum::LdsfldVarVar_size_20;
  687. return ir;
  688. }
  689. case 24:
  690. {
  691. ir->type = HiOpcodeEnum::LdsfldVarVar_size_24;
  692. return ir;
  693. }
  694. case 28:
  695. {
  696. ir->type = HiOpcodeEnum::LdsfldVarVar_size_28;
  697. return ir;
  698. }
  699. case 32:
  700. {
  701. ir->type = HiOpcodeEnum::LdsfldVarVar_size_32;
  702. return ir;
  703. }
  704. default:
  705. {
  706. CreateIR(irn, LdsfldVarVar_n_4);
  707. irn->dst = dstIdx;
  708. irn->klass = parent;
  709. irn->offset = offset;
  710. irn->size = desc.size;
  711. return irn;
  712. }
  713. }
  714. }
  715. default:
  716. {
  717. RaiseExecutionEngineException("field");
  718. return ir;
  719. }
  720. }
  721. }
  722. interpreter::IRCommon* CreateStsfld(TemporaryMemoryArena& pool, const FieldInfo* fieldInfo, uint32_t parent, int32_t dataIdx)
  723. {
  724. IL2CPP_ASSERT(fieldInfo->offset < (1 << 16));
  725. uint16_t offset = (uint16_t)fieldInfo->offset;
  726. const Il2CppType* type = fieldInfo->type;
  727. LocationDescInfo desc = ComputLocationDescInfo(type);
  728. CreateIR(ir, StsfldVarVar_i1);
  729. ir->klass = parent;
  730. ir->offset = offset;
  731. ir->data = dataIdx;
  732. switch (desc.type)
  733. {
  734. case LocationDescType::I1:
  735. {
  736. ir->type = HiOpcodeEnum::StsfldVarVar_i1;
  737. return ir;
  738. }
  739. case LocationDescType::U1:
  740. {
  741. ir->type = HiOpcodeEnum::StsfldVarVar_u1;
  742. return ir;
  743. }
  744. case LocationDescType::I2:
  745. {
  746. ir->type = HiOpcodeEnum::StsfldVarVar_i2;
  747. return ir;
  748. }
  749. case LocationDescType::U2:
  750. {
  751. ir->type = HiOpcodeEnum::StsfldVarVar_u2;
  752. return ir;
  753. }
  754. case LocationDescType::I4:
  755. {
  756. ir->type = HiOpcodeEnum::StsfldVarVar_i4;
  757. return ir;
  758. }
  759. case LocationDescType::I8:
  760. {
  761. ir->type = HiOpcodeEnum::StsfldVarVar_i8;
  762. return ir;
  763. }
  764. case LocationDescType::Ref:
  765. {
  766. ir->type = HiOpcodeEnum::StsfldVarVar_ref;
  767. return ir;
  768. }
  769. case LocationDescType::S:
  770. {
  771. switch (desc.size)
  772. {
  773. case 12:
  774. {
  775. ir->type = HiOpcodeEnum::StsfldVarVar_size_12;
  776. return ir;
  777. }
  778. case 16:
  779. {
  780. ir->type = HiOpcodeEnum::StsfldVarVar_size_16;
  781. return ir;
  782. }
  783. case 20:
  784. {
  785. ir->type = HiOpcodeEnum::StsfldVarVar_size_20;
  786. return ir;
  787. }
  788. case 24:
  789. {
  790. ir->type = HiOpcodeEnum::StsfldVarVar_size_24;
  791. return ir;
  792. }
  793. case 28:
  794. {
  795. ir->type = HiOpcodeEnum::StsfldVarVar_size_28;
  796. return ir;
  797. }
  798. case 32:
  799. {
  800. ir->type = HiOpcodeEnum::StsfldVarVar_size_32;
  801. return ir;
  802. }
  803. default:
  804. {
  805. CreateIR(irn, StsfldVarVar_n_4);
  806. irn->klass = parent;
  807. irn->offset = offset;
  808. irn->data = dataIdx;
  809. irn->size = desc.size;
  810. return irn;
  811. }
  812. }
  813. }
  814. case LocationDescType::StructContainsRef:
  815. {
  816. CreateIR(irn, StsfldVarVar_WriteBarrier_n_4);
  817. irn->klass = parent;
  818. irn->offset = offset;
  819. irn->data = dataIdx;
  820. irn->size = desc.size;
  821. return irn;
  822. }
  823. default:
  824. {
  825. RaiseExecutionEngineException("field");
  826. return ir;
  827. }
  828. }
  829. }
  830. interpreter::IRCommon* CreateLdthreadlocal(TemporaryMemoryArena& pool, int32_t dstIdx, const FieldInfo* fieldInfo, uint32_t parent)
  831. {
  832. IL2CPP_ASSERT(fieldInfo->offset == THREAD_STATIC_FIELD_OFFSET);
  833. int32_t offset = GetThreadStaticFieldOffset(fieldInfo);
  834. const Il2CppType* type = fieldInfo->type;
  835. LocationDescInfo desc = ComputLocationDescInfo(type);
  836. CreateIR(ir, LdthreadlocalVarVar_i1);
  837. ir->dst = dstIdx;
  838. ir->klass = parent;
  839. ir->offset = offset;
  840. switch (desc.type)
  841. {
  842. case LocationDescType::I1:
  843. {
  844. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_i1;
  845. return ir;
  846. }
  847. case LocationDescType::U1:
  848. {
  849. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_u1;
  850. return ir;
  851. }
  852. case LocationDescType::I2:
  853. {
  854. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_i2;
  855. return ir;
  856. }
  857. case LocationDescType::U2:
  858. {
  859. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_u2;
  860. return ir;
  861. }
  862. case LocationDescType::I4:
  863. {
  864. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_i4;
  865. return ir;
  866. }
  867. case LocationDescType::I8:
  868. {
  869. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_i8;
  870. return ir;
  871. }
  872. case LocationDescType::Ref:
  873. {
  874. ir->type = ARCH_ARGUMENT(HiOpcodeEnum::LdthreadlocalVarVar_i4, HiOpcodeEnum::LdthreadlocalVarVar_i8);
  875. return ir;
  876. }
  877. case LocationDescType::S:
  878. case LocationDescType::StructContainsRef:
  879. {
  880. switch (desc.size)
  881. {
  882. case 12:
  883. {
  884. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_12;
  885. return ir;
  886. }
  887. case 16:
  888. {
  889. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_16;
  890. return ir;
  891. }
  892. case 20:
  893. {
  894. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_20;
  895. return ir;
  896. }
  897. case 24:
  898. {
  899. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_24;
  900. return ir;
  901. }
  902. case 28:
  903. {
  904. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_28;
  905. return ir;
  906. }
  907. case 32:
  908. {
  909. ir->type = HiOpcodeEnum::LdthreadlocalVarVar_size_32;
  910. return ir;
  911. }
  912. default:
  913. {
  914. CreateIR(irn, LdthreadlocalVarVar_n_4);
  915. irn->dst = dstIdx;
  916. irn->klass = parent;
  917. irn->offset = offset;
  918. irn->size = desc.size;
  919. return irn;
  920. }
  921. }
  922. }
  923. default:
  924. {
  925. RaiseExecutionEngineException("field");
  926. return ir;
  927. }
  928. }
  929. }
  930. interpreter::IRCommon* CreateStthreadlocal(TemporaryMemoryArena& pool, const FieldInfo* fieldInfo, uint32_t parent, int32_t dataIdx)
  931. {
  932. IL2CPP_ASSERT(fieldInfo->offset == THREAD_STATIC_FIELD_OFFSET);
  933. int32_t offset = GetThreadStaticFieldOffset(fieldInfo);
  934. const Il2CppType* type = fieldInfo->type;
  935. LocationDescInfo desc = ComputLocationDescInfo(type);
  936. CreateIR(ir, StthreadlocalVarVar_i1);
  937. ir->klass = parent;
  938. ir->offset = offset;
  939. ir->data = dataIdx;
  940. switch (desc.type)
  941. {
  942. case LocationDescType::I1:
  943. {
  944. ir->type = HiOpcodeEnum::StthreadlocalVarVar_i1;
  945. return ir;
  946. }
  947. case LocationDescType::U1:
  948. {
  949. ir->type = HiOpcodeEnum::StthreadlocalVarVar_u1;
  950. return ir;
  951. }
  952. case LocationDescType::I2:
  953. {
  954. ir->type = HiOpcodeEnum::StthreadlocalVarVar_i2;
  955. return ir;
  956. }
  957. case LocationDescType::U2:
  958. {
  959. ir->type = HiOpcodeEnum::StthreadlocalVarVar_u2;
  960. return ir;
  961. }
  962. case LocationDescType::I4:
  963. {
  964. ir->type = HiOpcodeEnum::StthreadlocalVarVar_i4;
  965. return ir;
  966. }
  967. case LocationDescType::I8:
  968. {
  969. ir->type = HiOpcodeEnum::StthreadlocalVarVar_i8;
  970. return ir;
  971. }
  972. case LocationDescType::Ref:
  973. {
  974. ir->type = HiOpcodeEnum::StthreadlocalVarVar_ref;
  975. return ir;
  976. }
  977. case LocationDescType::S:
  978. {
  979. switch (desc.size)
  980. {
  981. case 12:
  982. {
  983. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_12;
  984. return ir;
  985. }
  986. case 16:
  987. {
  988. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_16;
  989. return ir;
  990. }
  991. case 20:
  992. {
  993. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_20;
  994. return ir;
  995. }
  996. case 24:
  997. {
  998. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_24;
  999. return ir;
  1000. }
  1001. case 28:
  1002. {
  1003. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_28;
  1004. return ir;
  1005. }
  1006. case 32:
  1007. {
  1008. ir->type = HiOpcodeEnum::StthreadlocalVarVar_size_32;
  1009. return ir;
  1010. }
  1011. default:
  1012. {
  1013. CreateIR(irn, StthreadlocalVarVar_n_4);
  1014. irn->klass = parent;
  1015. irn->offset = offset;
  1016. irn->data = dataIdx;
  1017. irn->size = desc.size;
  1018. return irn;
  1019. }
  1020. }
  1021. }
  1022. case LocationDescType::StructContainsRef:
  1023. {
  1024. CreateIR(irn, StthreadlocalVarVar_WriteBarrier_n_4);
  1025. irn->klass = parent;
  1026. irn->offset = offset;
  1027. irn->data = dataIdx;
  1028. irn->size = desc.size;
  1029. return irn;
  1030. }
  1031. default:
  1032. {
  1033. RaiseExecutionEngineException("field");
  1034. return ir;
  1035. }
  1036. }
  1037. }
  1038. // TransformContext implements
  1039. HiOpcodeEnum TransformContext::CalcGetMdArrElementVarVarOpcode(const Il2CppType* type)
  1040. {
  1041. LocationDescInfo desc = ComputLocationDescInfo(type);
  1042. switch (desc.type)
  1043. {
  1044. case LocationDescType::I1: return HiOpcodeEnum::GetMdArrElementVarVar_i1;
  1045. case LocationDescType::U1: return HiOpcodeEnum::GetMdArrElementVarVar_u1;
  1046. case LocationDescType::I2: return HiOpcodeEnum::GetMdArrElementVarVar_i2;
  1047. case LocationDescType::U2: return HiOpcodeEnum::GetMdArrElementVarVar_u2;
  1048. case LocationDescType::I4: return HiOpcodeEnum::GetMdArrElementVarVar_i4;
  1049. case LocationDescType::I8: return HiOpcodeEnum::GetMdArrElementVarVar_i8;
  1050. case LocationDescType::Ref: return ARCH_ARGUMENT(HiOpcodeEnum::GetMdArrElementVarVar_i4, HiOpcodeEnum::GetMdArrElementVarVar_i8);
  1051. case LocationDescType::S:
  1052. case LocationDescType::StructContainsRef: return HiOpcodeEnum::GetMdArrElementVarVar_n;
  1053. default:
  1054. {
  1055. RaiseExecutionEngineException("CalcGetMdArrElementVarVarOpcode");
  1056. return (HiOpcodeEnum)0;
  1057. }
  1058. }
  1059. }
  1060. TransformContext::TransformContext(hybridclr::metadata::Image* image, const MethodInfo* methodInfo, metadata::MethodBody& body, TemporaryMemoryArena& pool, il2cpp::utils::dynamic_array<uint64_t>& resolveDatas)
  1061. : image(image), methodInfo(methodInfo), body(body), pool(pool), resolveDatas(resolveDatas)
  1062. {
  1063. }
  1064. uint32_t TransformContext::GetOrAddResolveDataIndex(const void* ptr)
  1065. {
  1066. auto it = ptr2DataIdxs.find(ptr);
  1067. if (it != ptr2DataIdxs.end())
  1068. {
  1069. return it->second;
  1070. }
  1071. else
  1072. {
  1073. uint32_t newIndex = (uint32_t)resolveDatas.size();
  1074. resolveDatas.push_back((uint64_t)ptr);
  1075. ptr2DataIdxs.insert({ ptr, newIndex });
  1076. return newIndex;
  1077. }
  1078. }
  1079. void TransformContext::PushStackByType(const Il2CppType* type)
  1080. {
  1081. int32_t byteSize = GetTypeValueSize(type);
  1082. int32_t stackSize = GetStackSizeByByteSize(byteSize);
  1083. evalStack[evalStackTop].reduceType = GetEvalStackReduceDataType(type);
  1084. evalStack[evalStackTop].byteSize = byteSize;
  1085. evalStack[evalStackTop].locOffset = GetEvalStackNewTopOffset();
  1086. evalStackTop++;
  1087. curStackSize += stackSize;
  1088. maxStackSize = std::max(curStackSize, maxStackSize);
  1089. IL2CPP_ASSERT(maxStackSize < MAX_STACK_SIZE);
  1090. }
  1091. void TransformContext::PushStackByReduceType(EvalStackReduceDataType t)
  1092. {
  1093. int32_t byteSize = GetSizeByReduceType(t);
  1094. int32_t stackSize = GetStackSizeByByteSize(byteSize);
  1095. evalStack[evalStackTop].reduceType = t;
  1096. evalStack[evalStackTop].byteSize = byteSize;
  1097. evalStack[evalStackTop].locOffset = GetEvalStackNewTopOffset();
  1098. evalStackTop++; curStackSize += stackSize;
  1099. maxStackSize = std::max(curStackSize, maxStackSize);
  1100. IL2CPP_ASSERT(maxStackSize < MAX_STACK_SIZE);
  1101. }
  1102. void TransformContext::DuplicateStack()
  1103. {
  1104. IL2CPP_ASSERT(evalStackTop > 0);
  1105. EvalStackVarInfo& oldTop = evalStack[evalStackTop - 1];
  1106. int32_t stackSize = GetStackSizeByByteSize(oldTop.byteSize);
  1107. EvalStackVarInfo& newTop = evalStack[evalStackTop++];
  1108. newTop.reduceType = oldTop.reduceType;
  1109. newTop.byteSize = oldTop.byteSize;
  1110. newTop.locOffset = curStackSize;
  1111. curStackSize += stackSize;
  1112. maxStackSize = std::max(curStackSize, maxStackSize);
  1113. IL2CPP_ASSERT(maxStackSize < MAX_STACK_SIZE);
  1114. }
  1115. void TransformContext::PopStack()
  1116. {
  1117. IL2CPP_ASSERT(evalStackTop > 0);
  1118. --evalStackTop;
  1119. curStackSize = evalStack[evalStackTop].locOffset;
  1120. }
  1121. void TransformContext::PopStackN(int32_t n)
  1122. {
  1123. IL2CPP_ASSERT(evalStackTop >= n && n >= 0);
  1124. if (n > 0)
  1125. {
  1126. evalStackTop -= n;
  1127. curStackSize = evalStack[evalStackTop].locOffset;
  1128. }
  1129. }
  1130. void TransformContext::PopAllStack()
  1131. {
  1132. if (evalStackTop > 0)
  1133. {
  1134. evalStackTop = 0;
  1135. curStackSize = evalStackBaseOffset;
  1136. }
  1137. else
  1138. {
  1139. IL2CPP_ASSERT(curStackSize == evalStackBaseOffset);
  1140. }
  1141. }
  1142. void TransformContext::InsertMemoryBarrier()
  1143. {
  1144. if (prefixFlags & (int32_t)PrefixFlags::Volatile)
  1145. {
  1146. CreateAddIR(_mb, MemoryBarrier);
  1147. }
  1148. }
  1149. void TransformContext::ResetPrefixFlags()
  1150. {
  1151. prefixFlags = 0;
  1152. }
  1153. void TransformContext::Add_ldind(HiOpcodeEnum opCode, EvalStackReduceDataType dataType)
  1154. {
  1155. CreateAddIR(ir, LdindVarVar_i1);
  1156. ir->type = opCode;
  1157. ir->dst = ir->src = GetEvalStackTopOffset();
  1158. PopStack();
  1159. PushStackByReduceType(dataType);
  1160. InsertMemoryBarrier();
  1161. ResetPrefixFlags();
  1162. ip++;
  1163. }
  1164. void TransformContext::Add_stind(HiOpcodeEnum opCode)
  1165. {
  1166. IL2CPP_ASSERT(evalStackTop >= 2);
  1167. InsertMemoryBarrier();
  1168. ResetPrefixFlags();
  1169. CreateAddIR(ir, StindVarVar_i1);
  1170. ir->type = opCode;
  1171. ir->dst = evalStack[evalStackTop - 2].locOffset;
  1172. ir->src = evalStack[evalStackTop - 1].locOffset;
  1173. PopStackN(2);
  1174. ip++;
  1175. }
  1176. void TransformContext::PushOffset(int32_t* offsetPtr)
  1177. {
  1178. IL2CPP_ASSERT(splitOffsets.find(*(offsetPtr)) != splitOffsets.end());
  1179. relocationOffsets.push_back(offsetPtr);
  1180. }
  1181. void TransformContext::PushBranch(int32_t targetOffset)
  1182. {
  1183. IL2CPP_ASSERT(splitOffsets.find(targetOffset) != splitOffsets.end());
  1184. IRBasicBlock* targetBb = ip2bb[targetOffset];
  1185. if (!targetBb->inPending)
  1186. {
  1187. targetBb->inPending = true;
  1188. FlowInfo* fi = pool.NewAny<FlowInfo>();
  1189. fi->offset = targetOffset;
  1190. fi->curStackSize = curStackSize;
  1191. if (evalStackTop > 0)
  1192. {
  1193. fi->evalStack.insert(fi->evalStack.end(), evalStack, evalStack + evalStackTop);
  1194. }
  1195. else
  1196. {
  1197. IL2CPP_ASSERT(curStackSize == evalStackBaseOffset);
  1198. }
  1199. pendingFlows.push_back(fi);
  1200. }
  1201. }
  1202. bool TransformContext::FindNextFlow()
  1203. {
  1204. for (; nextFlowIdx < (int32_t)pendingFlows.size(); )
  1205. {
  1206. FlowInfo* fi = pendingFlows[nextFlowIdx++];
  1207. IRBasicBlock* nextBb = ip2bb[fi->offset];
  1208. if (!nextBb->visited)
  1209. {
  1210. ip = ipBase + fi->offset;
  1211. if (!fi->evalStack.empty()) {
  1212. std::memcpy(evalStack, &fi->evalStack[0], sizeof(EvalStackVarInfo) * fi->evalStack.size());
  1213. }
  1214. curStackSize = fi->curStackSize;
  1215. IL2CPP_ASSERT(curStackSize >= evalStackBaseOffset);
  1216. evalStackTop = (int32_t)fi->evalStack.size();
  1217. return true;
  1218. }
  1219. }
  1220. return false;
  1221. }
  1222. void TransformContext::AddInst(IRCommon* ir)
  1223. {
  1224. IL2CPP_ASSERT(ir->type != HiOpcodeEnum::None);
  1225. curbb->insts.push_back(ir);
  1226. if (ir2offsetMap)
  1227. {
  1228. ir2offsetMap->insert({ ir, ipOffset });
  1229. }
  1230. }
  1231. void TransformContext::AddInst_ldarg(int32_t argIdx)
  1232. {
  1233. ArgVarInfo& __arg = args[argIdx];
  1234. IRCommon* ir = CreateLoadExpandDataToStackVarVar(pool, GetEvalStackNewTopOffset(), __arg.argLocOffset, __arg.type, GetTypeValueSize(__arg.type));
  1235. AddInst(ir);
  1236. PushStackByType(__arg.type);
  1237. }
  1238. bool TransformContext::IsCreateNotNullObjectInstrument(IRCommon* ir)
  1239. {
  1240. switch (ir->type)
  1241. {
  1242. case HiOpcodeEnum::BoxVarVar:
  1243. {
  1244. IRBoxVarVar* irBox = (IRBoxVarVar*)ir;
  1245. Il2CppClass* klass = ((Il2CppClass*)resolveDatas[irBox->klass]);
  1246. return IS_CLASS_VALUE_TYPE(klass) && !il2cpp::vm::Class::IsNullable(klass);
  1247. }
  1248. case HiOpcodeEnum::NewSystemObjectVar:
  1249. case HiOpcodeEnum::NewString:
  1250. case HiOpcodeEnum::NewString_2:
  1251. case HiOpcodeEnum::NewString_3:
  1252. case HiOpcodeEnum::CtorDelegate:
  1253. case HiOpcodeEnum::NewDelegate:
  1254. //case HiOpcodeEnum::NewClassInterpVar_Ctor_0:
  1255. //case HiOpcodeEnum::NewClassInterpVar:
  1256. //case HiOpcodeEnum::NewClassVar:
  1257. //case HiOpcodeEnum::NewClassVar_Ctor_0:
  1258. //case HiOpcodeEnum::NewClassVar_NotCtor:
  1259. case HiOpcodeEnum::NewMdArrVarVar_length:
  1260. case HiOpcodeEnum::NewMdArrVarVar_length_bound:
  1261. case HiOpcodeEnum::NewArrVarVar:
  1262. case HiOpcodeEnum::LdsfldaFromFieldDataVarVar:
  1263. case HiOpcodeEnum::LdsfldaVarVar:
  1264. case HiOpcodeEnum::LdthreadlocalaVarVar:
  1265. case HiOpcodeEnum::LdlocVarAddress:
  1266. return true;
  1267. default:
  1268. return false;
  1269. }
  1270. }
  1271. void TransformContext::RemoveLastInstrument()
  1272. {
  1273. IL2CPP_ASSERT(!curbb->insts.empty());
  1274. curbb->insts.pop_back();
  1275. }
  1276. void TransformContext::AddInst_ldarga(int32_t argIdx)
  1277. {
  1278. IL2CPP_ASSERT(argIdx < actualParamCount);
  1279. ArgVarInfo& argInfo = args[argIdx];
  1280. CreateAddIR(ir, LdlocVarAddress);
  1281. ir->dst = GetEvalStackNewTopOffset();
  1282. ir->src = argInfo.argLocOffset;
  1283. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  1284. }
  1285. void TransformContext::AddInst_starg(int32_t argIdx)
  1286. {
  1287. IL2CPP_ASSERT(argIdx < actualParamCount);
  1288. ArgVarInfo& __arg = args[argIdx];
  1289. IRCommon* ir = CreateAssignVarVar(pool, __arg.argLocOffset, GetEvalStackTopOffset(), GetTypeValueSize(__arg.type));
  1290. AddInst(ir);
  1291. PopStack();
  1292. }
  1293. void TransformContext::CreateAddInst_ldloc(int32_t locIdx)
  1294. {
  1295. LocVarInfo& __loc = locals[locIdx];
  1296. IRCommon* ir = CreateLoadExpandDataToStackVarVar(pool, GetEvalStackNewTopOffset(), __loc.locOffset, __loc.type, GetTypeValueSize(__loc.type));
  1297. AddInst(ir);
  1298. PushStackByType(__loc.type);
  1299. }
  1300. void TransformContext::CreateAddInst_stloc(int32_t locIdx)
  1301. {
  1302. LocVarInfo& __loc = locals[locIdx];
  1303. IRCommon* ir = CreateAssignVarVar(pool, __loc.locOffset, GetEvalStackTopOffset(), GetTypeValueSize(__loc.type));
  1304. AddInst(ir);
  1305. PopStack();
  1306. }
  1307. void TransformContext::CreateAddInst_ldloca(int32_t locIdx)
  1308. {
  1309. CreateAddIR(ir, LdlocVarAddress);
  1310. LocVarInfo& __loc = locals[locIdx];
  1311. ir->dst = GetEvalStackNewTopOffset();
  1312. ir->src = __loc.locOffset;
  1313. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  1314. }
  1315. void TransformContext::CreateAddInst_ldc4(int32_t c, EvalStackReduceDataType rtype)
  1316. {
  1317. CreateAddIR(ir, LdcVarConst_4);
  1318. ir->dst = GetEvalStackNewTopOffset();
  1319. ir->src = c;
  1320. PushStackByReduceType(rtype);
  1321. }
  1322. void TransformContext::CreateAddInst_ldc8(int64_t c, EvalStackReduceDataType rtype)
  1323. {
  1324. CreateAddIR(ir, LdcVarConst_8);
  1325. ir->dst = GetEvalStackNewTopOffset();
  1326. ir->src = c;
  1327. PushStackByReduceType(rtype);
  1328. }
  1329. void TransformContext::Add_brtruefalse(bool c, int32_t targetOffset)
  1330. {
  1331. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  1332. IRCommon* lastIR = GetLastInstrument();
  1333. if (lastIR == nullptr || !IsCreateNotNullObjectInstrument(lastIR))
  1334. {
  1335. if (top.byteSize <= 4)
  1336. {
  1337. CreateAddIR(ir, BranchTrueVar_i4);
  1338. ir->type = c ? HiOpcodeEnum::BranchTrueVar_i4 : HiOpcodeEnum::BranchFalseVar_i4;
  1339. ir->op = top.locOffset;
  1340. ir->offset = targetOffset;
  1341. PushOffset(&ir->offset);
  1342. }
  1343. else
  1344. {
  1345. CreateAddIR(ir, BranchTrueVar_i8);
  1346. ir->type = c ? HiOpcodeEnum::BranchTrueVar_i8 : HiOpcodeEnum::BranchFalseVar_i8;
  1347. ir->op = top.locOffset;
  1348. ir->offset = targetOffset;
  1349. PushOffset(&ir->offset);
  1350. }
  1351. }
  1352. else
  1353. {
  1354. // optimize instrument sequence like` box T!; brtrue`
  1355. // this optimization is not semanticly equals to origin instrument because may ommit `Class::InitRuntime`.
  1356. // but it's ok in most occasions.
  1357. RemoveLastInstrument();
  1358. if (c)
  1359. {
  1360. // brtrue always true, replace with br
  1361. CreateAddIR(ir, BranchUncondition_4);
  1362. ir->offset = targetOffset;
  1363. PushOffset(&ir->offset);
  1364. }
  1365. else
  1366. {
  1367. // brfalse always false, run throughtly.
  1368. }
  1369. }
  1370. PopStack();
  1371. PushBranch(targetOffset);
  1372. }
  1373. void TransformContext::Add_bc(int32_t ipOffset, int32_t brOffset, int32_t opSize, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8)
  1374. {
  1375. int32_t targetOffset = ipOffset + brOffset + opSize;
  1376. EvalStackVarInfo& op1 = evalStack[evalStackTop - 2];
  1377. EvalStackVarInfo& op2 = evalStack[evalStackTop - 1];
  1378. IRBranchVarVar_Ceq_i4* ir = pool.AllocIR<IRBranchVarVar_Ceq_i4>();
  1379. ir->type = (HiOpcodeEnum)0;
  1380. ir->op1 = op1.locOffset;
  1381. ir->op2 = op2.locOffset;
  1382. ir->offset = targetOffset;
  1383. PushOffset(&ir->offset);
  1384. switch (op1.reduceType)
  1385. {
  1386. case EvalStackReduceDataType::I4:
  1387. {
  1388. switch (op2.reduceType)
  1389. {
  1390. case EvalStackReduceDataType::I4:
  1391. {
  1392. ir->type = opI4;
  1393. break;
  1394. }
  1395. case EvalStackReduceDataType::I8:
  1396. {
  1397. CreateAddIR(irConv, ConvertVarVar_i4_i8);
  1398. irConv->dst = irConv->src = op1.locOffset;
  1399. ir->type = opI8;
  1400. break;
  1401. }
  1402. default:
  1403. {
  1404. IL2CPP_ASSERT(false && "I4 not match");
  1405. break;
  1406. }
  1407. }
  1408. break;
  1409. }
  1410. case EvalStackReduceDataType::I8:
  1411. {
  1412. IL2CPP_ASSERT(op2.reduceType == EvalStackReduceDataType::I8);
  1413. ir->type = opI8;
  1414. break;
  1415. }
  1416. case EvalStackReduceDataType::R4:
  1417. {
  1418. switch (op2.reduceType)
  1419. {
  1420. case EvalStackReduceDataType::R4:
  1421. {
  1422. ir->type = opR4;
  1423. break;
  1424. }
  1425. default:
  1426. {
  1427. IL2CPP_ASSERT(false && "R4 not match");
  1428. break;
  1429. }
  1430. }
  1431. break;
  1432. }
  1433. case EvalStackReduceDataType::R8:
  1434. {
  1435. switch (op2.reduceType)
  1436. {
  1437. case EvalStackReduceDataType::R8:
  1438. {
  1439. ir->type = opR8;
  1440. break;
  1441. }
  1442. default:
  1443. {
  1444. IL2CPP_ASSERT(false && "R8 not match");
  1445. break;
  1446. }
  1447. }
  1448. break;
  1449. }
  1450. default:
  1451. {
  1452. IL2CPP_ASSERT(false && "nothing match");
  1453. }
  1454. }
  1455. AddInst(ir);
  1456. PopStackN(2);
  1457. PushBranch(targetOffset);
  1458. }
  1459. void TransformContext::Add_conv(int32_t dstTypeSize, EvalStackReduceDataType dstReduceType, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8)
  1460. {
  1461. IL2CPP_ASSERT(evalStackTop > 0);
  1462. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  1463. //if (top.reduceType != dstReduceType)
  1464. {
  1465. CreateIR(ir, ConvertVarVar_i4_u4);
  1466. ir->type = (HiOpcodeEnum)0;
  1467. ir->dst = ir->src = GetEvalStackTopOffset();
  1468. switch (top.reduceType)
  1469. {
  1470. case EvalStackReduceDataType::I4:
  1471. {
  1472. ir->type = opI4;
  1473. AddInst(ir);
  1474. break;
  1475. }
  1476. case EvalStackReduceDataType::I8:
  1477. {
  1478. ir->type = opI8;
  1479. AddInst(ir);
  1480. break;
  1481. }
  1482. case EvalStackReduceDataType::R4:
  1483. {
  1484. ir->type = opR4;
  1485. AddInst(ir);
  1486. break;
  1487. }
  1488. case EvalStackReduceDataType::R8:
  1489. {
  1490. ir->type = opR8;
  1491. AddInst(ir);
  1492. break;
  1493. }
  1494. default:
  1495. {
  1496. RaiseExecutionEngineException("conv");
  1497. break;
  1498. }
  1499. }
  1500. }
  1501. top.reduceType = dstReduceType;
  1502. top.byteSize = dstTypeSize;
  1503. ip++;
  1504. }
  1505. void TransformContext::Add_conv_ovf(int32_t dstTypeSize, EvalStackReduceDataType dstReduceType, HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8)
  1506. {
  1507. IL2CPP_ASSERT(evalStackTop > 0);
  1508. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  1509. //if (top.reduceType != dstReduceType)
  1510. {
  1511. CreateIR(ir, ConvertOverflowVarVar_i4_u4);
  1512. ir->type = (HiOpcodeEnum)0;
  1513. ir->dst = ir->src = GetEvalStackTopOffset();
  1514. switch (top.reduceType)
  1515. {
  1516. case EvalStackReduceDataType::I4:
  1517. {
  1518. ir->type = opI4;
  1519. AddInst(ir);
  1520. break;
  1521. }
  1522. case EvalStackReduceDataType::I8:
  1523. {
  1524. ir->type = opI8;
  1525. AddInst(ir);
  1526. break;
  1527. }
  1528. case EvalStackReduceDataType::R4:
  1529. {
  1530. ir->type = opR4;
  1531. AddInst(ir);
  1532. break;
  1533. }
  1534. case EvalStackReduceDataType::R8:
  1535. {
  1536. ir->type = opR8;
  1537. AddInst(ir);
  1538. break;
  1539. }
  1540. default:
  1541. {
  1542. RaiseExecutionEngineException("conv_ovf");
  1543. break;
  1544. }
  1545. }
  1546. }
  1547. top.reduceType = dstReduceType;
  1548. top.byteSize = dstTypeSize;
  1549. ip++;
  1550. }
  1551. void TransformContext::Add_binop(HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8)
  1552. {
  1553. IL2CPP_ASSERT(evalStackTop >= 2);
  1554. EvalStackVarInfo& op1 = evalStack[evalStackTop - 2];
  1555. EvalStackVarInfo& op2 = evalStack[evalStackTop - 1];
  1556. CreateIR(ir, BinOpVarVarVar_Add_i4);
  1557. ir->op1 = op1.locOffset;
  1558. ir->op2 = op2.locOffset;
  1559. ir->ret = op1.locOffset;
  1560. EvalStackReduceDataType resultType;
  1561. switch (op1.reduceType)
  1562. {
  1563. case EvalStackReduceDataType::I4:
  1564. {
  1565. switch (op2.reduceType)
  1566. {
  1567. case EvalStackReduceDataType::I4:
  1568. {
  1569. resultType = EvalStackReduceDataType::I4;
  1570. ir->type = opI4;
  1571. break;
  1572. }
  1573. case EvalStackReduceDataType::I8:
  1574. {
  1575. CreateAddIR(irConv, ConvertVarVar_i4_i8);
  1576. irConv->dst = irConv->src = op1.locOffset;
  1577. ir->type = opI8;
  1578. resultType = EvalStackReduceDataType::I8;
  1579. break;
  1580. }
  1581. default:
  1582. {
  1583. RaiseExecutionEngineException("Add_bin_op I4 op unknown");
  1584. resultType = (EvalStackReduceDataType)-1;
  1585. }
  1586. }
  1587. break;
  1588. }
  1589. case EvalStackReduceDataType::I8:
  1590. {
  1591. switch (op2.reduceType)
  1592. {
  1593. case EvalStackReduceDataType::I4:
  1594. {
  1595. CreateAddIR(irConv, ConvertVarVar_i4_i8);
  1596. irConv->dst = irConv->src = op2.locOffset;
  1597. resultType = EvalStackReduceDataType::I8;
  1598. ir->type = opI8;
  1599. break;
  1600. }
  1601. case EvalStackReduceDataType::I8:
  1602. {
  1603. resultType = EvalStackReduceDataType::I8;
  1604. ir->type = opI8;
  1605. break;
  1606. }
  1607. default:
  1608. {
  1609. RaiseExecutionEngineException("Add_bin_op I8 op unknown");
  1610. resultType = (EvalStackReduceDataType)-1;
  1611. break;
  1612. }
  1613. }
  1614. break;
  1615. }
  1616. case EvalStackReduceDataType::R4:
  1617. {
  1618. switch (op2.reduceType)
  1619. {
  1620. case EvalStackReduceDataType::R4:
  1621. {
  1622. resultType = EvalStackReduceDataType::R4;
  1623. ir->type = opR4;
  1624. break;
  1625. }
  1626. default:
  1627. {
  1628. RaiseExecutionEngineException("Add_bin_op R4 op unknown");
  1629. resultType = (EvalStackReduceDataType)-1;
  1630. break;
  1631. }
  1632. }
  1633. break;
  1634. }
  1635. case EvalStackReduceDataType::R8:
  1636. {
  1637. switch (op2.reduceType)
  1638. {
  1639. case EvalStackReduceDataType::R8:
  1640. {
  1641. resultType = EvalStackReduceDataType::R8;
  1642. ir->type = opR8;
  1643. break;
  1644. }
  1645. default:
  1646. {
  1647. RaiseExecutionEngineException("Add_bin_op R8 op unknown");
  1648. resultType = (EvalStackReduceDataType)-1;
  1649. break;
  1650. }
  1651. }
  1652. break;
  1653. }
  1654. default:
  1655. {
  1656. RaiseExecutionEngineException("Add_bin_op unknown");
  1657. resultType = (EvalStackReduceDataType)-1;
  1658. break;
  1659. }
  1660. }
  1661. PopStack();
  1662. op1.reduceType = resultType;
  1663. op1.byteSize = GetSizeByReduceType(resultType);
  1664. AddInst(ir);
  1665. ip++;
  1666. }
  1667. void TransformContext::Add_shiftop(HiOpcodeEnum opI4I4, HiOpcodeEnum opI4I8, HiOpcodeEnum opI8I4, HiOpcodeEnum opI8I8)
  1668. {
  1669. IL2CPP_ASSERT(evalStackTop >= 2);
  1670. EvalStackVarInfo& op1 = evalStack[evalStackTop - 2];
  1671. EvalStackVarInfo& op2 = evalStack[evalStackTop - 1];
  1672. CreateAddIR(ir, BitShiftBinOpVarVarVar_Shr_i4_i4);
  1673. ir->ret = op1.locOffset;
  1674. ir->value = op1.locOffset;
  1675. ir->shiftAmount = op2.locOffset;
  1676. switch (op1.reduceType)
  1677. {
  1678. case EvalStackReduceDataType::I4:
  1679. {
  1680. switch (op2.reduceType)
  1681. {
  1682. case EvalStackReduceDataType::I4:
  1683. {
  1684. ir->type = opI4I4;
  1685. break;
  1686. }
  1687. case EvalStackReduceDataType::I8:
  1688. {
  1689. ir->type = opI4I8;
  1690. break;
  1691. }
  1692. default:
  1693. {
  1694. RaiseExecutionEngineException("shitf i4");
  1695. }
  1696. }
  1697. break;
  1698. }
  1699. case EvalStackReduceDataType::I8:
  1700. {
  1701. switch (op2.reduceType)
  1702. {
  1703. case EvalStackReduceDataType::I4:
  1704. {
  1705. ir->type = opI8I4;
  1706. break;
  1707. }
  1708. case EvalStackReduceDataType::I8:
  1709. {
  1710. ir->type = opI8I8;
  1711. break;
  1712. }
  1713. default:
  1714. {
  1715. RaiseExecutionEngineException("shitf i8");
  1716. break;
  1717. }
  1718. }
  1719. break;
  1720. }
  1721. default:
  1722. {
  1723. RaiseExecutionEngineException("shitf i");
  1724. break;
  1725. }
  1726. }
  1727. PopStack();
  1728. ip++;
  1729. }
  1730. void TransformContext::Add_compare(HiOpcodeEnum opI4, HiOpcodeEnum opI8, HiOpcodeEnum opR4, HiOpcodeEnum opR8)
  1731. {
  1732. IL2CPP_ASSERT(evalStackTop >= 2);
  1733. EvalStackVarInfo& op1 = evalStack[evalStackTop - 2];
  1734. EvalStackVarInfo& op2 = evalStack[evalStackTop - 1];
  1735. CreateIR(ir, CompOpVarVarVar_Ceq_i4);
  1736. ir->c1 = op1.locOffset;
  1737. ir->c2 = op2.locOffset;
  1738. ir->ret = op1.locOffset;
  1739. switch (op1.reduceType)
  1740. {
  1741. case EvalStackReduceDataType::I4:
  1742. {
  1743. switch (op2.reduceType)
  1744. {
  1745. case EvalStackReduceDataType::I4:
  1746. {
  1747. ir->type = opI4;
  1748. break;
  1749. }
  1750. case EvalStackReduceDataType::I8:
  1751. {
  1752. CreateAddIR(irConv, ConvertVarVar_i4_i8);
  1753. irConv->dst = irConv->src = op1.locOffset;
  1754. ir->type = opI8;
  1755. break;
  1756. }
  1757. default:
  1758. {
  1759. RaiseExecutionEngineException("compare i4");
  1760. break;
  1761. }
  1762. }
  1763. break;
  1764. }
  1765. case EvalStackReduceDataType::I8:
  1766. {
  1767. switch (op2.reduceType)
  1768. {
  1769. case EvalStackReduceDataType::I4:
  1770. {
  1771. CreateAddIR(irConv, ConvertVarVar_i4_i8);
  1772. irConv->dst = irConv->src = op2.locOffset;
  1773. ir->type = opI8;
  1774. break;
  1775. }
  1776. case EvalStackReduceDataType::I8:
  1777. {
  1778. ir->type = opI8;
  1779. break;
  1780. }
  1781. default:
  1782. {
  1783. RaiseExecutionEngineException("compare i8");
  1784. break;
  1785. }
  1786. }
  1787. break;
  1788. }
  1789. case EvalStackReduceDataType::R4:
  1790. {
  1791. if (op2.reduceType == EvalStackReduceDataType::R4)
  1792. {
  1793. ir->type = opR4;
  1794. }
  1795. else
  1796. {
  1797. RaiseExecutionEngineException("compare r4");
  1798. }
  1799. break;
  1800. }
  1801. case EvalStackReduceDataType::R8:
  1802. {
  1803. if (op2.reduceType == EvalStackReduceDataType::R8)
  1804. {
  1805. ir->type = opR8;
  1806. }
  1807. else
  1808. {
  1809. RaiseExecutionEngineException("compare r8");
  1810. }
  1811. break;
  1812. }
  1813. default:
  1814. {
  1815. RaiseExecutionEngineException("compare");
  1816. break;
  1817. }
  1818. }
  1819. PopStackN(2);
  1820. AddInst(ir);
  1821. PushStackByReduceType(EvalStackReduceDataType::I4);
  1822. }
  1823. void TransformContext::Add_ldelem(EvalStackReduceDataType resultType, HiOpcodeEnum opI4)
  1824. {
  1825. IL2CPP_ASSERT(evalStackTop >= 2);
  1826. EvalStackVarInfo& arr = evalStack[evalStackTop - 2];
  1827. EvalStackVarInfo& index = evalStack[evalStackTop - 1];
  1828. CreateAddIR(ir, GetArrayElementVarVar_i1);
  1829. ir->type = opI4;
  1830. ir->arr = arr.locOffset;
  1831. ir->index = index.locOffset;
  1832. ir->dst = arr.locOffset;
  1833. PopStackN(2);
  1834. PushStackByReduceType(resultType);
  1835. ip++;
  1836. }
  1837. void TransformContext::Add_stelem(HiOpcodeEnum opI4)
  1838. {
  1839. IL2CPP_ASSERT(evalStackTop >= 3);
  1840. EvalStackVarInfo& arr = evalStack[evalStackTop - 3];
  1841. EvalStackVarInfo& index = evalStack[evalStackTop - 2];
  1842. EvalStackVarInfo& ele = evalStack[evalStackTop - 1];
  1843. CreateAddIR(ir, SetArrayElementVarVar_i1);
  1844. ir->type = opI4;
  1845. ir->arr = arr.locOffset;
  1846. ir->index = index.locOffset;
  1847. ir->ele = ele.locOffset;
  1848. PopStackN(3);
  1849. ip++;
  1850. }
  1851. bool TransformContext::FindFirstLeaveHandlerIndex(const std::vector<ExceptionClause>& exceptionClauses, uint32_t leaveOffset, uint32_t targetOffset, uint16_t& index)
  1852. {
  1853. index = 0;
  1854. for (const ExceptionClause& ec : exceptionClauses)
  1855. {
  1856. if (ec.flags == CorILExceptionClauseType::Finally)
  1857. {
  1858. if (ec.tryOffset <= leaveOffset && leaveOffset < ec.tryOffset + ec.tryLength)
  1859. return !(ec.tryOffset <= targetOffset && targetOffset < ec.tryOffset + ec.tryLength);
  1860. }
  1861. ++index;
  1862. }
  1863. return false;
  1864. }
  1865. bool TransformContext::IsLeaveInTryBlock(const std::vector<ExceptionClause>& exceptionClauses, uint32_t leaveOffset)
  1866. {
  1867. for (const ExceptionClause& ec : exceptionClauses)
  1868. {
  1869. if (ec.tryOffset <= leaveOffset && leaveOffset < ec.tryOffset + ec.tryLength)
  1870. {
  1871. return true;
  1872. }
  1873. if (ec.handlerOffsets <= leaveOffset && leaveOffset < ec.handlerOffsets + ec.handlerLength)
  1874. {
  1875. return false;
  1876. }
  1877. }
  1878. return false;
  1879. }
  1880. void TransformContext::Add_leave(uint32_t targetOffset)
  1881. {
  1882. uint32_t leaveOffset = (uint32_t)(ip - ipBase);
  1883. uint16_t firstHandlerIndex;
  1884. if (FindFirstLeaveHandlerIndex(body.exceptionClauses, leaveOffset, targetOffset, firstHandlerIndex))
  1885. {
  1886. CreateAddIR(ir, LeaveEx);
  1887. ir->target = targetOffset;
  1888. ir->firstHandlerIndex = firstHandlerIndex;
  1889. PushOffset(&ir->target);
  1890. }
  1891. else if (!IsLeaveInTryBlock(body.exceptionClauses, leaveOffset))
  1892. {
  1893. CreateAddIR(ir, LeaveEx_Directly);
  1894. ir->target = targetOffset;
  1895. PushOffset(&ir->target);
  1896. }
  1897. else
  1898. {
  1899. CreateAddIR(ir, BranchUncondition_4);
  1900. ir->offset = targetOffset;
  1901. PushOffset(&ir->offset);
  1902. }
  1903. PopAllStack();
  1904. PushBranch(targetOffset);
  1905. }
  1906. uint16_t TransformContext::FindFirstThrowHandlerIndex(const std::vector<ExceptionClause>& exceptionClauses, uint32_t throwOffset)
  1907. {
  1908. uint16_t index = 0;
  1909. for (const ExceptionClause& ec : exceptionClauses)
  1910. {
  1911. if (ec.flags == CorILExceptionClauseType::Finally || ec.flags == CorILExceptionClauseType::Exception || ec.flags == CorILExceptionClauseType::Filter)
  1912. {
  1913. if (ec.tryOffset <= throwOffset && throwOffset < ec.tryOffset + ec.tryLength)
  1914. return index;
  1915. }
  1916. ++index;
  1917. }
  1918. return index;
  1919. }
  1920. inline const Il2CppType* InflateIfNeeded(const Il2CppType* type, const Il2CppGenericContext* context, bool inflateMethodVars)
  1921. {
  1922. if (context == nullptr)
  1923. {
  1924. return type;
  1925. }
  1926. else
  1927. {
  1928. // FIXME memory leak
  1929. return il2cpp::metadata::GenericMetadata::InflateIfNeeded(type, context, inflateMethodVars);
  1930. }
  1931. }
  1932. #pragma region conv
  1933. #define CI_conv(dstTypeName, dstReduceType, dstTypeSize) \
  1934. Add_conv(dstTypeSize, EvalStackReduceDataType::dstReduceType, \
  1935. HiOpcodeEnum::ConvertVarVar_i4_##dstTypeName,\
  1936. HiOpcodeEnum::ConvertVarVar_i8_##dstTypeName,\
  1937. HiOpcodeEnum::ConvertVarVar_f4_##dstTypeName,\
  1938. HiOpcodeEnum::ConvertVarVar_f8_##dstTypeName);
  1939. #define CI_conv_un(dstTypeName, dstReduceType, dstTypeSize) \
  1940. Add_conv(dstTypeSize, EvalStackReduceDataType::dstReduceType, \
  1941. HiOpcodeEnum::ConvertVarVar_u4_##dstTypeName,\
  1942. HiOpcodeEnum::ConvertVarVar_u8_##dstTypeName,\
  1943. HiOpcodeEnum::ConvertVarVar_f4_##dstTypeName,\
  1944. HiOpcodeEnum::ConvertVarVar_f8_##dstTypeName);
  1945. #define CI_conv_ovf(dstTypeName, dstReduceType, dstTypeSize) \
  1946. Add_conv_ovf(dstTypeSize, EvalStackReduceDataType::dstReduceType, \
  1947. HiOpcodeEnum::ConvertOverflowVarVar_i4_##dstTypeName,\
  1948. HiOpcodeEnum::ConvertOverflowVarVar_i8_##dstTypeName,\
  1949. HiOpcodeEnum::ConvertOverflowVarVar_f4_##dstTypeName,\
  1950. HiOpcodeEnum::ConvertOverflowVarVar_f8_##dstTypeName);
  1951. #define CI_conv_un_ovf(dstTypeName, dstReduceType, dstTypeSize) \
  1952. Add_conv_ovf(dstTypeSize, EvalStackReduceDataType::dstReduceType, \
  1953. HiOpcodeEnum::ConvertOverflowVarVar_u4_##dstTypeName,\
  1954. HiOpcodeEnum::ConvertOverflowVarVar_u8_##dstTypeName,\
  1955. HiOpcodeEnum::ConvertOverflowVarVar_f4_##dstTypeName,\
  1956. HiOpcodeEnum::ConvertOverflowVarVar_f8_##dstTypeName);
  1957. #pragma endregion
  1958. #pragma region branch
  1959. #define CI_branch1(opName) IL2CPP_ASSERT(evalStackTop >= 2); \
  1960. brOffset = GetI1(ip+1); \
  1961. if (brOffset != 0) \
  1962. {\
  1963. Add_bc(ipOffset, brOffset, 2, HiOpcodeEnum::BranchVarVar_##opName##_i4, HiOpcodeEnum::BranchVarVar_##opName##_i8, HiOpcodeEnum::BranchVarVar_##opName##_f4, HiOpcodeEnum::BranchVarVar_##opName##_f8); \
  1964. }\
  1965. else\
  1966. {\
  1967. PopStackN(2);\
  1968. }\
  1969. ip += 2;
  1970. #define CI_branch4(opName) IL2CPP_ASSERT(evalStackTop >= 2); \
  1971. brOffset = GetI4LittleEndian(ip + 1); \
  1972. if (brOffset != 0) \
  1973. { \
  1974. Add_bc(ipOffset, brOffset, 5, HiOpcodeEnum::BranchVarVar_##opName##_i4, HiOpcodeEnum::BranchVarVar_##opName##_i8, HiOpcodeEnum::BranchVarVar_##opName##_f4, HiOpcodeEnum::BranchVarVar_##opName##_f8); \
  1975. }\
  1976. else \
  1977. {\
  1978. PopStackN(2);\
  1979. }\
  1980. ip += 5;
  1981. #define PopBranch() { \
  1982. if (FindNextFlow()) \
  1983. { \
  1984. continue; \
  1985. } \
  1986. else \
  1987. { \
  1988. goto finish_transform; \
  1989. } \
  1990. }
  1991. #pragma endregion
  1992. #pragma region binop
  1993. #define CI_binOp(op) Add_binop(HiOpcodeEnum::BinOpVarVarVar_##op##_i4, HiOpcodeEnum::BinOpVarVarVar_##op##_i8, HiOpcodeEnum::BinOpVarVarVar_##op##_f4, HiOpcodeEnum::BinOpVarVarVar_##op##_f8);
  1994. #define CI_binOpUn(op) Add_binop(HiOpcodeEnum::BinOpVarVarVar_##op##_i4, HiOpcodeEnum::BinOpVarVarVar_##op##_i8, (HiOpcodeEnum)0, (HiOpcodeEnum)0);
  1995. #define CI_binOpOvf(op) Add_binop(HiOpcodeEnum::BinOpOverflowVarVarVar_##op##_i4, HiOpcodeEnum::BinOpOverflowVarVarVar_##op##_i8, (HiOpcodeEnum)0, (HiOpcodeEnum)0);
  1996. #define CI_binOpUnOvf(op) Add_binop(HiOpcodeEnum::BinOpOverflowVarVarVar_##op##_u4, HiOpcodeEnum::BinOpOverflowVarVarVar_##op##_u8, (HiOpcodeEnum)0, (HiOpcodeEnum)0);
  1997. #pragma endregion
  1998. #pragma region shiftop
  1999. #define CI_binOpShift(op) Add_shiftop(HiOpcodeEnum::BitShiftBinOpVarVarVar_##op##_i4_i4, HiOpcodeEnum::BitShiftBinOpVarVarVar_##op##_i4_i8, HiOpcodeEnum::BitShiftBinOpVarVarVar_##op##_i8_i4, HiOpcodeEnum::BitShiftBinOpVarVarVar_##op##_i8_i8);
  2000. #pragma endregion
  2001. #define CI_compare(op) Add_compare(HiOpcodeEnum::CompOpVarVarVar_##op##_i4, HiOpcodeEnum::CompOpVarVarVar_##op##_i8, HiOpcodeEnum::CompOpVarVarVar_##op##_f4, HiOpcodeEnum::CompOpVarVarVar_##op##_f8);
  2002. #define CI_ldele(eleType, resultType) Add_ldelem(EvalStackReduceDataType::resultType, HiOpcodeEnum::GetArrayElementVarVar_##eleType);
  2003. #define CI_stele(eleType) Add_stelem(HiOpcodeEnum::SetArrayElementVarVar_##eleType);
  2004. static const MethodInfo* FindRedirectCreateString(const MethodInfo* shareMethod)
  2005. {
  2006. int32_t paramCount = shareMethod->parameters_count;
  2007. void* iter = nullptr;
  2008. for (const MethodInfo* searchMethod; (searchMethod = il2cpp::vm::Class::GetMethods(il2cpp_defaults.string_class, &iter)) != nullptr;)
  2009. {
  2010. if (searchMethod->parameters_count != paramCount || std::strcmp(searchMethod->name, "CreateString"))
  2011. {
  2012. continue;
  2013. }
  2014. bool sigMatch = true;
  2015. for (uint8_t i = 0; i < paramCount; i++)
  2016. {
  2017. if (!IsTypeEqual(GET_METHOD_PARAMETER_TYPE(searchMethod->parameters[i]), GET_METHOD_PARAMETER_TYPE(shareMethod->parameters[i])))
  2018. {
  2019. sigMatch = false;
  2020. break;
  2021. }
  2022. }
  2023. if (sigMatch)
  2024. {
  2025. return searchMethod;
  2026. }
  2027. }
  2028. return nullptr;
  2029. }
  2030. static bool ShouldBeInlined(const MethodInfo* method, int32_t depth)
  2031. {
  2032. if (depth >= RuntimeConfig::GetMaxMethodInlineDepth())
  2033. {
  2034. return false;
  2035. }
  2036. return metadata::MethodBodyCache::IsInlineable(method);
  2037. }
  2038. void TransformContext::TransformBody(int32_t depth, int32_t localVarOffset, interpreter::InterpMethodInfo& result)
  2039. {
  2040. TransformBodyImpl(depth, localVarOffset);
  2041. BuildInterpMethodInfo(result);
  2042. }
  2043. void TransformContext::TransformBodyImpl(int32_t depth, int32_t localVarOffset)
  2044. {
  2045. #pragma region header
  2046. const Il2CppGenericContext* genericContext = methodInfo->is_inflated ? &methodInfo->genericMethod->context : nullptr;
  2047. const Il2CppGenericContainer* klassContainer = GetGenericContainerFromIl2CppType(&methodInfo->klass->byval_arg);
  2048. const Il2CppGenericContainer* methodContainer = methodInfo->is_inflated ?
  2049. (const Il2CppGenericContainer*)methodInfo->genericMethod->methodDefinition->genericContainerHandle :
  2050. (const Il2CppGenericContainer*)methodInfo->genericContainerHandle;
  2051. BasicBlockSpliter bbc(body);
  2052. bbc.SplitBasicBlocks();
  2053. splitOffsets = bbc.GetSplitOffsets();
  2054. ip2bb = pool.NewNAny<IRBasicBlock*>(body.codeSize + 1);
  2055. uint32_t lastSplitBegin = 0;
  2056. for (uint32_t offset : splitOffsets)
  2057. {
  2058. IRBasicBlock* bb = pool.NewAny<IRBasicBlock>();
  2059. bb->visited = false;
  2060. bb->ilOffset = lastSplitBegin;
  2061. irbbs.push_back(bb);
  2062. for (uint32_t idx = lastSplitBegin; idx < offset; idx++)
  2063. {
  2064. ip2bb[idx] = bb;
  2065. }
  2066. lastSplitBegin = offset;
  2067. }
  2068. IRBasicBlock* endBb = pool.NewAny<IRBasicBlock>();
  2069. *endBb = { true, false, body.codeSize, 0 };
  2070. ip2bb[body.codeSize] = endBb;
  2071. curbb = irbbs[0];
  2072. IL2CPP_ASSERT(lastSplitBegin == body.codeSize);
  2073. bool instanceCall = IsInstanceMethod(methodInfo);
  2074. actualParamCount = methodInfo->parameters_count + instanceCall;
  2075. args = pool.NewNAny<ArgVarInfo>(actualParamCount);
  2076. locals = pool.NewNAny<LocVarInfo>((int)body.localVars.size());
  2077. evalStack = pool.NewNAny<EvalStackVarInfo>(body.maxStack + 100);
  2078. nextFlowIdx = 0;
  2079. totalArgSize = 0;
  2080. {
  2081. int32_t idx = 0;
  2082. if (instanceCall)
  2083. {
  2084. ArgVarInfo& self = args[0];
  2085. self.klass = methodInfo->klass;
  2086. self.type = IS_CLASS_VALUE_TYPE(self.klass) ? &self.klass->this_arg : &self.klass->byval_arg;
  2087. self.argOffset = idx;
  2088. self.argLocOffset = localVarOffset + totalArgSize;
  2089. totalArgSize += GetTypeValueStackObjectCount(self.type);
  2090. idx = 1;
  2091. }
  2092. for (uint32_t i = 0; i < methodInfo->parameters_count; i++)
  2093. {
  2094. ArgVarInfo& arg = args[idx + i];
  2095. arg.type = InflateIfNeeded((Il2CppType*)(GET_METHOD_PARAMETER_TYPE(methodInfo->parameters[i])), genericContext, true);
  2096. arg.klass = il2cpp::vm::Class::FromIl2CppType(arg.type);
  2097. arg.argOffset = idx + i;
  2098. arg.argLocOffset = localVarOffset + totalArgSize;
  2099. il2cpp::vm::Class::SetupFields(arg.klass);
  2100. totalArgSize += GetTypeValueStackObjectCount(arg.type);
  2101. }
  2102. }
  2103. totalArgLocalSize = totalArgSize;
  2104. for (size_t i = 0; i < body.localVars.size(); i++)
  2105. {
  2106. LocVarInfo& local = locals[i];
  2107. // FIXME memory leak
  2108. local.type = InflateIfNeeded(body.localVars[i], genericContext, true);
  2109. local.klass = il2cpp::vm::Class::FromIl2CppType(local.type);
  2110. il2cpp::vm::Class::SetupFields(local.klass);
  2111. local.locOffset = localVarOffset + totalArgLocalSize;
  2112. totalArgLocalSize += GetTypeValueStackObjectCount(local.type);
  2113. }
  2114. evalStackBaseOffset = localVarOffset + totalArgLocalSize;
  2115. int32_t totalLocalSize = totalArgLocalSize - totalArgSize;
  2116. maxStackSize = evalStackBaseOffset;
  2117. curStackSize = evalStackBaseOffset;
  2118. ipBase = body.ilcodes;
  2119. ip = body.ilcodes;
  2120. ipOffset = 0;
  2121. evalStackTop = 0;
  2122. prefixFlags = 0;
  2123. int32_t argIdx = 0;
  2124. int32_t varKst = 0;
  2125. int64_t varKst8 = 0;
  2126. int32_t brOffset = 0;
  2127. shareMethod = nullptr;
  2128. Token2RuntimeHandleMap tokenCache(64);
  2129. bool inMethodInlining = depth > 0;
  2130. hybridclr::metadata::PDBImage* pdbImage = image->GetPDBImage();
  2131. ir2offsetMap = pdbImage && !inMethodInlining ? new IR2OffsetMap(body.codeSize) : nullptr;
  2132. if (inMethodInlining)
  2133. {
  2134. if (instanceCall)
  2135. {
  2136. CreateAddIR(irCheckNull, CheckThrowIfNullVar);
  2137. irCheckNull->obj = args[0].argLocOffset;
  2138. }
  2139. else
  2140. {
  2141. if (!IS_CCTOR_FINISH_OR_NO_CCTOR(methodInfo->klass))
  2142. {
  2143. CreateAddIR(irInitStaticCtor, InitClassStaticCtor);
  2144. irInitStaticCtor->klass = (uint64_t)methodInfo->klass;
  2145. }
  2146. }
  2147. }
  2148. initLocals = (body.flags & (uint32_t)CorILMethodFormat::InitLocals) != 0;
  2149. // init local vars
  2150. if (initLocals && totalLocalSize > 0)
  2151. {
  2152. AddInst(CreateInitLocals(pool, totalLocalSize * sizeof(StackObject), locals[0].locOffset));
  2153. }
  2154. exClauses.resize_initialized(body.exceptionClauses.size());
  2155. int clauseIdx = 0;
  2156. for (ExceptionClause& ec : body.exceptionClauses)
  2157. {
  2158. InterpExceptionClause* iec = &exClauses[clauseIdx++];
  2159. iec->flags = ec.flags;
  2160. iec->tryBeginOffset = ec.tryOffset;
  2161. iec->tryEndOffset = ec.tryOffset + ec.tryLength;
  2162. iec->handlerBeginOffset = ec.handlerOffsets;
  2163. iec->handlerEndOffset = ec.handlerOffsets + ec.handlerLength;
  2164. PushOffset(&iec->tryBeginOffset);
  2165. PushOffset(&iec->tryEndOffset);
  2166. PushOffset(&iec->handlerBeginOffset);
  2167. PushOffset(&iec->handlerEndOffset);
  2168. if (ec.flags == CorILExceptionClauseType::Exception)
  2169. {
  2170. iec->filterBeginOffset = 0;
  2171. iec->exKlass = image->GetClassFromToken(tokenCache, ec.classTokenOrFilterOffset, klassContainer, methodContainer, genericContext);
  2172. }
  2173. else if (ec.flags == CorILExceptionClauseType::Filter)
  2174. {
  2175. iec->filterBeginOffset = ec.classTokenOrFilterOffset;
  2176. PushOffset(&iec->filterBeginOffset);
  2177. iec->exKlass = nullptr;
  2178. }
  2179. else
  2180. {
  2181. IL2CPP_ASSERT(ec.classTokenOrFilterOffset == 0);
  2182. iec->filterBeginOffset = 0;
  2183. iec->exKlass = nullptr;
  2184. }
  2185. switch (ec.flags)
  2186. {
  2187. case CorILExceptionClauseType::Exception:
  2188. {
  2189. IRBasicBlock* bb = ip2bb[iec->handlerBeginOffset];
  2190. IL2CPP_ASSERT(!bb->inPending);
  2191. bb->inPending = true;
  2192. FlowInfo* fi = pool.NewAny<FlowInfo>();
  2193. fi->offset = ec.handlerOffsets;
  2194. fi->curStackSize = evalStackBaseOffset + 1;
  2195. fi->evalStack.push_back({ NATIVE_INT_REDUCE_TYPE, PTR_SIZE, evalStackBaseOffset });
  2196. pendingFlows.push_back(fi);
  2197. break;
  2198. }
  2199. case CorILExceptionClauseType::Filter:
  2200. {
  2201. IRBasicBlock* bb = ip2bb[iec->filterBeginOffset];
  2202. IL2CPP_ASSERT(!bb->inPending);
  2203. bb->inPending = true;
  2204. {
  2205. FlowInfo* fi = pool.NewAny<FlowInfo>();
  2206. IL2CPP_ASSERT(ec.classTokenOrFilterOffset);
  2207. fi->offset = ec.classTokenOrFilterOffset;
  2208. fi->curStackSize = evalStackBaseOffset + 1;
  2209. fi->evalStack.push_back({ NATIVE_INT_REDUCE_TYPE, PTR_SIZE, evalStackBaseOffset });
  2210. pendingFlows.push_back(fi);
  2211. }
  2212. {
  2213. FlowInfo* fi = pool.NewAny<FlowInfo>();
  2214. IL2CPP_ASSERT(ec.handlerOffsets);
  2215. fi->offset = ec.handlerOffsets;
  2216. fi->curStackSize = evalStackBaseOffset + 1;
  2217. fi->evalStack.push_back({ NATIVE_INT_REDUCE_TYPE, PTR_SIZE, evalStackBaseOffset });
  2218. pendingFlows.push_back(fi);
  2219. }
  2220. break;
  2221. }
  2222. case CorILExceptionClauseType::Fault:
  2223. case CorILExceptionClauseType::Finally:
  2224. {
  2225. IRBasicBlock* bb = ip2bb[iec->handlerBeginOffset];
  2226. IL2CPP_ASSERT(!bb->inPending);
  2227. bb->inPending = true;
  2228. FlowInfo* fi = pool.NewAny<FlowInfo>();
  2229. fi->offset = ec.handlerOffsets;
  2230. fi->curStackSize = evalStackBaseOffset;
  2231. pendingFlows.push_back(fi);
  2232. break;
  2233. }
  2234. default:
  2235. {
  2236. RaiseExecutionEngineException("");
  2237. }
  2238. }
  2239. }
  2240. #pragma endregion
  2241. IRBasicBlock* lastBb = nullptr;
  2242. for (;;)
  2243. {
  2244. ipOffset = (uint32_t)(ip - ipBase);
  2245. curbb = ip2bb[ipOffset];
  2246. if (curbb != lastBb)
  2247. {
  2248. if (curbb && !curbb->visited)
  2249. {
  2250. curbb->visited = true;
  2251. lastBb = curbb;
  2252. }
  2253. else
  2254. {
  2255. PopBranch();
  2256. }
  2257. }
  2258. switch ((OpcodeValue)*ip)
  2259. {
  2260. case OpcodeValue::NOP:
  2261. {
  2262. ip++;
  2263. continue;
  2264. }
  2265. case OpcodeValue::BREAK:
  2266. {
  2267. ip++;
  2268. continue;
  2269. }
  2270. case OpcodeValue::LDARG_0:
  2271. {
  2272. AddInst_ldarg(0);
  2273. ip++;
  2274. continue;
  2275. }
  2276. case OpcodeValue::LDARG_1:
  2277. {
  2278. AddInst_ldarg(1);
  2279. ip++;
  2280. continue;
  2281. }
  2282. case OpcodeValue::LDARG_2:
  2283. {
  2284. AddInst_ldarg(2);
  2285. ip++;
  2286. continue;
  2287. }
  2288. case OpcodeValue::LDARG_3:
  2289. {
  2290. AddInst_ldarg(3);
  2291. ip++;
  2292. continue;
  2293. }
  2294. case OpcodeValue::LDLOC_0:
  2295. {
  2296. CreateAddInst_ldloc(0);
  2297. ip++;
  2298. continue;
  2299. }
  2300. case OpcodeValue::LDLOC_1:
  2301. {
  2302. CreateAddInst_ldloc(1);
  2303. ip++;
  2304. continue;
  2305. }
  2306. case OpcodeValue::LDLOC_2:
  2307. {
  2308. CreateAddInst_ldloc(2);
  2309. ip++;
  2310. continue;
  2311. }
  2312. case OpcodeValue::LDLOC_3:
  2313. {
  2314. CreateAddInst_ldloc(3);
  2315. ip++;
  2316. continue;
  2317. }
  2318. case OpcodeValue::STLOC_0:
  2319. {
  2320. CreateAddInst_stloc(0);
  2321. ip++;
  2322. continue;
  2323. }
  2324. case OpcodeValue::STLOC_1:
  2325. {
  2326. CreateAddInst_stloc(1);
  2327. ip++;
  2328. continue;
  2329. }
  2330. case OpcodeValue::STLOC_2:
  2331. {
  2332. CreateAddInst_stloc(2);
  2333. ip++;
  2334. continue;
  2335. }
  2336. case OpcodeValue::STLOC_3:
  2337. {
  2338. CreateAddInst_stloc(3);
  2339. ip++;
  2340. continue;
  2341. }
  2342. case OpcodeValue::LDARG_S:
  2343. {
  2344. argIdx = ip[1];
  2345. AddInst_ldarg(argIdx);
  2346. ip += 2;
  2347. continue;
  2348. }
  2349. case OpcodeValue::LDARGA_S:
  2350. {
  2351. argIdx = ip[1];
  2352. AddInst_ldarga(argIdx);
  2353. ip += 2;
  2354. continue;
  2355. }
  2356. case OpcodeValue::STARG_S:
  2357. {
  2358. argIdx = ip[1];
  2359. AddInst_starg(argIdx);
  2360. ip += 2;
  2361. continue;
  2362. }
  2363. case OpcodeValue::LDLOC_S:
  2364. {
  2365. argIdx = ip[1];
  2366. CreateAddInst_ldloc(argIdx);
  2367. ip += 2;
  2368. continue;
  2369. }
  2370. case OpcodeValue::LDLOCA_S:
  2371. {
  2372. argIdx = ip[1];
  2373. CreateAddInst_ldloca(argIdx);
  2374. ip += 2;
  2375. continue;
  2376. }
  2377. case OpcodeValue::STLOC_S:
  2378. {
  2379. argIdx = ip[1];
  2380. CreateAddInst_stloc(argIdx);
  2381. ip += 2;
  2382. continue;
  2383. }
  2384. case OpcodeValue::LDNULL:
  2385. {
  2386. CreateAddIR(ir, LdnullVar);
  2387. ir->dst = curStackSize;
  2388. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  2389. ip++;
  2390. continue;
  2391. }
  2392. case OpcodeValue::LDC_I4_M1:
  2393. {
  2394. CreateAddInst_ldc4(-1, EvalStackReduceDataType::I4);
  2395. ip++;
  2396. continue;
  2397. }
  2398. case OpcodeValue::LDC_I4_0:
  2399. {
  2400. CreateAddInst_ldc4(0, EvalStackReduceDataType::I4);
  2401. ip++;
  2402. continue;
  2403. }
  2404. case OpcodeValue::LDC_I4_1:
  2405. {
  2406. CreateAddInst_ldc4(1, EvalStackReduceDataType::I4);
  2407. ip++;
  2408. continue;
  2409. }
  2410. case OpcodeValue::LDC_I4_2:
  2411. {
  2412. CreateAddInst_ldc4(2, EvalStackReduceDataType::I4);
  2413. ip++;
  2414. continue;
  2415. }
  2416. case OpcodeValue::LDC_I4_3:
  2417. {
  2418. CreateAddInst_ldc4(3, EvalStackReduceDataType::I4);
  2419. ip++;
  2420. continue;
  2421. }
  2422. case OpcodeValue::LDC_I4_4:
  2423. {
  2424. CreateAddInst_ldc4(4, EvalStackReduceDataType::I4);
  2425. ip++;
  2426. continue;
  2427. }
  2428. case OpcodeValue::LDC_I4_5:
  2429. {
  2430. CreateAddInst_ldc4(5, EvalStackReduceDataType::I4);
  2431. ip++;
  2432. continue;
  2433. }
  2434. case OpcodeValue::LDC_I4_6:
  2435. {
  2436. CreateAddInst_ldc4(6, EvalStackReduceDataType::I4);
  2437. ip++;
  2438. continue;
  2439. }
  2440. case OpcodeValue::LDC_I4_7:
  2441. {
  2442. CreateAddInst_ldc4(7, EvalStackReduceDataType::I4);
  2443. ip++;
  2444. continue;
  2445. }
  2446. case OpcodeValue::LDC_I4_8:
  2447. {
  2448. CreateAddInst_ldc4(8, EvalStackReduceDataType::I4);
  2449. ip++;
  2450. continue;
  2451. }
  2452. case OpcodeValue::LDC_I4_S:
  2453. {
  2454. varKst = GetI1(ip + 1);
  2455. CreateAddInst_ldc4(varKst, EvalStackReduceDataType::I4);
  2456. ip += 2;
  2457. continue;
  2458. }
  2459. case OpcodeValue::LDC_I4:
  2460. {
  2461. varKst = GetI4LittleEndian(ip + 1);
  2462. CreateAddInst_ldc4(varKst, EvalStackReduceDataType::I4);
  2463. ip += 5;
  2464. continue;
  2465. }
  2466. case OpcodeValue::LDC_I8:
  2467. {
  2468. varKst8 = GetI8LittleEndian(ip + 1);
  2469. CreateAddInst_ldc8(varKst8, EvalStackReduceDataType::I8);
  2470. ip += 9;
  2471. continue;
  2472. }
  2473. case OpcodeValue::LDC_R4:
  2474. {
  2475. varKst = GetI4LittleEndian(ip + 1);
  2476. CreateAddInst_ldc4(varKst, EvalStackReduceDataType::R4);
  2477. ip += 5;
  2478. continue;
  2479. }
  2480. case OpcodeValue::LDC_R8:
  2481. {
  2482. varKst8 = GetI8LittleEndian(ip + 1);
  2483. CreateAddInst_ldc8(varKst8, EvalStackReduceDataType::R8);
  2484. ip += 9;
  2485. continue;
  2486. }
  2487. case OpcodeValue::DUP:
  2488. {
  2489. IL2CPP_ASSERT(evalStackTop > 0);
  2490. EvalStackVarInfo& __eval = evalStack[evalStackTop - 1];
  2491. IRCommon* ir = CreateAssignVarVar(pool, GetEvalStackNewTopOffset(), __eval.locOffset, __eval.byteSize);
  2492. AddInst(ir);
  2493. DuplicateStack();
  2494. ip++;
  2495. continue;
  2496. }
  2497. case OpcodeValue::POP:
  2498. {
  2499. PopStack();
  2500. ip++;
  2501. continue;
  2502. }
  2503. case OpcodeValue::JMP:
  2504. {
  2505. /* auto& x = ir.jump;
  2506. x.type = IRType::Jmp;
  2507. x.methodToken = GetI4LittleEndian(ip + 1);
  2508. irs.push_back(ir);
  2509. ip += 5;*/
  2510. RaiseNotSupportedException("not support jmp");
  2511. continue;
  2512. }
  2513. case OpcodeValue::CALL:
  2514. {
  2515. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  2516. ip += 5;
  2517. shareMethod = const_cast<MethodInfo*>(image->GetMethodInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  2518. IL2CPP_ASSERT(shareMethod);
  2519. }
  2520. LabelCall:
  2521. {
  2522. if (TryAddInstinctInstruments(shareMethod))
  2523. {
  2524. continue;
  2525. }
  2526. #if HYBRIDCLR_UNITY_2021_OR_NEW
  2527. if (!shareMethod->has_full_generic_sharing_signature)
  2528. #endif
  2529. {
  2530. if (!InitAndGetInterpreterDirectlyCallMethodPointer(shareMethod))
  2531. {
  2532. RaiseAOTGenericMethodNotInstantiatedException(shareMethod);
  2533. }
  2534. }
  2535. bool resolvedIsInstanceMethod = IsInstanceMethod(shareMethod);
  2536. int32_t resolvedTotalArgNum = shareMethod->parameters_count + resolvedIsInstanceMethod;
  2537. int32_t needDataSlotNum = (resolvedTotalArgNum + 3) / 4;
  2538. int32_t callArgEvalStackIdxBase = evalStackTop - resolvedTotalArgNum;
  2539. uint32_t methodDataIndex = GetOrAddResolveDataIndex(shareMethod);
  2540. if (hybridclr::metadata::IsInterpreterImplement(shareMethod))
  2541. {
  2542. uint16_t argBaseOffset = (uint16_t)GetEvalStackOffset(callArgEvalStackIdxBase);
  2543. if (ShouldBeInlined(shareMethod, depth) && TransformSubMethodBody(*this, shareMethod, depth + 1, argBaseOffset))
  2544. {
  2545. }
  2546. else
  2547. {
  2548. if (IsReturnVoidMethod(shareMethod))
  2549. {
  2550. CreateAddIR(ir, CallInterp_void);
  2551. ir->methodInfo = methodDataIndex;
  2552. ir->argBase = argBaseOffset;
  2553. }
  2554. else
  2555. {
  2556. CreateAddIR(ir, CallInterp_ret);
  2557. ir->methodInfo = methodDataIndex;
  2558. ir->argBase = argBaseOffset;
  2559. ir->ret = argBaseOffset;
  2560. }
  2561. }
  2562. PopStackN(resolvedTotalArgNum);
  2563. if (!IsReturnVoidMethod(shareMethod))
  2564. {
  2565. PushStackByType(shareMethod->return_type);
  2566. }
  2567. continue;
  2568. }
  2569. #if HYBRIDCLR_UNITY_2021_OR_NEW
  2570. if (!shareMethod->has_full_generic_sharing_signature)
  2571. #endif
  2572. {
  2573. if (TryAddCallCommonInstruments(shareMethod, methodDataIndex))
  2574. {
  2575. continue;
  2576. }
  2577. }
  2578. Managed2NativeCallMethod managed2NativeMethod = InterpreterModule::GetManaged2NativeMethodPointer(shareMethod, false);
  2579. IL2CPP_ASSERT(managed2NativeMethod);
  2580. uint32_t managed2NativeMethodDataIdx = GetOrAddResolveDataIndex((void*)managed2NativeMethod);
  2581. int32_t argIdxDataIndex;
  2582. uint16_t* __argIdxs;
  2583. AllocResolvedData(resolveDatas, needDataSlotNum, argIdxDataIndex, __argIdxs);
  2584. if (resolvedIsInstanceMethod)
  2585. {
  2586. __argIdxs[0] = GetEvalStackOffset(callArgEvalStackIdxBase);
  2587. }
  2588. for (uint8_t i = 0; i < shareMethod->parameters_count; i++)
  2589. {
  2590. int32_t curArgIdx = i + resolvedIsInstanceMethod;
  2591. __argIdxs[curArgIdx] = evalStack[callArgEvalStackIdxBase + curArgIdx].locOffset;
  2592. }
  2593. PopStackN(resolvedTotalArgNum);
  2594. if (!IsReturnVoidMethod(shareMethod))
  2595. {
  2596. PushStackByType(shareMethod->return_type);
  2597. interpreter::LocationDataType locDataType = GetLocationDataTypeByType(shareMethod->return_type);
  2598. if (interpreter::IsNeedExpandLocationType(locDataType))
  2599. {
  2600. CreateAddIR(ir, CallNativeInstance_ret_expand);
  2601. ir->type = resolvedIsInstanceMethod ? HiOpcodeEnum::CallNativeInstance_ret_expand : HiOpcodeEnum::CallNativeStatic_ret_expand;
  2602. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2603. ir->methodInfo = methodDataIndex;
  2604. ir->argIdxs = argIdxDataIndex;
  2605. ir->ret = GetEvalStackTopOffset();
  2606. ir->retLocationType = (uint8_t)locDataType;
  2607. }
  2608. else
  2609. {
  2610. CreateAddIR(ir, CallNativeInstance_ret);
  2611. ir->type = resolvedIsInstanceMethod ? HiOpcodeEnum::CallNativeInstance_ret : HiOpcodeEnum::CallNativeStatic_ret;
  2612. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2613. ir->methodInfo = methodDataIndex;
  2614. ir->argIdxs = argIdxDataIndex;
  2615. ir->ret = GetEvalStackTopOffset();
  2616. }
  2617. }
  2618. else
  2619. {
  2620. CreateAddIR(ir, CallNativeInstance_void);
  2621. ir->type = resolvedIsInstanceMethod ? HiOpcodeEnum::CallNativeInstance_void : HiOpcodeEnum::CallNativeStatic_void;
  2622. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2623. ir->methodInfo = methodDataIndex;
  2624. ir->argIdxs = argIdxDataIndex;
  2625. }
  2626. continue;
  2627. }
  2628. case OpcodeValue::CALLVIRT:
  2629. {
  2630. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  2631. ip += 5;
  2632. shareMethod = image->GetMethodInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  2633. }
  2634. LabelCallVir:
  2635. {
  2636. IL2CPP_ASSERT(shareMethod);
  2637. IL2CPP_ASSERT(hybridclr::metadata::IsInstanceMethod(shareMethod));
  2638. if ((!metadata::IsVirtualMethod(shareMethod->flags)) || metadata::IsSealed(shareMethod->flags))
  2639. {
  2640. goto LabelCall;
  2641. }
  2642. int32_t resolvedTotalArgNum = shareMethod->parameters_count + 1;
  2643. int32_t callArgEvalStackIdxBase = evalStackTop - resolvedTotalArgNum;
  2644. uint32_t methodDataIndex = GetOrAddResolveDataIndex(shareMethod);
  2645. bool isMultiDelegate = IsChildTypeOfMulticastDelegate(shareMethod->klass);
  2646. if (!isMultiDelegate && IsInterpreterMethod(shareMethod) && !IsInterface(shareMethod->klass->flags))
  2647. {
  2648. PopStackN(resolvedTotalArgNum);
  2649. uint16_t argBaseOffset = (uint16_t)GetEvalStackOffset(callArgEvalStackIdxBase);
  2650. if (IsReturnVoidMethod(shareMethod))
  2651. {
  2652. CreateAddIR(ir, CallInterpVirtual_void);
  2653. ir->method = methodDataIndex;
  2654. ir->argBase = argBaseOffset;
  2655. }
  2656. else
  2657. {
  2658. CreateAddIR(ir, CallInterpVirtual_ret);
  2659. ir->method = methodDataIndex;
  2660. ir->argBase = argBaseOffset;
  2661. ir->ret = argBaseOffset;
  2662. PushStackByType(shareMethod->return_type);
  2663. }
  2664. continue;
  2665. }
  2666. Managed2NativeCallMethod managed2NativeMethod = InterpreterModule::GetManaged2NativeMethodPointer(shareMethod, false);
  2667. IL2CPP_ASSERT(managed2NativeMethod);
  2668. uint32_t managed2NativeMethodDataIdx = GetOrAddResolveDataIndex((void*)managed2NativeMethod);
  2669. int32_t needDataSlotNum = (resolvedTotalArgNum + 3) / 4;
  2670. int32_t argIdxDataIndex;
  2671. uint16_t* __argIdxs;
  2672. AllocResolvedData(resolveDatas, needDataSlotNum, argIdxDataIndex, __argIdxs);
  2673. __argIdxs[0] = GetEvalStackOffset(callArgEvalStackIdxBase);
  2674. for (uint8_t i = 0; i < shareMethod->parameters_count; i++)
  2675. {
  2676. int32_t curArgIdx = i + 1;
  2677. __argIdxs[curArgIdx] = evalStack[callArgEvalStackIdxBase + curArgIdx].locOffset;
  2678. }
  2679. PopStackN(resolvedTotalArgNum);
  2680. const Il2CppType* returnType = shareMethod->return_type;
  2681. int32_t retIdx;
  2682. if (returnType->type != IL2CPP_TYPE_VOID)
  2683. {
  2684. PushStackByType(returnType);
  2685. retIdx = GetEvalStackTopOffset();
  2686. }
  2687. else
  2688. {
  2689. retIdx = -1;
  2690. }
  2691. if (isMultiDelegate)
  2692. {
  2693. if (std::strcmp(shareMethod->name, "Invoke") == 0)
  2694. {
  2695. Managed2NativeCallMethod staticManaged2NativeMethod = InterpreterModule::GetManaged2NativeMethodPointer(shareMethod, true);
  2696. IL2CPP_ASSERT(staticManaged2NativeMethod);
  2697. uint32_t staticManaged2NativeMethodDataIdx = GetOrAddResolveDataIndex((void*)staticManaged2NativeMethod);
  2698. if (retIdx < 0)
  2699. {
  2700. CreateAddIR(ir, CallDelegateInvoke_void);
  2701. ir->managed2NativeStaticMethod = staticManaged2NativeMethodDataIdx;
  2702. ir->managed2NativeInstanceMethod = managed2NativeMethodDataIdx;
  2703. ir->argIdxs = argIdxDataIndex;
  2704. ir->invokeParamCount = shareMethod->parameters_count;
  2705. }
  2706. else
  2707. {
  2708. interpreter::TypeDesc retDesc = GetTypeArgDesc(returnType);
  2709. if (IsNeedExpandLocationType(retDesc.type))
  2710. {
  2711. CreateAddIR(ir, CallDelegateInvoke_ret_expand);
  2712. ir->managed2NativeStaticMethod = staticManaged2NativeMethodDataIdx;
  2713. ir->managed2NativeInstanceMethod = managed2NativeMethodDataIdx;
  2714. ir->argIdxs = argIdxDataIndex;
  2715. ir->ret = retIdx;
  2716. ir->invokeParamCount = shareMethod->parameters_count;
  2717. ir->retLocationType = (uint8_t)retDesc.type;
  2718. }
  2719. else
  2720. {
  2721. CreateAddIR(ir, CallDelegateInvoke_ret);
  2722. ir->managed2NativeStaticMethod = staticManaged2NativeMethodDataIdx;
  2723. ir->managed2NativeInstanceMethod = managed2NativeMethodDataIdx;
  2724. ir->argIdxs = argIdxDataIndex;
  2725. ir->ret = retIdx;
  2726. ir->retTypeStackObjectSize = retDesc.stackObjectSize;
  2727. ir->invokeParamCount = shareMethod->parameters_count;
  2728. }
  2729. }
  2730. continue;
  2731. }
  2732. Il2CppMethodPointer directlyCallMethodPointer = InitAndGetInterpreterDirectlyCallMethodPointer(shareMethod);
  2733. if (std::strcmp(shareMethod->name, "BeginInvoke") == 0)
  2734. {
  2735. if (IsInterpreterMethod(shareMethod) || directlyCallMethodPointer == nullptr)
  2736. {
  2737. CreateAddIR(ir, CallDelegateBeginInvoke);
  2738. ir->methodInfo = methodDataIndex;
  2739. ir->result = retIdx;
  2740. ir->argIdxs = argIdxDataIndex;
  2741. continue;
  2742. }
  2743. }
  2744. else if (std::strcmp(shareMethod->name, "EndInvoke") == 0)
  2745. {
  2746. if (IsInterpreterMethod(shareMethod) || directlyCallMethodPointer == nullptr)
  2747. {
  2748. if (retIdx < 0)
  2749. {
  2750. CreateAddIR(ir, CallDelegateEndInvoke_void);
  2751. ir->methodInfo = methodDataIndex;
  2752. ir->asyncResult = __argIdxs[1];
  2753. }
  2754. else
  2755. {
  2756. CreateAddIR(ir, CallDelegateEndInvoke_ret);
  2757. ir->methodInfo = methodDataIndex;
  2758. ir->asyncResult = __argIdxs[1];
  2759. ir->ret = retIdx;
  2760. }
  2761. continue;
  2762. }
  2763. }
  2764. }
  2765. if (retIdx < 0)
  2766. {
  2767. CreateAddIR(ir, CallVirtual_void);
  2768. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2769. ir->methodInfo = methodDataIndex;
  2770. ir->argIdxs = argIdxDataIndex;
  2771. }
  2772. else
  2773. {
  2774. interpreter::LocationDataType locDataType = GetLocationDataTypeByType(returnType);
  2775. if (IsNeedExpandLocationType(locDataType))
  2776. {
  2777. CreateAddIR(ir, CallVirtual_ret_expand);
  2778. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2779. ir->methodInfo = methodDataIndex;
  2780. ir->argIdxs = argIdxDataIndex;
  2781. ir->ret = retIdx;
  2782. ir->retLocationType = (uint8_t)locDataType;
  2783. }
  2784. else
  2785. {
  2786. CreateAddIR(ir, CallVirtual_ret);
  2787. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2788. ir->methodInfo = methodDataIndex;
  2789. ir->argIdxs = argIdxDataIndex;
  2790. ir->ret = retIdx;
  2791. }
  2792. }
  2793. continue;
  2794. }
  2795. case OpcodeValue::CALLI:
  2796. {
  2797. IL2CPP_ASSERT(evalStackTop > 0);
  2798. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  2799. ResolveStandAloneMethodSig methodSig;
  2800. image->GetStandAloneMethodSigFromToken(token, klassContainer, methodContainer, genericContext, methodSig);
  2801. if (IsPrologExplicitThis(methodSig.flags))
  2802. {
  2803. RaiseNotSupportedException("not support StandAloneMethodSig flags:EXPLICITTHIS");
  2804. }
  2805. int32_t methodIdx = GetEvalStackTopOffset();
  2806. //uint32_t methodDataIndex = GetOrAddResolveDataIndex(shareMethod);
  2807. Managed2NativeCallMethod managed2NativeMethod = InterpreterModule::GetManaged2NativeMethodPointer(methodSig);
  2808. IL2CPP_ASSERT(managed2NativeMethod);
  2809. uint32_t managed2NativeMethodDataIdx = GetOrAddResolveDataIndex((void*)managed2NativeMethod);
  2810. bool hasThis = metadata::IsPrologHasThis(methodSig.flags);
  2811. int32_t resolvedTotalArgNum = (int32_t)methodSig.params.size() + hasThis;
  2812. int32_t needDataSlotNum = (resolvedTotalArgNum + 3) / 4;
  2813. int32_t argIdxDataIndex;
  2814. uint16_t* __argIdxs;
  2815. // we need at least one slot for argBasePtr when resolvedTotalArgNum == 0
  2816. AllocResolvedData(resolveDatas, std::max(needDataSlotNum, 1), argIdxDataIndex, __argIdxs);
  2817. int32_t callArgEvalStackIdxBase = evalStackTop - resolvedTotalArgNum - 1 /*funtion ptr*/;
  2818. // CallInd need know the argBasePtr when resolvedTotalArgNum == 0
  2819. if (needDataSlotNum == 0)
  2820. {
  2821. __argIdxs[0] = evalStack[callArgEvalStackIdxBase].locOffset;
  2822. }
  2823. if (hasThis)
  2824. {
  2825. __argIdxs[0] = evalStack[callArgEvalStackIdxBase].locOffset;
  2826. }
  2827. for (size_t i = 0; i < methodSig.params.size(); i++)
  2828. {
  2829. size_t curArgIdx = i + hasThis;
  2830. __argIdxs[curArgIdx] = evalStack[callArgEvalStackIdxBase + curArgIdx].locOffset;
  2831. }
  2832. PopStackN(resolvedTotalArgNum + 1);
  2833. if (!IsVoidType(methodSig.returnType))
  2834. {
  2835. PushStackByType(methodSig.returnType);
  2836. interpreter::LocationDataType locDataType = GetLocationDataTypeByType(methodSig.returnType);
  2837. if (interpreter::IsNeedExpandLocationType(locDataType))
  2838. {
  2839. CreateAddIR(ir, CallInd_ret_expand);
  2840. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2841. ir->methodInfo = methodIdx;
  2842. ir->argIdxs = argIdxDataIndex;
  2843. ir->ret = GetEvalStackTopOffset();
  2844. ir->retLocationType = (uint8_t)locDataType;
  2845. }
  2846. else
  2847. {
  2848. CreateAddIR(ir, CallInd_ret);
  2849. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2850. ir->methodInfo = methodIdx;
  2851. ir->argIdxs = argIdxDataIndex;
  2852. ir->ret = GetEvalStackTopOffset();
  2853. }
  2854. }
  2855. else
  2856. {
  2857. CreateAddIR(ir, CallInd_void);
  2858. ir->managed2NativeMethod = managed2NativeMethodDataIdx;
  2859. ir->methodInfo = methodIdx;
  2860. ir->argIdxs = argIdxDataIndex;
  2861. }
  2862. ip += 5;
  2863. continue;
  2864. }
  2865. case OpcodeValue::RET:
  2866. {
  2867. bool isVoidReturnType = methodInfo->return_type->type == IL2CPP_TYPE_VOID;
  2868. if (inMethodInlining)
  2869. {
  2870. if (!isVoidReturnType)
  2871. {
  2872. uint16_t retVarIdx = GetEvalStackTopOffset();
  2873. if (retVarIdx != localVarOffset)
  2874. {
  2875. IRCommon* ir = CreateAssignVarVar(pool, localVarOffset, retVarIdx, GetTypeValueSize(methodInfo->return_type));
  2876. AddInst(ir);
  2877. }
  2878. }
  2879. }
  2880. else if (isVoidReturnType)
  2881. {
  2882. CreateAddIR(ir, RetVar_void);
  2883. }
  2884. else
  2885. {
  2886. // ms.ret = nullptr;
  2887. IL2CPP_ASSERT(evalStackTop == 1);
  2888. int32_t size = GetTypeValueSize(methodInfo->return_type);
  2889. switch (size)
  2890. {
  2891. case 1:
  2892. {
  2893. CreateAddIR(ir, RetVar_ret_1);
  2894. ir->ret = GetEvalStackTopOffset();
  2895. break;
  2896. }
  2897. case 2:
  2898. {
  2899. CreateAddIR(ir, RetVar_ret_2);
  2900. ir->ret = GetEvalStackTopOffset();
  2901. break;
  2902. }
  2903. case 4:
  2904. {
  2905. CreateAddIR(ir, RetVar_ret_4);
  2906. ir->ret = GetEvalStackTopOffset();
  2907. break;
  2908. }
  2909. case 8:
  2910. {
  2911. CreateAddIR(ir, RetVar_ret_8);
  2912. ir->ret = GetEvalStackTopOffset();
  2913. break;
  2914. }
  2915. case 12:
  2916. {
  2917. CreateAddIR(ir, RetVar_ret_12);
  2918. ir->ret = GetEvalStackTopOffset();
  2919. break;
  2920. }
  2921. case 16:
  2922. {
  2923. CreateAddIR(ir, RetVar_ret_16);
  2924. ir->ret = GetEvalStackTopOffset();
  2925. break;
  2926. }
  2927. case 20:
  2928. {
  2929. CreateAddIR(ir, RetVar_ret_20);
  2930. ir->ret = GetEvalStackTopOffset();
  2931. break;
  2932. }
  2933. case 24:
  2934. {
  2935. CreateAddIR(ir, RetVar_ret_24);
  2936. ir->ret = GetEvalStackTopOffset();
  2937. break;
  2938. }
  2939. case 28:
  2940. {
  2941. CreateAddIR(ir, RetVar_ret_28);
  2942. ir->ret = GetEvalStackTopOffset();
  2943. break;
  2944. }
  2945. case 32:
  2946. {
  2947. CreateAddIR(ir, RetVar_ret_32);
  2948. ir->ret = GetEvalStackTopOffset();
  2949. break;
  2950. }
  2951. default:
  2952. {
  2953. CreateAddIR(ir, RetVar_ret_n);
  2954. ir->ret = GetEvalStackTopOffset();
  2955. ir->size = size;
  2956. break;
  2957. }
  2958. }
  2959. }
  2960. ip++;
  2961. PopBranch();
  2962. continue;
  2963. }
  2964. case OpcodeValue::BR_S:
  2965. {
  2966. brOffset = GetI1(ip + 1);
  2967. if (brOffset != 0)
  2968. {
  2969. int32_t targetOffset = ipOffset + brOffset + 2;
  2970. CreateAddIR(ir, BranchUncondition_4);
  2971. ir->offset = targetOffset;
  2972. PushOffset(&ir->offset);
  2973. PushBranch(targetOffset);
  2974. PopBranch();
  2975. }
  2976. else
  2977. {
  2978. ip += 2;
  2979. }
  2980. continue;
  2981. }
  2982. case OpcodeValue::LEAVE_S:
  2983. {
  2984. brOffset = GetI1(ip + 1);
  2985. int32_t targetOffset = ipOffset + brOffset + 2;
  2986. Add_leave((uint32_t)targetOffset);
  2987. PopBranch();
  2988. continue;
  2989. }
  2990. case OpcodeValue::BRFALSE_S:
  2991. {
  2992. IL2CPP_ASSERT(evalStackTop > 0);
  2993. brOffset = GetI1(ip + 1);
  2994. if (brOffset != 0)
  2995. {
  2996. int32_t targetOffset = ipOffset + brOffset + 2;
  2997. Add_brtruefalse(false, targetOffset);
  2998. }
  2999. else
  3000. {
  3001. PopStack();
  3002. }
  3003. ip += 2;
  3004. continue;
  3005. }
  3006. case OpcodeValue::BRTRUE_S:
  3007. {
  3008. IL2CPP_ASSERT(evalStackTop > 0);
  3009. brOffset = GetI1(ip + 1);
  3010. if (brOffset != 0)
  3011. {
  3012. int32_t targetOffset = ipOffset + brOffset + 2;
  3013. Add_brtruefalse(true, targetOffset);
  3014. }
  3015. else
  3016. {
  3017. PopStack();
  3018. }
  3019. ip += 2;
  3020. continue;
  3021. }
  3022. case OpcodeValue::BEQ_S:
  3023. {
  3024. CI_branch1(Ceq);
  3025. continue;
  3026. }
  3027. case OpcodeValue::BGE_S:
  3028. {
  3029. CI_branch1(Cge);
  3030. continue;
  3031. }
  3032. case OpcodeValue::BGT_S:
  3033. {
  3034. CI_branch1(Cgt);
  3035. continue;
  3036. }
  3037. case OpcodeValue::BLE_S:
  3038. {
  3039. CI_branch1(Cle);
  3040. continue;
  3041. }
  3042. case OpcodeValue::BLT_S:
  3043. {
  3044. CI_branch1(Clt);
  3045. continue;
  3046. }
  3047. case OpcodeValue::BNE_UN_S:
  3048. {
  3049. CI_branch1(CneUn);
  3050. continue;
  3051. }
  3052. case OpcodeValue::BGE_UN_S:
  3053. {
  3054. CI_branch1(CgeUn);
  3055. continue;
  3056. }
  3057. case OpcodeValue::BGT_UN_S:
  3058. {
  3059. CI_branch1(CgtUn);
  3060. continue;
  3061. }
  3062. case OpcodeValue::BLE_UN_S:
  3063. {
  3064. CI_branch1(CleUn);
  3065. continue;
  3066. }
  3067. case OpcodeValue::BLT_UN_S:
  3068. {
  3069. CI_branch1(CltUn);
  3070. continue;
  3071. }
  3072. case OpcodeValue::BR:
  3073. {
  3074. brOffset = GetI4LittleEndian(ip + 1);
  3075. if (brOffset != 0)
  3076. {
  3077. int32_t targetOffset = ipOffset + brOffset + 5;
  3078. CreateAddIR(ir, BranchUncondition_4);
  3079. ir->offset = targetOffset;
  3080. PushOffset(&ir->offset);
  3081. PushBranch(targetOffset);
  3082. PopBranch();
  3083. }
  3084. else
  3085. {
  3086. ip += 5;
  3087. }
  3088. continue;
  3089. }
  3090. case OpcodeValue::LEAVE:
  3091. {
  3092. brOffset = GetI4LittleEndian(ip + 1);
  3093. int32_t targetOffset = ipOffset + brOffset + 5;
  3094. Add_leave((uint32_t)targetOffset);
  3095. PopBranch();
  3096. continue;
  3097. }
  3098. case OpcodeValue::BRFALSE:
  3099. {
  3100. IL2CPP_ASSERT(evalStackTop > 0);
  3101. brOffset = GetI4LittleEndian(ip + 1);
  3102. if (brOffset != 0)
  3103. {
  3104. int32_t targetOffset = ipOffset + brOffset + 5;
  3105. Add_brtruefalse(false, targetOffset);
  3106. }
  3107. else
  3108. {
  3109. PopStack();
  3110. }
  3111. ip += 5;
  3112. continue;
  3113. }
  3114. case OpcodeValue::BRTRUE:
  3115. {
  3116. IL2CPP_ASSERT(evalStackTop > 0);
  3117. brOffset = GetI4LittleEndian(ip + 1);
  3118. if (brOffset != 0)
  3119. {
  3120. int32_t targetOffset = ipOffset + brOffset + 5;
  3121. Add_brtruefalse(true, targetOffset);
  3122. }
  3123. else
  3124. {
  3125. PopStack();
  3126. }
  3127. ip += 5;
  3128. continue;
  3129. }
  3130. case OpcodeValue::BEQ:
  3131. {
  3132. CI_branch4(Ceq);
  3133. continue;
  3134. }
  3135. case OpcodeValue::BGE:
  3136. {
  3137. CI_branch4(Cge);
  3138. continue;
  3139. }
  3140. case OpcodeValue::BGT:
  3141. {
  3142. CI_branch4(Cgt);
  3143. continue;
  3144. }
  3145. case OpcodeValue::BLE:
  3146. {
  3147. CI_branch4(Cle);
  3148. continue;
  3149. }
  3150. case OpcodeValue::BLT:
  3151. {
  3152. CI_branch4(Clt);
  3153. continue;
  3154. }
  3155. case OpcodeValue::BNE_UN:
  3156. {
  3157. CI_branch4(CneUn);
  3158. continue;
  3159. }
  3160. case OpcodeValue::BGE_UN:
  3161. {
  3162. CI_branch4(CgeUn);
  3163. continue;
  3164. }
  3165. case OpcodeValue::BGT_UN:
  3166. {
  3167. CI_branch4(CgtUn);
  3168. continue;
  3169. }
  3170. case OpcodeValue::BLE_UN:
  3171. {
  3172. CI_branch4(CleUn);
  3173. continue;
  3174. }
  3175. case OpcodeValue::BLT_UN:
  3176. {
  3177. CI_branch4(CltUn);
  3178. continue;
  3179. }
  3180. case OpcodeValue::SWITCH:
  3181. {
  3182. IL2CPP_ASSERT(evalStackTop > 0);
  3183. CreateIR(ir, BranchSwitch);
  3184. uint32_t switchValue = GetEvalStackTopOffset();
  3185. uint32_t n = (uint32_t)GetI4LittleEndian(ip + 1);
  3186. ir->value = GetEvalStackTopOffset();
  3187. ir->caseNum = n;
  3188. int32_t* caseOffsets;
  3189. AllocResolvedData(resolveDatas, (n + 1) / 2, *(int32_t*)&ir->caseOffsets, caseOffsets);
  3190. PopStack();
  3191. uint32_t instrSize = 1 + (n + 1) * 4;
  3192. const byte* caseOffsetIp = ip + 5;
  3193. // remove this instrument if all target is same to default.
  3194. uint32_t nextInstrumentOffset = ipOffset + instrSize;
  3195. bool anyNotDefaultCase = false;
  3196. for (uint32_t caseIdx = 0; caseIdx < n; caseIdx++)
  3197. {
  3198. int32_t targetOffset = (int32_t)(nextInstrumentOffset + GetI4LittleEndian(caseOffsetIp + caseIdx * 4));
  3199. caseOffsets[caseIdx] = targetOffset;
  3200. //PushOffset(caseOffsets + caseIdx);
  3201. if (targetOffset != nextInstrumentOffset)
  3202. {
  3203. anyNotDefaultCase = true;
  3204. PushBranch(targetOffset);
  3205. }
  3206. }
  3207. if (anyNotDefaultCase)
  3208. {
  3209. switchOffsetsInResolveData.push_back({ ir->caseOffsets, n });
  3210. AddInst(ir);
  3211. }
  3212. ip += instrSize;
  3213. continue;
  3214. }
  3215. case OpcodeValue::LDIND_I1:
  3216. {
  3217. Add_ldind(HiOpcodeEnum::LdindVarVar_i1, EvalStackReduceDataType::I4);
  3218. continue;
  3219. }
  3220. case OpcodeValue::LDIND_U1:
  3221. {
  3222. Add_ldind(HiOpcodeEnum::LdindVarVar_u1, EvalStackReduceDataType::I4);
  3223. continue;
  3224. }
  3225. case OpcodeValue::LDIND_I2:
  3226. {
  3227. Add_ldind(HiOpcodeEnum::LdindVarVar_i2, EvalStackReduceDataType::I4);
  3228. continue;
  3229. }
  3230. case OpcodeValue::LDIND_U2:
  3231. {
  3232. Add_ldind(HiOpcodeEnum::LdindVarVar_u2, EvalStackReduceDataType::I4);
  3233. continue;
  3234. }
  3235. case OpcodeValue::LDIND_I4:
  3236. {
  3237. Add_ldind(HiOpcodeEnum::LdindVarVar_i4, EvalStackReduceDataType::I4);
  3238. continue;
  3239. }
  3240. case OpcodeValue::LDIND_U4:
  3241. {
  3242. Add_ldind(HiOpcodeEnum::LdindVarVar_u4, EvalStackReduceDataType::I4);
  3243. continue;
  3244. }
  3245. case OpcodeValue::LDIND_I8:
  3246. {
  3247. Add_ldind(HiOpcodeEnum::LdindVarVar_i8, EvalStackReduceDataType::I8);
  3248. continue;
  3249. }
  3250. case OpcodeValue::LDIND_I:
  3251. {
  3252. Add_ldind(ARCH_ARGUMENT(HiOpcodeEnum::LdindVarVar_i4, HiOpcodeEnum::LdindVarVar_i8), NATIVE_INT_REDUCE_TYPE);
  3253. continue;
  3254. }
  3255. case OpcodeValue::LDIND_R4:
  3256. {
  3257. Add_ldind(HiOpcodeEnum::LdindVarVar_f4, EvalStackReduceDataType::R4);
  3258. continue;
  3259. }
  3260. case OpcodeValue::LDIND_R8:
  3261. {
  3262. Add_ldind(HiOpcodeEnum::LdindVarVar_f8, EvalStackReduceDataType::R8);
  3263. continue;
  3264. }
  3265. case OpcodeValue::LDIND_REF:
  3266. {
  3267. Add_ldind(ARCH_ARGUMENT(HiOpcodeEnum::LdindVarVar_i4, HiOpcodeEnum::LdindVarVar_i8), NATIVE_INT_REDUCE_TYPE);
  3268. continue;
  3269. }
  3270. case OpcodeValue::STIND_REF:
  3271. {
  3272. Add_stind(HiOpcodeEnum::StindVarVar_ref);
  3273. continue;
  3274. }
  3275. case OpcodeValue::STIND_I1:
  3276. {
  3277. Add_stind(HiOpcodeEnum::StindVarVar_i1);
  3278. continue;
  3279. }
  3280. case OpcodeValue::STIND_I2:
  3281. {
  3282. Add_stind(HiOpcodeEnum::StindVarVar_i2);
  3283. continue;
  3284. }
  3285. case OpcodeValue::STIND_I4:
  3286. {
  3287. Add_stind(HiOpcodeEnum::StindVarVar_i4);
  3288. continue;
  3289. }
  3290. case OpcodeValue::STIND_I8:
  3291. {
  3292. Add_stind(HiOpcodeEnum::StindVarVar_i8);
  3293. continue;
  3294. }
  3295. case OpcodeValue::STIND_R4:
  3296. {
  3297. Add_stind(HiOpcodeEnum::StindVarVar_f4);
  3298. continue;
  3299. }
  3300. case OpcodeValue::STIND_R8:
  3301. {
  3302. Add_stind(HiOpcodeEnum::StindVarVar_f8);
  3303. continue;
  3304. }
  3305. case OpcodeValue::ADD:
  3306. {
  3307. CI_binOp(Add);
  3308. continue;
  3309. }
  3310. case OpcodeValue::SUB:
  3311. {
  3312. CI_binOp(Sub);
  3313. continue;
  3314. }
  3315. case OpcodeValue::MUL:
  3316. {
  3317. CI_binOp(Mul);
  3318. continue;
  3319. }
  3320. case OpcodeValue::DIV:
  3321. {
  3322. CI_binOp(Div);
  3323. continue;
  3324. }
  3325. case OpcodeValue::DIV_UN:
  3326. {
  3327. CI_binOpUn(DivUn);
  3328. continue;
  3329. }
  3330. case OpcodeValue::REM:
  3331. {
  3332. CI_binOp(Rem);
  3333. continue;
  3334. }
  3335. case OpcodeValue::REM_UN:
  3336. {
  3337. CI_binOpUn(RemUn);
  3338. continue;
  3339. }
  3340. case OpcodeValue::AND:
  3341. {
  3342. CI_binOpUn(And);
  3343. continue;
  3344. }
  3345. case OpcodeValue::OR:
  3346. {
  3347. CI_binOpUn(Or);
  3348. continue;
  3349. }
  3350. case OpcodeValue::XOR:
  3351. {
  3352. CI_binOpUn(Xor);
  3353. continue;
  3354. }
  3355. case OpcodeValue::SHL:
  3356. {
  3357. CI_binOpShift(Shl);
  3358. continue;
  3359. }
  3360. case OpcodeValue::SHR:
  3361. {
  3362. CI_binOpShift(Shr);
  3363. continue;
  3364. }
  3365. case OpcodeValue::SHR_UN:
  3366. {
  3367. CI_binOpShift(ShrUn);
  3368. continue;
  3369. }
  3370. case OpcodeValue::NEG:
  3371. {
  3372. IL2CPP_ASSERT(evalStackTop > 0);
  3373. EvalStackVarInfo& op = evalStack[evalStackTop - 1];
  3374. CreateAddIR(ir, UnaryOpVarVar_Neg_i4);
  3375. ir->dst = ir->src = op.locOffset;
  3376. switch (op.reduceType)
  3377. {
  3378. case EvalStackReduceDataType::I4:
  3379. {
  3380. ir->type = HiOpcodeEnum::UnaryOpVarVar_Neg_i4;
  3381. break;
  3382. }
  3383. case EvalStackReduceDataType::I8:
  3384. {
  3385. ir->type = HiOpcodeEnum::UnaryOpVarVar_Neg_i8;
  3386. break;
  3387. }
  3388. case EvalStackReduceDataType::R4:
  3389. {
  3390. ir->type = HiOpcodeEnum::UnaryOpVarVar_Neg_f4;
  3391. break;
  3392. }
  3393. case EvalStackReduceDataType::R8:
  3394. {
  3395. ir->type = HiOpcodeEnum::UnaryOpVarVar_Neg_f8;
  3396. break;
  3397. }
  3398. default:
  3399. {
  3400. RaiseExecutionEngineException("NEG not suppport type");
  3401. break;
  3402. }
  3403. }
  3404. ip++;
  3405. continue;
  3406. }
  3407. case OpcodeValue::NOT:
  3408. {
  3409. IL2CPP_ASSERT(evalStackTop > 0);
  3410. EvalStackVarInfo& op = evalStack[evalStackTop - 1];
  3411. CreateAddIR(ir, UnaryOpVarVar_Not_i4);
  3412. ir->dst = ir->src = op.locOffset;
  3413. switch (op.reduceType)
  3414. {
  3415. case EvalStackReduceDataType::I4:
  3416. {
  3417. ir->type = HiOpcodeEnum::UnaryOpVarVar_Not_i4;
  3418. break;
  3419. }
  3420. case EvalStackReduceDataType::I8:
  3421. {
  3422. ir->type = HiOpcodeEnum::UnaryOpVarVar_Not_i8;
  3423. break;
  3424. }
  3425. default:
  3426. {
  3427. RaiseExecutionEngineException("NOT not suppport type");
  3428. break;
  3429. }
  3430. }
  3431. ip++;
  3432. continue;
  3433. }
  3434. case OpcodeValue::CONV_I1:
  3435. {
  3436. CI_conv(i1, I4, 4);
  3437. continue;
  3438. }
  3439. case OpcodeValue::CONV_I2:
  3440. {
  3441. CI_conv(i2, I4, 4);
  3442. continue;
  3443. }
  3444. case OpcodeValue::CONV_I4:
  3445. {
  3446. CI_conv(i4, I4, 4);
  3447. continue;
  3448. }
  3449. case OpcodeValue::CONV_I8:
  3450. {
  3451. CI_conv(i8, I8, 8);
  3452. continue;
  3453. }
  3454. case OpcodeValue::CONV_R4:
  3455. {
  3456. CI_conv(f4, R4, 4);
  3457. continue;
  3458. }
  3459. case OpcodeValue::CONV_R8:
  3460. {
  3461. CI_conv(f8, R8, 8);
  3462. continue;
  3463. }
  3464. case OpcodeValue::CONV_U4:
  3465. {
  3466. CI_conv(u4, I4, 4);
  3467. continue;
  3468. }
  3469. case OpcodeValue::CONV_U8:
  3470. {
  3471. CI_conv(u8, I8, 8);
  3472. continue;
  3473. }
  3474. case OpcodeValue::CPOBJ:
  3475. {
  3476. IL2CPP_ASSERT(evalStackTop >= 2);
  3477. EvalStackVarInfo& dst = evalStack[evalStackTop - 2];
  3478. EvalStackVarInfo& src = evalStack[evalStackTop - 1];
  3479. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3480. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  3481. IL2CPP_ASSERT(objKlass);
  3482. if (IS_CLASS_VALUE_TYPE(objKlass))
  3483. {
  3484. uint32_t size = GetTypeValueSize(objKlass);
  3485. if (!HYBRIDCLR_ENABLE_WRITE_BARRIERS || !objKlass->has_references)
  3486. {
  3487. switch (size)
  3488. {
  3489. case 1:
  3490. {
  3491. CreateAddIR(ir, CpobjVarVar_1);
  3492. ir->dst = dst.locOffset;
  3493. ir->src = src.locOffset;
  3494. break;
  3495. }
  3496. case 2:
  3497. {
  3498. CreateAddIR(ir, CpobjVarVar_2);
  3499. ir->dst = dst.locOffset;
  3500. ir->src = src.locOffset;
  3501. break;
  3502. }
  3503. case 4:
  3504. {
  3505. CreateAddIR(ir, CpobjVarVar_4);
  3506. ir->dst = dst.locOffset;
  3507. ir->src = src.locOffset;
  3508. break;
  3509. }
  3510. case 8:
  3511. {
  3512. CreateAddIR(ir, CpobjVarVar_8);
  3513. ir->dst = dst.locOffset;
  3514. ir->src = src.locOffset;
  3515. break;
  3516. }
  3517. case 12:
  3518. {
  3519. CreateAddIR(ir, CpobjVarVar_12);
  3520. ir->dst = dst.locOffset;
  3521. ir->src = src.locOffset;
  3522. break;
  3523. }
  3524. case 16:
  3525. {
  3526. CreateAddIR(ir, CpobjVarVar_16);
  3527. ir->dst = dst.locOffset;
  3528. ir->src = src.locOffset;
  3529. break;
  3530. }
  3531. default:
  3532. {
  3533. CreateAddIR(ir, CpobjVarVar_n_4);
  3534. ir->dst = dst.locOffset;
  3535. ir->src = src.locOffset;
  3536. ir->size = size;
  3537. break;
  3538. }
  3539. }
  3540. }
  3541. else
  3542. {
  3543. CreateAddIR(ir, CpobjVarVar_WriteBarrier_n_4);
  3544. ir->dst = dst.locOffset;
  3545. ir->src = src.locOffset;
  3546. ir->size = size;
  3547. }
  3548. }
  3549. else
  3550. {
  3551. CreateAddIR(ir, CpobjVarVar_ref);
  3552. ir->dst = dst.locOffset;
  3553. ir->src = src.locOffset;
  3554. }
  3555. PopStackN(2);
  3556. ip += 5;
  3557. continue;
  3558. }
  3559. case OpcodeValue::LDOBJ:
  3560. {
  3561. IL2CPP_ASSERT(evalStackTop >= 1);
  3562. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  3563. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3564. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  3565. IL2CPP_ASSERT(objKlass);
  3566. LocationDescInfo desc = ComputLocationDescInfo(&objKlass->byval_arg);
  3567. switch (desc.type)
  3568. {
  3569. case LocationDescType::I1:
  3570. {
  3571. CreateAddIR(ir, LdindVarVar_i1);
  3572. ir->dst = ir->src = top.locOffset;
  3573. break;
  3574. }
  3575. case LocationDescType::U1:
  3576. {
  3577. CreateAddIR(ir, LdindVarVar_u1);
  3578. ir->dst = ir->src = top.locOffset;
  3579. break;
  3580. }
  3581. case LocationDescType::I2:
  3582. {
  3583. CreateAddIR(ir, LdindVarVar_i2);
  3584. ir->dst = ir->src = top.locOffset;
  3585. break;
  3586. }
  3587. case LocationDescType::U2:
  3588. {
  3589. CreateAddIR(ir, LdindVarVar_u2);
  3590. ir->dst = ir->src = top.locOffset;
  3591. break;
  3592. }
  3593. case LocationDescType::I4:
  3594. {
  3595. CreateAddIR(ir, LdindVarVar_i4);
  3596. ir->dst = ir->src = top.locOffset;
  3597. break;
  3598. }
  3599. case LocationDescType::I8:
  3600. {
  3601. CreateAddIR(ir, LdindVarVar_i8);
  3602. ir->dst = ir->src = top.locOffset;
  3603. break;
  3604. }
  3605. case LocationDescType::Ref:
  3606. {
  3607. CreateAddIR(ir, LdobjVarVar_ref);
  3608. ir->dst = ir->src = top.locOffset;
  3609. break;
  3610. }
  3611. case LocationDescType::S:
  3612. case LocationDescType::StructContainsRef:
  3613. {
  3614. uint32_t size = GetTypeValueSize(objKlass);
  3615. switch (size)
  3616. {
  3617. case 1:
  3618. {
  3619. CreateAddIR(ir, LdobjVarVar_1);
  3620. ir->dst = ir->src = top.locOffset;
  3621. break;
  3622. }
  3623. case 2:
  3624. {
  3625. CreateAddIR(ir, LdobjVarVar_2);
  3626. ir->dst = ir->src = top.locOffset;
  3627. break;
  3628. }
  3629. case 4:
  3630. {
  3631. CreateAddIR(ir, LdobjVarVar_4);
  3632. ir->dst = ir->src = top.locOffset;
  3633. break;
  3634. }
  3635. case 8:
  3636. {
  3637. CreateAddIR(ir, LdobjVarVar_8);
  3638. ir->dst = ir->src = top.locOffset;
  3639. break;
  3640. }
  3641. case 12:
  3642. {
  3643. CreateAddIR(ir, LdobjVarVar_12);
  3644. ir->dst = ir->src = top.locOffset;
  3645. break;
  3646. }
  3647. case 16:
  3648. {
  3649. CreateAddIR(ir, LdobjVarVar_16);
  3650. ir->dst = ir->src = top.locOffset;
  3651. break;
  3652. }
  3653. default:
  3654. {
  3655. CreateAddIR(ir, LdobjVarVar_n_4);
  3656. ir->dst = ir->src = top.locOffset;
  3657. ir->size = size;
  3658. break;
  3659. }
  3660. }
  3661. break;
  3662. }
  3663. default:
  3664. {
  3665. RaiseExecutionEngineException("field");
  3666. }
  3667. }
  3668. PopStack();
  3669. PushStackByType(&objKlass->byval_arg);
  3670. InsertMemoryBarrier();
  3671. ResetPrefixFlags();
  3672. ip += 5;
  3673. continue;
  3674. }
  3675. case OpcodeValue::LDSTR:
  3676. {
  3677. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3678. Il2CppString* str = image->GetIl2CppUserStringFromRawIndex(DecodeTokenRowIndex(token));
  3679. uint32_t dataIdx = GetOrAddResolveDataIndex(str);
  3680. CreateAddIR(ir, LdstrVar);
  3681. ir->dst = GetEvalStackNewTopOffset();
  3682. ir->str = dataIdx;
  3683. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3684. ip += 5;
  3685. continue;
  3686. }
  3687. case OpcodeValue::NEWOBJ:
  3688. {
  3689. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3690. ip += 5;
  3691. // TODO token cache optimistic
  3692. shareMethod = const_cast<MethodInfo*>(image->GetMethodInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3693. IL2CPP_ASSERT(shareMethod);
  3694. IL2CPP_ASSERT(!std::strcmp(shareMethod->name, ".ctor"));
  3695. IL2CPP_ASSERT(hybridclr::metadata::IsInstanceMethod(shareMethod));
  3696. if (TryAddInstinctCtorInstruments(shareMethod))
  3697. {
  3698. continue;
  3699. }
  3700. Il2CppClass* klass = shareMethod->klass;
  3701. uint8_t paramCount = shareMethod->parameters_count;
  3702. if (klass == il2cpp_defaults.string_class)
  3703. {
  3704. const MethodInfo* searchMethod = FindRedirectCreateString(shareMethod);
  3705. if (searchMethod)
  3706. {
  3707. // insert nullptr to eval stack
  3708. int32_t thisIdx = evalStackTop - paramCount;
  3709. for (int32_t i = evalStackTop; i > thisIdx; i--)
  3710. {
  3711. evalStack[i] = evalStack[i - 1];
  3712. }
  3713. // locOffset of this is not important. You only need make sure the value is not equal to nullptr.
  3714. evalStack[thisIdx] = { NATIVE_INT_REDUCE_TYPE, PTR_SIZE, GetEvalStackOffset(thisIdx) };
  3715. ++evalStackTop;
  3716. shareMethod = searchMethod;
  3717. goto LabelCall;
  3718. }
  3719. }
  3720. if (!InitAndGetInterpreterDirectlyCallMethodPointer(shareMethod))
  3721. {
  3722. RaiseAOTGenericMethodNotInstantiatedException(shareMethod);
  3723. }
  3724. int32_t callArgEvalStackIdxBase = evalStackTop - shareMethod->parameters_count;
  3725. IL2CPP_ASSERT(callArgEvalStackIdxBase >= 0);
  3726. uint16_t objIdx = GetEvalStackOffset(callArgEvalStackIdxBase);
  3727. int32_t resolvedTotalArgNum = shareMethod->parameters_count + 1;
  3728. uint32_t methodDataIndex = GetOrAddResolveDataIndex(shareMethod);
  3729. if (IsInterpreterImplement(shareMethod))
  3730. {
  3731. if (IS_CLASS_VALUE_TYPE(klass))
  3732. {
  3733. CreateAddIR(ir, NewValueTypeInterpVar);
  3734. ir->obj = GetEvalStackOffset(callArgEvalStackIdxBase);
  3735. ir->method = methodDataIndex;
  3736. ir->argBase = ir->obj;
  3737. ir->argStackObjectNum = curStackSize - ir->argBase;
  3738. // IL2CPP_ASSERT(ir->argStackObjectNum > 0); may 0
  3739. PopStackN(shareMethod->parameters_count);
  3740. PushStackByType(&klass->byval_arg);
  3741. ir->ctorFrameBase = GetEvalStackNewTopOffset();
  3742. maxStackSize = std::max(maxStackSize, curStackSize + ir->argStackObjectNum + 1);
  3743. }
  3744. else
  3745. {
  3746. if (shareMethod->parameters_count == 0)
  3747. {
  3748. CreateAddIR(ir, NewClassInterpVar_Ctor_0);
  3749. ir->obj = GetEvalStackNewTopOffset();
  3750. ir->method = methodDataIndex;
  3751. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3752. ir->ctorFrameBase = GetEvalStackNewTopOffset();
  3753. maxStackSize = std::max(maxStackSize, curStackSize + 1); // 1 for __this
  3754. }
  3755. else
  3756. {
  3757. CreateAddIR(ir, NewClassInterpVar);
  3758. ir->obj = GetEvalStackOffset(callArgEvalStackIdxBase);
  3759. ir->method = methodDataIndex;
  3760. ir->argBase = ir->obj;
  3761. ir->argStackObjectNum = curStackSize - ir->argBase;
  3762. IL2CPP_ASSERT(ir->argStackObjectNum > 0);
  3763. PopStackN(shareMethod->parameters_count);
  3764. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3765. ir->ctorFrameBase = GetEvalStackNewTopOffset();
  3766. maxStackSize = std::max(maxStackSize, curStackSize + ir->argStackObjectNum + 1); // 1 for __this
  3767. }
  3768. }
  3769. IL2CPP_ASSERT(maxStackSize < MAX_STACK_SIZE);
  3770. continue;
  3771. }
  3772. // optimize when argv == 0
  3773. if (shareMethod->parameters_count == 0 && !IS_CLASS_VALUE_TYPE(klass))
  3774. {
  3775. CreateAddIR(ir, NewClassVar_Ctor_0);
  3776. ir->method = methodDataIndex;
  3777. ir->obj = GetEvalStackNewTopOffset();
  3778. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3779. continue;
  3780. }
  3781. int32_t needDataSlotNum = (resolvedTotalArgNum + 3) / 4;
  3782. Managed2NativeCallMethod managed2NativeMethod = InterpreterModule::GetManaged2NativeMethodPointer(shareMethod, false);
  3783. IL2CPP_ASSERT((void*)managed2NativeMethod);
  3784. //uint32_t managed2NativeMethodDataIdx = GetOrAddResolveDataIndex(managed2NativeMethod);
  3785. int32_t argIdxDataIndex;
  3786. uint16_t* __argIdxs;
  3787. AllocResolvedData(resolveDatas, needDataSlotNum, argIdxDataIndex, __argIdxs);
  3788. //
  3789. // arg1, arg2, arg3 ..., argN, obj or valuetype, __this(= obj or ref valuetype)
  3790. // obj on new top
  3791. PushStackByType(&klass->byval_arg);
  3792. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3793. __argIdxs[0] = GetEvalStackTopOffset(); // this
  3794. for (uint8_t i = 0; i < shareMethod->parameters_count; i++)
  3795. {
  3796. int32_t curArgIdx = i + 1;
  3797. __argIdxs[curArgIdx] = evalStack[callArgEvalStackIdxBase + i].locOffset;
  3798. }
  3799. PopStackN(resolvedTotalArgNum + 1); // args + obj + this
  3800. PushStackByType(&klass->byval_arg);
  3801. CreateAddIR(ir, NewClassVar);
  3802. ir->type = IS_CLASS_VALUE_TYPE(shareMethod->klass) ? HiOpcodeEnum::NewValueTypeVar : HiOpcodeEnum::NewClassVar;
  3803. ir->managed2NativeMethod = GetOrAddResolveDataIndex((void*)managed2NativeMethod);
  3804. ir->method = methodDataIndex;
  3805. ir->argIdxs = argIdxDataIndex;
  3806. ir->obj = objIdx;
  3807. continue;
  3808. }
  3809. case OpcodeValue::CASTCLASS:
  3810. {
  3811. IL2CPP_ASSERT(evalStackTop > 0);
  3812. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3813. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  3814. IL2CPP_ASSERT(objKlass);
  3815. if (il2cpp::vm::Class::IsNullable(objKlass))
  3816. {
  3817. objKlass = il2cpp::vm::Class::GetNullableArgument(objKlass);
  3818. }
  3819. uint32_t klassDataIdx = GetOrAddResolveDataIndex(objKlass);
  3820. CreateAddIR(ir, CastclassVar);
  3821. ir->obj = GetEvalStackTopOffset();
  3822. ir->klass = klassDataIdx;
  3823. ip += 5;
  3824. continue;
  3825. }
  3826. case OpcodeValue::ISINST:
  3827. {
  3828. IL2CPP_ASSERT(evalStackTop > 0);
  3829. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3830. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  3831. IL2CPP_ASSERT(objKlass);
  3832. if (il2cpp::vm::Class::IsNullable(objKlass))
  3833. {
  3834. objKlass = il2cpp::vm::Class::GetNullableArgument(objKlass);
  3835. }
  3836. uint32_t klassDataIdx = GetOrAddResolveDataIndex(objKlass);
  3837. CreateAddIR(ir, IsInstVar);
  3838. ir->obj = GetEvalStackTopOffset();
  3839. ir->klass = klassDataIdx;
  3840. ip += 5;
  3841. continue;
  3842. }
  3843. case OpcodeValue::CONV_R_UN:
  3844. {
  3845. IL2CPP_ASSERT(evalStackTop > 0);
  3846. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  3847. switch (top.reduceType)
  3848. {
  3849. case EvalStackReduceDataType::I4:
  3850. {
  3851. CreateAddIR(ir, ConvertVarVar_u4_f8);
  3852. ir->dst = ir->src = GetEvalStackTopOffset();
  3853. break;
  3854. }
  3855. case EvalStackReduceDataType::I8:
  3856. {
  3857. CreateAddIR(ir, ConvertVarVar_u8_f8);
  3858. ir->dst = ir->src = GetEvalStackTopOffset();
  3859. break;
  3860. }
  3861. default:
  3862. {
  3863. RaiseExecutionEngineException("");
  3864. break;
  3865. }
  3866. }
  3867. top.reduceType = EvalStackReduceDataType::R8;
  3868. top.byteSize = 8;
  3869. ip++;
  3870. continue;
  3871. }
  3872. case OpcodeValue::UNBOX:
  3873. {
  3874. IL2CPP_ASSERT(evalStackTop > 0);
  3875. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3876. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  3877. //if (il2cpp::vm::Class::IsNullable(objKlass))
  3878. //{
  3879. // objKlass = il2cpp::vm::Class::GetNullableArgument(objKlass);
  3880. //}
  3881. CreateAddIR(ir, UnBoxVarVar);
  3882. ir->addr = ir->obj = GetEvalStackTopOffset();
  3883. ir->klass = GetOrAddResolveDataIndex(objKlass);
  3884. PopStack();
  3885. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3886. ip += 5;
  3887. continue;
  3888. }
  3889. case OpcodeValue::THROW:
  3890. {
  3891. IL2CPP_ASSERT(evalStackTop > 0);
  3892. CreateAddIR(ir, ThrowEx);
  3893. ir->exceptionObj = GetEvalStackTopOffset();
  3894. ir->firstHandlerIndex = FindFirstThrowHandlerIndex(body.exceptionClauses, ipOffset);
  3895. PopAllStack();
  3896. PopBranch();
  3897. continue;
  3898. }
  3899. case OpcodeValue::LDFLD:
  3900. {
  3901. IL2CPP_ASSERT(evalStackTop > 0);
  3902. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3903. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3904. IL2CPP_ASSERT(fieldInfo);
  3905. // ldfld obj may be obj or or valuetype or ref valuetype....
  3906. EvalStackVarInfo& obj = evalStack[evalStackTop - 1];
  3907. uint16_t topIdx = GetEvalStackTopOffset();
  3908. IRCommon* ir = obj.reduceType != NATIVE_INT_REDUCE_TYPE && IS_CLASS_VALUE_TYPE(fieldInfo->parent) ? CreateValueTypeLdfld(pool, topIdx, topIdx, fieldInfo) : CreateClassLdfld(pool, topIdx, topIdx, fieldInfo);
  3909. AddInst(ir);
  3910. PopStack();
  3911. PushStackByType(fieldInfo->type);
  3912. InsertMemoryBarrier();
  3913. ResetPrefixFlags();
  3914. ip += 5;
  3915. continue;
  3916. }
  3917. case OpcodeValue::LDFLDA:
  3918. {
  3919. IL2CPP_ASSERT(evalStackTop > 0);
  3920. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3921. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3922. IL2CPP_ASSERT(fieldInfo);
  3923. uint16_t topIdx = GetEvalStackTopOffset();
  3924. CreateAddIR(ir, LdfldaVarVar);
  3925. ir->dst = topIdx;
  3926. ir->obj = topIdx;
  3927. ir->offset = GetFieldOffset(fieldInfo);
  3928. PopStack();
  3929. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  3930. ip += 5;
  3931. continue;
  3932. }
  3933. case OpcodeValue::STFLD:
  3934. {
  3935. InsertMemoryBarrier();
  3936. ResetPrefixFlags();
  3937. IL2CPP_ASSERT(evalStackTop >= 2);
  3938. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3939. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3940. IL2CPP_ASSERT(fieldInfo);
  3941. IRCommon* ir = CreateStfld(pool, GetEvalStackOffset_2(), fieldInfo, GetEvalStackOffset_1());
  3942. AddInst(ir);
  3943. PopStackN(2);
  3944. ip += 5;
  3945. continue;
  3946. }
  3947. case OpcodeValue::LDSFLD:
  3948. {
  3949. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3950. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3951. IL2CPP_ASSERT(fieldInfo);
  3952. uint32_t parentIndex = GetOrAddResolveDataIndex(fieldInfo->parent);
  3953. uint16_t dstIdx = GetEvalStackNewTopOffset();
  3954. IRCommon* ir = fieldInfo->offset != THREAD_STATIC_FIELD_OFFSET ?
  3955. CreateLdsfld(pool, dstIdx, fieldInfo, parentIndex)
  3956. : CreateLdthreadlocal(pool, dstIdx, fieldInfo, parentIndex);
  3957. AddInst(ir);
  3958. PushStackByType(fieldInfo->type);
  3959. InsertMemoryBarrier();
  3960. ResetPrefixFlags();
  3961. ip += 5;
  3962. continue;
  3963. }
  3964. case OpcodeValue::LDSFLDA:
  3965. {
  3966. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  3967. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  3968. IL2CPP_ASSERT(fieldInfo);
  3969. uint16_t dstIdx = GetEvalStackNewTopOffset();
  3970. if (fieldInfo->offset != THREAD_STATIC_FIELD_OFFSET)
  3971. {
  3972. bool ldfldFromFieldData = false;
  3973. if (hybridclr::metadata::IsInterpreterType(fieldInfo->parent))
  3974. {
  3975. const FieldDetail& fieldDet = hybridclr::metadata::MetadataModule::GetImage(fieldInfo->parent)
  3976. ->GetFieldDetailFromRawIndex(hybridclr::metadata::DecodeTokenRowIndex(fieldInfo->token - 1));
  3977. if (fieldDet.defaultValueIndex != kDefaultValueIndexNull)
  3978. {
  3979. ldfldFromFieldData = true;
  3980. CreateAddIR(ir, LdsfldaFromFieldDataVarVar);
  3981. ir->dst = dstIdx;
  3982. ir->src = GetOrAddResolveDataIndex(il2cpp::vm::Field::GetData(fieldInfo));
  3983. }
  3984. }
  3985. if (!ldfldFromFieldData)
  3986. {
  3987. CreateAddIR(ir, LdsfldaVarVar);
  3988. ir->dst = dstIdx;
  3989. ir->klass = GetOrAddResolveDataIndex(fieldInfo->parent);
  3990. ir->offset = fieldInfo->offset;
  3991. }
  3992. }
  3993. else
  3994. {
  3995. CreateAddIR(ir, LdthreadlocalaVarVar);
  3996. ir->dst = dstIdx;
  3997. ir->klass = GetOrAddResolveDataIndex(fieldInfo->parent);
  3998. ir->offset = GetThreadStaticFieldOffset(fieldInfo);
  3999. }
  4000. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4001. ip += 5;
  4002. continue;
  4003. }
  4004. case OpcodeValue::STSFLD:
  4005. {
  4006. InsertMemoryBarrier();
  4007. ResetPrefixFlags();
  4008. IL2CPP_ASSERT(evalStackTop >= 1);
  4009. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4010. FieldInfo* fieldInfo = const_cast<FieldInfo*>(image->GetFieldInfoFromToken(tokenCache, token, klassContainer, methodContainer, genericContext));
  4011. IL2CPP_ASSERT(fieldInfo);
  4012. uint32_t klassIndex = GetOrAddResolveDataIndex(fieldInfo->parent);
  4013. uint16_t dataIdx = GetEvalStackTopOffset();
  4014. IRCommon* ir = fieldInfo->offset != THREAD_STATIC_FIELD_OFFSET ?
  4015. CreateStsfld(pool, fieldInfo, klassIndex, dataIdx)
  4016. : CreateStthreadlocal(pool, fieldInfo, klassIndex, dataIdx);
  4017. AddInst(ir);
  4018. PopStack();
  4019. ip += 5;
  4020. continue;
  4021. }
  4022. case OpcodeValue::STOBJ:
  4023. {
  4024. InsertMemoryBarrier();
  4025. ResetPrefixFlags();
  4026. IL2CPP_ASSERT(evalStackTop >= 2);
  4027. EvalStackVarInfo& dst = evalStack[evalStackTop - 2];
  4028. EvalStackVarInfo& src = evalStack[evalStackTop - 1];
  4029. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4030. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4031. IL2CPP_ASSERT(objKlass);
  4032. if (IS_CLASS_VALUE_TYPE(objKlass))
  4033. {
  4034. uint32_t size = GetTypeValueSize(objKlass);
  4035. if (!HYBRIDCLR_ENABLE_WRITE_BARRIERS || !objKlass->has_references)
  4036. {
  4037. switch (size)
  4038. {
  4039. case 1:
  4040. {
  4041. CreateAddIR(ir, StobjVarVar_1);
  4042. ir->dst = dst.locOffset;
  4043. ir->src = src.locOffset;
  4044. break;
  4045. }
  4046. case 2:
  4047. {
  4048. CreateAddIR(ir, StobjVarVar_2);
  4049. ir->dst = dst.locOffset;
  4050. ir->src = src.locOffset;
  4051. break;
  4052. }
  4053. case 4:
  4054. {
  4055. CreateAddIR(ir, StobjVarVar_4);
  4056. ir->dst = dst.locOffset;
  4057. ir->src = src.locOffset;
  4058. break;
  4059. }
  4060. case 8:
  4061. {
  4062. CreateAddIR(ir, StobjVarVar_8);
  4063. ir->dst = dst.locOffset;
  4064. ir->src = src.locOffset;
  4065. break;
  4066. }
  4067. case 12:
  4068. {
  4069. CreateAddIR(ir, StobjVarVar_12);
  4070. ir->dst = dst.locOffset;
  4071. ir->src = src.locOffset;
  4072. break;
  4073. }
  4074. case 16:
  4075. {
  4076. CreateAddIR(ir, StobjVarVar_16);
  4077. ir->dst = dst.locOffset;
  4078. ir->src = src.locOffset;
  4079. break;
  4080. }
  4081. default:
  4082. {
  4083. CreateAddIR(ir, StobjVarVar_n_4);
  4084. ir->dst = dst.locOffset;
  4085. ir->src = src.locOffset;
  4086. ir->size = size;
  4087. break;
  4088. }
  4089. }
  4090. }
  4091. else
  4092. {
  4093. CreateAddIR(ir, StobjVarVar_WriteBarrier_n_4);
  4094. ir->dst = dst.locOffset;
  4095. ir->src = src.locOffset;
  4096. ir->size = size;
  4097. }
  4098. }
  4099. else
  4100. {
  4101. CreateAddIR(ir, StobjVarVar_ref);
  4102. ir->dst = dst.locOffset;
  4103. ir->src = src.locOffset;
  4104. }
  4105. PopStackN(2);
  4106. ip += 5;
  4107. continue;
  4108. }
  4109. case OpcodeValue::CONV_OVF_I1_UN:
  4110. {
  4111. CI_conv_un_ovf(i1, I4, 4);
  4112. continue;
  4113. }
  4114. case OpcodeValue::CONV_OVF_I2_UN:
  4115. {
  4116. CI_conv_un_ovf(i2, I4, 4);
  4117. continue;
  4118. }
  4119. case OpcodeValue::CONV_OVF_I4_UN:
  4120. {
  4121. CI_conv_un_ovf(i4, I4, 4);
  4122. continue;
  4123. }
  4124. case OpcodeValue::CONV_OVF_I8_UN:
  4125. {
  4126. CI_conv_un_ovf(i8, I8, 8);
  4127. continue;
  4128. }
  4129. case OpcodeValue::CONV_OVF_U1_UN:
  4130. {
  4131. CI_conv_un_ovf(u1, I4, 4);
  4132. continue;
  4133. }
  4134. case OpcodeValue::CONV_OVF_U2_UN:
  4135. {
  4136. CI_conv_un_ovf(u2, I4, 4);
  4137. continue;
  4138. }
  4139. case OpcodeValue::CONV_OVF_U4_UN:
  4140. {
  4141. CI_conv_un_ovf(u4, I4, 4);
  4142. continue;
  4143. }
  4144. case OpcodeValue::CONV_OVF_U8_UN:
  4145. {
  4146. CI_conv_un_ovf(u8, I8, 8);
  4147. continue;
  4148. }
  4149. case OpcodeValue::CONV_OVF_I_UN:
  4150. {
  4151. #if HYBRIDCLR_ARCH_64
  4152. CI_conv_un_ovf(i8, I8, 8);
  4153. #else
  4154. CI_conv_un_ovf(i4, I4, 4);
  4155. #endif
  4156. continue;
  4157. }
  4158. case OpcodeValue::CONV_OVF_U_UN:
  4159. {
  4160. #if HYBRIDCLR_ARCH_64
  4161. CI_conv_un_ovf(u8, I8, 8);
  4162. #else
  4163. CI_conv_un_ovf(u4, I4, 4);
  4164. #endif
  4165. continue;
  4166. }
  4167. case OpcodeValue::BOX:
  4168. {
  4169. IL2CPP_ASSERT(evalStackTop > 0);
  4170. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4171. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4172. /* if (il2cpp::vm::Class::IsNullable(objKlass))
  4173. {
  4174. objKlass = il2cpp::vm::Class::GetNullableArgument(objKlass);
  4175. }*/
  4176. PopStack();
  4177. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4178. if (IS_CLASS_VALUE_TYPE(objKlass))
  4179. {
  4180. CreateAddIR(ir, BoxVarVar);
  4181. ir->dst = ir->data = GetEvalStackTopOffset();
  4182. ir->klass = GetOrAddResolveDataIndex(objKlass);
  4183. }
  4184. else
  4185. {
  4186. // ignore class
  4187. }
  4188. ip += 5;
  4189. continue;
  4190. }
  4191. case OpcodeValue::NEWARR:
  4192. {
  4193. IL2CPP_ASSERT(evalStackTop > 0);
  4194. EvalStackVarInfo& varSize = evalStack[evalStackTop - 1];
  4195. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4196. Il2CppClass* eleKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4197. IL2CPP_ASSERT(eleKlass);
  4198. Il2CppClass* arrKlass = il2cpp::vm::Class::GetArrayClass(eleKlass, 1);
  4199. uint32_t arrKlassIndex = GetOrAddResolveDataIndex(arrKlass);
  4200. CreateAddIR(ir, NewArrVarVar);
  4201. ir->arr = ir->size = varSize.locOffset;
  4202. ir->klass = arrKlassIndex;
  4203. PopStack();
  4204. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4205. ip += 5;
  4206. continue;
  4207. }
  4208. case OpcodeValue::LDLEN:
  4209. {
  4210. IL2CPP_ASSERT(evalStackTop > 0);
  4211. CreateAddIR(ir, GetArrayLengthVarVar);
  4212. ir->arr = ir->len = GetEvalStackTopOffset();
  4213. PopStack();
  4214. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4215. ip++;
  4216. continue;
  4217. }
  4218. case OpcodeValue::LDELEMA:
  4219. {
  4220. IL2CPP_ASSERT(evalStackTop >= 2);
  4221. EvalStackVarInfo& arr = evalStack[evalStackTop - 2];
  4222. EvalStackVarInfo& index = evalStack[evalStackTop - 1];
  4223. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4224. Il2CppClass* eleKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4225. uint32_t eleKlassIndex = GetOrAddResolveDataIndex(eleKlass);
  4226. if (prefixFlags & (int32_t)PrefixFlags::ReadOnly)
  4227. {
  4228. CreateAddIR(ir, GetArrayElementAddressAddrVarVar);
  4229. ir->arr = ir->addr = arr.locOffset;
  4230. ir->index = index.locOffset;
  4231. }
  4232. else
  4233. {
  4234. CreateAddIR(ir, GetArrayElementAddressCheckAddrVarVar);
  4235. ir->arr = ir->addr = arr.locOffset;
  4236. ir->index = index.locOffset;
  4237. ir->eleKlass = eleKlassIndex;
  4238. }
  4239. ResetPrefixFlags();
  4240. PopStackN(2);
  4241. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4242. ip += 5;
  4243. continue;
  4244. }
  4245. case OpcodeValue::LDELEM_I1:
  4246. {
  4247. CI_ldele(i1, I4);
  4248. continue;
  4249. }
  4250. case OpcodeValue::LDELEM_U1:
  4251. {
  4252. CI_ldele(u1, I4);
  4253. continue;
  4254. }
  4255. case OpcodeValue::LDELEM_I2:
  4256. {
  4257. CI_ldele(i2, I4);
  4258. continue;
  4259. }
  4260. case OpcodeValue::LDELEM_U2:
  4261. {
  4262. CI_ldele(u2, I4);
  4263. continue;
  4264. }
  4265. case OpcodeValue::LDELEM_I4:
  4266. {
  4267. CI_ldele(i4, I4);
  4268. continue;
  4269. }
  4270. case OpcodeValue::LDELEM_U4:
  4271. {
  4272. CI_ldele(u4, I4);
  4273. continue;
  4274. }
  4275. case OpcodeValue::LDELEM_I8:
  4276. {
  4277. CI_ldele(i8, I8);
  4278. continue;
  4279. }
  4280. case OpcodeValue::LDELEM_I:
  4281. {
  4282. #if HYBRIDCLR_ARCH_64
  4283. CI_ldele(i8, I8);
  4284. #else
  4285. CI_ldele(i4, I4);
  4286. #endif
  4287. continue;
  4288. }
  4289. case OpcodeValue::LDELEM_R4:
  4290. {
  4291. CI_ldele(i4, R4);
  4292. continue;
  4293. }
  4294. case OpcodeValue::LDELEM_R8:
  4295. {
  4296. CI_ldele(i8, R8);
  4297. continue;
  4298. }
  4299. case OpcodeValue::LDELEM_REF:
  4300. {
  4301. #if HYBRIDCLR_ARCH_64
  4302. CI_ldele(i8, I8);
  4303. #else
  4304. CI_ldele(i4, I4);
  4305. #endif
  4306. continue;
  4307. }
  4308. case OpcodeValue::STELEM_I:
  4309. {
  4310. #if HYBRIDCLR_ARCH_64
  4311. CI_stele(i8)
  4312. #else
  4313. CI_stele(i4)
  4314. #endif
  4315. continue;
  4316. }
  4317. case OpcodeValue::STELEM_I1:
  4318. {
  4319. CI_stele(i1);
  4320. continue;
  4321. }
  4322. case OpcodeValue::STELEM_I2:
  4323. {
  4324. CI_stele(i2);
  4325. continue;
  4326. }
  4327. case OpcodeValue::STELEM_I4:
  4328. {
  4329. CI_stele(i4);
  4330. continue;
  4331. }
  4332. case OpcodeValue::STELEM_I8:
  4333. {
  4334. CI_stele(i8);
  4335. continue;
  4336. }
  4337. case OpcodeValue::STELEM_R4:
  4338. {
  4339. CI_stele(i4);
  4340. continue;
  4341. }
  4342. case OpcodeValue::STELEM_R8:
  4343. {
  4344. CI_stele(i8);
  4345. continue;
  4346. }
  4347. case OpcodeValue::STELEM_REF:
  4348. {
  4349. CI_stele(ref);
  4350. continue;
  4351. }
  4352. #define CI_ldele0(eleType) \
  4353. CreateAddIR(ir, GetArrayElementVarVar_##eleType); \
  4354. ir->arr = arr.locOffset; \
  4355. ir->index = index.locOffset; \
  4356. ir->dst = arr.locOffset;
  4357. case OpcodeValue::LDELEM:
  4358. {
  4359. IL2CPP_ASSERT(evalStackTop >= 2);
  4360. EvalStackVarInfo& arr = evalStack[evalStackTop - 2];
  4361. EvalStackVarInfo& index = evalStack[evalStackTop - 1];
  4362. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4363. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4364. const Il2CppType* eleType = &objKlass->byval_arg;
  4365. IL2CPP_ASSERT(index.reduceType == EvalStackReduceDataType::I4 || index.reduceType == EvalStackReduceDataType::I8);
  4366. bool isIndexInt32Type = index.reduceType == EvalStackReduceDataType::I4;
  4367. LocationDescInfo desc = ComputLocationDescInfo(eleType);
  4368. switch (desc.type)
  4369. {
  4370. case LocationDescType::I1: { CI_ldele0(i1); break; }
  4371. case LocationDescType::U1: { CI_ldele0(u1); break; }
  4372. case LocationDescType::I2: { CI_ldele0(i2); break; }
  4373. case LocationDescType::U2: { CI_ldele0(u2); break; }
  4374. case LocationDescType::I4: { CI_ldele0(i4); break; }
  4375. case LocationDescType::I8: { CI_ldele0(i8); break; }
  4376. case LocationDescType::Ref:
  4377. {
  4378. if (HYBRIDCLR_ARCH_64)
  4379. {
  4380. CI_ldele0(i8);
  4381. }
  4382. else
  4383. {
  4384. CI_ldele0(i4);
  4385. }
  4386. break;
  4387. }
  4388. case LocationDescType::S:
  4389. case LocationDescType::StructContainsRef:
  4390. {
  4391. CreateAddIR(ir, GetArrayElementVarVar_size_1);
  4392. ir->arr = arr.locOffset;
  4393. ir->index = index.locOffset;
  4394. ir->dst = arr.locOffset;
  4395. uint32_t size = il2cpp::vm::Class::GetValueSize(objKlass, nullptr);
  4396. switch (size)
  4397. {
  4398. case 1:
  4399. {
  4400. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_1;
  4401. break;
  4402. }
  4403. case 2:
  4404. {
  4405. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_2;
  4406. break;
  4407. }
  4408. case 4:
  4409. {
  4410. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_4;
  4411. break;
  4412. }
  4413. case 8:
  4414. {
  4415. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_8;
  4416. break;
  4417. }
  4418. case 12:
  4419. {
  4420. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_12;
  4421. break;
  4422. }
  4423. case 16:
  4424. {
  4425. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_16;
  4426. break;
  4427. }
  4428. case 20:
  4429. {
  4430. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_20;
  4431. break;
  4432. }
  4433. case 24:
  4434. {
  4435. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_24;
  4436. break;
  4437. }
  4438. case 28:
  4439. {
  4440. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_28;
  4441. break;
  4442. }
  4443. case 32:
  4444. {
  4445. ir->type = HiOpcodeEnum::GetArrayElementVarVar_size_32;
  4446. break;
  4447. }
  4448. default:
  4449. {
  4450. ir->type = HiOpcodeEnum::GetArrayElementVarVar_n;
  4451. }
  4452. }
  4453. break;
  4454. }
  4455. default:
  4456. {
  4457. RaiseExecutionEngineException("ldelem not support type");
  4458. }
  4459. }
  4460. PopStackN(2);
  4461. PushStackByType(eleType);
  4462. ip += 5;
  4463. continue;
  4464. }
  4465. #define CI_stele0(eleType) \
  4466. CreateAddIR(ir, SetArrayElementVarVar_##eleType); \
  4467. ir->arr = arr.locOffset; \
  4468. ir->index = index.locOffset; \
  4469. ir->ele = ele.locOffset;
  4470. case OpcodeValue::STELEM:
  4471. {
  4472. IL2CPP_ASSERT(evalStackTop >= 3);
  4473. EvalStackVarInfo& arr = evalStack[evalStackTop - 3];
  4474. EvalStackVarInfo& index = evalStack[evalStackTop - 2];
  4475. EvalStackVarInfo& ele = evalStack[evalStackTop - 1];
  4476. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4477. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4478. const Il2CppType* eleType = &objKlass->byval_arg;
  4479. IL2CPP_ASSERT(index.reduceType == EvalStackReduceDataType::I4 || index.reduceType == EvalStackReduceDataType::I8);
  4480. bool isIndexInt32Type = index.reduceType == EvalStackReduceDataType::I4;
  4481. LocationDescInfo desc = ComputLocationDescInfo(eleType);
  4482. switch (desc.type)
  4483. {
  4484. case LocationDescType::I1: { CI_stele0(i1); break; }
  4485. case LocationDescType::U1: { CI_stele0(u1); break; }
  4486. case LocationDescType::I2: { CI_stele0(i2); break; }
  4487. case LocationDescType::U2: { CI_stele0(u2); break; }
  4488. case LocationDescType::I4: { CI_stele0(i4); break; }
  4489. case LocationDescType::I8: { CI_stele0(i8); break; }
  4490. case LocationDescType::Ref: { CI_stele0(ref); break; }
  4491. case LocationDescType::S:
  4492. {
  4493. uint32_t size = il2cpp::vm::Class::GetValueSize(objKlass, nullptr);
  4494. switch (size)
  4495. {
  4496. case 12:
  4497. {
  4498. CreateAddIR(ir, SetArrayElementVarVar_size_12);
  4499. ir->arr = arr.locOffset;
  4500. ir->index = index.locOffset;
  4501. ir->ele = ele.locOffset;
  4502. break;
  4503. }
  4504. case 16:
  4505. {
  4506. CreateAddIR(ir, SetArrayElementVarVar_size_16);
  4507. ir->arr = arr.locOffset;
  4508. ir->index = index.locOffset;
  4509. ir->ele = ele.locOffset;
  4510. break;
  4511. }
  4512. default:
  4513. {
  4514. CreateAddIR(ir, SetArrayElementVarVar_n);
  4515. ir->arr = arr.locOffset;
  4516. ir->index = index.locOffset;
  4517. ir->ele = ele.locOffset;
  4518. break;
  4519. }
  4520. }
  4521. break;
  4522. }
  4523. case LocationDescType::StructContainsRef:
  4524. {
  4525. CreateAddIR(ir, SetArrayElementVarVar_WriteBarrier_n);
  4526. ir->arr = arr.locOffset;
  4527. ir->index = index.locOffset;
  4528. ir->ele = ele.locOffset;
  4529. break;
  4530. }
  4531. default:
  4532. {
  4533. RaiseExecutionEngineException("stelem not support type");
  4534. }
  4535. }
  4536. PopStackN(3);
  4537. ip += 5;
  4538. continue;
  4539. }
  4540. case OpcodeValue::UNBOX_ANY:
  4541. {
  4542. IL2CPP_ASSERT(evalStackTop > 0);
  4543. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4544. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4545. IL2CPP_ASSERT(objKlass);
  4546. if (IS_CLASS_VALUE_TYPE(objKlass))
  4547. {
  4548. CreateAddIR(ir, UnBoxAnyVarVar);
  4549. ir->dst = ir->obj = GetEvalStackTopOffset();
  4550. ir->klass = GetOrAddResolveDataIndex(objKlass);
  4551. PopStack();
  4552. PushStackByType(&objKlass->byval_arg);
  4553. }
  4554. else
  4555. {
  4556. CreateAddIR(ir, CastclassVar);
  4557. ir->obj = GetEvalStackTopOffset();
  4558. ir->klass = GetOrAddResolveDataIndex(objKlass);
  4559. }
  4560. ip += 5;
  4561. continue;
  4562. }
  4563. case OpcodeValue::CONV_OVF_I1:
  4564. {
  4565. CI_conv_ovf(i1, I4, 4);
  4566. continue;
  4567. }
  4568. case OpcodeValue::CONV_OVF_U1:
  4569. {
  4570. CI_conv_ovf(u1, I4, 4);
  4571. continue;
  4572. }
  4573. case OpcodeValue::CONV_OVF_I2:
  4574. {
  4575. CI_conv_ovf(i2, I4, 4);
  4576. continue;
  4577. }
  4578. case OpcodeValue::CONV_OVF_U2:
  4579. {
  4580. CI_conv_ovf(u2, I4, 4);
  4581. continue;
  4582. }
  4583. case OpcodeValue::CONV_OVF_I4:
  4584. {
  4585. CI_conv_ovf(i4, I4, 4);
  4586. continue;
  4587. }
  4588. case OpcodeValue::CONV_OVF_U4:
  4589. {
  4590. CI_conv_ovf(u4, I4, 4);
  4591. continue;
  4592. }
  4593. case OpcodeValue::CONV_OVF_I8:
  4594. {
  4595. CI_conv_ovf(i8, I8, 8);
  4596. continue;
  4597. }
  4598. case OpcodeValue::CONV_OVF_U8:
  4599. {
  4600. CI_conv_ovf(u8, I8, 8);
  4601. continue;
  4602. }
  4603. case OpcodeValue::REFANYVAL:
  4604. {
  4605. IL2CPP_ASSERT(evalStackTop > 0);
  4606. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4607. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4608. CreateAddIR(ir, RefAnyValueVarVar);
  4609. ir->addr = ir->typedRef = GetEvalStackTopOffset();
  4610. ir->klass = GetOrAddResolveDataIndex(objKlass);
  4611. PopStack();
  4612. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4613. ip += 5;
  4614. continue;
  4615. }
  4616. case OpcodeValue::CKFINITE:
  4617. {
  4618. IL2CPP_ASSERT(evalStackTop > 0);
  4619. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  4620. switch (top.reduceType)
  4621. {
  4622. case EvalStackReduceDataType::R4:
  4623. {
  4624. CreateAddIR(ir, CheckFiniteVar_f4);
  4625. ir->src = GetEvalStackTopOffset();
  4626. break;
  4627. }
  4628. case EvalStackReduceDataType::R8:
  4629. {
  4630. CreateAddIR(ir, CheckFiniteVar_f8);
  4631. ir->src = GetEvalStackTopOffset();
  4632. break;
  4633. }
  4634. default:
  4635. {
  4636. RaiseExecutionEngineException("CKFINITE invalid reduceType");
  4637. break;
  4638. }
  4639. }
  4640. ip++;
  4641. continue;
  4642. }
  4643. case OpcodeValue::MKREFANY:
  4644. {
  4645. IL2CPP_ASSERT(evalStackTop > 0);
  4646. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4647. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4648. IL2CPP_ASSERT(objKlass);
  4649. CreateAddIR(ir, MakeRefVarVar);
  4650. ir->dst = ir->data = GetEvalStackTopOffset();
  4651. ir->klass = GetOrAddResolveDataIndex(objKlass);
  4652. PopStack();
  4653. Il2CppType typedRef = {};
  4654. typedRef.type = IL2CPP_TYPE_TYPEDBYREF;
  4655. PushStackByType(&typedRef);
  4656. ip += 5;
  4657. continue;
  4658. }
  4659. case OpcodeValue::LDTOKEN:
  4660. {
  4661. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 1);
  4662. void* runtimeHandle = (void*)image->GetRuntimeHandleFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4663. CreateAddIR(ir, LdtokenVar);
  4664. ir->runtimeHandle = GetEvalStackNewTopOffset();
  4665. ir->token = GetOrAddResolveDataIndex(runtimeHandle);
  4666. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4667. ip += 5;
  4668. continue;
  4669. }
  4670. case OpcodeValue::CONV_U2:
  4671. {
  4672. CI_conv(u2, I4, 4);
  4673. continue;
  4674. }
  4675. case OpcodeValue::CONV_U1:
  4676. {
  4677. CI_conv(u1, I4, 4);
  4678. continue;
  4679. }
  4680. case OpcodeValue::CONV_I:
  4681. {
  4682. #if HYBRIDCLR_ARCH_64
  4683. CI_conv(i8, I8, 8);
  4684. #else
  4685. CI_conv(i4, I4, 4);
  4686. #endif
  4687. continue;
  4688. }
  4689. case OpcodeValue::CONV_OVF_I:
  4690. {
  4691. #if HYBRIDCLR_ARCH_64
  4692. CI_conv_ovf(i8, I8, 8);
  4693. #else
  4694. CI_conv_ovf(i4, I4, 4);
  4695. #endif
  4696. continue;
  4697. }
  4698. case OpcodeValue::CONV_OVF_U:
  4699. {
  4700. #if HYBRIDCLR_ARCH_64
  4701. CI_conv_ovf(u8, I8, 8);
  4702. #else
  4703. CI_conv_ovf(u4, I4, 4);
  4704. #endif
  4705. continue;
  4706. }
  4707. case OpcodeValue::ADD_OVF:
  4708. {
  4709. CI_binOpOvf(Add);
  4710. continue;
  4711. }
  4712. case OpcodeValue::ADD_OVF_UN:
  4713. {
  4714. CI_binOpUnOvf(Add);
  4715. continue;
  4716. }
  4717. case OpcodeValue::MUL_OVF:
  4718. {
  4719. CI_binOpOvf(Mul);
  4720. continue;
  4721. }
  4722. case OpcodeValue::MUL_OVF_UN:
  4723. {
  4724. CI_binOpUnOvf(Mul);
  4725. continue;
  4726. }
  4727. case OpcodeValue::SUB_OVF:
  4728. {
  4729. CI_binOpOvf(Sub);
  4730. continue;
  4731. }
  4732. case OpcodeValue::SUB_OVF_UN:
  4733. {
  4734. CI_binOpUnOvf(Sub);
  4735. continue;
  4736. }
  4737. case OpcodeValue::ENDFINALLY:
  4738. {
  4739. CreateAddIR(ir, EndFinallyEx);
  4740. PopBranch();
  4741. continue;
  4742. }
  4743. case OpcodeValue::STIND_I:
  4744. {
  4745. Add_stind(ARCH_ARGUMENT(HiOpcodeEnum::StindVarVar_i4, HiOpcodeEnum::StindVarVar_i8));
  4746. continue;
  4747. }
  4748. case OpcodeValue::CONV_U:
  4749. {
  4750. #if HYBRIDCLR_ARCH_64
  4751. CI_conv(u8, I8, 8);
  4752. #else
  4753. CI_conv(u4, I4, 4);
  4754. #endif
  4755. continue;
  4756. }
  4757. case OpcodeValue::PREFIX7:
  4758. case OpcodeValue::PREFIX6:
  4759. case OpcodeValue::PREFIX5:
  4760. case OpcodeValue::PREFIX4:
  4761. case OpcodeValue::PREFIX3:
  4762. case OpcodeValue::PREFIX2:
  4763. {
  4764. ip++;
  4765. continue;
  4766. }
  4767. case OpcodeValue::PREFIX1:
  4768. {
  4769. // This is the prefix for all the 2-byte opcodes.
  4770. // Figure out the second byte of the 2-byte opcode.
  4771. byte ops = *(ip + 1);
  4772. switch ((OpcodeValue)ops)
  4773. {
  4774. case OpcodeValue::ARGLIST:
  4775. {
  4776. RaiseExecutionEngineException("");
  4777. ip += 2;
  4778. continue;
  4779. }
  4780. case OpcodeValue::CEQ:
  4781. {
  4782. CI_compare(Ceq);
  4783. ip += 2;
  4784. continue;
  4785. }
  4786. case OpcodeValue::CGT:
  4787. {
  4788. CI_compare(Cgt);
  4789. ip += 2;
  4790. continue;
  4791. }
  4792. case OpcodeValue::CGT_UN:
  4793. {
  4794. CI_compare(CgtUn);
  4795. ip += 2;
  4796. continue;
  4797. }
  4798. case OpcodeValue::CLT:
  4799. {
  4800. CI_compare(Clt);
  4801. ip += 2;
  4802. continue;
  4803. }
  4804. case OpcodeValue::CLT_UN:
  4805. {
  4806. CI_compare(CltUn);
  4807. ip += 2;
  4808. continue;
  4809. }
  4810. case OpcodeValue::LDFTN:
  4811. {
  4812. uint32_t methodToken = (uint32_t)GetI4LittleEndian(ip + 2);
  4813. MethodInfo* methodInfo = const_cast<MethodInfo*>(image->GetMethodInfoFromToken(tokenCache, methodToken, klassContainer, methodContainer, genericContext));
  4814. IL2CPP_ASSERT(methodInfo);
  4815. CreateAddIR(ir, LdcVarConst_8);
  4816. ir->dst = GetEvalStackNewTopOffset();
  4817. ir->src = (uint64_t)methodInfo;
  4818. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4819. ip += 6;
  4820. continue;
  4821. }
  4822. case OpcodeValue::LDVIRTFTN:
  4823. {
  4824. IL2CPP_ASSERT(evalStackTop > 0);
  4825. uint32_t methodToken = (uint32_t)GetI4LittleEndian(ip + 2);
  4826. MethodInfo* methodInfo = const_cast<MethodInfo*>(image->GetMethodInfoFromToken(tokenCache, methodToken, klassContainer, methodContainer, genericContext));
  4827. IL2CPP_ASSERT(methodInfo);
  4828. CreateAddIR(ir, LdvirftnVarVar);
  4829. ir->resultMethod = ir->obj = GetEvalStackTopOffset();
  4830. ir->virtualMethod = GetOrAddResolveDataIndex(methodInfo);
  4831. PopStack();
  4832. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4833. ip += 6;
  4834. continue;
  4835. }
  4836. case OpcodeValue::UNUSED56:
  4837. {
  4838. ip += 2;
  4839. continue;
  4840. }
  4841. case OpcodeValue::LDARG:
  4842. {
  4843. argIdx = GetU2LittleEndian(ip + 2);
  4844. AddInst_ldarg(argIdx);
  4845. ip += 4;
  4846. continue;
  4847. }
  4848. case OpcodeValue::LDARGA:
  4849. {
  4850. argIdx = GetU2LittleEndian(ip + 2);
  4851. AddInst_ldarga(argIdx);
  4852. ip += 4;
  4853. continue;
  4854. }
  4855. case OpcodeValue::STARG:
  4856. {
  4857. argIdx = GetU2LittleEndian(ip + 2);
  4858. AddInst_starg(argIdx);
  4859. ip += 4;
  4860. continue;
  4861. }
  4862. case OpcodeValue::LDLOC:
  4863. {
  4864. argIdx = GetU2LittleEndian(ip + 2);
  4865. CreateAddInst_ldloc(argIdx);
  4866. ip += 4;
  4867. continue;
  4868. }
  4869. case OpcodeValue::LDLOCA:
  4870. {
  4871. argIdx = GetU2LittleEndian(ip + 2);
  4872. CreateAddInst_ldloca(argIdx);
  4873. ip += 4;
  4874. continue;
  4875. }
  4876. case OpcodeValue::STLOC:
  4877. {
  4878. argIdx = GetU2LittleEndian(ip + 2);
  4879. CreateAddInst_stloc(argIdx);
  4880. ip += 4;
  4881. continue;
  4882. }
  4883. case OpcodeValue::LOCALLOC:
  4884. {
  4885. IL2CPP_ASSERT(evalStackTop > 0);
  4886. EvalStackVarInfo& top = evalStack[evalStackTop - 1];
  4887. switch (top.reduceType)
  4888. {
  4889. case EvalStackReduceDataType::I4:
  4890. case EvalStackReduceDataType::I8: // FIXE ME
  4891. {
  4892. CreateAddIR(ir, LocalAllocVarVar_n_4);
  4893. ir->dst = ir->size = GetEvalStackTopOffset();
  4894. break;
  4895. }
  4896. default:
  4897. {
  4898. RaiseExecutionEngineException("LOCALLOC invalid reduceType");
  4899. break;
  4900. }
  4901. }
  4902. PopStack();
  4903. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  4904. ip += 2;
  4905. continue;
  4906. }
  4907. case OpcodeValue::UNUSED57:
  4908. {
  4909. ip += 2;
  4910. continue;
  4911. }
  4912. case OpcodeValue::ENDFILTER:
  4913. {
  4914. CreateAddIR(ir, EndFilterEx);
  4915. ir->value = GetEvalStackTopOffset();
  4916. PopAllStack();
  4917. PopBranch();
  4918. continue;
  4919. }
  4920. case OpcodeValue::UNALIGNED_:
  4921. {
  4922. // Nothing to do here.
  4923. prefixFlags |= (int32_t)PrefixFlags::Unaligned;
  4924. uint8_t alignment = ip[2];
  4925. IL2CPP_ASSERT(alignment == 1 || alignment == 2 || alignment == 4);
  4926. ip += 3;
  4927. continue;
  4928. }
  4929. case OpcodeValue::VOLATILE_:
  4930. {
  4931. // Set a flag that causes a memory barrier to be associated with the next load or store.
  4932. //CI_volatileFlag = true;
  4933. prefixFlags |= (int32_t)PrefixFlags::Volatile;
  4934. ip += 2;
  4935. continue;
  4936. }
  4937. case OpcodeValue::TAIL_:
  4938. {
  4939. prefixFlags |= (int32_t)PrefixFlags::Tail;
  4940. ip += 2;
  4941. continue;
  4942. }
  4943. case OpcodeValue::INITOBJ:
  4944. {
  4945. IL2CPP_ASSERT(evalStackTop > 0);
  4946. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 2);
  4947. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  4948. if (IS_CLASS_VALUE_TYPE(objKlass))
  4949. {
  4950. uint32_t objSize = GetTypeValueSize(objKlass);
  4951. if ((HYBRIDCLR_ENABLE_WRITE_BARRIERS && objKlass->has_references))
  4952. {
  4953. CreateAddIR(ir, InitobjVar_WriteBarrier_n_4);
  4954. ir->obj = GetEvalStackTopOffset();
  4955. ir->size = objSize;
  4956. }
  4957. else
  4958. {
  4959. bool convert = false;
  4960. switch (objSize)
  4961. {
  4962. case 1:
  4963. {
  4964. CreateAddIR(ir, InitobjVar_1);
  4965. ir->obj = GetEvalStackTopOffset();
  4966. convert = true;
  4967. break;
  4968. }
  4969. case 2:
  4970. {
  4971. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 2)
  4972. {
  4973. CreateAddIR(ir, InitobjVar_2);
  4974. ir->obj = GetEvalStackTopOffset();
  4975. convert = true;
  4976. }
  4977. break;
  4978. }
  4979. case 4:
  4980. {
  4981. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 4)
  4982. {
  4983. CreateAddIR(ir, InitobjVar_4);
  4984. ir->obj = GetEvalStackTopOffset();
  4985. convert = true;
  4986. }
  4987. break;
  4988. }
  4989. case 8:
  4990. {
  4991. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 8)
  4992. {
  4993. CreateAddIR(ir, InitobjVar_8);
  4994. ir->obj = GetEvalStackTopOffset();
  4995. convert = true;
  4996. }
  4997. break;
  4998. }
  4999. case 12:
  5000. {
  5001. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 4)
  5002. {
  5003. CreateAddIR(ir, InitobjVar_12);
  5004. ir->obj = GetEvalStackTopOffset();
  5005. convert = true;
  5006. }
  5007. break;
  5008. }
  5009. case 16:
  5010. {
  5011. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 8)
  5012. {
  5013. CreateAddIR(ir, InitobjVar_16);
  5014. ir->obj = GetEvalStackTopOffset();
  5015. convert = true;
  5016. }
  5017. break;
  5018. }
  5019. case 20:
  5020. {
  5021. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 4)
  5022. {
  5023. CreateAddIR(ir, InitobjVar_20);
  5024. ir->obj = GetEvalStackTopOffset();
  5025. convert = true;
  5026. }
  5027. break;
  5028. }
  5029. case 24:
  5030. {
  5031. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 8)
  5032. {
  5033. CreateAddIR(ir, InitobjVar_24);
  5034. ir->obj = GetEvalStackTopOffset();
  5035. convert = true;
  5036. }
  5037. break;
  5038. }
  5039. case 28:
  5040. {
  5041. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 4)
  5042. {
  5043. CreateAddIR(ir, InitobjVar_28);
  5044. ir->obj = GetEvalStackTopOffset();
  5045. convert = true;
  5046. }
  5047. break;
  5048. }
  5049. case 32:
  5050. {
  5051. if (SUPPORT_MEMORY_NOT_ALIGMENT_ACCESS || objKlass->minimumAlignment >= 8)
  5052. {
  5053. CreateAddIR(ir, InitobjVar_32);
  5054. ir->obj = GetEvalStackTopOffset();
  5055. convert = true;
  5056. }
  5057. break;
  5058. }
  5059. }
  5060. if (!convert)
  5061. {
  5062. CreateAddIR(ir, InitobjVar_n_4);
  5063. ir->obj = GetEvalStackTopOffset();
  5064. ir->size = objSize;
  5065. }
  5066. }
  5067. }
  5068. else
  5069. {
  5070. CreateAddIR(ir, InitobjVar_ref);
  5071. ir->obj = GetEvalStackTopOffset();
  5072. }
  5073. PopStack();
  5074. ip += 6;
  5075. break;
  5076. }
  5077. case OpcodeValue::CONSTRAINED_:
  5078. {
  5079. uint32_t typeToken = (uint32_t)GetI4LittleEndian(ip + 2);
  5080. Il2CppClass* conKlass = image->GetClassFromToken(tokenCache, typeToken, klassContainer, methodContainer, genericContext);
  5081. IL2CPP_ASSERT(conKlass);
  5082. ip += 6;
  5083. IL2CPP_ASSERT(*ip == (uint8_t)OpcodeValue::CALLVIRT);
  5084. uint32_t methodToken = (uint32_t)GetI4LittleEndian(ip + 1);
  5085. ip += 5;
  5086. // TODO token cache optimistic
  5087. shareMethod = const_cast<MethodInfo*>(image->GetMethodInfoFromToken(tokenCache, methodToken, klassContainer, methodContainer, genericContext));
  5088. IL2CPP_ASSERT(shareMethod);
  5089. int32_t resolvedTotalArgNum = shareMethod->parameters_count + 1;
  5090. int32_t selfIdx = evalStackTop - resolvedTotalArgNum;
  5091. EvalStackVarInfo& self = evalStack[selfIdx];
  5092. if (IS_CLASS_VALUE_TYPE(conKlass))
  5093. {
  5094. // impl in self
  5095. const MethodInfo* implMethod = image->FindImplMethod(conKlass, shareMethod);
  5096. if (implMethod->klass == conKlass)
  5097. {
  5098. shareMethod = implMethod;
  5099. goto LabelCall;
  5100. }
  5101. else if (conKlass->enumtype && !std::strcmp(shareMethod->name, "GetHashCode"))
  5102. {
  5103. Il2CppTypeEnum typeEnum = conKlass->element_class->byval_arg.type;
  5104. self.reduceType = EvalStackReduceDataType::I4;
  5105. if (typeEnum == IL2CPP_TYPE_I8 || typeEnum == IL2CPP_TYPE_U8)
  5106. {
  5107. CreateAddIR(ir, GetEnumHashCode);
  5108. ir->dst = ir->src = self.locOffset;
  5109. }
  5110. else
  5111. {
  5112. CreateAddIR(ir, LdindVarVar_i1);
  5113. ir->dst = ir->src = self.locOffset;
  5114. switch (conKlass->element_class->byval_arg.type)
  5115. {
  5116. case IL2CPP_TYPE_U1: ir->type = HiOpcodeEnum::LdindVarVar_u1; break;
  5117. case IL2CPP_TYPE_I1: ir->type = HiOpcodeEnum::LdindVarVar_i1; break;
  5118. case IL2CPP_TYPE_U2: ir->type = HiOpcodeEnum::LdindVarVar_u2; break;
  5119. case IL2CPP_TYPE_I2: ir->type = HiOpcodeEnum::LdindVarVar_u2; break;
  5120. case IL2CPP_TYPE_U4: ir->type = HiOpcodeEnum::LdindVarVar_u4; break;
  5121. case IL2CPP_TYPE_I4: ir->type = HiOpcodeEnum::LdindVarVar_i4; break;
  5122. case IL2CPP_TYPE_CHAR: ir->type = HiOpcodeEnum::LdindVarVar_u2; break;
  5123. case IL2CPP_TYPE_BOOLEAN: ir->type = HiOpcodeEnum::LdindVarVar_i1; break;
  5124. default:
  5125. IL2CPP_ASSERT(false && "GetHashCode");
  5126. break;
  5127. }
  5128. }
  5129. }
  5130. else
  5131. {
  5132. CreateAddIR(ir, BoxRefVarVar);
  5133. ir->dst = ir->src = self.locOffset;
  5134. ir->klass = GetOrAddResolveDataIndex(conKlass);
  5135. self.reduceType = NATIVE_INT_REDUCE_TYPE;
  5136. self.byteSize = GetSizeByReduceType(self.reduceType);
  5137. goto LabelCallVir;
  5138. }
  5139. }
  5140. else
  5141. {
  5142. // deref object. FIXME gc memory barrier
  5143. #if HYBRIDCLR_ARCH_64
  5144. CreateAddIR(ir, LdindVarVar_i8);
  5145. #else
  5146. CreateAddIR(ir, LdindVarVar_i4);
  5147. #endif
  5148. ir->dst = ir->src = self.locOffset;
  5149. self.reduceType = NATIVE_INT_REDUCE_TYPE;
  5150. self.byteSize = GetSizeByReduceType(self.reduceType);
  5151. goto LabelCallVir;
  5152. }
  5153. continue;
  5154. }
  5155. case OpcodeValue::CPBLK:
  5156. {
  5157. // we don't sure dst or src is volatile. so insert memory barrier ahead and end.
  5158. IL2CPP_ASSERT(evalStackTop >= 3);
  5159. InsertMemoryBarrier();
  5160. ResetPrefixFlags();
  5161. CreateAddIR(ir, CpblkVarVar);
  5162. ir->dst = GetEvalStackOffset_3();
  5163. ir->src = GetEvalStackOffset_2();
  5164. ir->size = GetEvalStackOffset_1();
  5165. PopStackN(3);
  5166. InsertMemoryBarrier();
  5167. ResetPrefixFlags();
  5168. ip += 2;
  5169. continue;
  5170. }
  5171. case OpcodeValue::INITBLK:
  5172. {
  5173. IL2CPP_ASSERT(evalStackTop >= 3);
  5174. InsertMemoryBarrier();
  5175. ResetPrefixFlags();
  5176. CreateAddIR(ir, InitblkVarVarVar);
  5177. ir->addr = GetEvalStackOffset_3();
  5178. ir->value = GetEvalStackOffset_2();
  5179. ir->size = GetEvalStackOffset_1();
  5180. PopStackN(3);
  5181. ip += 2;
  5182. continue;
  5183. }
  5184. case OpcodeValue::NO_:
  5185. {
  5186. uint8_t checkType = ip[2];
  5187. // {typecheck:0x1} | {rangecheck:0x2} | {nullcheck:0x4}
  5188. IL2CPP_ASSERT(checkType < 8);
  5189. ip += 3;
  5190. continue;
  5191. }
  5192. case OpcodeValue::RETHROW:
  5193. {
  5194. CreateAddIR(ir, RethrowEx);
  5195. AddInst(ir);
  5196. PopAllStack();
  5197. PopBranch();
  5198. continue;
  5199. }
  5200. case OpcodeValue::UNUSED:
  5201. {
  5202. ip += 2;
  5203. continue;
  5204. }
  5205. case OpcodeValue::SIZEOF:
  5206. {
  5207. uint32_t token = (uint32_t)GetI4LittleEndian(ip + 2);
  5208. Il2CppClass* objKlass = image->GetClassFromToken(tokenCache, token, klassContainer, methodContainer, genericContext);
  5209. IL2CPP_ASSERT(objKlass);
  5210. int32_t typeSize = GetTypeValueSize(&objKlass->byval_arg);
  5211. CreateAddInst_ldc4(typeSize, EvalStackReduceDataType::I4);
  5212. ip += 6;
  5213. continue;
  5214. }
  5215. case OpcodeValue::REFANYTYPE:
  5216. {
  5217. IL2CPP_ASSERT(evalStackTop > 0);
  5218. CreateAddIR(ir, RefAnyTypeVarVar);
  5219. ir->dst = ir->typedRef = GetEvalStackOffset_1();
  5220. PopStack();
  5221. PushStackByReduceType(NATIVE_INT_REDUCE_TYPE);
  5222. ip += 2;
  5223. continue;
  5224. }
  5225. case OpcodeValue::READONLY_:
  5226. {
  5227. prefixFlags |= (int32_t)PrefixFlags::ReadOnly;
  5228. ip += 2;
  5229. // generic md array also can follow readonly
  5230. //IL2CPP_ASSERT(*ip == (byte)OpcodeValue::LDELEMA && "According to the ECMA spec, READONLY may only precede LDELEMA");
  5231. continue;
  5232. }
  5233. case OpcodeValue::UNUSED53:
  5234. case OpcodeValue::UNUSED54:
  5235. case OpcodeValue::UNUSED55:
  5236. case OpcodeValue::UNUSED70:
  5237. {
  5238. ip += 2;
  5239. continue;
  5240. }
  5241. default:
  5242. {
  5243. //UNREACHABLE();
  5244. RaiseExecutionEngineException("not support instruction");
  5245. continue;
  5246. }
  5247. }
  5248. continue;
  5249. }
  5250. case OpcodeValue::PREFIXREF:
  5251. {
  5252. ip++;
  5253. continue;
  5254. }
  5255. default:
  5256. {
  5257. RaiseExecutionEngineException("not support instruction");
  5258. continue;
  5259. }
  5260. }
  5261. ip++;
  5262. }
  5263. finish_transform:
  5264. totalIRSize = 0;
  5265. for (IRBasicBlock* bb : irbbs)
  5266. {
  5267. bb->codeOffset = totalIRSize;
  5268. for (IRCommon* ir : bb->insts)
  5269. {
  5270. totalIRSize += g_instructionSizes[(int)ir->type];
  5271. }
  5272. }
  5273. endBb->codeOffset = totalIRSize;
  5274. for (int32_t* relocOffsetPtr : relocationOffsets)
  5275. {
  5276. int32_t relocOffset = *relocOffsetPtr;
  5277. IL2CPP_ASSERT(splitOffsets.find(relocOffset) != splitOffsets.end());
  5278. *relocOffsetPtr = ip2bb[relocOffset]->codeOffset;
  5279. }
  5280. for (auto switchOffsetPair : switchOffsetsInResolveData)
  5281. {
  5282. int32_t* offsetStartPtr = (int32_t*)&resolveDatas[switchOffsetPair.first];
  5283. for (int32_t i = 0; i < switchOffsetPair.second; i++)
  5284. {
  5285. int32_t relocOffset = offsetStartPtr[i];
  5286. IL2CPP_ASSERT(splitOffsets.find(relocOffset) != splitOffsets.end());
  5287. offsetStartPtr[i] = ip2bb[relocOffset]->codeOffset;
  5288. }
  5289. }
  5290. }
  5291. void TransformContext::BuildInterpMethodInfo(interpreter::InterpMethodInfo& result)
  5292. {
  5293. il2cpp::utils::dynamic_array<hybridclr::metadata::ILMapper>* ilMappers;
  5294. if (ir2offsetMap)
  5295. {
  5296. ilMappers = new il2cpp::utils::dynamic_array<hybridclr::metadata::ILMapper>();
  5297. ilMappers->reserve(ir2offsetMap->size());
  5298. }
  5299. else
  5300. {
  5301. ilMappers = nullptr;
  5302. }
  5303. byte* tranCodes = (byte*)HYBRIDCLR_METADATA_MALLOC(totalIRSize);
  5304. uint32_t tranOffset = 0;
  5305. for (IRBasicBlock* bb : irbbs)
  5306. {
  5307. //bb->codeOffset = tranOffset;
  5308. for (IRCommon* ir : bb->insts)
  5309. {
  5310. if (ilMappers)
  5311. {
  5312. auto it = ir2offsetMap->find(ir);
  5313. if (it != ir2offsetMap->end())
  5314. {
  5315. hybridclr::metadata::ILMapper ilMapper;
  5316. ilMapper.irOffset = tranOffset;
  5317. ilMapper.ilOffset = it->second;
  5318. ilMappers->push_back(ilMapper);
  5319. }
  5320. }
  5321. uint32_t irSize = g_instructionSizes[(int)ir->type];
  5322. std::memcpy(tranCodes + tranOffset, &ir->type, irSize);
  5323. tranOffset += irSize;
  5324. }
  5325. bb->~IRBasicBlock();
  5326. }
  5327. IL2CPP_ASSERT(tranOffset == totalIRSize);
  5328. for (FlowInfo* fi : pendingFlows)
  5329. {
  5330. fi->~FlowInfo();
  5331. }
  5332. MethodArgDesc* argDescs;
  5333. if (actualParamCount > 0)
  5334. {
  5335. argDescs = (MethodArgDesc*)HYBRIDCLR_METADATA_CALLOC(actualParamCount, sizeof(MethodArgDesc));
  5336. for (int32_t i = 0; i < actualParamCount; i++)
  5337. {
  5338. const Il2CppType* argType = args[i].type;
  5339. TypeDesc typeDesc = GetTypeArgDesc(argType);
  5340. MethodArgDesc& argDesc = argDescs[i];
  5341. argDesc.type = typeDesc.type;
  5342. IL2CPP_ASSERT(typeDesc.stackObjectSize < 0x10000);
  5343. argDesc.stackObjectSize = (uint16_t)typeDesc.stackObjectSize;
  5344. argDesc.passbyValWhenInvoke = argType->byref || !IsValueType(argType);
  5345. }
  5346. }
  5347. else
  5348. {
  5349. argDescs = nullptr;
  5350. }
  5351. result.args = argDescs;
  5352. result.argCount = actualParamCount;
  5353. result.argStackObjectSize = totalArgSize;
  5354. result.retStackObjectSize = IsVoidType(methodInfo->return_type) ? 0 : GetTypeArgDesc(methodInfo->return_type).stackObjectSize;
  5355. result.codes = tranCodes;
  5356. result.codeLength = totalIRSize;
  5357. result.evalStackBaseOffset = evalStackBaseOffset;
  5358. result.localVarBaseOffset = totalArgSize;
  5359. result.localStackSize = totalArgLocalSize;
  5360. result.maxStackSize = maxStackSize;
  5361. result.initLocals = initLocals;
  5362. if (resolveDatas.empty())
  5363. {
  5364. result.resolveDatas = nullptr;
  5365. }
  5366. else
  5367. {
  5368. //result.resolveData = (uint8_t*)HYBRIDCLR_MALLOC(resolveDatas.size() * sizeof(uint8_t));
  5369. size_t dataSize = resolveDatas.size() * sizeof(uint64_t);
  5370. uint64_t* data = (uint64_t*)HYBRIDCLR_METADATA_MALLOC(dataSize);
  5371. std::memcpy(data, resolveDatas.data(), dataSize);
  5372. result.resolveDatas = data;
  5373. }
  5374. if (exClauses.empty())
  5375. {
  5376. result.exClauses = nullptr;
  5377. result.exClauseCount = 0;
  5378. }
  5379. else
  5380. {
  5381. size_t dataSize = exClauses.size() * sizeof(InterpExceptionClause);
  5382. InterpExceptionClause* data = (InterpExceptionClause*)HYBRIDCLR_METADATA_MALLOC(dataSize);
  5383. std::memcpy(data, exClauses.data(), dataSize);
  5384. result.exClauses = data;
  5385. result.exClauseCount = (uint32_t)exClauses.size();
  5386. }
  5387. if (ilMappers)
  5388. {
  5389. image->GetPDBImage()->SetMethodDebugInfo(methodInfo, *ilMappers);
  5390. }
  5391. }
  5392. bool TransformContext::TransformSubMethodBody(TransformContext& callingCtx, const MethodInfo* methodInfo, int32_t depth, int32_t localVarOffset)
  5393. {
  5394. metadata::Image* image = metadata::MetadataModule::GetUnderlyingInterpreterImage(methodInfo);
  5395. IL2CPP_ASSERT(image);
  5396. metadata::MethodBody* methodBody = metadata::MethodBodyCache::GetMethodBody(image, methodInfo->token);
  5397. if (methodBody == nullptr || methodBody->ilcodes == nullptr)
  5398. {
  5399. TEMP_FORMAT(errMsg, "Method body is null. %s.%s::%s", methodInfo->klass->namespaze, methodInfo->klass->name, methodInfo->name);
  5400. il2cpp::vm::Exception::Raise(il2cpp::vm::Exception::GetExecutionEngineException(errMsg));
  5401. }
  5402. TransformContext ctx(image, methodInfo, *methodBody, callingCtx.pool, callingCtx.resolveDatas);
  5403. try
  5404. {
  5405. ctx.TransformBodyImpl(depth, localVarOffset);
  5406. callingCtx.maxStackSize = std::max(callingCtx.maxStackSize, ctx.maxStackSize);
  5407. callingCtx.curbb->insts.insert(callingCtx.curbb->insts.end(), ctx.curbb->insts.begin(), ctx.curbb->insts.end());
  5408. return true;
  5409. }
  5410. catch (Il2CppExceptionWrapper&)
  5411. {
  5412. //LOG_ERROR("TransformSubMethodBody failed: %s", ex.what());
  5413. metadata::MethodBodyCache::DisableInline(methodInfo);
  5414. return false;
  5415. }
  5416. return false;
  5417. }
  5418. }
  5419. }