BfStmtEvaluator.cpp 247 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707
  1. #include "BfCompiler.h"
  2. #include "BfSystem.h"
  3. #include "BfParser.h"
  4. #include "BfCodeGen.h"
  5. #include "BfExprEvaluator.h"
  6. #include <fcntl.h>
  7. #include "BfConstResolver.h"
  8. #include "BfMangler.h"
  9. #include "BeefySysLib/util/PerfTimer.h"
  10. #include "BeefySysLib/util/BeefPerf.h"
  11. #include "BfSourceClassifier.h"
  12. #include "BfAutoComplete.h"
  13. #include "BfDemangler.h"
  14. #include "BfResolvePass.h"
  15. #include "BfFixits.h"
  16. #include "BfIRCodeGen.h"
  17. #include "BfDefBuilder.h"
  18. #pragma warning(push)
  19. #pragma warning(disable:4141)
  20. #pragma warning(disable:4146)
  21. #pragma warning(disable:4291)
  22. #pragma warning(disable:4244)
  23. #pragma warning(disable:4267)
  24. #pragma warning(disable:4624)
  25. #pragma warning(disable:4800)
  26. #pragma warning(disable:4996)
  27. #include "llvm/IR/Module.h"
  28. #include "llvm/IR/Constants.h"
  29. #include "llvm/IR/GlobalValue.h"
  30. #include "llvm/IR/GlobalVariable.h"
  31. #include "llvm/ADT/ArrayRef.h"
  32. #include "llvm/IR/InlineAsm.h"
  33. #include "llvm/Support/FileSystem.h"
  34. #include "BeefySysLib/util/AllocDebug.h"
  35. #pragma warning(pop)
  36. USING_NS_BF;
  37. bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfScopeData* scopeData)
  38. {
  39. if ((((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)) ||
  40. (mBfIRBuilder->mIgnoreWrites)) && (deferredCallEntry->mDeferredBlock == NULL))
  41. {
  42. // For resolve entries, we only keep deferred blocks because we need to process them later so we can
  43. // resolve inside of them. This is also required for lambda bind scan-pass
  44. delete deferredCallEntry;
  45. return false;
  46. }
  47. if (mBfIRBuilder->mIgnoreWrites)
  48. {
  49. deferredCallEntry->mIgnored = true;
  50. scopeData->mDeferredCallEntries.PushBack(deferredCallEntry);
  51. return true;
  52. }
  53. // We don't need to do a "clear handlers" if we're just adding another dyn to an existing dyn list
  54. bool isDyn = mCurMethodState->mCurScope->IsDyn(scopeData);
  55. if (mCurMethodState->mPendingNullConditional != NULL)
  56. isDyn = true;
  57. deferredCallEntry->mOrigScopeArgs = deferredCallEntry->mScopeArgs;
  58. if (!isDyn)
  59. {
  60. mCurMethodState->mCurScope->ClearHandlers(scopeData);
  61. if (!mBfIRBuilder->mIgnoreWrites)
  62. {
  63. if ((IsTargetingBeefBackend()) && (deferredCallEntry->mModuleMethodInstance.mMethodInstance != NULL) &&
  64. (!mContext->IsSentinelMethod(deferredCallEntry->mModuleMethodInstance.mMethodInstance)))
  65. {
  66. SizedArray<BfIRType, 8> origParamTypes;
  67. BfIRType origReturnType;
  68. deferredCallEntry->mModuleMethodInstance.mMethodInstance->GetIRFunctionInfo(this, origReturnType, origParamTypes);
  69. int sretIdx = deferredCallEntry->mModuleMethodInstance.mMethodInstance->GetStructRetIdx();
  70. BF_ASSERT(origParamTypes.size() == deferredCallEntry->mScopeArgs.size() + ((sretIdx != -1) ? 1 : 0));
  71. int argIdx = 0;
  72. int paramIdx = 0;
  73. for (int argIdx = 0; argIdx < (int)deferredCallEntry->mScopeArgs.size(); argIdx++, paramIdx++)
  74. {
  75. if (argIdx == sretIdx)
  76. paramIdx++;
  77. auto scopeArg = deferredCallEntry->mScopeArgs[argIdx];
  78. if ((scopeArg.IsConst()) || (scopeArg.IsFake()))
  79. continue;
  80. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  81. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  82. auto allocaInst = mBfIRBuilder->CreateAlloca(origParamTypes[paramIdx]);
  83. mBfIRBuilder->ClearDebugLocation_Last();
  84. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  85. if (WantsLifetimes())
  86. {
  87. mBfIRBuilder->CreateLifetimeStart(allocaInst);
  88. mBfIRBuilder->ClearDebugLocation_Last();
  89. }
  90. mBfIRBuilder->CreateStore(scopeArg, allocaInst);
  91. mBfIRBuilder->ClearDebugLocation_Last();
  92. deferredCallEntry->mScopeArgs[argIdx] = allocaInst;
  93. if (WantsLifetimes())
  94. scopeData->mDeferredLifetimeEnds.push_back(allocaInst);
  95. }
  96. deferredCallEntry->mArgsNeedLoad = true;
  97. }
  98. }
  99. scopeData->mDeferredCallEntries.PushFront(deferredCallEntry);
  100. return true;
  101. }
  102. bool isLooped = mCurMethodState->mCurScope->IsLooped(scopeData);
  103. BfDeferredCallEntry* listEntry = NULL;
  104. if (!scopeData->mDeferredCallEntries.IsEmpty())
  105. {
  106. listEntry = scopeData->mDeferredCallEntries.mHead;
  107. if (!listEntry->IsDynList())
  108. listEntry = NULL;
  109. }
  110. auto deferredCallEntryType = ResolveTypeDef(mCompiler->mDeferredCallTypeDef);
  111. AddDependency(deferredCallEntryType, mCurTypeInstance, BfDependencyMap::DependencyFlag_Allocates);
  112. mBfIRBuilder->PopulateType(deferredCallEntryType);
  113. auto deferredCallEntryTypePtr = CreatePointerType(deferredCallEntryType);
  114. UpdateSrcPos(mCurMethodInstance->mMethodDef->GetRefNode(), BfSrcPosFlag_NoSetDebugLoc);
  115. if (listEntry == NULL)
  116. {
  117. listEntry = new BfDeferredCallEntry();
  118. if (!mBfIRBuilder->mIgnoreWrites)
  119. {
  120. listEntry->mDynCallTail = CreateAlloca(deferredCallEntryTypePtr, false, "deferredCallTail");
  121. if (WantsLifetimes())
  122. scopeData->mDeferredLifetimeEnds.push_back(listEntry->mDynCallTail);
  123. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  124. mBfIRBuilder->SaveDebugLocation();
  125. mBfIRBuilder->SetInsertPointAtStart(mCurMethodState->mIRInitBlock);
  126. auto scopeHead = &mCurMethodState->mHeadScope;
  127. if (scopeHead->mDIScope)
  128. mBfIRBuilder->SetCurrentDebugLocation(mCurFilePosition.mCurLine + 1, 0, scopeHead->mDIScope, BfIRMDNode());
  129. if (WantsLifetimes())
  130. mBfIRBuilder->CreateLifetimeStart(listEntry->mDynCallTail);
  131. auto storeInst = mBfIRBuilder->CreateStore(GetDefaultValue(deferredCallEntryTypePtr), listEntry->mDynCallTail);
  132. mBfIRBuilder->ClearDebugLocation(storeInst);
  133. if (WantsDebugInfo())
  134. {
  135. auto deferredCallEntryType = ResolveTypeDef(mCompiler->mDeferredCallTypeDef);
  136. auto deferredCallEntryTypePtr = CreatePointerType(deferredCallEntryType);
  137. String varName = StrFormat("__deferred%d", mCurMethodState->mDeferredLoopListCount);
  138. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  139. if (scopeHead->mDIScope)
  140. mBfIRBuilder->SetCurrentDebugLocation(mCurFilePosition.mCurLine + 1, 0, scopeHead->mDIScope, BfIRMDNode());
  141. mBfIRBuilder->CreateStatementStart();
  142. //TODO: Make this work for LLVM - we need a proper debug location
  143. //if (IsTargetingBeefBackend())
  144. {
  145. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(scopeHead->mDIScope, varName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(deferredCallEntryTypePtr));
  146. mBfIRBuilder->DbgInsertDeclare(listEntry->mDynCallTail, diVariable);
  147. }
  148. mCurMethodState->mDeferredLoopListCount++;
  149. }
  150. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  151. mBfIRBuilder->RestoreDebugLocation();
  152. }
  153. mCurMethodState->mCurScope->ClearHandlers(scopeData);
  154. scopeData->mDeferredCallEntries.PushFront(listEntry);
  155. }
  156. BfIRValue deferredAlloca;
  157. SizedArray<BfType*, 4> types;
  158. SizedArray<String, 8> memberNames;
  159. int instAlign = 1;
  160. int dataPos = 0;
  161. int instSize = 0;
  162. Array<int> memberPositions;
  163. String typeName;
  164. BfDeferredMethodCallData* deferredMethodCallData = NULL;
  165. if (deferredCallEntry->mDeferredBlock != NULL)
  166. {
  167. HashContext hashCtx;
  168. hashCtx.Mixin(deferredCallEntry->mDeferredBlock->GetSrcStart());
  169. auto parserData = deferredCallEntry->mDeferredBlock->GetParserData();
  170. if (parserData != NULL)
  171. hashCtx.MixinStr(parserData->mFileName);
  172. int64 blockId = BfDeferredMethodCallData::GenerateMethodId(this, hashCtx.Finish64());
  173. deferredCallEntry->mBlockId = blockId;
  174. auto deferType = deferredCallEntryType;
  175. BfIRType deferIRType;
  176. auto int64Type = GetPrimitiveType(BfTypeCode_Int64);
  177. types.push_back(int64Type);
  178. memberNames.push_back("__methodId");
  179. types.push_back(deferredCallEntryTypePtr);
  180. memberNames.push_back("__next");
  181. for (auto& capture : deferredCallEntry->mCaptures)
  182. {
  183. BfType* type = capture.mValue.mType;
  184. types.push_back(type);
  185. memberNames.push_back(capture.mName);
  186. }
  187. SizedArray<BfIRType, 4> llvmTypes;
  188. SizedArray<BfIRMDNode, 8> diFieldTypes;
  189. typeName = StrFormat("_BF_DeferredData_%s", BfTypeUtils::HashEncode64(blockId).c_str());
  190. auto valueType = ResolveTypeDef(mCompiler->mValueTypeTypeDef);
  191. llvmTypes.push_back(mBfIRBuilder->MapType(valueType));
  192. //int dataPos = 0;
  193. for (int i = 0; i < (int)memberNames.size(); i++)
  194. {
  195. auto type = types[i];
  196. auto memberName = memberNames[i];
  197. if (!type->IsValuelessType())
  198. {
  199. llvmTypes.push_back(mBfIRBuilder->MapType(type));
  200. instAlign = BF_MAX(instAlign, (int)type->mAlign);
  201. int alignSize = (int)type->mAlign;
  202. int dataSize = type->mSize;
  203. if (alignSize > 1)
  204. dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
  205. memberPositions.push_back(dataPos);
  206. dataPos += type->mSize;
  207. }
  208. }
  209. instSize = dataPos;
  210. deferIRType = mBfIRBuilder->CreateStructType(typeName);
  211. mBfIRBuilder->StructSetBody(deferIRType, llvmTypes, instSize, instAlign, false);
  212. auto prevInsertPoint = mBfIRBuilder->GetInsertBlock();
  213. if (!isLooped)
  214. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  215. deferredAlloca = mBfIRBuilder->CreateAlloca(deferIRType);
  216. mBfIRBuilder->SetAllocaAlignment(deferredAlloca, instAlign);
  217. mBfIRBuilder->SetAllocaNoChkStkHint(deferredAlloca);
  218. if (!isLooped)
  219. mBfIRBuilder->SetInsertPoint(prevInsertPoint);
  220. auto gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, 2); // mNext
  221. auto prevVal = mBfIRBuilder->CreateLoad(listEntry->mDynCallTail);
  222. mBfIRBuilder->CreateStore(prevVal, gepInstance);
  223. gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, 1); // mMethodId
  224. mBfIRBuilder->CreateStore(GetConstValue64(blockId), gepInstance);
  225. if (!deferredCallEntry->mCaptures.empty())
  226. {
  227. int dataIdx = 3;
  228. for (int captureIdx = 0; captureIdx < (int)deferredCallEntry->mCaptures.size(); captureIdx++)
  229. {
  230. auto& capture = deferredCallEntry->mCaptures[captureIdx];
  231. if (!capture.mValue.mType->IsValuelessType())
  232. {
  233. auto gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, dataIdx);
  234. mBfIRBuilder->CreateStore(capture.mValue.mValue, gepInstance);
  235. dataIdx++;
  236. }
  237. }
  238. }
  239. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateBitCast(deferredAlloca, mBfIRBuilder->MapType(deferredCallEntryTypePtr)), listEntry->mDynCallTail);
  240. deferredCallEntry->mDeferredAlloca = deferredAlloca;
  241. listEntry->mDynList.PushFront(deferredCallEntry);
  242. }
  243. else
  244. {
  245. auto& llvmArgs = deferredCallEntry->mScopeArgs;
  246. auto moduleMethodInstance = deferredCallEntry->mModuleMethodInstance;
  247. auto methodInstance = moduleMethodInstance.mMethodInstance;
  248. auto methodDef = methodInstance->mMethodDef;
  249. auto owningType = methodInstance->mMethodInstanceGroup->mOwner;
  250. auto voidType = GetPrimitiveType(BfTypeCode_None);
  251. auto voidPtrType = CreatePointerType(voidType);
  252. BfDeferredMethodCallData** deferredMethodCallDataPtr = NULL;
  253. if (mDeferredMethodCallData.TryGetValue(methodInstance, &deferredMethodCallDataPtr))
  254. {
  255. deferredMethodCallData = *deferredMethodCallDataPtr;
  256. }
  257. else
  258. {
  259. deferredMethodCallData = new BfDeferredMethodCallData();
  260. mDeferredMethodCallData[methodInstance] = deferredMethodCallData;
  261. deferredMethodCallData->mMethodId = BfDeferredMethodCallData::GenerateMethodId(this, methodInstance->mIdHash);
  262. auto int64Type = GetPrimitiveType(BfTypeCode_Int64);
  263. auto methodDef = moduleMethodInstance.mMethodInstance->mMethodDef;
  264. auto thisType = moduleMethodInstance.mMethodInstance->mMethodInstanceGroup->mOwner;
  265. types.push_back(int64Type);
  266. memberNames.push_back("__methodId");
  267. types.push_back(deferredCallEntryTypePtr);
  268. memberNames.push_back("__next");
  269. if (!methodDef->mIsStatic)
  270. {
  271. types.push_back(thisType);
  272. memberNames.push_back("__this");
  273. }
  274. for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
  275. {
  276. if (methodInstance->IsParamSkipped(paramIdx))
  277. paramIdx++;
  278. types.push_back(methodInstance->GetParamType(paramIdx));
  279. memberNames.push_back(methodInstance->GetParamName(paramIdx));
  280. }
  281. SizedArray<BfIRType, 4> llvmTypes;
  282. //String typeName;
  283. typeName += StrFormat("_BF_DeferredData_%s", BfTypeUtils::HashEncode64(deferredMethodCallData->mMethodId).c_str());
  284. BfLogSysM("Building type: %s from methodInstance:%p\n", typeName.c_str(), methodInstance);
  285. //Array<int> memberPositions;
  286. //int instAlign = 1;
  287. //int dataPos = 0;
  288. BF_ASSERT(types.size() == memberNames.size());
  289. for (int i = 0; i < (int)types.size(); i++)
  290. {
  291. auto type = types[i];
  292. auto memberName = memberNames[i];
  293. if (!type->IsValuelessType())
  294. {
  295. llvmTypes.push_back(mBfIRBuilder->MapType(type));
  296. instAlign = BF_MAX(instAlign, (int)type->mAlign);
  297. int alignSize = (int)type->mAlign;
  298. int dataSize = type->mSize;
  299. if (alignSize > 1)
  300. dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
  301. memberPositions.push_back(dataPos);
  302. dataPos += type->mSize;
  303. }
  304. }
  305. instSize = dataPos;
  306. deferredMethodCallData->mAlign = instAlign;
  307. deferredMethodCallData->mSize = instSize;
  308. deferredMethodCallData->mDeferType = mBfIRBuilder->CreateStructType(typeName);
  309. mBfIRBuilder->StructSetBody(deferredMethodCallData->mDeferType, llvmTypes, instSize, instAlign, false);
  310. deferredMethodCallData->mDeferTypePtr = mBfIRBuilder->GetPointerTo(deferredMethodCallData->mDeferType);
  311. }
  312. auto deferType = deferredMethodCallData->mDeferType;
  313. auto prevInsertPoint = mBfIRBuilder->GetInsertBlock();
  314. if (!isLooped)
  315. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  316. deferredAlloca = mBfIRBuilder->CreateAlloca(BfIRType(deferredMethodCallData->mDeferType));
  317. mBfIRBuilder->ClearDebugLocation(deferredAlloca);
  318. mBfIRBuilder->SetAllocaAlignment(deferredAlloca, deferredMethodCallData->mAlign);
  319. mBfIRBuilder->SetAllocaNoChkStkHint(deferredAlloca);
  320. if (!isLooped)
  321. mBfIRBuilder->SetInsertPoint(prevInsertPoint);
  322. auto gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, 1);
  323. auto prevVal = mBfIRBuilder->CreateLoad(listEntry->mDynCallTail);
  324. mBfIRBuilder->CreateStore(prevVal, gepInstance);
  325. gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, 0);
  326. mBfIRBuilder->CreateStore(GetConstValue64(deferredMethodCallData->mMethodId), gepInstance);
  327. int dataIdx = 2;
  328. int argIdx = 0;
  329. if (!methodDef->mIsStatic)
  330. {
  331. gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, 2);
  332. if (owningType->IsStruct())
  333. {
  334. if ((!methodDef->mIsMutating) && (owningType->IsSplattable()))
  335. {
  336. BfTypedValue splatVal(llvmArgs[0], owningType, BfTypedValueKind_ThisSplatHead);
  337. BfTypedValue aggVal = AggregateSplat(splatVal, &llvmArgs[0]);
  338. aggVal = LoadValue(aggVal);
  339. mBfIRBuilder->CreateStore(aggVal.mValue, gepInstance);
  340. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, owningType);
  341. }
  342. else
  343. {
  344. auto thisArg = mBfIRBuilder->CreateLoad(llvmArgs[0]);
  345. mBfIRBuilder->CreateStore(thisArg, gepInstance);
  346. argIdx++;
  347. }
  348. }
  349. else
  350. {
  351. mBfIRBuilder->CreateStore(llvmArgs[0], gepInstance);
  352. argIdx++;
  353. }
  354. dataIdx++;
  355. }
  356. for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++, dataIdx++)
  357. {
  358. if (methodInstance->IsParamSkipped(paramIdx))
  359. paramIdx++;
  360. auto paramType = methodInstance->GetParamType(paramIdx);
  361. bool paramIsSplat = methodInstance->GetParamIsSplat(paramIdx);
  362. gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredAlloca, 0, dataIdx/*, methodDef->mParams[paramIdx]->mName*/);
  363. if (paramType->IsStruct())
  364. {
  365. if (paramIsSplat)
  366. {
  367. BfTypedValue splatVal(llvmArgs[argIdx], paramType, BfTypedValueKind_SplatHead);
  368. BfTypedValue aggVal = AggregateSplat(splatVal, &llvmArgs[argIdx]);
  369. aggVal = LoadValue(aggVal);
  370. mBfIRBuilder->CreateStore(aggVal.mValue, gepInstance);
  371. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramType);
  372. }
  373. else
  374. {
  375. auto val = mBfIRBuilder->CreateLoad(llvmArgs[argIdx]);
  376. mBfIRBuilder->CreateStore(val, gepInstance);
  377. argIdx++;
  378. }
  379. }
  380. else
  381. {
  382. mBfIRBuilder->CreateStore(llvmArgs[argIdx], gepInstance);
  383. argIdx++;
  384. }
  385. }
  386. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateBitCast(deferredAlloca, mBfIRBuilder->MapType(deferredCallEntryTypePtr)), listEntry->mDynCallTail);
  387. deferredCallEntry->mDeferredAlloca = deferredAlloca;
  388. listEntry->mDynList.PushFront(deferredCallEntry);
  389. }
  390. if ((mBfIRBuilder->DbgHasInfo()) && (mCompiler->mOptions.mEmitDebugInfo) && (mCurMethodState->mCurScope->mDIScope))
  391. {
  392. auto int64Type = GetPrimitiveType(BfTypeCode_Int64);
  393. auto moduleMethodInstance = deferredCallEntry->mModuleMethodInstance;
  394. auto methodInstance = moduleMethodInstance.mMethodInstance;
  395. BfIRMDNode deferDIType;
  396. if ((deferredMethodCallData != NULL) && (deferredMethodCallData->mDeferDIType))
  397. {
  398. deferDIType = deferredMethodCallData->mDeferDIType;
  399. }
  400. else
  401. {
  402. BfIRMDNode diForwardDecl;
  403. SizedArray<BfIRMDNode, 8> diFieldTypes;
  404. if ((mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo))
  405. {
  406. String dbgTypeName;
  407. if (mCompiler->mOptions.IsCodeView())
  408. dbgTypeName += "_bf::";
  409. dbgTypeName += typeName;
  410. diForwardDecl = mBfIRBuilder->DbgCreateReplaceableCompositeType(llvm::dwarf::DW_TAG_structure_type, dbgTypeName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mFileInstance->mDIFile,
  411. mCurFilePosition.mCurLine, instSize * 8, instAlign * 8);
  412. if (methodInstance != NULL)
  413. {
  414. // We make a fake member to get inserted into the DbgModule data so we can show what method this deferred call goes to
  415. StringT<128> mangledName;
  416. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
  417. auto memberType = mBfIRBuilder->DbgCreateMemberType(diForwardDecl, mangledName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine,
  418. 0, 0, -1, 0, mBfIRBuilder->DbgGetType(int64Type));
  419. diFieldTypes.push_back(memberType);
  420. }
  421. }
  422. for (int i = 0; i < (int)types.size(); i++)
  423. {
  424. auto type = types[i];
  425. auto memberName = memberNames[i];
  426. if ((mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo))
  427. {
  428. int memberFlags = 0;
  429. auto memberType = mBfIRBuilder->DbgCreateMemberType(diForwardDecl, memberName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine,
  430. type->mSize * 8, type->mAlign * 8, memberPositions[i] * 8, memberFlags, mBfIRBuilder->DbgGetType(type));
  431. diFieldTypes.push_back(memberType);
  432. }
  433. }
  434. int diFlags = 0;
  435. mBfIRBuilder->DbgMakePermanent(diForwardDecl, BfIRMDNode(), diFieldTypes);
  436. deferDIType = mBfIRBuilder->DbgCreatePointerType(diForwardDecl);
  437. if (deferredMethodCallData != NULL)
  438. deferredMethodCallData->mDeferDIType = deferDIType;
  439. }
  440. // We don't actually want to see this, and it doesn't emit properly in LLVM CodeView anyway - it only accepts static allocs,
  441. // not dynamic allocas
  442. String varName = StrFormat("$__deferredCall_%d", mCurMethodState->mDeferredLoopListEntryCount);
  443. mCurMethodState->mDeferredLoopListEntryCount++;
  444. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  445. varName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, deferDIType);
  446. mBfIRBuilder->DbgInsertDeclare(deferredAlloca, diVariable);
  447. }
  448. return true;
  449. }
  450. BfDeferredCallEntry* BfModule::AddDeferredBlock(BfBlock* block, BfScopeData* scopeData, Array<BfDeferredCapture>* captures)
  451. {
  452. BfDeferredCallEntry* deferredCallEntry = new BfDeferredCallEntry();
  453. deferredCallEntry->mDeferredBlock = block;
  454. if (captures != NULL)
  455. deferredCallEntry->mCaptures = *captures;
  456. AddDeferredCallEntry(deferredCallEntry, scopeData);
  457. return deferredCallEntry;
  458. }
  459. BfDeferredCallEntry* BfModule::AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scopeData, BfAstNode* srcNode, bool bypassVirtual, bool doNullCheck)
  460. {
  461. BfDeferredCallEntry* deferredCallEntry = new BfDeferredCallEntry();
  462. BF_ASSERT(moduleMethodInstance);
  463. deferredCallEntry->mModuleMethodInstance = moduleMethodInstance;
  464. for (auto arg : llvmArgs)
  465. {
  466. deferredCallEntry->mScopeArgs.push_back(arg);
  467. }
  468. deferredCallEntry->mSrcNode = srcNode;
  469. deferredCallEntry->mBypassVirtual = bypassVirtual;
  470. deferredCallEntry->mDoNullCheck = doNullCheck;
  471. if (!AddDeferredCallEntry(deferredCallEntry, scopeData))
  472. return NULL;
  473. return deferredCallEntry;
  474. }
  475. void BfModule::EmitDeferredCall(BfModuleMethodInstance moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfDeferredBlockFlags flags)
  476. {
  477. if (moduleMethodInstance.mMethodInstance->GetOwner()->IsInstanceOf(mCompiler->mInternalTypeDef))
  478. {
  479. if (moduleMethodInstance.mMethodInstance->mMethodDef->mName.StartsWith("SetDeleted"))
  480. {
  481. intptr typeSize = 0;
  482. intptr typeAlign = 1;
  483. intptr clearSize = 0;
  484. bool isDynSize = false;
  485. bool mayBeZero = false;
  486. auto ptrValue = llvmArgs[0];
  487. BfIRValue arraySize;
  488. if ((moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted") ||
  489. (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeletedArray"))
  490. {
  491. auto constant = mBfIRBuilder->GetConstant(llvmArgs[1]);
  492. if (constant != NULL)
  493. typeSize = constant->mInt64;
  494. constant = mBfIRBuilder->GetConstant(llvmArgs[2]);
  495. if (constant != NULL)
  496. typeAlign = constant->mInt64;
  497. if (llvmArgs.size() >= 4)
  498. arraySize = llvmArgs[3];
  499. intptr allocSize = typeSize;
  500. if (arraySize)
  501. {
  502. allocSize = BF_ALIGN(typeSize, typeAlign);
  503. auto constant = mBfIRBuilder->GetConstant(arraySize);
  504. if (constant != NULL)
  505. allocSize = allocSize * (intptr)constant->mInt64;
  506. else
  507. {
  508. isDynSize = true;
  509. mayBeZero = true;
  510. }
  511. }
  512. clearSize = BF_MIN(allocSize, mSystem->mPtrSize);
  513. }
  514. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeletedX")
  515. {
  516. // Note: this infers that mayBeZero is false still, because the deferred call would not have
  517. // been added if the array size was zero
  518. typeSize = 1;
  519. clearSize = typeSize;
  520. arraySize = llvmArgs[1];
  521. isDynSize = true;
  522. }
  523. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted1")
  524. {
  525. clearSize = 1;
  526. }
  527. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted2")
  528. {
  529. clearSize = 2;
  530. }
  531. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted4")
  532. {
  533. clearSize = 4;
  534. }
  535. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted8")
  536. {
  537. clearSize = 8;
  538. }
  539. else if (moduleMethodInstance.mMethodInstance->mMethodDef->mName == "SetDeleted16")
  540. {
  541. clearSize = 16;
  542. }
  543. if (clearSize > 0)
  544. {
  545. BfTypeCode clearTypeCode = BfTypeCode_Int8;
  546. if (clearSize >= mSystem->mPtrSize)
  547. clearTypeCode = BfTypeCode_IntPtr;
  548. else if (clearSize >= 4)
  549. clearTypeCode = BfTypeCode_Int32;
  550. else if (clearSize >= 2)
  551. clearTypeCode = BfTypeCode_Int16;
  552. auto intType = GetPrimitiveType(clearTypeCode);
  553. auto intPtrType = CreatePointerType(intType);
  554. if (isDynSize)
  555. {
  556. if (clearSize >= mSystem->mPtrSize)
  557. {
  558. auto ddSize1Block = mBfIRBuilder->CreateBlock("DDSize1");
  559. auto ddDoneBlock = mBfIRBuilder->CreateBlock("DDDone");
  560. auto cmp = mBfIRBuilder->CreateCmpGT(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0), true);
  561. mBfIRBuilder->CreateCondBr(cmp, ddSize1Block, ddDoneBlock);
  562. mBfIRBuilder->AddBlock(ddSize1Block);
  563. mBfIRBuilder->SetInsertPoint(ddSize1Block);
  564. auto intPtrVal = mBfIRBuilder->CreateBitCast(ptrValue, mBfIRBuilder->MapType(intPtrType));
  565. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(clearTypeCode, (uint64)0xDDDDDDDDDDDDDDDDULL), intPtrVal);
  566. mBfIRBuilder->CreateBr(ddDoneBlock);
  567. mBfIRBuilder->AddBlock(ddDoneBlock);
  568. mBfIRBuilder->SetInsertPoint(ddDoneBlock);
  569. if ((flags & BfDeferredBlockFlag_MoveNewBlocksToEnd) != 0)
  570. {
  571. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddSize1Block);
  572. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddDoneBlock);
  573. }
  574. }
  575. else
  576. {
  577. // If we allocate at least this many then we can do an IntPtr-sized marking, otherwise just one element's worth
  578. int intPtrCount = (int)((mSystem->mPtrSize + typeSize - 1) / typeSize);
  579. BfIRBlock ddSizePtrBlock = mBfIRBuilder->CreateBlock("DDSizePtr");
  580. BfIRBlock ddCheck1Block = mBfIRBuilder->CreateBlock("DDCheck1");
  581. BfIRBlock ddSize1Block;
  582. if (mayBeZero)
  583. ddSize1Block = mBfIRBuilder->CreateBlock("DDSize1");
  584. BfIRBlock ddDoneBlock = mBfIRBuilder->CreateBlock("DDDone");
  585. auto intptrType = GetPrimitiveType(BfTypeCode_IntPtr);
  586. auto intptrPtrType = CreatePointerType(intptrType);
  587. auto cmpPtr = mBfIRBuilder->CreateCmpGTE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, intPtrCount), true);
  588. mBfIRBuilder->CreateCondBr(cmpPtr, ddSizePtrBlock, ddCheck1Block);
  589. mBfIRBuilder->AddBlock(ddSizePtrBlock);
  590. mBfIRBuilder->SetInsertPoint(ddSizePtrBlock);
  591. auto intptrPtrVal = mBfIRBuilder->CreateBitCast(ptrValue, mBfIRBuilder->MapType(intptrPtrType));
  592. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)0xDDDDDDDDDDDDDDDDULL), intptrPtrVal);
  593. mBfIRBuilder->CreateBr(ddDoneBlock);
  594. mBfIRBuilder->AddBlock(ddCheck1Block);
  595. mBfIRBuilder->SetInsertPoint(ddCheck1Block);
  596. if (mayBeZero)
  597. {
  598. auto cmp1 = mBfIRBuilder->CreateCmpGT(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0), true);
  599. mBfIRBuilder->CreateCondBr(cmp1, ddSize1Block, ddDoneBlock);
  600. mBfIRBuilder->AddBlock(ddSize1Block);
  601. mBfIRBuilder->SetInsertPoint(ddSize1Block);
  602. }
  603. auto intPtrVal = mBfIRBuilder->CreateBitCast(ptrValue, mBfIRBuilder->MapType(intPtrType));
  604. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(clearTypeCode, (uint64)0xDDDDDDDDDDDDDDDDULL), intPtrVal);
  605. mBfIRBuilder->CreateBr(ddDoneBlock);
  606. mBfIRBuilder->AddBlock(ddDoneBlock);
  607. mBfIRBuilder->SetInsertPoint(ddDoneBlock);
  608. if ((flags & BfDeferredBlockFlag_MoveNewBlocksToEnd) != 0)
  609. {
  610. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddSizePtrBlock);
  611. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddCheck1Block);
  612. if (mayBeZero)
  613. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddSize1Block);
  614. mCurMethodState->mCurScope->mAtEndBlocks.push_back(ddDoneBlock);
  615. }
  616. }
  617. }
  618. else
  619. {
  620. auto intPtrVal = mBfIRBuilder->CreateBitCast(ptrValue, mBfIRBuilder->MapType(intPtrType));
  621. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(clearTypeCode, (uint64)0xDDDDDDDDDDDDDDDDULL), intPtrVal);
  622. }
  623. }
  624. return;
  625. }
  626. }
  627. if (moduleMethodInstance.mMethodInstance == mContext->mValueTypeDeinitSentinel)
  628. {
  629. BF_ASSERT(llvmArgs.size() == 3);
  630. auto sizeConstant = mBfIRBuilder->GetConstant(llvmArgs[1]);
  631. int clearSize = BF_MIN(sizeConstant->mInt32, 32);
  632. auto alignConstant = mBfIRBuilder->GetConstant(llvmArgs[2]);
  633. int clearAlign = alignConstant->mInt32;
  634. mBfIRBuilder->CreateMemSet(llvmArgs[0], GetConstValue8(0xDD), GetConstValue(clearSize), clearAlign);
  635. return;
  636. }
  637. auto methodInstance = moduleMethodInstance.mMethodInstance;
  638. auto methodOwner = methodInstance->mMethodInstanceGroup->mOwner;
  639. bool isDtor = methodInstance->mMethodDef->mMethodType == BfMethodType_Dtor;
  640. bool isScopeDtor = isDtor && ((flags & BfDeferredBlockFlag_BypassVirtual) != 0);
  641. if ((isDtor) && (methodInstance->GetParamCount() != 0))
  642. {
  643. // Dtor declared with params
  644. AssertErrorState();
  645. return;
  646. }
  647. BfIRBlock nullLabel;
  648. BfIRBlock notNullLabel;
  649. if ((flags & BfDeferredBlockFlag_DoNullChecks) != 0)
  650. {
  651. nullLabel = mBfIRBuilder->CreateBlock("deferred.isNull");
  652. notNullLabel = mBfIRBuilder->CreateBlock("deferred.notNull");
  653. auto notNullVal = mBfIRBuilder->CreateIsNotNull(llvmArgs[0]);
  654. mBfIRBuilder->CreateCondBr(notNullVal, notNullLabel, nullLabel);
  655. mBfIRBuilder->AddBlock(notNullLabel);
  656. mBfIRBuilder->SetInsertPoint(notNullLabel);
  657. }
  658. bool skipAccessCheck = false;
  659. if ((flags & BfDeferredBlockFlag_SkipObjectAccessCheck) != 0)
  660. skipAccessCheck = true;
  661. if ((!methodInstance->mMethodDef->mIsStatic) && (methodOwner->IsObjectOrInterface()) && (!isScopeDtor) &&
  662. (!skipAccessCheck))
  663. {
  664. EmitObjectAccessCheck(BfTypedValue(llvmArgs[0], methodOwner));
  665. }
  666. BfExprEvaluator expressionEvaluator(this);
  667. expressionEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, ((flags & BfDeferredBlockFlag_BypassVirtual) != 0), llvmArgs);
  668. if ((flags & BfDeferredBlockFlag_DoNullChecks) != 0)
  669. {
  670. mBfIRBuilder->CreateBr(nullLabel);
  671. mBfIRBuilder->AddBlock(nullLabel);
  672. mBfIRBuilder->SetInsertPoint(nullLabel);
  673. if (!mBfIRBuilder->mIgnoreWrites)
  674. {
  675. if ((flags & BfDeferredBlockFlag_MoveNewBlocksToEnd) != 0)
  676. {
  677. mCurMethodState->mCurScope->mAtEndBlocks.push_back(notNullLabel);
  678. mCurMethodState->mCurScope->mAtEndBlocks.push_back(nullLabel);
  679. }
  680. }
  681. }
  682. }
  683. void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool moveBlocks)
  684. {
  685. if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (deferredCallEntry.mHandlerCount > 0))
  686. {
  687. // We only want to process deferred blocks once, otherwise it could significantly slow down autocompletion
  688. return;
  689. }
  690. deferredCallEntry.mHandlerCount++;
  691. if (deferredCallEntry.IsDynList())
  692. {
  693. EmitDeferredCallProcessor(deferredCallEntry.mDynList, deferredCallEntry.mDynCallTail);
  694. return;
  695. }
  696. if (deferredCallEntry.mDeferredBlock != NULL)
  697. {
  698. // Only show warnings on the first pass
  699. // For errors, show on the first pass OR as long as we haven't gotten any errors within this method. I'm not sure if there's a case
  700. // where the first emission succeeds but a subsequent one would fail, but we leave this logic to handle that possibility
  701. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, (deferredCallEntry.mHandlerCount > 1) && (mCurMethodInstance->mHasFailed));
  702. SetAndRestoreValue<bool> prevIgnoreWarnings(mIgnoreWarnings, (deferredCallEntry.mHandlerCount > 1));
  703. BfScopeData scopeData;
  704. mCurMethodState->AddScope(&scopeData);
  705. NewScopeState();
  706. for (auto& capture : deferredCallEntry.mCaptures)
  707. {
  708. BfLocalVariable* localVar = new BfLocalVariable();
  709. localVar->mIsReadOnly = true;
  710. localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  711. localVar->mReadFromId = 0;
  712. localVar->mName = capture.mName;
  713. localVar->mValue = capture.mValue.mValue;
  714. localVar->mResolvedType = capture.mValue.mType;
  715. if ((mBfIRBuilder->DbgHasInfo()) && (!localVar->mResolvedType->IsValuelessType()))
  716. {
  717. auto addr = CreateAlloca(localVar->mResolvedType);
  718. mBfIRBuilder->CreateAlignedStore(localVar->mValue, addr, localVar->mResolvedType->mAlign);
  719. localVar->mAddr = addr;
  720. }
  721. AddLocalVariableDef(localVar, true);
  722. }
  723. SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, deferredCallEntry.mEmitRefNode);
  724. VisitEmbeddedStatement(deferredCallEntry.mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
  725. RestoreScopeState();
  726. return;
  727. }
  728. auto args = deferredCallEntry.mScopeArgs;
  729. if (deferredCallEntry.mArgsNeedLoad)
  730. {
  731. for (auto& arg : args)
  732. {
  733. if (!arg.IsConst())
  734. arg = mBfIRBuilder->CreateLoad(arg);
  735. }
  736. }
  737. if (deferredCallEntry.mCastThis)
  738. {
  739. args[0] = mBfIRBuilder->CreateBitCast(args[0], mBfIRBuilder->MapTypeInstPtr(deferredCallEntry.mModuleMethodInstance.mMethodInstance->GetOwner()));
  740. }
  741. BfDeferredBlockFlags flags = BfDeferredBlockFlag_None;
  742. if (deferredCallEntry.mBypassVirtual)
  743. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_BypassVirtual);
  744. if (deferredCallEntry.mDoNullCheck)
  745. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_DoNullChecks | BfDeferredBlockFlag_SkipObjectAccessCheck | BfDeferredBlockFlag_MoveNewBlocksToEnd);
  746. if (moveBlocks)
  747. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_MoveNewBlocksToEnd);
  748. EmitDeferredCall(deferredCallEntry.mModuleMethodInstance, args, flags);
  749. }
  750. void BfModule::EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail)
  751. {
  752. int64 collisionId = 0;
  753. struct _CallInfo
  754. {
  755. BfModuleMethodInstance mModuleMethodInstance;
  756. bool mBypassVirtual;
  757. };
  758. //typedef std::map<int64, _CallInfo> MapType;
  759. //MapType methodInstanceMap;
  760. Dictionary<int64, _CallInfo> methodInstanceMap;
  761. int blockCount = 0;
  762. HashSet<BfMethodInstance*> nullCheckMethodSet;
  763. BfDeferredCallEntry* deferredCallEntry = callEntries.mHead;
  764. while (deferredCallEntry != NULL)
  765. {
  766. BfModuleMethodInstance moduleMethodInstance = deferredCallEntry->mModuleMethodInstance;
  767. int64 methodId = 0;
  768. if (moduleMethodInstance.mMethodInstance != NULL)
  769. {
  770. int64 idHash = moduleMethodInstance.mMethodInstance->mIdHash;
  771. auto deferredMethodCallData = mDeferredMethodCallData[moduleMethodInstance.mMethodInstance];
  772. BF_ASSERT(deferredMethodCallData->mMethodId != 0);
  773. //methodInstanceMap[deferredMethodCallData->mMethodId] = moduleMethodInstance;
  774. _CallInfo* callInfo = NULL;
  775. if (methodInstanceMap.TryAdd(deferredMethodCallData->mMethodId, NULL, &callInfo))
  776. {
  777. callInfo->mModuleMethodInstance = moduleMethodInstance;
  778. callInfo->mBypassVirtual = deferredCallEntry->mBypassVirtual;
  779. }
  780. else
  781. {
  782. // Only bypass virtual if ALL these calls are devirtualized
  783. callInfo->mBypassVirtual &= deferredCallEntry->mBypassVirtual;
  784. }
  785. }
  786. else
  787. blockCount++;
  788. if (deferredCallEntry->mDoNullCheck)
  789. nullCheckMethodSet.Add(deferredCallEntry->mModuleMethodInstance.mMethodInstance);
  790. deferredCallEntry = deferredCallEntry->mNext;
  791. }
  792. bool moveBlocks = mCurMethodState->mCurScope != mCurMethodState->mTailScope;
  793. auto valueScopeStart = ValueScopeStart();
  794. if (valueScopeStart)
  795. mBfIRBuilder->SetName(valueScopeStart, "deferredScopeVal");
  796. BfIRBlock condBB = mBfIRBuilder->CreateBlock("deferCall.cond", true);
  797. if (moveBlocks)
  798. mCurMethodState->mCurScope->mAtEndBlocks.push_back(condBB);
  799. mBfIRBuilder->CreateBr(condBB);
  800. auto deferredCallEntryType = ResolveTypeDef(mCompiler->mDeferredCallTypeDef);
  801. auto deferredCallEntryTypePtr = CreatePointerType(deferredCallEntryType);
  802. BfIRBlock bodyBB = mBfIRBuilder->CreateBlock("deferCall.body");
  803. if (moveBlocks)
  804. mCurMethodState->mCurScope->mAtEndBlocks.push_back(bodyBB);
  805. BfIRBlock endBB = mBfIRBuilder->CreateBlock("deferCall.end");
  806. if (moveBlocks)
  807. mCurMethodState->mCurScope->mAtEndBlocks.push_back(endBB);
  808. BfIRBlock exitBB = endBB;
  809. BfIRValue deferredCallTail;
  810. mBfIRBuilder->SetInsertPoint(condBB);
  811. deferredCallTail = mBfIRBuilder->CreateLoad(callTail);
  812. auto isNotNull = mBfIRBuilder->CreateIsNotNull(deferredCallTail);
  813. ValueScopeEnd(valueScopeStart);
  814. mBfIRBuilder->CreateCondBr(isNotNull, bodyBB, exitBB);
  815. mBfIRBuilder->AddBlock(bodyBB);
  816. mBfIRBuilder->SetInsertPoint(bodyBB);
  817. BfIRValue switchInst;
  818. bool wantsSwitch = ((int)methodInstanceMap.size() + blockCount) > 1;
  819. if (blockCount > 0)
  820. {
  821. // A block may embed a switch so we need a switch whenever we have blocks
  822. wantsSwitch = true;
  823. }
  824. if (mCurMethodState->mCancelledDeferredCall)
  825. wantsSwitch = true;
  826. if (wantsSwitch)
  827. {
  828. if (IsTargetingBeefBackend())
  829. deferredCallTail = mBfIRBuilder->CreateLoad(callTail);
  830. auto idPtr = mBfIRBuilder->CreateInBoundsGEP(deferredCallTail, 0, 1); // mMethodId
  831. auto id = mBfIRBuilder->CreateLoad(idPtr);
  832. switchInst = mBfIRBuilder->CreateSwitch(id, exitBB, (int)methodInstanceMap.size());
  833. ValueScopeEnd(valueScopeStart);
  834. }
  835. BfDeferredCallEntry* prevHead = callEntries.mHead;
  836. BfDeferredCallEntry* prevCallEntry = NULL;
  837. HashSet<BfDeferredCallEntry*> handledSet;
  838. deferredCallEntry = callEntries.mHead;
  839. while (deferredCallEntry != NULL)
  840. {
  841. auto block = deferredCallEntry->mDeferredBlock;
  842. if (block == NULL)
  843. {
  844. deferredCallEntry = deferredCallEntry->mNext;
  845. continue;
  846. }
  847. int64 blockId = deferredCallEntry->mBlockId;
  848. //auto itr = handledSet.insert(deferredCallEntry);
  849. //if (!itr.second)
  850. if (!handledSet.Add(deferredCallEntry))
  851. {
  852. // Already handled, can happen if we defer again within the block
  853. deferredCallEntry = deferredCallEntry->mNext;
  854. continue;
  855. }
  856. if (switchInst)
  857. {
  858. String caseName = StrFormat("deferCall.%s", BfTypeUtils::HashEncode64(blockId).c_str());
  859. auto caseBB = mBfIRBuilder->CreateBlock(caseName, true);
  860. if (moveBlocks)
  861. mCurMethodState->mCurScope->mAtEndBlocks.push_back(caseBB);
  862. mBfIRBuilder->AddSwitchCase(switchInst, GetConstValue64(blockId), caseBB);
  863. mBfIRBuilder->SetInsertPoint(caseBB);
  864. }
  865. // Update .mDeferredAlloca to use the deferredCallTail
  866. if (IsTargetingBeefBackend())
  867. deferredCallTail = mBfIRBuilder->CreateLoad(callTail);
  868. auto nextPtr = mBfIRBuilder->CreateInBoundsGEP(deferredCallTail, 0, 2); // mNext
  869. auto next = mBfIRBuilder->CreateLoad(nextPtr);
  870. mBfIRBuilder->CreateStore(next, callTail);
  871. deferredCallEntry->mDeferredAlloca = mBfIRBuilder->CreateBitCast(deferredCallTail, mBfIRBuilder->GetType(deferredCallEntry->mDeferredAlloca));
  872. int dataIdx = 3;
  873. // Update .mCaptures to contain the stored values at the time the defer occurred
  874. for (int captureIdx = 0; captureIdx < (int)deferredCallEntry->mCaptures.size(); captureIdx++)
  875. {
  876. auto& capture = deferredCallEntry->mCaptures[captureIdx];
  877. if (!capture.mValue.mType->IsValuelessType())
  878. {
  879. auto gepInstance = mBfIRBuilder->CreateInBoundsGEP(deferredCallEntry->mDeferredAlloca, 0, dataIdx);
  880. capture.mValue.mValue = mBfIRBuilder->CreateLoad(gepInstance);
  881. dataIdx++;
  882. }
  883. }
  884. auto prevHead = callEntries.mHead;
  885. EmitDeferredCall(*deferredCallEntry, moveBlocks);
  886. ValueScopeEnd(valueScopeStart);
  887. mBfIRBuilder->CreateBr(condBB);
  888. if (prevHead != callEntries.mHead)
  889. {
  890. // The list changed, start over and ignore anything we've already handled
  891. deferredCallEntry = callEntries.mHead;
  892. }
  893. else
  894. deferredCallEntry = deferredCallEntry->mNext;
  895. }
  896. // Blocks may have added new method types, so rebuild map
  897. if (blockCount > 0)
  898. {
  899. deferredCallEntry = callEntries.mHead;
  900. while (deferredCallEntry != NULL)
  901. {
  902. BfModuleMethodInstance moduleMethodInstance = deferredCallEntry->mModuleMethodInstance;
  903. if (moduleMethodInstance.mMethodInstance != NULL)
  904. {
  905. auto deferredMethodCallData = mDeferredMethodCallData[moduleMethodInstance.mMethodInstance];
  906. //methodInstanceMap.insert(MapType::value_type(deferredMethodCallData->mMethodId, moduleMethodInstance));
  907. _CallInfo* callInfo = NULL;
  908. if (methodInstanceMap.TryAdd(deferredMethodCallData->mMethodId, NULL, &callInfo))
  909. {
  910. callInfo->mModuleMethodInstance = moduleMethodInstance;
  911. callInfo->mBypassVirtual = deferredCallEntry->mBypassVirtual;
  912. }
  913. }
  914. deferredCallEntry = deferredCallEntry->mNext;
  915. }
  916. }
  917. BfExprEvaluator exprEvaluator(this);
  918. //for (auto itr = methodInstanceMap.begin(); itr != methodInstanceMap.end(); ++itr)
  919. for (auto& callInfoKV : methodInstanceMap)
  920. {
  921. auto moduleMethodInstance = callInfoKV.mValue.mModuleMethodInstance;
  922. bool bypassVirtual = callInfoKV.mValue.mBypassVirtual;
  923. auto methodInstance = moduleMethodInstance.mMethodInstance;
  924. auto methodDef = methodInstance->mMethodDef;
  925. auto methodOwner = methodInstance->mMethodInstanceGroup->mOwner;
  926. BfIRValue deferredCallInst = deferredCallTail;
  927. auto deferredMethodCallData = mDeferredMethodCallData[methodInstance];
  928. int64 methodId = deferredMethodCallData->mMethodId;
  929. if (switchInst)
  930. {
  931. String caseName = StrFormat("deferCall.%s", BfTypeUtils::HashEncode64(methodId).c_str());
  932. auto caseBB = mBfIRBuilder->CreateBlock(caseName, true);
  933. if (moveBlocks)
  934. mCurMethodState->mCurScope->mAtEndBlocks.push_back(caseBB);
  935. mBfIRBuilder->AddSwitchCase(switchInst, GetConstValue64(methodId), caseBB);
  936. mBfIRBuilder->SetInsertPoint(caseBB);
  937. }
  938. if (IsTargetingBeefBackend())
  939. deferredCallTail = mBfIRBuilder->CreateLoad(callTail);
  940. auto nextPtr = mBfIRBuilder->CreateInBoundsGEP(deferredCallTail, 0, 2); // mNext
  941. auto next = mBfIRBuilder->CreateLoad(nextPtr);
  942. mBfIRBuilder->CreateStore(next, callTail);
  943. deferredCallInst = mBfIRBuilder->CreateBitCast(deferredCallTail, deferredMethodCallData->mDeferTypePtr);
  944. int paramIdx = 0;
  945. if (!methodDef->mIsStatic)
  946. paramIdx = -1;
  947. SizedArray<BfIRValue, 8> llvmArgs;
  948. for (int argIdx = 0; paramIdx < methodInstance->GetParamCount(); argIdx++, paramIdx++)
  949. {
  950. auto argPtr = mBfIRBuilder->CreateInBoundsGEP(deferredCallInst, 0, argIdx + 2);
  951. bool isStruct = false;
  952. bool doSplat = methodInstance->GetParamIsSplat(paramIdx);;
  953. BfTypedValue typedVal;
  954. if (paramIdx == -1)
  955. {
  956. typedVal = BfTypedValue(argPtr, methodOwner, true);
  957. }
  958. else
  959. {
  960. auto paramType = methodInstance->GetParamType(paramIdx);
  961. typedVal = BfTypedValue(argPtr, paramType, true);
  962. }
  963. if (doSplat)
  964. {
  965. exprEvaluator.SplatArgs(typedVal, llvmArgs);
  966. continue;
  967. }
  968. if ((argIdx == 0) && (!methodDef->mIsStatic))
  969. {
  970. // 'this'
  971. isStruct = methodOwner->IsStruct();
  972. }
  973. else
  974. {
  975. while (methodInstance->IsParamSkipped(paramIdx))
  976. paramIdx++;
  977. if (paramIdx >= methodInstance->GetParamCount())
  978. break;
  979. auto paramType = methodInstance->GetParamType(paramIdx);
  980. isStruct = paramType->IsStruct();
  981. }
  982. if (isStruct)
  983. {
  984. llvmArgs.push_back(argPtr);
  985. }
  986. else
  987. {
  988. auto arg = mBfIRBuilder->CreateLoad(argPtr);
  989. llvmArgs.push_back(arg);
  990. }
  991. }
  992. BfDeferredBlockFlags flags = BfDeferredBlockFlag_None;
  993. if (moveBlocks)
  994. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_MoveNewBlocksToEnd);
  995. if (nullCheckMethodSet.Contains(moduleMethodInstance.mMethodInstance))
  996. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_DoNullChecks | BfDeferredBlockFlag_SkipObjectAccessCheck);
  997. if (bypassVirtual)
  998. flags = (BfDeferredBlockFlags)(flags | BfDeferredBlockFlag_BypassVirtual);
  999. EmitDeferredCall(moduleMethodInstance, llvmArgs, flags);
  1000. ValueScopeEnd(valueScopeStart);
  1001. mBfIRBuilder->CreateBr(condBB);
  1002. }
  1003. if (endBB)
  1004. {
  1005. mBfIRBuilder->AddBlock(endBB);
  1006. mBfIRBuilder->SetInsertPoint(endBB);
  1007. }
  1008. }
  1009. void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTypedValue initValue, BfTypedValue& checkResult)
  1010. {
  1011. BF_ASSERT(!localVar->mAddr);
  1012. localVar->mAddr = AllocLocalVariable(localVar->mResolvedType, localVar->mName);
  1013. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  1014. auto varType = localVar->mResolvedType;
  1015. AddDependency(varType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
  1016. if (!initValue)
  1017. {
  1018. AssertErrorState();
  1019. checkResult = BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), boolType);
  1020. return;
  1021. }
  1022. auto initType = initValue.mType;
  1023. bool isDynamicCast = false;
  1024. if (varType->IsGenericParam())
  1025. {
  1026. auto genericParamType = (BfGenericParamType*) varType;
  1027. auto genericParam = GetGenericParamInstance(genericParamType);
  1028. auto typeConstraint = genericParam->mTypeConstraint;
  1029. if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & BfGenericParamFlag_Class))
  1030. typeConstraint = mContext->mBfObjectType;
  1031. if (typeConstraint != NULL)
  1032. varType = typeConstraint;
  1033. initValue = GetDefaultTypedValue(varType);
  1034. }
  1035. BfTypeInstance* srcTypeInstance = initValue.mType->ToTypeInstance();
  1036. BfTypeInstance* varTypeInstance = varType->ToTypeInstance();
  1037. if (CanCast(initValue, varType))
  1038. {
  1039. if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()) && (!varType->IsVar()))
  1040. {
  1041. if (!IsInSpecializedSection())
  1042. {
  1043. if (initValue.mType != varType)
  1044. Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' because static cast cannot fail and a value of type '%s' can never be null",
  1045. TypeToString(varType).c_str()), checkNode);
  1046. else
  1047. Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' because a value of type '%s' can never be null",
  1048. TypeToString(varType).c_str()), checkNode);
  1049. }
  1050. }
  1051. }
  1052. // else if ((initType->IsInterface()) || (initType == mContext->mBfObjectType))
  1053. // {
  1054. // // Interface or System.Object -> *
  1055. // isDynamicCast = true;
  1056. // }
  1057. // else if ((srcTypeInstance != NULL) && (varTypeInstance != NULL) &&
  1058. // ((srcTypeInstance->IsObject()) && (TypeIsSubTypeOf(varTypeInstance, srcTypeInstance))))
  1059. // {
  1060. // // Class downcast
  1061. // isDynamicCast = true;
  1062. // }
  1063. // else if ((!CanCast(GetFakeTypedValue(varType), initType)) && (!initType->IsGenericParam()))
  1064. // {
  1065. // if (!IsInSpecializedSection())
  1066. // {
  1067. // Fail(StrFormat("Cannot convert type '%s' to '%s' via any conversion",
  1068. // TypeToString(initValue.mType).c_str(), TypeToString(varType).c_str()), checkNode);
  1069. // }
  1070. // }
  1071. if (!isDynamicCast)
  1072. {
  1073. //initValue = Cast(checkNode, initValue, varType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
  1074. initValue = Cast(checkNode, initValue, varType);
  1075. if (!initValue)
  1076. {
  1077. checkResult = BfTypedValue(GetConstValue(0, boolType), boolType);
  1078. }
  1079. else
  1080. {
  1081. if (localVar->mAddr)
  1082. {
  1083. initValue = LoadValue(initValue);
  1084. if (!initValue.mType->IsVar())
  1085. mBfIRBuilder->CreateAlignedStore(initValue.mValue, localVar->mAddr, initValue.mType->mAlign);
  1086. }
  1087. if (varType->IsVar())
  1088. {
  1089. checkResult = GetDefaultTypedValue(boolType, false, BfDefaultValueKind_Undef);
  1090. }
  1091. else if ((varType->IsPointer()) || (varType->IsObjectOrInterface()))
  1092. {
  1093. checkResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
  1094. }
  1095. else
  1096. {
  1097. checkResult = BfTypedValue(GetConstValue(1, boolType), boolType);
  1098. }
  1099. }
  1100. return;
  1101. }
  1102. if (mCompiler->IsAutocomplete())
  1103. {
  1104. auto allocaResult = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(boolType));
  1105. auto val = mBfIRBuilder->CreateLoad(allocaResult);
  1106. checkResult = BfTypedValue(val, boolType);
  1107. return;
  1108. }
  1109. int wantTypeId = 0;
  1110. if (!varType->IsGenericParam())
  1111. wantTypeId = varType->mTypeId;
  1112. auto objectType = mContext->mBfObjectType;
  1113. PopulateType(objectType, BfPopulateType_Full);
  1114. initValue = LoadValue(initValue);
  1115. auto prevBB = mBfIRBuilder->GetInsertBlock();
  1116. auto matchBB = mBfIRBuilder->CreateBlock("is.match");
  1117. auto endBB = mBfIRBuilder->CreateBlock("is.done");
  1118. BfIRValue boolResult = CreateAlloca(boolType);
  1119. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), boolResult);
  1120. EmitDynamicCastCheck(initValue, varType, matchBB, endBB);
  1121. AddBasicBlock(matchBB);
  1122. mBfIRBuilder->CreateStore(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), boolResult);
  1123. mBfIRBuilder->CreateBr(endBB);
  1124. AddBasicBlock(endBB);
  1125. checkResult = BfTypedValue(mBfIRBuilder->CreateLoad(boolResult), boolType);
  1126. }
  1127. BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfExprEvaluator* exprEvaluator)
  1128. {
  1129. if (mCurMethodState == NULL)
  1130. {
  1131. Fail("Invalid variable declaration", varDecl);
  1132. return NULL;
  1133. }
  1134. BfAutoComplete* bfAutocomplete = NULL;
  1135. // Just a check
  1136. mBfIRBuilder->GetInsertBlock();
  1137. if (mCompiler->mResolvePassData != NULL)
  1138. bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
  1139. if (bfAutocomplete != NULL)
  1140. bfAutocomplete->CheckTypeRef(varDecl->mTypeRef, true, true);
  1141. bool isConst = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Const);
  1142. bool isReadOnly = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_ReadOnly);
  1143. bool isStatic = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Static);
  1144. BfLocalVariable* localDef = new BfLocalVariable();
  1145. if (varDecl->mNameNode != NULL)
  1146. {
  1147. varDecl->mNameNode->ToString(localDef->mName);
  1148. localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
  1149. }
  1150. else
  1151. {
  1152. localDef->mName = "val";
  1153. }
  1154. localDef->mIsStatic = isStatic;
  1155. bool handledExprBoolResult = false;
  1156. bool handledVarInit = false;
  1157. bool handledVarStore = false;
  1158. BfType* unresolvedType = NULL;
  1159. BfType* resolvedType = NULL;
  1160. BfTypedValue initValue;
  1161. bool hadVarType = false;
  1162. bool isLet = varDecl->mTypeRef->IsA<BfLetTypeReference>();
  1163. bool initHandled = false;
  1164. auto _DoConditionalInit = [&](BfType* expectedType)
  1165. {
  1166. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  1167. auto _EmitCond = [&](BfIRValue condVal, BfTypedValue initValue)
  1168. {
  1169. initValue = Cast(varDecl->mInitializer, initValue, expectedType);
  1170. if (!initValue)
  1171. return;
  1172. initHandled = true;
  1173. if (localDef->mIsReadOnly)
  1174. {
  1175. if ((initValue.IsReadOnly()) ||
  1176. (initValue.mKind == BfTypedValueKind_TempAddr))
  1177. {
  1178. localDef->mAddr = initValue.mValue;
  1179. exprEvaluator->mResult = BfTypedValue(condVal, boolType);
  1180. return;
  1181. }
  1182. }
  1183. localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
  1184. auto doAssignBlock = mBfIRBuilder->CreateBlock("assign");
  1185. auto skipAssignBlock = mBfIRBuilder->CreateBlock("skipAssign");
  1186. auto insertBlock = mBfIRBuilder->GetInsertBlock();
  1187. mBfIRBuilder->CreateCondBr(condVal, doAssignBlock, skipAssignBlock);
  1188. mBfIRBuilder->AddBlock(doAssignBlock);
  1189. mBfIRBuilder->SetInsertPoint(doAssignBlock);
  1190. initValue = LoadValue(initValue);
  1191. mBfIRBuilder->CreateStore(initValue.mValue, localDef->mAddr);
  1192. mBfIRBuilder->CreateBr(skipAssignBlock);
  1193. mBfIRBuilder->AddBlock(skipAssignBlock);
  1194. mBfIRBuilder->SetInsertPoint(skipAssignBlock);
  1195. auto phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2);
  1196. mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), insertBlock);
  1197. mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), doAssignBlock);
  1198. exprEvaluator->mResult = BfTypedValue(phiVal, boolType);
  1199. };
  1200. bool handled = false;
  1201. if ((initValue) && (initValue.mType->IsPayloadEnum()))
  1202. {
  1203. auto typeInst = initValue.mType->ToTypeInstance();
  1204. PopulateType(typeInst);
  1205. BfType* outType = NULL;
  1206. int tagId = -1;
  1207. if (typeInst->GetResultInfo(outType, tagId))
  1208. {
  1209. int dscDataIdx = -1;
  1210. auto dscType = typeInst->GetDiscriminatorType(&dscDataIdx);
  1211. BfIRValue dscVal = ExtractValue(initValue, dscDataIdx);
  1212. auto eqVal = mBfIRBuilder->CreateCmpEQ(dscVal, GetConstValue(tagId, dscType));
  1213. exprEvaluator->mResult = BfTypedValue(eqVal, boolType);
  1214. PopulateType(outType);
  1215. if (!outType->IsValuelessType())
  1216. {
  1217. auto outPtrType = CreatePointerType(outType);
  1218. initValue = MakeAddressable(initValue);
  1219. auto payloadVal = mBfIRBuilder->CreateBitCast(initValue.mValue, mBfIRBuilder->MapType(outPtrType));
  1220. auto payload = BfTypedValue(payloadVal, outType, true);
  1221. if ((initValue.mKind == BfTypedValueKind_ReadOnlyAddr) ||
  1222. (initValue.mKind == BfTypedValueKind_TempAddr) ||
  1223. (initValue.mKind == BfTypedValueKind_ReadOnlyTempAddr))
  1224. payload.mKind = initValue.mKind;
  1225. _EmitCond(eqVal, payload);
  1226. }
  1227. handled = true;
  1228. }
  1229. }
  1230. if (handled)
  1231. {
  1232. handledExprBoolResult = true;
  1233. handledVarInit = true;
  1234. handledVarStore = true;
  1235. }
  1236. else if ((initValue) && (initValue.mType->IsNullable()))
  1237. {
  1238. auto underlyingType = initValue.mType->GetUnderlyingType();
  1239. exprEvaluator->mResult = BfTypedValue(ExtractValue(initValue, 2), boolType);
  1240. handledExprBoolResult = true;
  1241. if (!resolvedType->IsNullable())
  1242. {
  1243. if (initValue.IsAddr())
  1244. initValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(initValue.mValue, 0, 1), initValue.mType->GetUnderlyingType(), true);
  1245. else
  1246. initValue = BfTypedValue(mBfIRBuilder->CreateExtractValue(initValue.mValue, 1), initValue.mType->GetUnderlyingType());
  1247. }
  1248. if ((initValue) && (!initValue.mType->IsValuelessType()))
  1249. {
  1250. _EmitCond(exprEvaluator->mResult.mValue, initValue);
  1251. handledVarStore = true;
  1252. }
  1253. handledVarInit = true;
  1254. }
  1255. else if (initValue)
  1256. {
  1257. BfAstNode* refNode = varDecl;
  1258. if (varDecl->mInitializer != NULL)
  1259. refNode = varDecl->mInitializer;
  1260. TryInitVar(refNode, localDef, initValue, exprEvaluator->mResult);
  1261. handledExprBoolResult = true;
  1262. handledVarInit = true;
  1263. handledVarStore = true;
  1264. }
  1265. };
  1266. if ((varDecl->mTypeRef->IsA<BfVarTypeReference>()) || (isLet))
  1267. {
  1268. hadVarType = true;
  1269. if (varDecl->mInitializer == NULL)
  1270. {
  1271. if (!isLet)
  1272. {
  1273. BfLocalVarEntry* shadowEntry;
  1274. if (mCurMethodState->mLocalVarSet.TryGet(BfLocalVarEntry(localDef), &shadowEntry))
  1275. {
  1276. auto prevLocal = shadowEntry->mLocalVar;
  1277. if (prevLocal->mLocalVarIdx >= mCurMethodState->GetLocalStartIdx())
  1278. {
  1279. BfExprEvaluator exprEvaluator(this);
  1280. initValue = exprEvaluator.LoadLocal(prevLocal);
  1281. resolvedType = initValue.mType;
  1282. unresolvedType = resolvedType;
  1283. localDef->mLocalVarId = prevLocal->mLocalVarId;
  1284. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  1285. localDef->mIsShadow = true;
  1286. exprEvaluator.mResultLocalVarRefNode = varDecl->mNameNode;
  1287. exprEvaluator.mResultLocalVar = prevLocal;
  1288. exprEvaluator.CheckResultForReading(initValue);
  1289. if (bfAutocomplete != NULL)
  1290. bfAutocomplete->CheckVarResolution(varDecl->mTypeRef, resolvedType);
  1291. }
  1292. }
  1293. }
  1294. if (!initValue)
  1295. {
  1296. Fail("Implicitly-typed variables must be initialized", varDecl);
  1297. initValue = GetDefaultTypedValue(mContext->mBfObjectType);
  1298. }
  1299. }
  1300. else
  1301. {
  1302. if (isConst)
  1303. {
  1304. BfConstResolver constResolver(this);
  1305. initValue = constResolver.Resolve(varDecl->mInitializer);
  1306. }
  1307. else
  1308. {
  1309. BfExprEvaluator valExprEvaluator(this);
  1310. valExprEvaluator.mAllowReadOnlyReference = isLet;
  1311. initValue = CreateValueFromExpression(valExprEvaluator, varDecl->mInitializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_AllowSplat | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_VariableDeclaration));
  1312. if ((exprEvaluator != NULL) && (initValue))
  1313. {
  1314. if (initValue.mType->IsNullable())
  1315. {
  1316. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  1317. initValue = LoadValue(initValue);
  1318. exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateExtractValue(initValue.mValue, 2), boolType);
  1319. handledExprBoolResult = true;
  1320. initValue = BfTypedValue(mBfIRBuilder->CreateExtractValue(initValue.mValue, 1), initValue.mType->GetUnderlyingType());
  1321. }
  1322. else
  1323. {
  1324. auto typeInst = initValue.mType->ToTypeInstance();
  1325. if (typeInst != NULL)
  1326. {
  1327. PopulateType(typeInst);
  1328. BfType* outType = NULL;
  1329. int tagId = -1;
  1330. if (typeInst->GetResultInfo(outType, tagId))
  1331. {
  1332. handledExprBoolResult = true;
  1333. unresolvedType = outType;
  1334. resolvedType = outType;
  1335. isReadOnly = isLet;
  1336. localDef->mIsReadOnly = isLet;
  1337. _DoConditionalInit(outType);
  1338. }
  1339. }
  1340. }
  1341. }
  1342. }
  1343. }
  1344. if (!initValue)
  1345. {
  1346. initValue = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Var));
  1347. }
  1348. if (initValue.mType->IsNull())
  1349. {
  1350. Fail("Implicitly-typed variables cannot be initialized to 'null'", varDecl->mInitializer);
  1351. initValue = GetDefaultTypedValue(mContext->mBfObjectType);
  1352. }
  1353. if (unresolvedType == NULL)
  1354. unresolvedType = initValue.mType;
  1355. resolvedType = unresolvedType;
  1356. if ((initValue.IsTempAddr()) && (!localDef->mAddr) && (initValue.mType == resolvedType))
  1357. {
  1358. // Take over value
  1359. localDef->mAddr = initValue.mValue;
  1360. handledVarInit = true;
  1361. if (isLet)
  1362. {
  1363. localDef->mValue = mBfIRBuilder->CreateLoad(localDef->mAddr);
  1364. }
  1365. }
  1366. if (bfAutocomplete != NULL)
  1367. bfAutocomplete->CheckVarResolution(varDecl->mTypeRef, resolvedType);
  1368. }
  1369. else
  1370. {
  1371. BfTypeState typeState;
  1372. typeState.mCurVarInitializer = varDecl->mInitializer;
  1373. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  1374. BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef);
  1375. if (varDecl->mInitializer != NULL)
  1376. flags = (BfResolveTypeRefFlags)(flags | BfResolveTypeRefFlag_AllowInferredSizedArray);
  1377. unresolvedType = ResolveTypeRef(varDecl->mTypeRef, BfPopulateType_Data, flags);
  1378. if (unresolvedType == NULL)
  1379. unresolvedType = GetPrimitiveType(BfTypeCode_Var);
  1380. resolvedType = unresolvedType;
  1381. }
  1382. auto _CheckConst = [&]
  1383. {
  1384. if (initValue.mValue.IsConst())
  1385. {
  1386. auto constant = mBfIRBuilder->GetConstant(initValue.mValue);
  1387. // NullPtr is stand-in for GlobalVar during autocomplete
  1388. if ((constant->mConstType == BfConstType_GlobalVar) ||
  1389. (constant->mTypeCode == BfTypeCode_NullPtr))
  1390. {
  1391. // Not really constant
  1392. // localNeedsAddr = false;
  1393. // isConst = false;
  1394. // initHandled = true;
  1395. // localDef->mValue = initValue.mValue;
  1396. if (GetStringPoolIdx(initValue.mValue, mBfIRBuilder) == -1)
  1397. isConst = false;
  1398. }
  1399. }
  1400. };
  1401. localDef->mResolvedType = resolvedType;
  1402. localDef->mIsReadOnly = isReadOnly;
  1403. if (!initHandled)
  1404. {
  1405. if (isLet)
  1406. {
  1407. localDef->mIsReadOnly = true;
  1408. if (initValue)
  1409. {
  1410. if ((initValue.mValue) && (initValue.mValue.IsConst()))
  1411. {
  1412. isConst = true;
  1413. }
  1414. }
  1415. }
  1416. }
  1417. _CheckConst();
  1418. bool localNeedsAddr = false;
  1419. bool allowValueAccess = true;
  1420. if (mHasFullDebugInfo)
  1421. {
  1422. //if (!IsTargetingBeefBackend())
  1423. if (!isConst)
  1424. localNeedsAddr = true;
  1425. /*if (mCurMethodInstance->mMethodDef->mName != "Boop2")
  1426. dbgNeedsAddr = true;*/
  1427. }
  1428. // This is required because of lifetime and LLVM domination rules for certain instances of variable declarations in binary conditionals.
  1429. // IE: if ((something) && (let a = somethingElse))
  1430. if ((exprEvaluator != NULL) && (!isConst))
  1431. {
  1432. localNeedsAddr = true;
  1433. allowValueAccess = false;
  1434. }
  1435. if ((varDecl->mEqualsNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!initHandled))
  1436. {
  1437. mCompiler->mResolvePassData->mAutoComplete->CheckEmptyStart(varDecl->mEqualsNode, resolvedType);
  1438. }
  1439. BfIRInitType initType = BfIRInitType_NotSet;
  1440. if (varDecl->mInitializer != NULL)
  1441. {
  1442. initType = BfIRInitType_NotNeeded_AliveOnDecl;
  1443. if ((!initValue) && (!initHandled))
  1444. {
  1445. if ((isConst) || (isStatic))
  1446. {
  1447. BfConstResolver constResolver(this);
  1448. initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_ActualizeValues);
  1449. if (!initValue)
  1450. initValue = GetDefaultTypedValue(resolvedType);
  1451. }
  1452. else if (varDecl->mInitializer->IsA<BfUninitializedExpression>())
  1453. {
  1454. // Fake 'is assigned'
  1455. }
  1456. else
  1457. { //
  1458. auto expectedType = resolvedType;
  1459. if (expectedType->IsRef())
  1460. expectedType = expectedType->GetUnderlyingType();
  1461. BfExprEvaluator valExprEvaluator(this);
  1462. valExprEvaluator.mAllowReadOnlyReference = isReadOnly;
  1463. initValue = CreateValueFromExpression(valExprEvaluator, varDecl->mInitializer, expectedType, (BfEvalExprFlags)(BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_VariableDeclaration));
  1464. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  1465. if (exprEvaluator != NULL)
  1466. _DoConditionalInit(expectedType);
  1467. if ((!handledVarInit) && (initValue))
  1468. initValue = Cast(varDecl->mInitializer, initValue, resolvedType, BfCastFlags_PreferAddr);
  1469. }
  1470. if ((initValue) && (resolvedType->IsUndefSizedArray()))
  1471. {
  1472. resolvedType = initValue.mType;
  1473. unresolvedType = resolvedType;
  1474. }
  1475. }
  1476. if ((!handledVarInit) && (!isConst))
  1477. {
  1478. if (initValue)
  1479. {
  1480. // Handled later
  1481. }
  1482. else if (varDecl->mInitializer->IsA<BfUninitializedExpression>())
  1483. {
  1484. // Fake 'is assigned'
  1485. initType = BfIRInitType_Uninitialized;
  1486. }
  1487. else
  1488. {
  1489. AssertErrorState();
  1490. }
  1491. }
  1492. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  1493. }
  1494. else
  1495. {
  1496. if (isConst)
  1497. {
  1498. Fail("Const locals must be initialized", varDecl->mModSpecifier);
  1499. initValue = GetDefaultTypedValue(resolvedType, true);
  1500. }
  1501. else if (isReadOnly)
  1502. {
  1503. Fail("Readonly locals must be initialized", varDecl->mModSpecifier);
  1504. initValue = GetDefaultTypedValue(resolvedType, true);
  1505. }
  1506. else if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(varDecl->mTypeRef))
  1507. {
  1508. Fail("Ref locals must be initialized", refTypeRef->mRefToken);
  1509. }
  1510. else
  1511. {
  1512. BF_ASSERT(!resolvedType->IsRef());
  1513. }
  1514. }
  1515. PopulateType(resolvedType);
  1516. AddDependency(resolvedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
  1517. localDef->mResolvedType = resolvedType;
  1518. _CheckConst();
  1519. if (isStatic)
  1520. {
  1521. NOP;
  1522. }
  1523. if ((initValue.mKind == BfTypedValueKind_TempAddr) && (!initHandled))
  1524. {
  1525. BF_ASSERT(initValue.IsAddr());
  1526. BF_ASSERT(initValue.mType->IsComposite());
  1527. handledVarInit = true;
  1528. handledVarStore = true;
  1529. if (!localDef->mAddr)
  1530. {
  1531. localDef->mAddr = initValue.mValue;
  1532. if (localDef->mIsReadOnly)
  1533. localDef->mValue = mBfIRBuilder->CreateLoad(localDef->mAddr);
  1534. }
  1535. if (WantsLifetimes())
  1536. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(localDef->mAddr);
  1537. }
  1538. if ((!localDef->mAddr) && (!isConst) && (!isStatic) && ((!localDef->mIsReadOnly) || (localNeedsAddr)))
  1539. {
  1540. if ((exprEvaluator != NULL) && (exprEvaluator->mResultIsTempComposite))
  1541. {
  1542. //TODO: Can we remove this one?
  1543. BF_ASSERT(initValue.IsAddr());
  1544. BF_ASSERT(initValue.mType->IsComposite());
  1545. localDef->mAddr = initValue.mValue;
  1546. }
  1547. else
  1548. localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
  1549. }
  1550. if (isStatic)
  1551. {
  1552. String name = mModuleName + "_" + mCurMethodInstance->mMethodDef->mName + "_" + localDef->mName;
  1553. HashContext closureHashCtx;
  1554. closureHashCtx.Mixin(varDecl->mSrcStart);
  1555. uint64 closureHash = closureHashCtx.Finish64();
  1556. name += "$";
  1557. name += BfTypeUtils::HashEncode64(closureHash);
  1558. initValue = LoadValue(initValue);
  1559. if ((initValue) && (!initValue.mValue.IsConst()))
  1560. {
  1561. Fail("Static local variables can only be initialized with a const value", varDecl->mInitializer);
  1562. initValue = BfTypedValue();
  1563. }
  1564. localDef->mAddr = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(localDef->mResolvedType), false, BfIRLinkageType_Internal, initValue.mValue, name);;
  1565. initHandled = true;
  1566. }
  1567. bool wantsStore = false;
  1568. if ((initValue) && (!handledVarStore) && (!isConst) && (!initHandled))
  1569. {
  1570. initValue = LoadValue(initValue);
  1571. if (initValue.IsSplat())
  1572. {
  1573. BF_ASSERT(!mIsComptimeModule);
  1574. if (!localDef->mAddr)
  1575. localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
  1576. AggregateSplatIntoAddr(initValue, localDef->mAddr);
  1577. initHandled = true;
  1578. }
  1579. else
  1580. {
  1581. initValue = AggregateSplat(initValue);
  1582. localDef->mValue = initValue.mValue;
  1583. if ((localDef->mAddr) && (!localDef->mResolvedType->IsValuelessType()))
  1584. {
  1585. if (!initValue.mType->IsVar())
  1586. wantsStore = true;
  1587. }
  1588. else
  1589. {
  1590. BF_ASSERT(isReadOnly || isLet || initValue.mType->IsValuelessType() || (mBfIRBuilder->mIgnoreWrites));
  1591. }
  1592. }
  1593. }
  1594. if ((localDef->mIsReadOnly) && (!isConst) && (!localDef->mValue) && (!initHandled))
  1595. {
  1596. if (!resolvedType->IsValuelessType())
  1597. {
  1598. AssertErrorState();
  1599. initValue = GetDefaultTypedValue(resolvedType);
  1600. localDef->mValue = initValue.mValue;
  1601. }
  1602. }
  1603. if ((!localDef->mAddr) && (!isConst) && ((!localDef->mIsReadOnly) || (localNeedsAddr)))
  1604. {
  1605. localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
  1606. }
  1607. if ((exprEvaluator != NULL) && (!handledExprBoolResult))
  1608. {
  1609. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  1610. if (!initValue)
  1611. {
  1612. AssertErrorState();
  1613. exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), boolType);
  1614. }
  1615. else if ((resolvedType->IsPointer()) || (resolvedType->IsObjectOrInterface()))
  1616. {
  1617. exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateIsNotNull(initValue.mValue), boolType);
  1618. }
  1619. else if (resolvedType->IsVar())
  1620. {
  1621. exprEvaluator->mResult = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean), false, BfDefaultValueKind_Undef);
  1622. }
  1623. else
  1624. {
  1625. // Always true
  1626. if ((!IsInSpecializedSection()) && (!resolvedType->IsGenericParam()))
  1627. Warn(BfWarning_CS0472_ValueTypeNullCompare, StrFormat("Variable declaration is always 'true' since a value of type '%s' can never be null",
  1628. TypeToString(initValue.mType).c_str()), varDecl);
  1629. exprEvaluator->mResult = BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), boolType);
  1630. }
  1631. }
  1632. if ((unresolvedType->IsGenericParam()) && (resolvedType->IsValuelessType()) && (mHasFullDebugInfo))
  1633. {
  1634. // We do this in order to be able to bind to lines that contain valueless variable declarations in some generics
  1635. // We don't need to do this in non-generics because the breakpoint will just move to the next line that actually has instructions
  1636. EmitEnsureInstructionAt();
  1637. }
  1638. if ((resolvedType->IsVoid()) && (!IsInSpecializedSection()))
  1639. {
  1640. Warn(0, StrFormat("Variable '%s' is declared as 'void'", localDef->mName.c_str()), varDecl->mTypeRef);
  1641. }
  1642. if ((!handledVarInit) && (isConst))
  1643. localDef->mConstValue = initValue.mValue;
  1644. if (!allowValueAccess)
  1645. localDef->mValue = BfIRValue();
  1646. if (!localDef->mIsShadow)
  1647. CheckVariableDef(localDef);
  1648. ValidateAllocation(localDef->mResolvedType, varDecl->mTypeRef);
  1649. if ((exprEvaluator == NULL) && (varDecl->GetSourceData() != NULL))
  1650. UpdateSrcPos(varDecl);
  1651. localDef->Init();
  1652. if (localDef->mConstValue)
  1653. initType = BfIRInitType_NotNeeded;
  1654. BfLocalVariable* localVar = AddLocalVariableDef(localDef, true, false, BfIRValue(), initType);
  1655. if (wantsStore)
  1656. mBfIRBuilder->CreateStore(initValue.mValue, localVar->mAddr);
  1657. return localVar;
  1658. }
  1659. BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfTypedValue val, bool updateSrcLoc, bool forceAddr)
  1660. {
  1661. if (varDecl->mEqualsNode != NULL)
  1662. Fail("Unexpected initialization", varDecl->mEqualsNode);
  1663. if (varDecl->mInitializer != NULL)
  1664. CreateValueFromExpression(varDecl->mInitializer);
  1665. auto isLet = varDecl->mTypeRef->IsA<BfLetTypeReference>();
  1666. auto isVar = varDecl->mTypeRef->IsA<BfVarTypeReference>();
  1667. bool isRef = false;
  1668. if (auto varRefTypeReference = BfNodeDynCast<BfVarRefTypeReference>(varDecl->mTypeRef))
  1669. {
  1670. BF_ASSERT(val.IsAddr());
  1671. isRef = true;
  1672. isLet = varRefTypeReference->mVarToken->GetToken() == BfToken_Let;
  1673. isVar = varRefTypeReference->mVarToken->GetToken() == BfToken_Var;
  1674. }
  1675. else
  1676. {
  1677. BF_ASSERT(!val.IsAddr());
  1678. }
  1679. auto autoComplete = mCompiler->GetAutoComplete();
  1680. if ((autoComplete != NULL) && ((isLet) || (isVar)))
  1681. autoComplete->CheckVarResolution(varDecl->mTypeRef, val.mType);
  1682. // BfType* type = val.mType;
  1683. // if (type == NULL)
  1684. // {
  1685. // type = ResolveTypeRef(varDecl->mTypeRef);
  1686. // if (type == NULL)
  1687. // type = mContext->mBfObjectType;
  1688. // }
  1689. BfType* type = NULL;
  1690. if ((isLet) || (isVar))
  1691. {
  1692. type = val.mType;
  1693. }
  1694. else
  1695. {
  1696. type = ResolveTypeRef(varDecl->mTypeRef);
  1697. }
  1698. if (type == NULL)
  1699. {
  1700. type = GetPrimitiveType(BfTypeCode_Var);
  1701. val = GetDefaultTypedValue(type);
  1702. }
  1703. if ((type->IsVar()) || (type->IsLet()))
  1704. {
  1705. }
  1706. if (isRef)
  1707. {
  1708. type = CreateRefType(type);
  1709. }
  1710. BfLocalVariable* localDef = new BfLocalVariable();
  1711. if (varDecl->mNameNode != NULL)
  1712. varDecl->mNameNode->ToString(localDef->mName);
  1713. localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
  1714. localDef->mResolvedType = type;
  1715. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  1716. localDef->mValue = val.mValue;
  1717. if (isLet)
  1718. {
  1719. localDef->mIsReadOnly = true;
  1720. }
  1721. if ((!localDef->mIsReadOnly) || (mHasFullDebugInfo) || (forceAddr))
  1722. {
  1723. localDef->mAddr = AllocLocalVariable(localDef->mResolvedType, localDef->mName);
  1724. if ((val.mValue) && (!localDef->mResolvedType->IsValuelessType()) && (!localDef->mResolvedType->IsVar()))
  1725. {
  1726. if (val.IsSplat())
  1727. AggregateSplatIntoAddr(val, localDef->mAddr);
  1728. else
  1729. mBfIRBuilder->CreateAlignedStore(val.mValue, localDef->mAddr, localDef->mResolvedType->mAlign);
  1730. }
  1731. if (forceAddr)
  1732. localDef->mValue = BfIRValue();
  1733. }
  1734. CheckVariableDef(localDef);
  1735. if ((updateSrcLoc) && (varDecl->GetSourceData() != NULL))
  1736. UpdateSrcPos(varDecl);
  1737. localDef->Init();
  1738. return AddLocalVariableDef(localDef, true);
  1739. }
  1740. void BfModule::CheckTupleVariableDeclaration(BfTupleExpression* tupleExpr, BfType* initType)
  1741. {
  1742. if (initType == NULL)
  1743. return;
  1744. BfTypeInstance* initTupleType = NULL;
  1745. if ((initType != NULL) && (initType->IsTuple()))
  1746. initTupleType = (BfTypeInstance*)initType;
  1747. if (initTupleType != NULL)
  1748. {
  1749. mBfIRBuilder->PopulateType(initTupleType);
  1750. AddDependency(initTupleType, mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
  1751. int paramCountDiff = (int)tupleExpr->mValues.size() - (int)initTupleType->mFieldInstances.size();
  1752. if (paramCountDiff > 0)
  1753. {
  1754. Fail(StrFormat("Too many variable names, expected %d fewer.", paramCountDiff), tupleExpr->mValues[(int)initTupleType->mFieldInstances.size()]);
  1755. }
  1756. else if (paramCountDiff < 0)
  1757. {
  1758. BfAstNode* refNode = tupleExpr->mCloseParen;
  1759. if (refNode == NULL)
  1760. refNode = tupleExpr;
  1761. Fail(StrFormat("Too few variable names, expected %d more.", -paramCountDiff), refNode);
  1762. }
  1763. }
  1764. else
  1765. {
  1766. Fail(StrFormat("Value result type '%s' must be a tuple type to be applicable for tuple decomposition", TypeToString(initType).c_str()), tupleExpr);
  1767. }
  1768. }
  1769. void BfModule::HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock)
  1770. {
  1771. BfTypeInstance* initTupleType = NULL;
  1772. if ((initTupleValue) && (initTupleValue.mType->IsTuple()))
  1773. initTupleType = (BfTypeInstance*)initTupleValue.mType;
  1774. CheckTupleVariableDeclaration(tupleExpr, initTupleValue.mType);
  1775. for (int varIdx = 0; varIdx < (int)tupleExpr->mValues.size(); varIdx++)
  1776. {
  1777. BfType* resolvedType = NULL;
  1778. BfTypedValue initValue;
  1779. if ((initTupleType != NULL) && (varIdx < (int)initTupleType->mFieldInstances.size()))
  1780. {
  1781. auto fieldInstance = &initTupleType->mFieldInstances[varIdx];
  1782. auto fieldDef = fieldInstance->GetFieldDef();
  1783. resolvedType = fieldInstance->GetResolvedType();
  1784. if (fieldInstance->mDataIdx != -1)
  1785. {
  1786. if (initTupleValue.IsAddr())
  1787. {
  1788. initValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(initTupleValue.mValue, 0, fieldInstance->mDataIdx), resolvedType, true);
  1789. initValue = LoadValue(initValue);
  1790. }
  1791. else
  1792. initValue = BfTypedValue(mBfIRBuilder->CreateExtractValue(initTupleValue.mValue, fieldInstance->mDataIdx), resolvedType);
  1793. }
  1794. BfTupleNameNode* tupleNameNode = NULL;
  1795. if (varIdx < (int)tupleExpr->mNames.size())
  1796. tupleNameNode = tupleExpr->mNames[varIdx];
  1797. if (!fieldDef->IsUnnamedTupleField())
  1798. {
  1799. if (tupleNameNode != NULL)
  1800. {
  1801. if (fieldDef->mName != tupleNameNode->mNameNode->ToString())
  1802. {
  1803. Fail(StrFormat("Mismatched tuple field name, expected '%s'", fieldDef->mName.c_str()), tupleNameNode->mNameNode);
  1804. }
  1805. }
  1806. }
  1807. else if ((tupleNameNode != NULL) && (tupleNameNode->mNameNode != NULL))
  1808. {
  1809. Fail(StrFormat("Unexpected tuple field name, expected unnamed tuple field", fieldDef->mName.c_str()), tupleNameNode->mNameNode);
  1810. }
  1811. }
  1812. else
  1813. {
  1814. resolvedType = mContext->mBfObjectType;
  1815. initValue = GetDefaultTypedValue(resolvedType);
  1816. }
  1817. BfExpression* varNameNode = tupleExpr->mValues[varIdx];
  1818. if (!varNameNode->IsExact<BfIdentifierNode>())
  1819. {
  1820. if (BfTupleExpression* innerTupleExpr = BfNodeDynCast<BfTupleExpression>(varNameNode))
  1821. {
  1822. HandleTupleVariableDeclaration(varDecl, innerTupleExpr, initValue, isReadOnly, isConst, false, declBlock);
  1823. }
  1824. else if (!varNameNode->IsExact<BfUninitializedExpression>())
  1825. Fail("Variable name expected", varNameNode);
  1826. continue;
  1827. }
  1828. bool initHandled = false;
  1829. BfLocalVariable* localDef = new BfLocalVariable();
  1830. varNameNode->ToString(localDef->mName);
  1831. localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varNameNode);
  1832. localDef->mResolvedType = resolvedType;
  1833. localDef->mReadFromId = 0; // Don't give usage errors for binds
  1834. if (isReadOnly)
  1835. {
  1836. localDef->mIsReadOnly = true;
  1837. if ((initValue) && (initValue.mValue.IsConst()))
  1838. {
  1839. isConst = true;
  1840. }
  1841. }
  1842. CheckVariableDef(localDef);
  1843. if ((!isConst) && ((forceAddr) || (!localDef->mIsReadOnly) || (mHasFullDebugInfo)))
  1844. {
  1845. localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
  1846. }
  1847. if ((varDecl != NULL) && (varDecl->mEqualsNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!initHandled))
  1848. {
  1849. mCompiler->mResolvePassData->mAutoComplete->CheckEmptyStart(varDecl->mEqualsNode, resolvedType);
  1850. }
  1851. if ((varDecl == NULL) || (varDecl->mInitializer != NULL))
  1852. {
  1853. if ((!isConst) && (!initHandled))
  1854. {
  1855. if (initValue)
  1856. {
  1857. if (!forceAddr)
  1858. localDef->mValue = initValue.mValue;
  1859. if (localDef->mAddr)
  1860. {
  1861. mBfIRBuilder->CreateStore(initValue.mValue, localDef->mAddr);
  1862. }
  1863. }
  1864. else if ((varDecl == NULL) || (varDecl->mInitializer->IsA<BfUninitializedExpression>()))
  1865. {
  1866. // Fake 'is assigned'
  1867. }
  1868. else
  1869. {
  1870. AssertErrorState();
  1871. }
  1872. }
  1873. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  1874. }
  1875. else if ((varDecl != NULL) && (varDecl->mInitializer == NULL))
  1876. {
  1877. if (auto refTypeRef = BfNodeDynCast<BfRefTypeRef>(varDecl->mTypeRef))
  1878. {
  1879. Fail("Ref variables must be initialized", refTypeRef->mRefToken);
  1880. }
  1881. else
  1882. {
  1883. BF_ASSERT(!localDef->mResolvedType->IsRef());
  1884. }
  1885. }
  1886. if (isConst)
  1887. localDef->mConstValue = initValue.mValue;
  1888. CheckVariableDef(localDef);
  1889. if ((varDecl != NULL) && (varDecl->GetSourceData() != NULL))
  1890. UpdateSrcPos(varDecl);
  1891. localDef->Init();
  1892. auto defBlock = mBfIRBuilder->GetInsertBlock();
  1893. if (declBlock != NULL)
  1894. mBfIRBuilder->SetInsertPoint(*declBlock);
  1895. AddLocalVariableDef(localDef, true, false, BfIRValue(), BfIRInitType_NotNeeded);
  1896. if (declBlock != NULL)
  1897. mBfIRBuilder->SetInsertPoint(defBlock);
  1898. }
  1899. }
  1900. void BfModule::HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl)
  1901. {
  1902. BfAutoComplete* bfAutocomplete = mCompiler->GetAutoComplete();
  1903. if (bfAutocomplete != NULL)
  1904. bfAutocomplete->CheckTypeRef(varDecl->mTypeRef, true);
  1905. BfTupleExpression* tupleExpr = BfNodeDynCast<BfTupleExpression>(varDecl->mNameNode);
  1906. bool isConst = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Const);
  1907. bool isReadOnly = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_ReadOnly);
  1908. BfTypedValue initTupleValue;
  1909. bool hadVarType = false;
  1910. bool isLet = varDecl->mTypeRef->IsA<BfLetTypeReference>();
  1911. bool isVar = varDecl->mTypeRef->IsA<BfVarTypeReference>();
  1912. bool wasVarOrLet = isVar || isLet;
  1913. if ((!isLet) && (!isVar))
  1914. {
  1915. ResolveTypeRef(varDecl->mTypeRef);
  1916. Fail("'var' or 'let' expected", varDecl->mTypeRef);
  1917. isVar = true;
  1918. }
  1919. if ((isVar) || (isLet))
  1920. {
  1921. hadVarType = true;
  1922. if (varDecl->mInitializer == NULL)
  1923. {
  1924. Fail("Implicitly-typed variables must be initialized", varDecl);
  1925. initTupleValue = GetDefaultTypedValue(mContext->mBfObjectType);
  1926. }
  1927. else
  1928. {
  1929. if (isConst)
  1930. {
  1931. BfConstResolver constResolver(this);
  1932. initTupleValue = constResolver.Resolve(varDecl->mInitializer);
  1933. }
  1934. else
  1935. {
  1936. initTupleValue = CreateValueFromExpression(varDecl->mInitializer, NULL);
  1937. }
  1938. }
  1939. initTupleValue = LoadValue(initTupleValue);
  1940. if ((bfAutocomplete != NULL) && (wasVarOrLet))
  1941. bfAutocomplete->CheckVarResolution(varDecl->mTypeRef, initTupleValue.mType);
  1942. }
  1943. bool isCompatible = false;
  1944. if (initTupleValue)
  1945. HandleTupleVariableDeclaration(varDecl, tupleExpr, initTupleValue, isLet || isReadOnly, isConst, false);
  1946. else
  1947. AssertErrorState();
  1948. }
  1949. void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray<BfExpression*>& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlockStart, BfIRBlock& matchedBlockEnd, BfIRBlock& falseBlockStart, BfIRBlock& falseBlockEnd, bool& hadConditional, bool clearOutOnMismatch)
  1950. {
  1951. SetAndRestoreValue<bool> prevInCondBlock(mCurMethodState->mInConditionalBlock);
  1952. auto tupleType = tupleVal.mType->ToTypeInstance();
  1953. struct DeferredAssign
  1954. {
  1955. BfExpression* mExpr;
  1956. BfTypedValue mArgValue;
  1957. BfTypedValue mTupleElement;
  1958. int mFieldIdx;
  1959. };
  1960. Array<DeferredAssign> deferredAssigns;
  1961. auto autoComplete = mCompiler->GetAutoComplete();
  1962. for (int tupleFieldIdx = 0; tupleFieldIdx < (int)tupleType->mFieldInstances.size(); tupleFieldIdx++)
  1963. {
  1964. auto tupleFieldInstance = &tupleType->mFieldInstances[tupleFieldIdx];
  1965. if (tupleFieldIdx >= arguments.size())
  1966. {
  1967. BfError* error = Fail(StrFormat("Not enough parameters specified, expected %d more.", tupleType->mFieldInstances.size() - (int)arguments.size()), tooFewRef);
  1968. break;
  1969. }
  1970. BfTypedValue tupleElement;
  1971. if (tupleFieldInstance->mDataIdx >= 0)
  1972. {
  1973. tupleElement = ExtractValue(tupleVal, tupleFieldInstance, tupleFieldInstance->mDataIdx);
  1974. }
  1975. else
  1976. tupleElement = GetDefaultTypedValue(tupleFieldInstance->GetResolvedType());
  1977. auto expr = BfNodeDynCast<BfExpression>(arguments[tupleFieldIdx]);
  1978. if (auto varDecl = BfNodeDynCast<BfVariableDeclaration>(expr))
  1979. {
  1980. bool isVarOrLet = (varDecl->mTypeRef->IsExact<BfLetTypeReference>()) || (varDecl->mTypeRef->IsExact<BfVarTypeReference>());
  1981. bool isRef = false;
  1982. if (varDecl->mTypeRef->IsExact<BfVarRefTypeReference>())
  1983. {
  1984. isVarOrLet = true;
  1985. isRef = true;
  1986. }
  1987. if (!isVarOrLet)
  1988. {
  1989. auto wantType = ResolveTypeRef(varDecl->mTypeRef);
  1990. if (wantType == NULL)
  1991. wantType = mContext->mBfObjectType;
  1992. if (wantType != NULL)
  1993. tupleElement = Cast(varDecl->mTypeRef, tupleElement, wantType);
  1994. if (!tupleElement)
  1995. tupleElement = GetDefaultTypedValue(wantType);
  1996. }
  1997. PopulateType(tupleElement.mType);
  1998. if (!isRef)
  1999. tupleElement = LoadValue(tupleElement);
  2000. auto localVar = HandleVariableDeclaration(varDecl, tupleElement, false, true);
  2001. localVar->mReadFromId = 0; // Don't give usage errors for binds
  2002. continue;
  2003. }
  2004. if (auto uninitExpr = BfNodeDynCast<BfUninitializedExpression>(expr))
  2005. {
  2006. continue;
  2007. }
  2008. if (tupleFieldInstance->mDataIdx >= 0)
  2009. {
  2010. if (auto tupleExpr = BfNodeDynCast<BfTupleExpression>(expr))
  2011. {
  2012. if (tupleElement.mType->IsTuple())
  2013. {
  2014. BfAstNode* tooFewRef = tupleExpr->mCloseParen;
  2015. if (tupleExpr->mValues.size() > 0)
  2016. tooFewRef = tupleExpr->mValues[tupleExpr->mValues.size() - 1];
  2017. if (tooFewRef == NULL)
  2018. tooFewRef = tupleExpr->mOpenParen;
  2019. HandleCaseEnumMatch_Tuple(tupleElement, tupleExpr->mValues, tooFewRef, phiVal, matchedBlockStart, matchedBlockEnd, falseBlockStart, falseBlockEnd, hadConditional, clearOutOnMismatch);
  2020. continue;
  2021. }
  2022. }
  2023. }
  2024. if (expr == NULL)
  2025. {
  2026. // Error would have occured in the parser
  2027. //AssertErrorState();
  2028. }
  2029. else
  2030. {
  2031. mCurMethodState->mInConditionalBlock = true;
  2032. auto tupleElementAddr = tupleElement;
  2033. BfTypedValue exprResult;
  2034. if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(expr))
  2035. {
  2036. if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(invocationExpr->mTarget))
  2037. {
  2038. if (memberRefExpr->mTarget == NULL)
  2039. {
  2040. if (tupleElement.mType->IsPayloadEnum())
  2041. {
  2042. auto intType = GetPrimitiveType(BfTypeCode_Int32);
  2043. BfTypedValue enumTagVal;
  2044. if (tupleElement.IsAddr())
  2045. {
  2046. enumTagVal = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(tupleElement.mValue, 0, 2), intType, true);
  2047. enumTagVal = LoadValue(enumTagVal);
  2048. }
  2049. else
  2050. enumTagVal = BfTypedValue(mBfIRBuilder->CreateExtractValue(tupleElement.mValue, 2), intType, false);
  2051. int uncondTagId = -1;
  2052. bool hadConditional = false;
  2053. exprResult = TryCaseEnumMatch(tupleElementAddr, enumTagVal, expr, NULL, NULL, NULL, uncondTagId, hadConditional, clearOutOnMismatch);
  2054. }
  2055. }
  2056. }
  2057. }
  2058. if (!exprResult)
  2059. {
  2060. tupleElement = LoadValue(tupleElement);
  2061. bool isMatchedBlockEnd = matchedBlockEnd == mBfIRBuilder->GetInsertBlock();
  2062. bool isFalseBlockEnd = falseBlockEnd == mBfIRBuilder->GetInsertBlock();
  2063. BfExprEvaluator exprEvaluator(this);
  2064. exprEvaluator.mExpectingType = tupleFieldInstance->GetResolvedType();
  2065. exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowOutExpr;
  2066. if (mCurMethodState->mDeferredLocalAssignData != NULL)
  2067. {
  2068. SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true);
  2069. SetAndRestoreValue<bool> prevIfMayBeSkipped(mCurMethodState->mDeferredLocalAssignData->mIfMayBeSkipped, true);
  2070. exprEvaluator.Evaluate(expr);
  2071. }
  2072. else
  2073. {
  2074. exprEvaluator.Evaluate(expr);
  2075. }
  2076. if (isMatchedBlockEnd)
  2077. matchedBlockEnd = mBfIRBuilder->GetInsertBlock();
  2078. if (isFalseBlockEnd)
  2079. falseBlockEnd = mBfIRBuilder->GetInsertBlock();
  2080. auto argValue = exprEvaluator.mResult;
  2081. if (!argValue)
  2082. continue;
  2083. if (argValue.mType->IsRef())
  2084. {
  2085. auto refType = (BfRefType*)argValue.mType;
  2086. if (refType->mRefKind != BfRefType::RefKind_Out)
  2087. {
  2088. BfAstNode* refNode = expr;
  2089. if (auto unaryOperatorExpr = BfNodeDynCast<BfUnaryOperatorExpression>(expr))
  2090. refNode = unaryOperatorExpr->mOpToken;
  2091. Fail("Only 'out' refs can be used to assign to an existing value", refNode);
  2092. }
  2093. DeferredAssign deferredAssign = { expr, argValue, tupleElement, tupleFieldIdx };
  2094. deferredAssigns.push_back(deferredAssign);
  2095. if (mCurMethodState->mDeferredLocalAssignData != NULL)
  2096. {
  2097. SetAndRestoreValue<bool> prevIsIfCondition(mCurMethodState->mDeferredLocalAssignData->mIsIfCondition, true);
  2098. SetAndRestoreValue<bool> prevIfMayBeSkipped(mCurMethodState->mDeferredLocalAssignData->mIfMayBeSkipped, true);
  2099. exprEvaluator.MarkResultAssigned();
  2100. }
  2101. else
  2102. {
  2103. exprEvaluator.MarkResultAssigned();
  2104. }
  2105. continue;
  2106. }
  2107. if (!argValue.mType->IsValueType())
  2108. argValue = LoadValue(argValue);
  2109. argValue = Cast(expr, argValue, tupleFieldInstance->GetResolvedType());
  2110. if (!argValue)
  2111. continue;
  2112. exprEvaluator.PerformBinaryOperation(expr, expr, BfBinaryOp_Equality, expr, BfBinOpFlag_NoClassify, tupleElement, argValue);
  2113. exprResult = exprEvaluator.mResult;
  2114. }
  2115. if (exprResult)
  2116. {
  2117. hadConditional = true;
  2118. if (phiVal)
  2119. {
  2120. auto insertBlock = mBfIRBuilder->GetInsertBlock();
  2121. mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), insertBlock);
  2122. }
  2123. matchedBlockStart = matchedBlockEnd = mBfIRBuilder->CreateBlock("match", false);
  2124. mBfIRBuilder->CreateCondBr(exprResult.mValue, matchedBlockStart, falseBlockStart);
  2125. mBfIRBuilder->AddBlock(matchedBlockStart);
  2126. mBfIRBuilder->SetInsertPoint(matchedBlockStart);
  2127. }
  2128. }
  2129. }
  2130. if (!deferredAssigns.empty())
  2131. mBfIRBuilder->SetInsertPoint(matchedBlockEnd);
  2132. // We assign these only after the value checks succeed
  2133. for (auto& deferredAssign : deferredAssigns)
  2134. {
  2135. auto argValue = RemoveRef(deferredAssign.mArgValue);
  2136. auto tupleElement = Cast(deferredAssign.mExpr, deferredAssign.mTupleElement, argValue.mType);
  2137. if (!tupleElement)
  2138. continue;
  2139. tupleElement = LoadValue(tupleElement);
  2140. if (!tupleElement.mType->IsValuelessType())
  2141. mBfIRBuilder->CreateStore(tupleElement.mValue, argValue.mValue);
  2142. }
  2143. if ((clearOutOnMismatch) && (!deferredAssigns.IsEmpty()))
  2144. {
  2145. auto curInsertPoint = mBfIRBuilder->GetInsertBlock();
  2146. mBfIRBuilder->SetInsertPoint(falseBlockEnd);
  2147. for (auto& deferredAssign : deferredAssigns)
  2148. {
  2149. auto tupleFieldInstance = &tupleType->mFieldInstances[deferredAssign.mFieldIdx];
  2150. // We have to re-process the expr because we haven't done it in this branch, and then clear the result out
  2151. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, mHadBuildError); // Don't fail twice
  2152. BfExprEvaluator exprEvaluator(this);
  2153. exprEvaluator.mExpectingType = tupleFieldInstance->GetResolvedType();
  2154. exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowOutExpr;
  2155. exprEvaluator.Evaluate(deferredAssign.mExpr);
  2156. auto argValue = exprEvaluator.mResult;
  2157. if (!argValue)
  2158. continue;
  2159. mBfIRBuilder->CreateMemSet(argValue.mValue, GetConstValue8(0), GetConstValue(argValue.mType->mSize), GetConstValue(argValue.mType->mAlign));
  2160. }
  2161. falseBlockEnd = mBfIRBuilder->GetInsertBlock();
  2162. mBfIRBuilder->SetInsertPoint(curInsertPoint);
  2163. }
  2164. if (arguments.size() > tupleType->mFieldInstances.size())
  2165. {
  2166. for (int i = (int)tupleType->mFieldInstances.size(); i < (int)arguments.size(); i++)
  2167. {
  2168. // For autocomplete and such
  2169. auto expr = arguments[i];
  2170. if (expr != NULL)
  2171. CreateValueFromExpression(expr);
  2172. }
  2173. BfAstNode* errorRef = arguments[(int)tupleType->mFieldInstances.size()];
  2174. BfError* error = Fail(StrFormat("Too many arguments, expected %d fewer.", arguments.size() - tupleType->mFieldInstances.size()), errorRef);
  2175. }
  2176. }
  2177. BfTypedValue BfModule::TryCaseTupleMatch(BfTypedValue tupleVal, BfTupleExpression* tupleExpr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, bool& hadConditional, bool clearOutOnMismatch)
  2178. {
  2179. if (!tupleVal.mType->IsTuple())
  2180. return BfTypedValue();
  2181. auto tupleType = (BfTypeInstance*)tupleVal.mType;
  2182. BfAstNode* tooFewRef = tupleExpr->mCloseParen;
  2183. if ((tooFewRef == NULL) && (!tupleExpr->mCommas.IsEmpty()))
  2184. tooFewRef = tupleExpr->mCommas[tupleExpr->mCommas.size() - 1];
  2185. else if (tooFewRef == NULL)
  2186. tooFewRef = tupleExpr->mOpenParen;
  2187. ///
  2188. auto autoComplete = mCompiler->GetAutoComplete();
  2189. bool wasCapturingMethodInfo = false;
  2190. if (autoComplete != NULL)
  2191. {
  2192. wasCapturingMethodInfo = autoComplete->mIsCapturingMethodMatchInfo;
  2193. autoComplete->CheckInvocation(tupleExpr, tupleExpr->mOpenParen, tupleExpr->mCloseParen, tupleExpr->mCommas);
  2194. if (autoComplete->mIsCapturingMethodMatchInfo)
  2195. {
  2196. autoComplete->mMethodMatchInfo->mInstanceList.Clear();
  2197. auto methodMatchInfo = autoComplete->mMethodMatchInfo;
  2198. // auto methodDef = tupleType->mTypeDef->mMethods[0];
  2199. //
  2200. // BfAutoComplete::MethodMatchEntry methodMatchEntry;
  2201. // methodMatchEntry.mMethodDef = methodDef;
  2202. // methodMatchEntry.mTypeInstance = tupleType;
  2203. // methodMatchEntry.mCurMethodInstance = mCurMethodInstance;
  2204. // //methodMatchEntry.mPayloadEnumField = fieldInstance;
  2205. //autoComplete->mMethodMatchInfo->mInstanceList.push_back(methodMatchEntry);
  2206. methodMatchInfo->mBestIdx = 0;
  2207. methodMatchInfo->mMostParamsMatched = 0;
  2208. int cursorIdx = tupleExpr->GetParser()->mCursorIdx;
  2209. if ((tupleExpr->mCloseParen == NULL) || (cursorIdx <= tupleExpr->mCloseParen->GetSrcStart()))
  2210. {
  2211. int paramIdx = 0;
  2212. for (int commaIdx = 0; commaIdx < (int)tupleExpr->mCommas.size(); commaIdx++)
  2213. {
  2214. auto commaNode = tupleExpr->mCommas[commaIdx];
  2215. if ((commaNode != NULL) && (cursorIdx >= commaNode->GetSrcStart()))
  2216. paramIdx = commaIdx + 1;
  2217. }
  2218. bool isEmpty = true;
  2219. if (paramIdx < (int)tupleExpr->mValues.size())
  2220. {
  2221. auto paramNode = tupleExpr->mValues[paramIdx];
  2222. if (paramNode != NULL)
  2223. isEmpty = false;
  2224. }
  2225. if (isEmpty)
  2226. {
  2227. if (paramIdx < (int)tupleType->mFieldInstances.size())
  2228. {
  2229. auto fieldDef = tupleType->mFieldInstances[paramIdx].GetFieldDef();
  2230. String insertStr;
  2231. if (fieldDef->IsUnnamedTupleField())
  2232. insertStr = "p";
  2233. insertStr += fieldDef->mName;
  2234. insertStr.Insert(0, "let ");
  2235. autoComplete->mEntriesSet.Clear();
  2236. autoComplete->AddEntry(AutoCompleteEntry("paramName", insertStr));
  2237. autoComplete->mInsertStartIdx = cursorIdx;
  2238. autoComplete->mInsertEndIdx = cursorIdx;
  2239. }
  2240. }
  2241. }
  2242. }
  2243. }
  2244. defer
  2245. (
  2246. if (autoComplete != NULL)
  2247. autoComplete->mIsCapturingMethodMatchInfo = (wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo);
  2248. );
  2249. ///
  2250. //BfIRValue phiVal;
  2251. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  2252. //phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2);
  2253. auto startBlock = mBfIRBuilder->GetInsertBlock();
  2254. //auto dscrType = enumType->GetDiscriminatorType();
  2255. //BfIRValue eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagId));
  2256. BfIRBlock falseBlockStart;
  2257. BfIRBlock falseBlockEnd;
  2258. BfIRBlock doneBlockStart;
  2259. if (notEqBlock != NULL)
  2260. doneBlockStart = *notEqBlock;
  2261. else
  2262. doneBlockStart = mBfIRBuilder->CreateBlock("caseDone", false);
  2263. BfIRBlock doneBlockEnd = doneBlockStart;
  2264. if (clearOutOnMismatch)
  2265. {
  2266. falseBlockStart = falseBlockEnd = mBfIRBuilder->CreateBlock("caseNotEq", false);
  2267. mBfIRBuilder->AddBlock(falseBlockStart);
  2268. }
  2269. BfIRBlock matchedBlockStart = mBfIRBuilder->CreateBlock("caseMatch", false);
  2270. if (matchBlock != NULL)
  2271. *matchBlock = matchedBlockStart;
  2272. mBfIRBuilder->CreateBr(matchedBlockStart);
  2273. mBfIRBuilder->AddBlock(matchedBlockStart);
  2274. mBfIRBuilder->SetInsertPoint(doneBlockEnd);
  2275. BfIRValue phiVal;
  2276. if (eqBlock == NULL)
  2277. phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2);
  2278. mBfIRBuilder->SetInsertPoint(matchedBlockStart);
  2279. BfIRBlock matchedBlockEnd = matchedBlockStart;
  2280. HandleCaseEnumMatch_Tuple(tupleVal, tupleExpr->mValues, tooFewRef, falseBlockStart ? BfIRValue() : phiVal, matchedBlockStart, matchedBlockEnd,
  2281. falseBlockStart ? falseBlockStart : doneBlockStart, falseBlockEnd ? falseBlockEnd : doneBlockEnd, hadConditional, clearOutOnMismatch);
  2282. if (phiVal)
  2283. {
  2284. auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0);
  2285. if (falseBlockEnd)
  2286. mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlockEnd);
  2287. auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
  2288. mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlockEnd);
  2289. }
  2290. if (eqBlock != NULL)
  2291. mBfIRBuilder->CreateBr(*eqBlock);
  2292. else
  2293. mBfIRBuilder->CreateBr(doneBlockStart);
  2294. if (falseBlockEnd)
  2295. {
  2296. mBfIRBuilder->SetInsertPoint(falseBlockEnd);
  2297. mBfIRBuilder->CreateBr(doneBlockStart);
  2298. //mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), falseBlock);
  2299. }
  2300. mBfIRBuilder->AddBlock(doneBlockStart);
  2301. mBfIRBuilder->SetInsertPoint(doneBlockEnd);
  2302. if (phiVal)
  2303. return BfTypedValue(phiVal, boolType);
  2304. else
  2305. return GetDefaultTypedValue(boolType);
  2306. }
  2307. BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVal, BfExpression* expr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, int& tagId, bool& hadConditional, bool clearOutOnMismatch)
  2308. {
  2309. auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(expr);
  2310. if (invocationExpr == NULL)
  2311. return BfTypedValue();
  2312. auto activeTypeDef = GetActiveTypeDef();
  2313. BfType* targetType = NULL;
  2314. BfIdentifierNode* nameNode = NULL;
  2315. BfTokenNode* dotNode = NULL;
  2316. if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(invocationExpr->mTarget))
  2317. {
  2318. if (memberRefExpr->mTarget == NULL)
  2319. {
  2320. targetType = enumVal.mType;
  2321. }
  2322. else if (auto typeRef = BfNodeDynCast<BfTypeReference>(memberRefExpr->mTarget))
  2323. {
  2324. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  2325. targetType = ResolveTypeRef(typeRef);
  2326. }
  2327. else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(memberRefExpr->mTarget))
  2328. {
  2329. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  2330. targetType = ResolveTypeRef(identifier, NULL);
  2331. }
  2332. if (auto nameIdentifier = BfNodeDynCast<BfIdentifierNode>(memberRefExpr->mMemberName))
  2333. {
  2334. dotNode = memberRefExpr->mDotToken;
  2335. nameNode = nameIdentifier;
  2336. }
  2337. else
  2338. return BfTypedValue();
  2339. }
  2340. else if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(invocationExpr->mTarget))
  2341. {
  2342. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  2343. targetType = ResolveTypeRef(qualifiedNameNode->mLeft, NULL);
  2344. nameNode = qualifiedNameNode->mRight;
  2345. }
  2346. else if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(invocationExpr->mTarget))
  2347. {
  2348. targetType = mCurTypeInstance;
  2349. nameNode = identiferNode;
  2350. }
  2351. else
  2352. return BfTypedValue();
  2353. // These may have been colorized as methods, so change that
  2354. SetElementType(nameNode, BfSourceElementType_Normal);
  2355. if ((targetType == NULL) || (!targetType->IsPayloadEnum()))
  2356. return BfTypedValue();
  2357. auto enumType = targetType->ToTypeInstance();
  2358. PopulateType(enumType);
  2359. StringT<128> enumCaseName;
  2360. if (nameNode != NULL)
  2361. nameNode->ToString(enumCaseName);
  2362. auto tagType = GetPrimitiveType(BfTypeCode_Int32);
  2363. if (enumVal.mType != enumType)
  2364. {
  2365. Fail(StrFormat("Cannot match enum type '%s' with type '%s'",
  2366. TypeToString(enumVal.mType).c_str(), TypeToString(enumType).c_str()));
  2367. enumVal = GetDefaultTypedValue(enumType);
  2368. tagVal = GetDefaultTypedValue(tagType);
  2369. }
  2370. for (int fieldIdx = 0; fieldIdx < (int)enumType->mFieldInstances.size(); fieldIdx++)
  2371. {
  2372. auto fieldInstance = &enumType->mFieldInstances[fieldIdx];
  2373. auto fieldDef = fieldInstance->GetFieldDef();
  2374. if (fieldDef == NULL)
  2375. continue;
  2376. if ((fieldInstance->mIsEnumPayloadCase) && (fieldDef->mName == enumCaseName))
  2377. {
  2378. if ((!enumType->IsTypeMemberIncluded(fieldDef->mDeclaringType, activeTypeDef, this)) ||
  2379. (!enumType->IsTypeMemberAccessible(fieldDef->mDeclaringType, activeTypeDef)))
  2380. continue;
  2381. auto resolvePassData = mCompiler->mResolvePassData;
  2382. if (resolvePassData != NULL)
  2383. {
  2384. if (resolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field)
  2385. resolvePassData->HandleFieldReference(nameNode, enumType->mTypeDef, fieldDef);
  2386. String filter;
  2387. auto autoComplete = resolvePassData->mAutoComplete;
  2388. if ((autoComplete != NULL) && (autoComplete->InitAutocomplete(dotNode, nameNode, filter)))
  2389. autoComplete->AddEnumTypeMembers(enumType, enumCaseName, false, enumType == mCurTypeInstance);
  2390. }
  2391. BF_ASSERT(fieldInstance->mResolvedType->IsTuple());
  2392. auto tupleType = (BfTypeInstance*)fieldInstance->mResolvedType;
  2393. PopulateType(tupleType);
  2394. mBfIRBuilder->PopulateType(tupleType);
  2395. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  2396. tagId = -fieldInstance->mDataIdx - 1;
  2397. auto startBlock = mBfIRBuilder->GetInsertBlock();
  2398. auto dscrType = enumType->GetDiscriminatorType();
  2399. BfIRValue eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagId));
  2400. BfIRBlock falseBlockStart;
  2401. BfIRBlock falseBlockEnd;
  2402. BfIRBlock doneBlockStart;
  2403. BfIRBlock doneBlockEnd;
  2404. if (notEqBlock != NULL)
  2405. doneBlockStart = doneBlockEnd = *notEqBlock;
  2406. else
  2407. doneBlockStart = doneBlockEnd = mBfIRBuilder->CreateBlock("caseDone", false);
  2408. if (clearOutOnMismatch)
  2409. {
  2410. falseBlockStart = falseBlockEnd = mBfIRBuilder->CreateBlock("caseNotEq", false);
  2411. mBfIRBuilder->AddBlock(falseBlockStart);
  2412. }
  2413. BfIRBlock matchedBlockStart = mBfIRBuilder->CreateBlock("caseMatch", false);
  2414. BfIRBlock matchedBlockEnd = matchedBlockStart;
  2415. if (matchBlock != NULL)
  2416. *matchBlock = matchedBlockStart;
  2417. mBfIRBuilder->CreateCondBr(eqResult, matchedBlockStart, falseBlockStart ? falseBlockStart : doneBlockStart);
  2418. mBfIRBuilder->AddBlock(matchedBlockStart);
  2419. mBfIRBuilder->SetInsertPoint(doneBlockEnd);
  2420. BfIRValue phiVal;
  2421. if (eqBlock == NULL)
  2422. phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 1 + (int)tupleType->mFieldInstances.size());
  2423. mBfIRBuilder->SetInsertPoint(matchedBlockEnd);
  2424. BfTypedValue tupleVal;
  2425. if (!enumVal.IsAddr())
  2426. {
  2427. auto unionInnerType = enumType->GetUnionInnerType();
  2428. if (unionInnerType == tupleType)
  2429. {
  2430. tupleVal = ExtractValue(enumVal, NULL, 1);
  2431. }
  2432. }
  2433. if (!tupleVal)
  2434. {
  2435. if (!tupleType->IsValuelessType())
  2436. {
  2437. tupleVal = ExtractValue(enumVal, NULL, 1);
  2438. tupleVal = Cast(NULL, tupleVal, tupleType, BfCastFlags_Force);
  2439. }
  2440. else
  2441. tupleVal = GetDefaultTypedValue(tupleType);
  2442. }
  2443. ////
  2444. BfAstNode* tooFewRef = invocationExpr->mCloseParen;
  2445. if ((tooFewRef == NULL) && (!invocationExpr->mCommas.IsEmpty()))
  2446. tooFewRef = invocationExpr->mCommas[invocationExpr->mCommas.size() - 1];
  2447. else if (tooFewRef == NULL)
  2448. tooFewRef = invocationExpr->mOpenParen;
  2449. ///
  2450. auto autoComplete = mCompiler->GetAutoComplete();
  2451. bool wasCapturingMethodInfo = false;
  2452. if (autoComplete != NULL)
  2453. {
  2454. wasCapturingMethodInfo = autoComplete->mIsCapturingMethodMatchInfo;
  2455. autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);
  2456. if (autoComplete->mIsCapturingMethodMatchInfo)
  2457. {
  2458. autoComplete->mMethodMatchInfo->mInstanceList.Clear();
  2459. auto methodMatchInfo = autoComplete->mMethodMatchInfo;
  2460. BfAutoComplete::MethodMatchEntry methodMatchEntry;
  2461. methodMatchEntry.mTypeInstance = enumType;
  2462. methodMatchEntry.mCurMethodInstance = mCurMethodInstance;
  2463. methodMatchEntry.mPayloadEnumField = fieldInstance;
  2464. autoComplete->mMethodMatchInfo->mInstanceList.push_back(methodMatchEntry);
  2465. methodMatchInfo->mBestIdx = 0;
  2466. methodMatchInfo->mMostParamsMatched = 0;
  2467. int cursorIdx = invocationExpr->GetParser()->mCursorIdx;
  2468. if ((invocationExpr->mCloseParen == NULL) || (cursorIdx <= invocationExpr->mCloseParen->GetSrcStart()))
  2469. {
  2470. int paramIdx = 0;
  2471. for (int commaIdx = 0; commaIdx < (int)invocationExpr->mCommas.size(); commaIdx++)
  2472. {
  2473. auto commaNode = invocationExpr->mCommas[commaIdx];
  2474. if ((commaNode != NULL) && (cursorIdx >= commaNode->GetSrcStart()))
  2475. paramIdx = commaIdx + 1;
  2476. }
  2477. bool isEmpty = true;
  2478. if (paramIdx < (int)invocationExpr->mArguments.size())
  2479. {
  2480. auto paramNode = invocationExpr->mArguments[paramIdx];
  2481. if (paramNode != NULL)
  2482. isEmpty = false;
  2483. }
  2484. if (isEmpty)
  2485. {
  2486. if (paramIdx < (int)tupleType->mFieldInstances.size())
  2487. {
  2488. auto fieldDef = tupleType->mFieldInstances[paramIdx].GetFieldDef();
  2489. String insertStr;
  2490. if (fieldDef->IsUnnamedTupleField())
  2491. insertStr = "p";
  2492. insertStr += fieldDef->mName;
  2493. insertStr.Insert(0, "let ");
  2494. autoComplete->mEntriesSet.Clear();
  2495. autoComplete->AddEntry(AutoCompleteEntry("paramName", insertStr));
  2496. autoComplete->mInsertStartIdx = cursorIdx;
  2497. autoComplete->mInsertEndIdx = cursorIdx;
  2498. }
  2499. }
  2500. }
  2501. }
  2502. }
  2503. defer
  2504. (
  2505. if (autoComplete != NULL)
  2506. autoComplete->mIsCapturingMethodMatchInfo = (wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo);
  2507. );
  2508. ///
  2509. HandleCaseEnumMatch_Tuple(tupleVal, invocationExpr->mArguments, tooFewRef, falseBlockStart ? BfIRValue() : phiVal, matchedBlockStart, matchedBlockEnd,
  2510. falseBlockStart ? falseBlockStart : doneBlockStart, falseBlockEnd ? falseBlockEnd : doneBlockEnd,
  2511. hadConditional, clearOutOnMismatch);
  2512. ///////
  2513. if (phiVal)
  2514. {
  2515. auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0);
  2516. if (falseBlockEnd)
  2517. mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlockEnd);
  2518. else
  2519. mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, startBlock);
  2520. auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1);
  2521. mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlockEnd);
  2522. }
  2523. if (eqBlock != NULL)
  2524. mBfIRBuilder->CreateBr(*eqBlock);
  2525. else
  2526. mBfIRBuilder->CreateBr(doneBlockStart);
  2527. if (falseBlockEnd)
  2528. {
  2529. mBfIRBuilder->SetInsertPoint(falseBlockEnd);
  2530. mBfIRBuilder->CreateBr(doneBlockStart);
  2531. //mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), falseBlock);
  2532. }
  2533. mBfIRBuilder->AddBlock(doneBlockStart);
  2534. mBfIRBuilder->SetInsertPoint(doneBlockEnd);
  2535. if (phiVal)
  2536. return BfTypedValue(phiVal, boolType);
  2537. else
  2538. return GetDefaultTypedValue(boolType);
  2539. }
  2540. }
  2541. return BfTypedValue();
  2542. }
  2543. BfTypedValue BfModule::HandleCaseBind(BfTypedValue enumVal, const BfTypedValue& tagVal, BfEnumCaseBindExpression* bindExpr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, int* outEnumIdx)
  2544. {
  2545. BfTypeInstance* tupleType = NULL;
  2546. auto activeTypeDef = GetActiveTypeDef();
  2547. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  2548. BfIRValue eqResult;
  2549. if (bindExpr->mEnumMemberExpr != NULL)
  2550. {
  2551. int enumIdx = -1;
  2552. String findName;
  2553. BfType* type = NULL;
  2554. BfAstNode* targetNode = NULL;
  2555. BfAstNode* nameNode = NULL;
  2556. BfAstNode* dotNode = NULL;
  2557. if (auto memberExpr = BfNodeDynCast<BfMemberReferenceExpression>(bindExpr->mEnumMemberExpr))
  2558. {
  2559. dotNode = memberExpr->mDotToken;
  2560. if (memberExpr->mMemberName != NULL)
  2561. {
  2562. nameNode = memberExpr->mMemberName;
  2563. findName = memberExpr->mMemberName->ToString();
  2564. if (memberExpr->mTarget == NULL)
  2565. {
  2566. type = enumVal.mType;
  2567. }
  2568. else if (auto typeRef = BfNodeDynCast<BfTypeReference>(memberExpr->mTarget))
  2569. {
  2570. type = ResolveTypeRef(typeRef);
  2571. }
  2572. }
  2573. targetNode = memberExpr->mTarget;
  2574. }
  2575. else if (auto identiferNode = BfNodeDynCast<BfIdentifierNode>(bindExpr->mEnumMemberExpr))
  2576. {
  2577. if (mCurTypeInstance->IsPayloadEnum())
  2578. {
  2579. nameNode = identiferNode;
  2580. findName = nameNode->ToString();
  2581. targetNode = identiferNode;
  2582. type = mCurTypeInstance;
  2583. }
  2584. else
  2585. {
  2586. Fail("Expected a qualified enum case name. Consider prefixing name with a dot to infer enum type name.", bindExpr->mEnumMemberExpr);
  2587. }
  2588. }
  2589. if (!findName.empty())
  2590. {
  2591. if (type != NULL)
  2592. {
  2593. if (type != enumVal.mType)
  2594. {
  2595. Fail(StrFormat("Enum case type '%s' does not match compared value of type '%s'",
  2596. TypeToString(enumVal.mType).c_str(), TypeToString(type).c_str()), targetNode);
  2597. }
  2598. if (type->IsEnum())
  2599. {
  2600. auto enumType = (BfTypeInstance*)type;
  2601. for (auto& fieldInstance : enumType->mFieldInstances)
  2602. {
  2603. auto fieldDef = fieldInstance.GetFieldDef();
  2604. if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()) && (fieldDef->mName == findName))
  2605. {
  2606. if ((!enumType->IsTypeMemberIncluded(fieldDef->mDeclaringType, activeTypeDef, this)) ||
  2607. (!enumType->IsTypeMemberAccessible(fieldDef->mDeclaringType, activeTypeDef)))
  2608. continue;
  2609. auto resolvePassData = mCompiler->mResolvePassData;
  2610. if (resolvePassData != NULL)
  2611. {
  2612. if (resolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field)
  2613. resolvePassData->HandleFieldReference(nameNode, enumType->mTypeDef, fieldDef);
  2614. String filter;
  2615. auto autoComplete = resolvePassData->mAutoComplete;
  2616. if ((autoComplete != NULL) && (autoComplete->InitAutocomplete(dotNode, nameNode, filter)))
  2617. autoComplete->AddEnumTypeMembers(enumType, findName, false, enumType == mCurTypeInstance);
  2618. }
  2619. enumIdx = -fieldInstance.mDataIdx - 1;
  2620. if (outEnumIdx != NULL)
  2621. *outEnumIdx = enumIdx;
  2622. if (fieldInstance.mIsEnumPayloadCase)
  2623. tupleType = fieldInstance.mResolvedType->ToTypeInstance();
  2624. }
  2625. }
  2626. if (enumIdx == -1)
  2627. {
  2628. Fail("Enum case not found", nameNode);
  2629. }
  2630. }
  2631. else
  2632. {
  2633. Fail(StrFormat("Type '%s' is not an enum type", TypeToString(type).c_str()), targetNode);
  2634. }
  2635. }
  2636. }
  2637. BF_ASSERT(tagVal.mType->IsPrimitiveType());
  2638. eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(((BfPrimitiveType*)tagVal.mType)->mTypeDef->mTypeCode, enumIdx));
  2639. }
  2640. else
  2641. {
  2642. eqResult = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0);
  2643. }
  2644. BfIRBlock falseBlock;
  2645. if (notEqBlock != NULL)
  2646. {
  2647. falseBlock = *notEqBlock;
  2648. }
  2649. else
  2650. {
  2651. falseBlock = mBfIRBuilder->CreateBlock("notEqBlock", false);
  2652. }
  2653. auto mainBlock = mBfIRBuilder->GetInsertBlock();
  2654. BfIRBlock trueBlock = mBfIRBuilder->CreateBlock("eqBlock", false);
  2655. if (matchBlock != NULL)
  2656. *matchBlock = trueBlock;
  2657. mBfIRBuilder->AddBlock(trueBlock);
  2658. mBfIRBuilder->SetInsertPoint(trueBlock);
  2659. if ((tupleType != NULL) && (bindExpr->mBindNames != NULL))
  2660. {
  2661. BfIRValue valueScopeStart;
  2662. if (IsTargetingBeefBackend())
  2663. valueScopeStart = mBfIRBuilder->CreateValueScopeStart();
  2664. bool isVar = bindExpr->mBindToken->GetToken() == BfToken_Var;
  2665. bool isLet = bindExpr->mBindToken->GetToken() == BfToken_Let;
  2666. BfTypedValue tupleVal;
  2667. if (enumVal.IsAddr())
  2668. {
  2669. auto ptrVal = mBfIRBuilder->CreateInBoundsGEP(enumVal.mValue, 0, 1);
  2670. tupleVal = BfTypedValue(mBfIRBuilder->CreateBitCast(ptrVal, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, true);
  2671. }
  2672. else
  2673. {
  2674. auto unionInnerType = enumVal.mType->ToTypeInstance()->GetUnionInnerType();
  2675. tupleVal = ExtractValue(enumVal, NULL, 1);
  2676. if (unionInnerType != tupleType)
  2677. {
  2678. tupleVal = MakeAddressable(tupleVal);
  2679. tupleVal = BfTypedValue(mBfIRBuilder->CreateBitCast(tupleVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, true);
  2680. }
  2681. }
  2682. HandleTupleVariableDeclaration(NULL, bindExpr->mBindNames, tupleVal, isLet, false, true /*, &mainBlock*/);
  2683. auto autoComplete = mCompiler->GetAutoComplete();
  2684. if ((autoComplete != NULL) && ((isVar || isLet)))
  2685. autoComplete->CheckVarResolution(bindExpr->mBindToken, tupleType);
  2686. if (valueScopeStart)
  2687. mBfIRBuilder->CreateValueScopeSoftEnd(valueScopeStart);
  2688. }
  2689. if (eqBlock != NULL)
  2690. mBfIRBuilder->CreateBr(*eqBlock);
  2691. else
  2692. mBfIRBuilder->CreateBr(falseBlock);
  2693. // Don't create the condBr until now, so HandleTupleVariableDeclaration can create the variable declarations in mainBlock--
  2694. // we need them there since the code that uses the new variables is created outside the eqBlock
  2695. mBfIRBuilder->SetInsertPoint(mainBlock);
  2696. mBfIRBuilder->CreateCondBr(eqResult, trueBlock, falseBlock);
  2697. mBfIRBuilder->AddBlock(falseBlock);
  2698. mBfIRBuilder->SetInsertPoint(falseBlock);
  2699. return BfTypedValue(eqResult, boolType);
  2700. }
  2701. void BfModule::AddBasicBlock(BfIRBlock bb, bool activate)
  2702. {
  2703. mBfIRBuilder->AddBlock(bb);
  2704. if (activate)
  2705. mBfIRBuilder->SetInsertPoint(bb);
  2706. }
  2707. void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator, BfEmbeddedStatementFlags flags)
  2708. {
  2709. auto block = BfNodeDynCast<BfBlock>(stmt);
  2710. BfLabelNode* labelNode = NULL;
  2711. if (block == NULL)
  2712. {
  2713. auto labeledBlock = BfNodeDynCast<BfLabeledBlock>(stmt);
  2714. if (labeledBlock != NULL)
  2715. {
  2716. block = labeledBlock->mBlock;
  2717. labelNode = labeledBlock->mLabelNode;
  2718. }
  2719. }
  2720. BfAstNode* openBrace = NULL;
  2721. BfAstNode* closeBrace = NULL;
  2722. if (block != NULL)
  2723. {
  2724. openBrace = block->mOpenBrace;
  2725. closeBrace = block->mCloseBrace;
  2726. if (openBrace == NULL)
  2727. {
  2728. auto checkScope = mCurMethodState->mCurScope;
  2729. while ((checkScope != NULL) && (closeBrace == NULL))
  2730. {
  2731. closeBrace = checkScope->mCloseNode;
  2732. checkScope = checkScope->mPrevScope;
  2733. }
  2734. BF_ASSERT(closeBrace != NULL);
  2735. }
  2736. }
  2737. if ((block != NULL) && (openBrace != NULL))
  2738. UpdateSrcPos(openBrace);
  2739. if ((flags & BfEmbeddedStatementFlags_Unscoped) != 0)
  2740. {
  2741. SetAndRestoreValue<BfExprEvaluator*> prevExprEvaluator(mCurMethodState->mCurScope->mExprEvaluator, exprEvaluator);
  2742. SetAndRestoreValue<bool> prevAllowReturn(mCurMethodState->mDisableReturns, true);
  2743. VisitCodeBlock(block);
  2744. }
  2745. else if (mCurMethodState != NULL)
  2746. {
  2747. bool isIgnore = mBfIRBuilder->mIgnoreWrites;
  2748. mCurMethodState->mInHeadScope = false;
  2749. BfScopeData scopeData;
  2750. if (IsTargetingBeefBackend())
  2751. scopeData.mValueScopeStart = mBfIRBuilder->CreateValueScopeStart();
  2752. mCurMethodState->AddScope(&scopeData);
  2753. if (block != NULL)
  2754. {
  2755. mCurMethodState->mCurScope->mAstBlock = block;
  2756. mCurMethodState->mCurScope->mCloseNode = closeBrace;
  2757. }
  2758. if (labelNode != NULL)
  2759. scopeData.mLabelNode = labelNode->mLabel;
  2760. NewScopeState(block != NULL);
  2761. mCurMethodState->mCurScope->mOuterIsConditional = (flags & BfEmbeddedStatementFlags_IsConditional) != 0;
  2762. mCurMethodState->mCurScope->mIsDeferredBlock = (flags & BfEmbeddedStatementFlags_IsDeferredBlock) != 0;
  2763. mCurMethodState->mCurScope->mExprEvaluator = exprEvaluator;
  2764. //
  2765. {
  2766. SetAndRestoreValue<bool> inDeferredBlock(mCurMethodState->mInDeferredBlock, mCurMethodState->mInDeferredBlock || mCurMethodState->mCurScope->mIsDeferredBlock);
  2767. if (block != NULL)
  2768. {
  2769. if (labelNode != NULL)
  2770. VisitCodeBlock(block, BfIRBlock(), BfIRBlock(), BfIRBlock(), false, NULL, labelNode);
  2771. else
  2772. VisitCodeBlock(block);
  2773. }
  2774. else
  2775. {
  2776. if (auto varDecl = BfNodeDynCast<BfVariableDeclaration>(stmt))
  2777. {
  2778. Fail("Variable declarations must be wrapped in a block statement", varDecl);
  2779. }
  2780. VisitChild(stmt);
  2781. }
  2782. }
  2783. if ((block != NULL) && (closeBrace != NULL))
  2784. {
  2785. UpdateSrcPos(closeBrace);
  2786. if (!mCurMethodState->mLeftBlockUncond)
  2787. EmitEnsureInstructionAt();
  2788. }
  2789. if (block != NULL)
  2790. {
  2791. BfAutoParentNodeEntry autoParentNodeEntry(this, block);
  2792. RestoreScopeState();
  2793. }
  2794. else
  2795. RestoreScopeState();
  2796. BF_ASSERT(isIgnore == mBfIRBuilder->mIgnoreWrites);
  2797. }
  2798. else
  2799. {
  2800. if (block != NULL)
  2801. VisitCodeBlock(block);
  2802. else
  2803. VisitChild(stmt);
  2804. }
  2805. }
  2806. void BfModule::VisitCodeBlock(BfBlock* block, BfIRBlock continueBlock, BfIRBlock breakBlock, BfIRBlock fallthroughBlock, bool defaultBreak, bool* hadReturn, BfLabelNode* labelNode, bool closeScope)
  2807. {
  2808. BfBreakData breakData;
  2809. breakData.mIRContinueBlock = continueBlock;
  2810. breakData.mIRBreakBlock = breakBlock;
  2811. breakData.mIRFallthroughBlock = fallthroughBlock;
  2812. breakData.mScope = mCurMethodState->mCurScope;
  2813. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  2814. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  2815. Visit(block);
  2816. if (closeScope)
  2817. RestoreScopeState();
  2818. if ((!mCurMethodState->mLeftBlockUncond) && (defaultBreak))
  2819. {
  2820. mBfIRBuilder->CreateBr(breakBlock);
  2821. }
  2822. if (hadReturn != NULL)
  2823. {
  2824. *hadReturn = mCurMethodState->mHadReturn;
  2825. mCurMethodState->SetHadReturn(false);
  2826. mCurMethodState->mLeftBlockUncond = false;
  2827. }
  2828. }
  2829. void BfModule::VisitCodeBlock(BfBlock* block)
  2830. {
  2831. BP_ZONE("BfModule::VisitCodeBlock");
  2832. BfAutoParentNodeEntry autoParentNodeEntry(this, block);
  2833. BfIRBlock prevInsertBlock;
  2834. bool hadReturn = false;
  2835. int startLocalMethod = 0; // was -1
  2836. auto rootMethodState = mCurMethodState->GetRootMethodState();
  2837. BfIRBlock startInsertBlock = mBfIRBuilder->GetInsertBlock();
  2838. bool allowLocalMethods = mCurMethodInstance != NULL;
  2839. //int startDeferredLocalIdx = (int)rootMethodState->mDeferredLocalMethods.size();
  2840. int curLocalMethodIdx = -1;
  2841. // Scan for any local method declarations
  2842. if (allowLocalMethods)
  2843. {
  2844. startLocalMethod = (int)mCurMethodState->mLocalMethods.size();
  2845. curLocalMethodIdx = startLocalMethod;
  2846. auto itr = block->begin();
  2847. while (itr != block->end())
  2848. {
  2849. BfAstNode* child = *itr;
  2850. if (auto localMethodDecl = BfNodeDynCastExact<BfLocalMethodDeclaration>(child))
  2851. {
  2852. BfLocalMethod* localMethod;
  2853. auto rootMethodState = mCurMethodState->GetRootMethodState();
  2854. String methodName;
  2855. if (localMethodDecl->mMethodDeclaration->mNameNode != NULL)
  2856. {
  2857. methodName = GetLocalMethodName(localMethodDecl->mMethodDeclaration->mNameNode->ToString(), localMethodDecl->mMethodDeclaration->mOpenParen, mCurMethodState, mCurMethodState->mMixinState);
  2858. BfLocalMethod** localMethodPtr = NULL;
  2859. if (rootMethodState->mLocalMethodCache.TryGetValue(methodName, &localMethodPtr))
  2860. {
  2861. localMethod = *localMethodPtr;
  2862. }
  2863. else
  2864. {
  2865. localMethod = new BfLocalMethod();
  2866. localMethod->mSystem = mSystem;
  2867. localMethod->mModule = this;
  2868. localMethod->mMethodDeclaration = localMethodDecl->mMethodDeclaration;
  2869. localMethod->mSource = mCurTypeInstance->mTypeDef->mSource;
  2870. localMethod->mSource->mRefCount++;
  2871. if (mCurMethodState->mClosureState != NULL)
  2872. localMethod->mOuterLocalMethod = mCurMethodState->mClosureState->mLocalMethod;
  2873. auto autoComplete = mCompiler->GetAutoComplete();
  2874. if ((autoComplete != NULL) && (autoComplete->mResolveType == BfResolveType_Autocomplete))
  2875. {
  2876. auto autoComplete = mCompiler->mResolvePassData->mAutoComplete;
  2877. if (!autoComplete->IsAutocompleteNode(localMethod->mMethodDeclaration))
  2878. localMethod->mDeclOnly = true;
  2879. }
  2880. if (localMethod->mMethodDeclaration->mNameNode != NULL)
  2881. localMethod->mMethodName = localMethod->mMethodDeclaration->mNameNode->ToString();
  2882. localMethod->mExpectedFullName = methodName;
  2883. rootMethodState->mLocalMethodCache[methodName] = localMethod;
  2884. mContext->mLocalMethodGraveyard.push_back(localMethod);
  2885. }
  2886. BF_ASSERT(mCurMethodState->mCurScope != NULL);
  2887. localMethod->mDeclDIScope = mCurMethodState->mCurScope->mDIScope;
  2888. localMethod->mDeclMethodState = mCurMethodState;
  2889. localMethod->mDeclMixinState = mCurMethodState->mMixinState;
  2890. if (localMethod->mDeclMixinState != NULL)
  2891. localMethod->mDeclMixinState->mHasDeferredUsage = true;
  2892. mCurMethodState->mLocalMethods.push_back(localMethod);
  2893. String* namePtr;
  2894. if (!mCurMethodState->mLocalMethodMap.TryAdd(localMethod->mMethodName, &namePtr, &localMethodPtr))
  2895. {
  2896. BF_ASSERT(localMethod != *localMethodPtr);
  2897. localMethod->mNextWithSameName = *localMethodPtr;
  2898. }
  2899. *localMethodPtr = localMethod;
  2900. }
  2901. }
  2902. ++itr;
  2903. }
  2904. }
  2905. bool wantsAllLocalMethods = true;
  2906. auto autoComplete = mCompiler->GetAutoComplete();
  2907. if (autoComplete != NULL)
  2908. {
  2909. // If we only need reasoning "at the cursor" then we don't need all local methods
  2910. if ((!autoComplete->mIsAutoComplete) ||
  2911. (autoComplete->mResolveType == BfResolveType_GetCurrentLocation) ||
  2912. (autoComplete->mResolveType == BfResolveType_GetFixits) ||
  2913. (autoComplete->mResolveType == BfResolveType_GetResultString) ||
  2914. (autoComplete->mResolveType == BfResolveType_GetSymbolInfo) ||
  2915. (autoComplete->mResolveType == BfResolveType_ShowFileSymbolReferences))
  2916. wantsAllLocalMethods = false;
  2917. }
  2918. /*if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mResolveType == BfResolveType_ShowFileSymbolReferences))
  2919. {
  2920. if (mCompiler->mResolvePassData->mSymbolReferenceLocalIdx != -1)
  2921. {
  2922. // We need to reproduce the behavior when we found the symbol - only process autocomplete nodes, otherwise local method ids will be wrong
  2923. // when we have local methods that were skipped the first time but not the second
  2924. wantsAllLocalMethods = false;
  2925. }
  2926. }*/
  2927. SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites);
  2928. bool hadUnreachableCode = false;
  2929. // Handle statements
  2930. auto itr = block->begin();
  2931. while (itr != block->end())
  2932. {
  2933. BfAstNode* child = *itr;
  2934. if (auto localMethodDecl = BfNodeDynCastExact<BfLocalMethodDeclaration>(child))
  2935. {
  2936. /*if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Mixin))
  2937. Fail("Mixins cannot contain local methods", child);*/
  2938. if (!allowLocalMethods)
  2939. {
  2940. Fail("Invalid use of local methods", child);
  2941. }
  2942. else if (localMethodDecl->mMethodDeclaration->mNameNode != NULL)
  2943. {
  2944. BfLocalMethod* localMethod = mCurMethodState->mLocalMethods[curLocalMethodIdx];
  2945. BF_ASSERT(localMethod->mMethodDeclaration == localMethodDecl->mMethodDeclaration);
  2946. if ((wantsAllLocalMethods) || (autoComplete->IsAutocompleteNode(localMethod->mMethodDeclaration)))
  2947. {
  2948. if (!mCurMethodInstance->IsSpecializedGenericMethodOrType())
  2949. GetLocalMethodInstance(localMethod, BfTypeVector(), NULL, true); // Only necessary on unspecialized pass
  2950. }
  2951. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  2952. mCompiler->mResolvePassData->mAutoComplete->CheckMethod(localMethod->mMethodDeclaration, true);
  2953. curLocalMethodIdx++;
  2954. }
  2955. ++itr;
  2956. continue;
  2957. }
  2958. if ((mCurMethodState != NULL) && (mCurMethodState->mLeftBlockUncond)) // mLeftBlock is cleared after conditional block is completed
  2959. {
  2960. if (mCurMethodState->mHadReturn)
  2961. hadReturn = true;
  2962. if ((!hadUnreachableCode) && (!mCurMethodState->mInPostReturn))
  2963. {
  2964. Warn(BfWarning_CS0162_UnreachableCode, "Unreachable code", child);
  2965. hadUnreachableCode = true;
  2966. prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  2967. mCurMethodState->mInPostReturn = true;
  2968. mBfIRBuilder->mIgnoreWrites = true;
  2969. }
  2970. }
  2971. if (itr.IsLast())
  2972. {
  2973. if (auto expr = BfNodeDynCast<BfExpression>(child))
  2974. {
  2975. if (expr->IsExpression())
  2976. {
  2977. if (mCurMethodState != NULL)
  2978. {
  2979. if (mCurMethodState->mCurScope->mExprEvaluator != NULL)
  2980. {
  2981. if ((mAttributeState != NULL) &&
  2982. ((mAttributeState->mFlags & (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)) == (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)))
  2983. {
  2984. // Resolve as just 'false'
  2985. mCurMethodState->mCurScope->mExprEvaluator->mResult = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean));
  2986. }
  2987. else
  2988. {
  2989. auto exprEvaluator = mCurMethodState->mCurScope->mExprEvaluator;
  2990. // Evaluate last child as an expression
  2991. exprEvaluator->VisitChild(expr);
  2992. exprEvaluator->FinishExpressionResult();
  2993. if ((exprEvaluator->mResult) && (!exprEvaluator->mResult.mType->IsValuelessType()) && (!exprEvaluator->mResult.IsAddr()) && (!exprEvaluator->mResult.mValue.IsFake()))
  2994. {
  2995. if ((mCurMethodState->mCurScope != NULL) && (mCurMethodState->mCurScope->mPrevScope != NULL))
  2996. {
  2997. // We need to make sure we don't retain any values through the scope's ValueScopeHardEnd - and extend alloca through previous scope
  2998. bool wasReadOnly = exprEvaluator->mResult.IsReadOnly();
  2999. FixIntUnknown(exprEvaluator->mResult, exprEvaluator->mExpectingType);
  3000. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  3001. auto tempVar = CreateAlloca(exprEvaluator->mResult.mType, false, "blockExpr");
  3002. mBfIRBuilder->SetInsertPointAtStart(startInsertBlock);
  3003. auto lifetimeStart = mBfIRBuilder->CreateLifetimeStart(tempVar);
  3004. mBfIRBuilder->ClearDebugLocation(lifetimeStart);
  3005. if (!mBfIRBuilder->mIgnoreWrites)
  3006. mCurMethodState->mCurScope->mPrevScope->mDeferredLifetimeEnds.push_back(tempVar);
  3007. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  3008. if (exprEvaluator->mResult.IsSplat())
  3009. AggregateSplatIntoAddr(exprEvaluator->mResult, tempVar);
  3010. else
  3011. mBfIRBuilder->CreateAlignedStore(exprEvaluator->mResult.mValue, tempVar, exprEvaluator->mResult.mType->mAlign);
  3012. exprEvaluator->mResult = BfTypedValue(tempVar, exprEvaluator->mResult.mType,
  3013. exprEvaluator->mResult.IsThis() ?
  3014. (wasReadOnly ? BfTypedValueKind_ReadOnlyThisAddr : BfTypedValueKind_ThisAddr) :
  3015. (wasReadOnly ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr));
  3016. }
  3017. }
  3018. }
  3019. break;
  3020. }
  3021. else if (mCurMethodState->InMainMixinScope())
  3022. {
  3023. mCurMethodState->mMixinState->mResultExpr = expr;
  3024. break;
  3025. }
  3026. else if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
  3027. {
  3028. // Only in mixin definition - result ignored
  3029. CreateValueFromExpression(expr);
  3030. break;
  3031. }
  3032. else
  3033. {
  3034. FailAfter("Expression block cannot be used here. Consider adding semicolon if a statement was intended.", expr);
  3035. }
  3036. }
  3037. }
  3038. }
  3039. }
  3040. UpdateSrcPos(child);
  3041. BfAutoParentNodeEntry autoParentNode(this, child);
  3042. if ((mAttributeState != NULL) &&
  3043. ((mAttributeState->mFlags & (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)) == (BfAttributeState::Flag_StopOnError | BfAttributeState::Flag_HadError)))
  3044. {
  3045. // Ignore child
  3046. }
  3047. else
  3048. child->Accept(this);
  3049. mContext->CheckLockYield();
  3050. ++itr;
  3051. }
  3052. if (mCurMethodState != NULL)
  3053. {
  3054. // Any local method that hasn't been called needs to be processed now
  3055. for (int localMethodIdx = startLocalMethod; localMethodIdx < (int)mCurMethodState->mLocalMethods.size(); localMethodIdx++)
  3056. {
  3057. auto localMethod = mCurMethodState->mLocalMethods[localMethodIdx];
  3058. if ((wantsAllLocalMethods) || (autoComplete->IsAutocompleteNode(localMethod->mMethodDeclaration)))
  3059. {
  3060. //??
  3061. auto moduleMethodInstance = GetLocalMethodInstance(localMethod, BfTypeVector(), NULL, true);
  3062. }
  3063. mContext->CheckLockYield();
  3064. }
  3065. while ((int)mCurMethodState->mLocalMethods.size() > startLocalMethod)
  3066. {
  3067. auto localMethod = mCurMethodState->mLocalMethods.back();
  3068. #if _DEBUG
  3069. BfLocalMethod** localMethodPtr = NULL;
  3070. mCurMethodState->mLocalMethodMap.TryGetValue(localMethod->mMethodName, &localMethodPtr);
  3071. BF_ASSERT(*localMethodPtr == localMethod);
  3072. #endif
  3073. if (localMethod->mNextWithSameName == NULL)
  3074. mCurMethodState->mLocalMethodMap.Remove(localMethod->mMethodName);
  3075. else
  3076. {
  3077. mCurMethodState->mLocalMethodMap[localMethod->mMethodName] = localMethod->mNextWithSameName;
  3078. localMethod->mNextWithSameName = NULL;
  3079. }
  3080. mCurMethodState->mLocalMethods.pop_back();
  3081. }
  3082. if (hadUnreachableCode)
  3083. {
  3084. if (hadReturn)
  3085. mCurMethodState->SetHadReturn(true);
  3086. mCurMethodState->mLeftBlockUncond = true;
  3087. mCurMethodState->mInPostReturn = false;
  3088. if (prevInsertBlock)
  3089. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  3090. }
  3091. }
  3092. }
  3093. void BfModule::Visit(BfAstNode* astNode)
  3094. {
  3095. AssertErrorState();
  3096. }
  3097. void BfModule::Visit(BfIdentifierNode* identifierNode)
  3098. {
  3099. Visit((BfExpression*)identifierNode);
  3100. }
  3101. void BfModule::Visit(BfTypeReference* typeRef)
  3102. {
  3103. Visit((BfAstNode*)typeRef);
  3104. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  3105. mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(typeRef, true);
  3106. }
  3107. void BfModule::Visit(BfEmptyStatement* astNode)
  3108. {
  3109. }
  3110. void BfModule::Visit(BfTryStatement* tryStmt)
  3111. {
  3112. Fail("Exceptions not supported", tryStmt->mTryToken);
  3113. VisitChild(tryStmt->mStatement);
  3114. }
  3115. void BfModule::Visit(BfCatchStatement* catchStmt)
  3116. {
  3117. Fail("Exceptions not supported", catchStmt->mCatchToken);
  3118. }
  3119. void BfModule::Visit(BfFinallyStatement* finallyStmt)
  3120. {
  3121. Fail("Exceptions not supported", finallyStmt->mFinallyToken);
  3122. VisitChild(finallyStmt->mStatement);
  3123. }
  3124. void BfModule::Visit(BfCheckedStatement* checkedStmt)
  3125. {
  3126. Fail("'checked' not supported", checkedStmt->mCheckedToken);
  3127. VisitChild(checkedStmt->mStatement);
  3128. }
  3129. void BfModule::Visit(BfUncheckedStatement* uncheckedStmt)
  3130. {
  3131. VisitChild(uncheckedStmt->mStatement);
  3132. }
  3133. void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool includeFalseStmt)
  3134. {
  3135. auto autoComplete = mCompiler->GetAutoComplete();
  3136. if (autoComplete != NULL)
  3137. autoComplete->CheckIdentifier(ifStmt->mIfToken, true);
  3138. if (ifStmt->mCondition == NULL)
  3139. {
  3140. AssertErrorState();
  3141. return;
  3142. }
  3143. //TODO: Only conditionally create the scopeData here if we create a variable inside the condition statement
  3144. UpdateSrcPos(ifStmt);
  3145. BfScopeData newScope;
  3146. newScope.mOuterIsConditional = true;
  3147. newScope.mScopeKind = BfScopeKind_StatementTarget;
  3148. if (ifStmt->mLabelNode != NULL)
  3149. newScope.mLabelNode = ifStmt->mLabelNode->mLabel;
  3150. mCurMethodState->AddScope(&newScope);
  3151. NewScopeState();
  3152. BfBreakData breakData;
  3153. breakData.mScope = &newScope;
  3154. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  3155. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  3156. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  3157. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  3158. deferredLocalAssignData.mIsIfCondition = true;
  3159. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, true);
  3160. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  3161. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  3162. BfAutoParentNodeEntry autoParentNodeEntry(this, ifStmt);
  3163. BfTypedValue condValue = CreateValueFromExpression(ifStmt->mCondition, boolType);
  3164. newScope.mScopeKind = BfScopeKind_Normal;
  3165. deferredLocalAssignData.mIsIfCondition = false;
  3166. // The "extend chain" is only valid for the conditional -- since that expression may contain unconditionally executed and
  3167. // conditionally executed code (in the case of "(GetVal(out a) && GetVal(out b))" for example
  3168. mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
  3169. if (!condValue)
  3170. {
  3171. AssertErrorState();
  3172. condValue = BfTypedValue(GetDefaultValue(boolType), boolType);
  3173. }
  3174. BfIRBlock trueBB;
  3175. BfIRBlock falseBB;
  3176. bool isConstBranch = false;
  3177. bool constResult = false;
  3178. if (condValue.mValue.IsConst())
  3179. {
  3180. auto constant = mBfIRBuilder->GetConstant(condValue.mValue);
  3181. if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean))
  3182. {
  3183. isConstBranch = true;
  3184. constResult = constant->mBool;
  3185. }
  3186. }
  3187. if (!isConstBranch)
  3188. {
  3189. trueBB = mBfIRBuilder->CreateBlock("if.then", true);
  3190. falseBB = (ifStmt->mFalseStatement == NULL) ? BfIRBlock() : mBfIRBuilder->CreateBlock("if.else");
  3191. }
  3192. else
  3193. EmitEnsureInstructionAt();
  3194. auto contBB = mBfIRBuilder->CreateBlock("if.end");
  3195. if (!isConstBranch)
  3196. {
  3197. mBfIRBuilder->CreateCondBr(condValue.mValue, trueBB, (falseBB) ? falseBB : contBB);
  3198. }
  3199. // TRUE statement
  3200. bool ignoredLastBlock = true;
  3201. if (includeTrueStmt)
  3202. {
  3203. SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites);
  3204. if (trueBB)
  3205. mBfIRBuilder->SetInsertPoint(trueBB);
  3206. if ((isConstBranch) && (constResult != true))
  3207. mBfIRBuilder->mIgnoreWrites = true;
  3208. else
  3209. ignoredLastBlock = false;
  3210. VisitEmbeddedStatement(ifStmt->mTrueStatement);
  3211. }
  3212. prevDLA.Restore();
  3213. if (mCurMethodState->mDeferredLocalAssignData != NULL)
  3214. mCurMethodState->mDeferredLocalAssignData->mHadBreak |= deferredLocalAssignData.mHadBreak;
  3215. bool trueHadReturn = mCurMethodState->mHadReturn;
  3216. // We restore the scopeData before the False block because we don't want variables created in the if condition to
  3217. // be visible in the false section
  3218. //RestoreScopeState();
  3219. RestoreScoreState_LocalVariables();
  3220. if ((!mCurMethodState->mLeftBlockUncond) && (!ignoredLastBlock))
  3221. mBfIRBuilder->CreateBr_NoCollapse(contBB);
  3222. if (mCurMethodState->mLeftBlockUncond)
  3223. mCurMethodState->mLeftBlockCond = true;
  3224. mCurMethodState->mLeftBlockUncond = false;
  3225. mCurMethodState->SetHadReturn(false);
  3226. bool falseHadReturn = false;
  3227. if (ifStmt->mFalseStatement != NULL)
  3228. {
  3229. BfDeferredLocalAssignData falseDeferredLocalAssignData(&newScope);
  3230. falseDeferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  3231. if (falseBB)
  3232. {
  3233. mBfIRBuilder->AddBlock(falseBB);
  3234. mBfIRBuilder->SetInsertPoint(falseBB);
  3235. }
  3236. ignoredLastBlock = true;
  3237. //
  3238. {
  3239. SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites);
  3240. if ((isConstBranch) && (constResult != false))
  3241. mBfIRBuilder->mIgnoreWrites = true;
  3242. else
  3243. ignoredLastBlock = false;
  3244. falseDeferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
  3245. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &falseDeferredLocalAssignData);
  3246. if (includeFalseStmt)
  3247. VisitEmbeddedStatement(ifStmt->mFalseStatement, NULL, BfEmbeddedStatementFlags_IsConditional);
  3248. }
  3249. if ((!mCurMethodState->mLeftBlockUncond) && (!ignoredLastBlock))
  3250. {
  3251. if (IsTargetingBeefBackend())
  3252. {
  3253. // If we don't do this, then with:
  3254. // if (a) { } else if (b) { }
  3255. // Then we hit the closing second brace even if 'b' is false
  3256. //SetIllegalSrcPos();
  3257. //BfIRBuilder->ClearDebugLocation();
  3258. }
  3259. auto br = mBfIRBuilder->CreateBr_NoCollapse(contBB);
  3260. //mBfIRBuilder->ClearDebugLocation(br);
  3261. }
  3262. falseHadReturn = mCurMethodState->mHadReturn;
  3263. if (mCurMethodState->mLeftBlockUncond)
  3264. mCurMethodState->mLeftBlockCond = true;
  3265. mCurMethodState->mLeftBlockUncond = false;
  3266. mCurMethodState->SetHadReturn(false);
  3267. deferredLocalAssignData.SetIntersection(falseDeferredLocalAssignData);
  3268. mCurMethodState->ApplyDeferredLocalAssignData(deferredLocalAssignData);
  3269. }
  3270. else
  3271. {
  3272. // If we had a const-ignored if statement with no else
  3273. if (ignoredLastBlock)
  3274. {
  3275. if (!mCurMethodState->mLeftBlockUncond)
  3276. mBfIRBuilder->CreateBr_NoCollapse(contBB);
  3277. }
  3278. }
  3279. mBfIRBuilder->AddBlock(contBB);
  3280. mBfIRBuilder->SetInsertPoint(contBB);
  3281. if (isConstBranch)
  3282. mCurMethodState->SetHadReturn(constResult ? trueHadReturn : falseHadReturn);
  3283. else
  3284. mCurMethodState->SetHadReturn(trueHadReturn && falseHadReturn);
  3285. mCurMethodState->mLeftBlockUncond = mCurMethodState->mHadReturn;
  3286. if (mCurMethodState->mHadReturn)
  3287. {
  3288. mBfIRBuilder->EraseFromParent(contBB);
  3289. }
  3290. else
  3291. {
  3292. mBfIRBuilder->SetInsertPoint(contBB);
  3293. }
  3294. RestoreScopeState();
  3295. }
  3296. void BfModule::Visit(BfIfStatement* ifStmt)
  3297. {
  3298. DoIfStatement(ifStmt, true, true);
  3299. }
  3300. void BfModule::Visit(BfVariableDeclaration* varDecl)
  3301. {
  3302. BP_ZONE("BfModule::Visit(BfVariableDeclaration)");
  3303. UpdateSrcPos(varDecl);
  3304. BfTupleExpression* tupleVariableDeclaration = BfNodeDynCast<BfTupleExpression>(varDecl->mNameNode);
  3305. if (tupleVariableDeclaration != NULL)
  3306. {
  3307. HandleTupleVariableDeclaration(varDecl);
  3308. }
  3309. else
  3310. HandleVariableDeclaration(varDecl);
  3311. }
  3312. void BfModule::Visit(BfLocalMethodDeclaration* methodDecl)
  3313. {
  3314. Fail("Local method declarations must be wrapped in a block statement", methodDecl->mMethodDeclaration->mNameNode);
  3315. }
  3316. void BfModule::Visit(BfAttributedStatement* attribStmt)
  3317. {
  3318. BfAttributeState attributeState;
  3319. attributeState.mSrc = attribStmt->mAttributes;
  3320. attributeState.mTarget = (BfAttributeTargets)(BfAttributeTargets_Invocation | BfAttributeTargets_MemberAccess);
  3321. if (auto block = BfNodeDynCast<BfBlock>(attribStmt->mStatement))
  3322. attributeState.mTarget = BfAttributeTargets_Block;
  3323. attributeState.mCustomAttributes = GetCustomAttributes(attribStmt->mAttributes, attributeState.mTarget);
  3324. SetAndRestoreValue<BfAttributeState*> prevAttributeState(mAttributeState, &attributeState);
  3325. if (auto ignoreErrorsAttrib = attributeState.mCustomAttributes->Get(mCompiler->mIgnoreErrorsAttributeTypeDef))
  3326. {
  3327. SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
  3328. if (!ignoreErrorsAttrib->mCtorArgs.IsEmpty())
  3329. {
  3330. auto constant = mCurTypeInstance->mConstHolder->GetConstant(ignoreErrorsAttrib->mCtorArgs[0]);
  3331. if (constant->mBool)
  3332. attributeState.mFlags = BfAttributeState::Flag_StopOnError;
  3333. }
  3334. VisitChild(attribStmt->mStatement);
  3335. attributeState.mUsed = true;
  3336. }
  3337. else
  3338. {
  3339. VisitChild(attribStmt->mStatement);
  3340. }
  3341. FinishAttributeState(&attributeState);
  3342. }
  3343. void BfModule::Visit(BfExpression* expression)
  3344. {
  3345. UpdateSrcPos(expression);
  3346. BfExprEvaluator exprEvaluator(this);
  3347. exprEvaluator.mUsedAsStatement = true;
  3348. exprEvaluator.Evaluate(expression);
  3349. }
  3350. void BfModule::Visit(BfExpressionStatement* expressionStmt)
  3351. {
  3352. expressionStmt->mExpression->Accept(this);
  3353. }
  3354. void BfModule::Visit(BfThrowStatement* throwStmt)
  3355. {
  3356. if (throwStmt->mExpression == NULL)
  3357. {
  3358. AssertErrorState();
  3359. return;
  3360. }
  3361. UpdateSrcPos(throwStmt->mThrowToken);
  3362. auto throwValue = CreateValueFromExpression(throwStmt->mExpression);
  3363. Fail("Exceptions are not supported", throwStmt->mThrowToken);
  3364. if (mCurMethodInstance->mReturnType->IsVoid())
  3365. EmitReturn(BfTypedValue());
  3366. else
  3367. EmitReturn(GetDefaultTypedValue(mCurMethodInstance->mReturnType));
  3368. }
  3369. void BfModule::Visit(BfDeleteStatement* deleteStmt)
  3370. {
  3371. UpdateSrcPos(deleteStmt);
  3372. auto autoComplete = mCompiler->GetAutoComplete();
  3373. if (autoComplete != NULL)
  3374. autoComplete->CheckIdentifier(deleteStmt->mDeleteToken, true);
  3375. bool isAppendDelete = false;
  3376. BfTypedValue customAllocator;
  3377. if (deleteStmt->mAllocExpr != NULL)
  3378. {
  3379. if (auto expr = BfNodeDynCast<BfExpression>(deleteStmt->mAllocExpr))
  3380. customAllocator = CreateValueFromExpression(expr);
  3381. else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(deleteStmt->mAllocExpr))
  3382. {
  3383. if (tokenNode->mToken == BfToken_Append)
  3384. isAppendDelete = true;
  3385. }
  3386. }
  3387. BfAttributeState attributeState;
  3388. attributeState.mTarget = BfAttributeTargets_Delete;
  3389. SetAndRestoreValue<BfAttributeState*> prevAttributeState(mAttributeState, &attributeState);
  3390. attributeState.mCustomAttributes = GetCustomAttributes(deleteStmt->mAttributes, attributeState.mTarget);
  3391. if (deleteStmt->mExpression == NULL)
  3392. {
  3393. AssertErrorState();
  3394. return;
  3395. }
  3396. auto val = CreateValueFromExpression(deleteStmt->mExpression);
  3397. if (!val)
  3398. return;
  3399. if (val.mType->IsAllocType())
  3400. val.mType = val.mType->GetUnderlyingType();
  3401. BfGenericParamType* genericType = NULL;
  3402. if (val.mType->IsGenericParam())
  3403. genericType = (BfGenericParamType*)val.mType;
  3404. if ((val.mType->IsPointer()) && (val.mType->GetUnderlyingType()->IsGenericParam()))
  3405. genericType = (BfGenericParamType*)val.mType->GetUnderlyingType();
  3406. auto checkType = val.mType;
  3407. if (genericType != NULL)
  3408. {
  3409. auto genericParamInst = GetGenericParamInstance(genericType);
  3410. if (genericParamInst->mTypeConstraint != NULL)
  3411. checkType = genericParamInst->mTypeConstraint;
  3412. bool canAlwaysDelete = checkType->IsDelegate() || checkType->IsFunction() || checkType->IsArray();
  3413. if (auto checkTypeInst = checkType->ToTypeInstance())
  3414. {
  3415. if ((checkTypeInst->IsInstanceOf(mCompiler->mDelegateTypeDef)) ||
  3416. (checkTypeInst->IsInstanceOf(mCompiler->mFunctionTypeDef)))
  3417. canAlwaysDelete = true;
  3418. }
  3419. if (!canAlwaysDelete)
  3420. {
  3421. if (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
  3422. return;
  3423. if (genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr)
  3424. return;
  3425. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Struct) && (checkType->IsPointer()))
  3426. return;
  3427. Fail(StrFormat("Must add 'where %s : delete' constraint to generic parameter to delete generic type '%s'",
  3428. genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
  3429. return;
  3430. }
  3431. }
  3432. if (checkType->IsVar())
  3433. {
  3434. // Mixin or unconstrained generic
  3435. return;
  3436. }
  3437. if ((!checkType->IsPointer()) && (!checkType->IsObjectOrInterface()))
  3438. {
  3439. Fail(StrFormat("Cannot delete a value of type '%s'", TypeToString(val.mType).c_str()), deleteStmt->mExpression);
  3440. return;
  3441. }
  3442. if (val.mType->IsGenericParam())
  3443. return;
  3444. auto bodyBB = mBfIRBuilder->CreateBlock("delete.body");
  3445. auto endBB = mBfIRBuilder->CreateBlock("delete.end");
  3446. bool mayBeSentinel = false;
  3447. if (checkType->IsPointer())
  3448. {
  3449. auto innerType = checkType->GetUnderlyingType();
  3450. PopulateType(innerType);
  3451. if (innerType->IsValuelessType())
  3452. mayBeSentinel = true;
  3453. }
  3454. BfIRValue isNotNull;
  3455. if (mayBeSentinel)
  3456. {
  3457. auto intVal = mBfIRBuilder->CreatePtrToInt(val.mValue, BfTypeCode_IntPtr);
  3458. isNotNull = mBfIRBuilder->CreateCmpGT(intVal, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1), false);
  3459. }
  3460. else
  3461. {
  3462. isNotNull = mBfIRBuilder->CreateIsNotNull(val.mValue);
  3463. }
  3464. mBfIRBuilder->CreateCondBr(isNotNull, bodyBB, endBB);
  3465. mBfIRBuilder->AddBlock(bodyBB);
  3466. mBfIRBuilder->SetInsertPoint(bodyBB);
  3467. if (val.mType->IsObjectOrInterface())
  3468. {
  3469. EmitObjectAccessCheck(val);
  3470. }
  3471. SizedArray<BfIRValue, 4> llvmArgs;
  3472. auto bitAddr = mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
  3473. llvmArgs.push_back(bitAddr);
  3474. if (val.mType->IsObjectOrInterface())
  3475. {
  3476. auto objectType = mContext->mBfObjectType;
  3477. BfTypeInstance* checkTypeInst = val.mType->ToTypeInstance();
  3478. bool allowPrivate = checkTypeInst == mCurTypeInstance;
  3479. bool allowProtected = allowPrivate || TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst);
  3480. while (checkTypeInst != NULL)
  3481. {
  3482. auto dtorMethodDef = checkTypeInst->mTypeDef->GetMethodByName("~this");
  3483. if (dtorMethodDef)
  3484. {
  3485. if (!CheckProtection(dtorMethodDef->mProtection, checkTypeInst->mTypeDef, allowProtected, allowPrivate))
  3486. {
  3487. auto error = Fail(StrFormat("'%s.~this()' is inaccessible due to its protection level", TypeToString(checkTypeInst).c_str()), deleteStmt->mExpression); // CS0122
  3488. }
  3489. }
  3490. checkTypeInst = checkTypeInst->mBaseType;
  3491. allowPrivate = false;
  3492. }
  3493. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  3494. {
  3495. auto preDelete = GetInternalMethod((deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete");
  3496. SizedArray<BfIRValue, 4> llvmArgs;
  3497. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
  3498. mBfIRBuilder->CreateCall(preDelete.mFunc, llvmArgs);
  3499. }
  3500. // call dtor
  3501. BfExprEvaluator expressionEvaluator(this);
  3502. PopulateType(val.mType);
  3503. PopulateType(objectType, BfPopulateType_DataAndMethods);
  3504. if (objectType->mVirtualMethodTable.size() == 0)
  3505. {
  3506. if (!mCompiler->IsAutocomplete())
  3507. AssertErrorState();
  3508. }
  3509. else if (!IsSkippingExtraResolveChecks())
  3510. {
  3511. BfMethodInstance* methodInstance = objectType->mVirtualMethodTable[mCompiler->GetVTableMethodOffset() + 0].mImplementingMethod;
  3512. BF_ASSERT(methodInstance->mMethodDef->mName == "~this");
  3513. SizedArray<BfIRValue, 4> llvmArgs;
  3514. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
  3515. expressionEvaluator.CreateCall(deleteStmt->mDeleteToken, methodInstance, mBfIRBuilder->GetFakeVal(), false, llvmArgs);
  3516. }
  3517. if ((deleteStmt->mTargetTypeToken != NULL) && (!isAppendDelete))
  3518. {
  3519. if (deleteStmt->mAllocExpr != NULL)
  3520. {
  3521. if (customAllocator)
  3522. {
  3523. auto customAllocTypeInst = customAllocator.mType->ToTypeInstance();
  3524. if (customAllocTypeInst != NULL)
  3525. {
  3526. if ((customAllocTypeInst != NULL) && (customAllocTypeInst->mTypeDef->GetMethodByName("FreeObject") != NULL))
  3527. {
  3528. BfTypedValueExpression typedValueExpr;
  3529. typedValueExpr.Init(val);
  3530. typedValueExpr.mRefNode = deleteStmt->mAllocExpr;
  3531. BfExprEvaluator exprEvaluator(this);
  3532. SizedArray<BfExpression*, 2> argExprs;
  3533. argExprs.push_back(&typedValueExpr);
  3534. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  3535. BfResolvedArgs argValues(&sizedArgExprs);
  3536. exprEvaluator.ResolveArgValues(argValues);
  3537. exprEvaluator.mNoBind = true;
  3538. exprEvaluator.MatchMethod(deleteStmt->mAllocExpr, NULL, customAllocator, false, true, "FreeObject", argValues, BfMethodGenericArguments());
  3539. customAllocator = BfTypedValue();
  3540. }
  3541. }
  3542. }
  3543. }
  3544. }
  3545. else
  3546. {
  3547. if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule))
  3548. {
  3549. SizedArray<BfIRValue, 4> llvmArgs;
  3550. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
  3551. auto moduleMethodInstance = GetInternalMethod("Dbg_MarkObjectDeleted");
  3552. mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, llvmArgs);
  3553. }
  3554. else if (!isAppendDelete)
  3555. {
  3556. mBfIRBuilder->CreateCall(GetBuiltInFunc(BfBuiltInFuncType_Free), llvmArgs);
  3557. }
  3558. }
  3559. }
  3560. else
  3561. {
  3562. if ((isAppendDelete) || (customAllocator))
  3563. {
  3564. // Do nothing
  3565. }
  3566. else
  3567. {
  3568. auto func = GetBuiltInFunc(BfBuiltInFuncType_Free);
  3569. if (!func)
  3570. {
  3571. BF_ASSERT(mCompiler->mIsResolveOnly);
  3572. }
  3573. else
  3574. mBfIRBuilder->CreateCall(func, llvmArgs);
  3575. }
  3576. }
  3577. if (customAllocator.mType == GetPrimitiveType(BfTypeCode_NullPtr))
  3578. {
  3579. if (!checkType->IsObjectOrInterface())
  3580. Warn(0, "Type '%' has no destructor, so delete:null has no effect", deleteStmt->mExpression);
  3581. }
  3582. else if (customAllocator)
  3583. {
  3584. auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  3585. auto ptrValue = BfTypedValue(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(voidPtrType)), voidPtrType);
  3586. BfTypedValueExpression typedValueExpr;
  3587. typedValueExpr.Init(ptrValue);
  3588. BfExprEvaluator exprEvaluator(this);
  3589. SizedArray<BfExpression*, 2> argExprs;
  3590. argExprs.push_back(&typedValueExpr);
  3591. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  3592. BfResolvedArgs argValues(&sizedArgExprs);
  3593. exprEvaluator.ResolveArgValues(argValues);
  3594. exprEvaluator.mNoBind = true;
  3595. exprEvaluator.MatchMethod(deleteStmt->mAllocExpr, NULL, customAllocator, false, false, "Free", argValues, BfMethodGenericArguments());
  3596. }
  3597. mBfIRBuilder->CreateBr(endBB);
  3598. mBfIRBuilder->AddBlock(endBB);
  3599. mBfIRBuilder->SetInsertPoint(endBB);
  3600. }
  3601. void BfModule::Visit(BfSwitchStatement* switchStmt)
  3602. {
  3603. BfScopeData outerScope;
  3604. outerScope.mInnerIsConditional = false;
  3605. outerScope.mCloseNode = switchStmt;
  3606. if (switchStmt->mCloseBrace != NULL)
  3607. outerScope.mCloseNode = switchStmt->mCloseBrace;
  3608. mCurMethodState->AddScope(&outerScope);
  3609. NewScopeState();
  3610. auto valueScopeStartOuter = ValueScopeStart();
  3611. BfTypedValue switchValue;
  3612. if (switchStmt->mSwitchValue == NULL)
  3613. {
  3614. AssertErrorState();
  3615. UpdateSrcPos(switchStmt->mSwitchToken);
  3616. }
  3617. else
  3618. {
  3619. UpdateExprSrcPos(switchStmt->mSwitchValue);
  3620. BfEvalExprFlags flags = BfEvalExprFlags_None;
  3621. flags = BfEvalExprFlags_AllowSplat;
  3622. switchValue = CreateValueFromExpression(switchStmt->mSwitchValue, NULL, flags);
  3623. }
  3624. EmitEnsureInstructionAt();
  3625. if (!switchValue)
  3626. {
  3627. AssertErrorState();
  3628. switchValue = GetDefaultTypedValue(mContext->mBfObjectType);
  3629. }
  3630. if (switchValue.mType->IsPointer())
  3631. {
  3632. auto underlyingType = switchValue.mType->GetUnderlyingType();
  3633. if (underlyingType->IsEnum())
  3634. {
  3635. switchValue = LoadValue(switchValue);
  3636. switchValue = BfTypedValue(switchValue.mValue, underlyingType, true);
  3637. }
  3638. }
  3639. // We make the switch value conditional, but all other uses of this scope is conditional since it's conditional on cases
  3640. BfScopeData newScope;
  3641. newScope.mInnerIsConditional = true;
  3642. newScope.mCloseNode = switchStmt;
  3643. if (switchStmt->mCloseBrace != NULL)
  3644. newScope.mCloseNode = switchStmt->mCloseBrace;
  3645. if (switchStmt->mLabelNode != NULL)
  3646. newScope.mLabelNode = switchStmt->mLabelNode->mLabel;
  3647. mCurMethodState->AddScope(&newScope);
  3648. NewScopeState();
  3649. BfTypedValue switchValueAddr = switchValue;
  3650. BfLocalVariable* localDef = new BfLocalVariable();
  3651. localDef->mName = "_";
  3652. localDef->mResolvedType = switchValueAddr.mType;
  3653. localDef->mIsReadOnly = true;
  3654. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  3655. if (switchValue.IsAddr())
  3656. {
  3657. localDef->mAddr = switchValue.mValue;
  3658. }
  3659. else
  3660. {
  3661. localDef->mValue = switchValue.mValue;
  3662. localDef->mIsSplat = switchValue.IsSplat();
  3663. }
  3664. bool wantsDebugInfo = mHasFullDebugInfo && !mBfIRBuilder->mIgnoreWrites;
  3665. bool tryExtendValue = false;
  3666. bool addDebugInfo = true;
  3667. if ((wantsDebugInfo) && (!switchValue.mType->IsValuelessType()) && (!switchValue.mType->IsVar()))
  3668. {
  3669. if (IsTargetingBeefBackend())
  3670. {
  3671. // We don't need to make a copy
  3672. if (switchValue.IsSplat())
  3673. {
  3674. localDef->mIsSplat = true;
  3675. if (WantsDebugInfo())
  3676. {
  3677. bool found = false;
  3678. String varName = "_";
  3679. for (auto dbgVar : mCurMethodState->mLocals)
  3680. {
  3681. if (dbgVar->mAddr == switchValue.mValue)
  3682. {
  3683. varName += "$a$" + dbgVar->mName;
  3684. found = true;
  3685. break;
  3686. }
  3687. }
  3688. if (found)
  3689. {
  3690. auto fakeVal = CreateAlloca(GetPrimitiveType(BfTypeCode_Int32), true, "_fake");
  3691. addDebugInfo = false;
  3692. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope, varName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(localDef->mResolvedType), BfIRInitType_NotNeeded_AliveOnDecl);
  3693. mBfIRBuilder->DbgInsertDeclare(fakeVal, diVariable);
  3694. }
  3695. }
  3696. }
  3697. else
  3698. {
  3699. // if (!localDef->mAddr)
  3700. // {
  3701. // BfIRValue value = localDef->mValue;
  3702. // if (newLocalVar->mConstValue)
  3703. // value = localDef->mConstValue;
  3704. // auto aliasValue = mBfIRBuilder->CreateAliasValue(value);
  3705. // mBfIRBuilder->DbgInsertValueIntrinsic(aliasValue, diVariable);
  3706. // scopeData.mDeferredLifetimeEnds.push_back(aliasValue);
  3707. // }
  3708. tryExtendValue = true;
  3709. }
  3710. }
  3711. else if ((switchValue.mType->IsComposite()) && (switchValue.IsAddr()))
  3712. {
  3713. auto refType = CreateRefType(switchValue.mType);
  3714. auto allocaVal = CreateAlloca(refType);
  3715. mBfIRBuilder->CreateStore(switchValue.mValue, allocaVal);
  3716. auto diType = mBfIRBuilder->DbgGetType(refType);
  3717. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  3718. localDef->mName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
  3719. mBfIRBuilder->DbgInsertDeclare(allocaVal, diVariable);
  3720. addDebugInfo = false;
  3721. }
  3722. else
  3723. {
  3724. if (switchValueAddr.IsSplat())
  3725. {
  3726. auto addr = CreateAlloca(switchValue.mType);
  3727. if (switchValue.IsSplat())
  3728. AggregateSplatIntoAddr(switchValue, addr);
  3729. else
  3730. mBfIRBuilder->CreateStore(switchValue.mValue, addr);
  3731. localDef->mAddr = addr;
  3732. localDef->mValue = BfIRValue();
  3733. localDef->mIsSplat = false;
  3734. }
  3735. }
  3736. }
  3737. if (!localDef->mResolvedType->IsVar())
  3738. AddLocalVariableDef(localDef, addDebugInfo, true);
  3739. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  3740. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  3741. int numExpressions = 0;
  3742. SizedArray<BfIRBlock, 8> blocks;
  3743. SizedArray<BfWhenExpression*, 8> whenExprs;
  3744. SizedArray<BfIRBlock, 8> whenFailBlocks;
  3745. BfIRBlock defaultBlock;
  3746. auto endBlock = mBfIRBuilder->CreateBlock("switch.end");
  3747. for (BfSwitchCase* switchCase : switchStmt->mSwitchCases)
  3748. {
  3749. auto caseBlock = mBfIRBuilder->CreateBlock(StrFormat("switch.%d", blocks.size()));
  3750. blocks.push_back(caseBlock);
  3751. numExpressions += (int)switchCase->mCaseExpressions.size();
  3752. }
  3753. defaultBlock = mBfIRBuilder->CreateBlock("default");
  3754. bool hasDefaultCase = switchStmt->mDefaultCase != NULL;
  3755. if (hasDefaultCase)
  3756. blocks.push_back(defaultBlock);
  3757. SizedArray<BfDeferredLocalAssignData, 8> deferredLocalAssignDataVec;
  3758. deferredLocalAssignDataVec.resize(blocks.size());
  3759. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  3760. BfTypedValue enumTagVal;
  3761. // Declare cases
  3762. int blockIdx = 0;
  3763. bool hadConstIntVals = false;
  3764. bool hadWhen = false;
  3765. BfIRValue switchStatement;
  3766. auto switchBlock = mBfIRBuilder->GetInsertBlock();
  3767. BfIRBlock noSwitchBlock = mBfIRBuilder->CreateBlock("noSwitch", true);
  3768. BfPrimitiveType* intCoercibleType = GetIntCoercibleType(switchValue.mType);
  3769. bool isConstSwitch = false;
  3770. if ((switchValue.mValue.IsConst()) || (switchValue.mType->IsValuelessType()))
  3771. {
  3772. isConstSwitch = true;
  3773. }
  3774. if (switchValue.mValue)
  3775. {
  3776. mBfIRBuilder->PopulateType(switchValue.mType);
  3777. if (intCoercibleType != NULL)
  3778. {
  3779. auto intValue = GetIntCoercible(switchValue);
  3780. switchStatement = mBfIRBuilder->CreateSwitch(intValue.mValue, noSwitchBlock, numExpressions);
  3781. }
  3782. else if (switchValue.mType->IsPayloadEnum())
  3783. {
  3784. enumTagVal = ExtractValue(switchValue, NULL, 2);
  3785. enumTagVal = LoadValue(enumTagVal);
  3786. switchStatement = mBfIRBuilder->CreateSwitch(enumTagVal.mValue, noSwitchBlock, numExpressions);
  3787. }
  3788. else if ((!isConstSwitch) && (!switchValue.mType->IsVar()))
  3789. switchStatement = mBfIRBuilder->CreateSwitch(switchValue.mValue, noSwitchBlock, numExpressions);
  3790. }
  3791. auto valueScopeStartInner = ValueScopeStart();
  3792. mBfIRBuilder->SetInsertPoint(noSwitchBlock);
  3793. bool isPayloadEnum = switchValue.mType->IsPayloadEnum();
  3794. bool isTuple = switchValue.mType->IsTuple();
  3795. bool isIntegralSwitch = switchValue.mType->IsIntegral() || (intCoercibleType != NULL) || ((switchValue.mType->IsEnum()) && (!isPayloadEnum));
  3796. auto _ShowCaseError = [&] (int64 id, BfAstNode* errNode)
  3797. {
  3798. if (isPayloadEnum)
  3799. {
  3800. auto enumType = switchValue.mType->ToTypeInstance();
  3801. for (auto fieldInstance : enumType->mFieldInstances)
  3802. {
  3803. auto fieldDef = fieldInstance.GetFieldDef();
  3804. if (fieldDef->IsEnumCaseEntry())
  3805. {
  3806. int enumIdx = -fieldInstance.mDataIdx - 1;
  3807. if (enumIdx == id)
  3808. {
  3809. Fail(StrFormat("The switch statement already contains a case for the the value '%s'", fieldDef->mName.c_str()), errNode);
  3810. return;
  3811. }
  3812. }
  3813. }
  3814. }
  3815. Fail(StrFormat("The switch statement already contains a case for the the value '%lld'", id), errNode);
  3816. };
  3817. int caseCount = 0;
  3818. bool allHadReturns = true;
  3819. bool hadCondCase = false;
  3820. BfIRBlock lastDefaultBlock;
  3821. struct _CaseState
  3822. {
  3823. BfIRBlock mCondBlock;
  3824. BfIRBlock mUncondBlock;
  3825. };
  3826. bool hadConstMatch = false;
  3827. auto startingLocalVarId = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  3828. bool prevHadFallthrough = false;
  3829. Dictionary<int64, _CaseState> handledCases;
  3830. for (BfSwitchCase* switchCase : switchStmt->mSwitchCases)
  3831. {
  3832. deferredLocalAssignDataVec[blockIdx].mScopeData = mCurMethodState->mCurScope;
  3833. deferredLocalAssignDataVec[blockIdx].ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
  3834. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignDataVec[blockIdx]);
  3835. mCurMethodState->mDeferredLocalAssignData->mVarIdBarrier = startingLocalVarId;
  3836. SetIllegalSrcPos();
  3837. auto caseBlock = blocks[blockIdx];
  3838. BfScopeData caseScopeData;
  3839. bool openedScope = false;
  3840. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  3841. {
  3842. // This does the enum autocomplete popup
  3843. BfAstNode* checkNode = NULL;
  3844. int caseExprIdx = (int)switchCase->mCaseExpressions.size();
  3845. if (caseExprIdx == 0)
  3846. checkNode = switchCase->mCaseToken;
  3847. else if (caseExprIdx - 1 < (int)switchCase->mCaseCommas.size())
  3848. checkNode = switchCase->mCaseCommas[caseExprIdx - 1];
  3849. if (checkNode != NULL)
  3850. mCompiler->mResolvePassData->mAutoComplete->CheckEmptyStart(checkNode, switchValue.mType);
  3851. }
  3852. bool mayHaveMatch = false;
  3853. BfWhenExpression* whenExpr = NULL;
  3854. for (BfExpression* caseExpr : switchCase->mCaseExpressions)
  3855. {
  3856. if (auto checkWhenExpr = BfNodeDynCast<BfWhenExpression>(caseExpr))
  3857. {
  3858. hadWhen = true;
  3859. whenExpr = checkWhenExpr;
  3860. }
  3861. if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(caseExpr))
  3862. {
  3863. if (prevHadFallthrough)
  3864. {
  3865. Fail("Destructuring cannot be used when the previous case contains a fallthrough", caseExpr);
  3866. }
  3867. }
  3868. }
  3869. bool wantsOpenedScope = isPayloadEnum || isTuple;
  3870. BfIRBlock lastNotEqBlock;
  3871. for (BfExpression* caseExpr : switchCase->mCaseExpressions)
  3872. {
  3873. BfConstant* constantInt = NULL;
  3874. if (auto checkWhenExpr = BfNodeDynCast<BfWhenExpression>(caseExpr))
  3875. continue;
  3876. if ((!openedScope) && (wantsOpenedScope))
  3877. {
  3878. openedScope = true;
  3879. caseScopeData.mOuterIsConditional = true;
  3880. mCurMethodState->AddScope(&caseScopeData);
  3881. NewScopeState();
  3882. UpdateSrcPos(caseExpr);
  3883. SetIllegalSrcPos();
  3884. }
  3885. BfIRValue eqResult;
  3886. BfIRBlock notEqBB;
  3887. bool handled = false;
  3888. BfTypedValue caseValue;
  3889. BfIRBlock doBlock = caseBlock;
  3890. bool hadConditional = false;
  3891. if (isPayloadEnum)
  3892. {
  3893. auto dscrType = switchValue.mType->ToTypeInstance()->GetDiscriminatorType();
  3894. if (!enumTagVal)
  3895. {
  3896. enumTagVal = ExtractValue(switchValue, NULL, 2);
  3897. enumTagVal = LoadValue(enumTagVal);
  3898. }
  3899. notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq.%d", blockIdx), false);
  3900. int tagId = -1;
  3901. BfIRBlock matchBlock;
  3902. BfTypedValue eqTypedResult;
  3903. if (auto bindExpr = BfNodeDynCast<BfEnumCaseBindExpression>(caseExpr))
  3904. {
  3905. eqTypedResult = HandleCaseBind(switchValueAddr, enumTagVal, bindExpr, &caseBlock, &notEqBB, &matchBlock, &tagId);
  3906. }
  3907. else
  3908. {
  3909. eqTypedResult = TryCaseEnumMatch(switchValueAddr, enumTagVal, caseExpr, &caseBlock, &notEqBB, &matchBlock, tagId, hadConditional, false);
  3910. if (hadConditional)
  3911. hadCondCase = true;
  3912. }
  3913. if (tagId != -1)
  3914. {
  3915. doBlock = matchBlock; // Jump to binds rather than just the code
  3916. caseValue = BfTypedValue(GetConstValue(tagId, GetPrimitiveType(dscrType->mTypeDef->mTypeCode)), dscrType);
  3917. }
  3918. else
  3919. hadCondCase = true;
  3920. if (eqTypedResult)
  3921. {
  3922. handled = true;
  3923. eqResult = eqTypedResult.mValue;
  3924. }
  3925. }
  3926. else if (auto tupleExpr = BfNodeDynCast<BfTupleExpression>(caseExpr))
  3927. {
  3928. notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq.%d", blockIdx), false);
  3929. BfIRBlock matchBlock;
  3930. BfTypedValue eqTypedResult = TryCaseTupleMatch(switchValue, tupleExpr, &caseBlock, &notEqBB, &matchBlock, hadConditional, false);
  3931. if (hadConditional)
  3932. hadCondCase = true;
  3933. if (eqTypedResult)
  3934. {
  3935. mayHaveMatch = true;
  3936. handled = true;
  3937. eqResult = eqTypedResult.mValue;
  3938. }
  3939. }
  3940. if (!eqResult)
  3941. {
  3942. caseValue = CreateValueFromExpression(caseExpr, switchValue.mType, (BfEvalExprFlags)(BfEvalExprFlags_AllowEnumId | BfEvalExprFlags_NoCast));
  3943. if (!caseValue)
  3944. continue;
  3945. }
  3946. BfTypedValue caseIntVal = caseValue;
  3947. if ((isIntegralSwitch) || (isPayloadEnum))
  3948. {
  3949. if ((intCoercibleType != NULL) &&
  3950. (caseValue.mType == switchValue.mType) &&
  3951. (caseValue.mValue.IsConst()))
  3952. {
  3953. caseIntVal = GetIntCoercible(caseValue);
  3954. constantInt = mBfIRBuilder->GetConstant(caseIntVal.mValue);
  3955. }
  3956. else
  3957. {
  3958. // For a non-const case, allow for conversion operators, otherwise cast now
  3959. if ((isIntegralSwitch) && (caseValue.mValue.IsConst()))
  3960. {
  3961. if (caseValue.mType != switchValue.mType)
  3962. {
  3963. caseValue = Cast(caseExpr, caseValue, switchValue.mType);
  3964. if (!caseValue)
  3965. continue;
  3966. caseIntVal = caseValue;
  3967. }
  3968. }
  3969. if ((caseValue.mType == switchValue.mType) || (eqResult))
  3970. {
  3971. constantInt = mBfIRBuilder->GetConstant(caseValue.mValue);
  3972. if ((constantInt != NULL) && (!mBfIRBuilder->IsInt(constantInt->mTypeCode)))
  3973. constantInt = NULL;
  3974. }
  3975. }
  3976. }
  3977. if ((!switchStatement) && (!isConstSwitch))
  3978. {
  3979. // Do nothing
  3980. mayHaveMatch = true;
  3981. }
  3982. else if ((constantInt != NULL) && (!hadWhen) && (!isConstSwitch))
  3983. {
  3984. if (!hadConditional)
  3985. {
  3986. _CaseState* caseState = NULL;
  3987. handledCases.TryAdd(constantInt->mInt64, NULL, &caseState);
  3988. if (caseState->mUncondBlock)
  3989. {
  3990. _ShowCaseError(constantInt->mInt64, caseExpr);
  3991. }
  3992. else
  3993. {
  3994. caseState->mUncondBlock = doBlock;
  3995. mBfIRBuilder->AddSwitchCase(switchStatement, caseIntVal.mValue, doBlock);
  3996. hadConstIntVals = true;
  3997. }
  3998. }
  3999. mayHaveMatch = true;
  4000. }
  4001. else if (!handled)
  4002. {
  4003. hadCondCase = true;
  4004. if (!eqResult)
  4005. {
  4006. BfExprEvaluator exprEvaluator(this);
  4007. BfAstNode* refNode = switchCase->mColonToken;
  4008. if ((caseValue.mType->IsPayloadEnum()) && (caseValue.mValue.IsConst()) && (switchValue.mType == caseValue.mType))
  4009. {
  4010. if (!enumTagVal)
  4011. {
  4012. enumTagVal = ExtractValue(switchValue, NULL, 2);
  4013. enumTagVal = LoadValue(enumTagVal);
  4014. }
  4015. eqResult = mBfIRBuilder->CreateCmpEQ(enumTagVal.mValue, caseValue.mValue);
  4016. }
  4017. else
  4018. {
  4019. exprEvaluator.PerformBinaryOperation(switchStmt->mSwitchValue, caseExpr, BfBinaryOp_Equality, refNode, (BfBinOpFlags)(BfBinOpFlag_ForceLeftType), switchValue, caseValue);
  4020. if (switchStmt->mSwitchValue != NULL)
  4021. UpdateSrcPos(switchStmt->mSwitchValue);
  4022. SetIllegalSrcPos();
  4023. eqResult = exprEvaluator.mResult.mValue;
  4024. if (!eqResult)
  4025. eqResult = GetConstValue(0, boolType);
  4026. }
  4027. }
  4028. ValueScopeEnd(valueScopeStartInner);
  4029. bool isConstResult = false;
  4030. bool constResult = false;
  4031. if (eqResult.IsConst())
  4032. {
  4033. auto constant = mBfIRBuilder->GetConstant(eqResult);
  4034. if (constant->mTypeCode == BfTypeCode_Boolean)
  4035. {
  4036. isConstResult = true;
  4037. constResult = constant->mBool;
  4038. }
  4039. }
  4040. if (isConstResult)
  4041. {
  4042. if (constResult)
  4043. {
  4044. mBfIRBuilder->CreateBr(caseBlock);
  4045. mayHaveMatch = true;
  4046. if (whenExpr == NULL)
  4047. {
  4048. hadConstMatch = true;
  4049. }
  4050. else
  4051. {
  4052. notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq.%d", blockIdx));
  4053. mBfIRBuilder->AddBlock(notEqBB);
  4054. mBfIRBuilder->SetInsertPoint(notEqBB);
  4055. }
  4056. }
  4057. }
  4058. else
  4059. {
  4060. notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq.%d", blockIdx));
  4061. mayHaveMatch = true;
  4062. mBfIRBuilder->CreateCondBr(eqResult, caseBlock, notEqBB);
  4063. mBfIRBuilder->AddBlock(notEqBB);
  4064. mBfIRBuilder->SetInsertPoint(notEqBB);
  4065. }
  4066. }
  4067. if (notEqBB)
  4068. lastNotEqBlock = notEqBB;
  4069. if ((!hadCondCase) && (notEqBB))
  4070. lastDefaultBlock = notEqBB;
  4071. }
  4072. if ((whenExpr != NULL) && (switchCase->mCaseExpressions.size() == 1))
  4073. {
  4074. // This was a "case when" expression, always matches
  4075. mayHaveMatch = true;
  4076. auto notEqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.notEq_when.%d", blockIdx));
  4077. mBfIRBuilder->CreateBr(caseBlock);
  4078. mBfIRBuilder->AddBlock(notEqBB);
  4079. mBfIRBuilder->SetInsertPoint(notEqBB);
  4080. lastNotEqBlock = notEqBB;
  4081. }
  4082. if ((lastDefaultBlock) && (switchStatement))
  4083. mBfIRBuilder->SetSwitchDefaultDest(switchStatement, lastDefaultBlock);
  4084. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  4085. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, !mayHaveMatch && !prevHadFallthrough);
  4086. mBfIRBuilder->AddBlock(caseBlock);
  4087. mBfIRBuilder->SetInsertPoint(caseBlock);
  4088. if (whenExpr != NULL)
  4089. {
  4090. UpdateSrcPos(whenExpr);
  4091. BfTypedValue whenValue;
  4092. if (whenExpr->mExpression != NULL)
  4093. whenValue = CreateValueFromExpression(whenExpr->mExpression, boolType, BfEvalExprFlags_AllowEnumId);
  4094. if (!whenValue)
  4095. {
  4096. AssertErrorState();
  4097. whenValue = GetDefaultTypedValue(boolType);
  4098. }
  4099. bool constResult = false;
  4100. if (mBfIRBuilder->TryGetBool(whenValue.mValue, constResult))
  4101. {
  4102. if (!constResult)
  4103. prevIgnoreWrites.Set();
  4104. }
  4105. else
  4106. {
  4107. BfIRBlock eqBB = mBfIRBuilder->CreateBlock(StrFormat("switch.when.%d", blockIdx));
  4108. mBfIRBuilder->CreateCondBr(whenValue.mValue, eqBB, lastNotEqBlock);
  4109. mBfIRBuilder->AddBlock(eqBB);
  4110. mBfIRBuilder->SetInsertPoint(eqBB);
  4111. }
  4112. }
  4113. BfIRBlock fallthroughBlock;
  4114. if (blockIdx < (int) blocks.size() - 1)
  4115. fallthroughBlock = blocks[blockIdx + 1];
  4116. else
  4117. fallthroughBlock = defaultBlock;
  4118. bool hadReturn = false;
  4119. if ((switchCase->mCodeBlock != NULL) && (!switchCase->mCodeBlock->mChildArr.IsEmpty()))
  4120. {
  4121. UpdateSrcPos(switchCase->mCodeBlock);
  4122. VisitCodeBlock(switchCase->mCodeBlock, BfIRBlock(), endBlock, fallthroughBlock, true, &hadReturn, switchStmt->mLabelNode, openedScope);
  4123. openedScope = false;
  4124. deferredLocalAssignDataVec[blockIdx].mHadReturn = hadReturn;
  4125. caseCount++;
  4126. if ((!hadReturn) &&
  4127. ((!mCurMethodState->mDeferredLocalAssignData->mHadFallthrough) || (mCurMethodState->mDeferredLocalAssignData->mHadBreak)))
  4128. allHadReturns = false;
  4129. if (auto block = BfNodeDynCast<BfBlock>(switchCase->mCodeBlock))
  4130. {
  4131. //
  4132. }
  4133. else
  4134. {
  4135. if (switchStmt->mCloseBrace != NULL)
  4136. {
  4137. UpdateSrcPos(switchStmt->mCloseBrace);
  4138. }
  4139. EmitEnsureInstructionAt();
  4140. }
  4141. //UpdateSrcPos(switchCase->mCodeBlock);
  4142. //SetIllegalSrcPos();
  4143. mBfIRBuilder->ClearDebugLocation();
  4144. }
  4145. else
  4146. {
  4147. if (openedScope)
  4148. RestoreScopeState();
  4149. mBfIRBuilder->CreateBr(endBlock);
  4150. allHadReturns = false;
  4151. }
  4152. prevIgnoreWrites.Restore();
  4153. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  4154. prevHadFallthrough = mCurMethodState->mDeferredLocalAssignData->mHadFallthrough;
  4155. blockIdx++;
  4156. }
  4157. // Check for comprehensiveness
  4158. bool isComprehensive = true;
  4159. if ((switchValue) && (switchStmt->mDefaultCase == NULL))
  4160. {
  4161. if (switchValue.mType->IsEnum())
  4162. {
  4163. if (hadConstMatch)
  4164. {
  4165. // Already handled
  4166. }
  4167. else
  4168. {
  4169. auto enumType = switchValue.mType->ToTypeInstance();
  4170. if (enumType->IsPayloadEnum())
  4171. {
  4172. int lastTagId = -1;
  4173. for (auto& field : enumType->mFieldInstances)
  4174. {
  4175. auto fieldDef = field.GetFieldDef();
  4176. if (fieldDef == NULL)
  4177. continue;
  4178. if (!fieldDef->IsEnumCaseEntry())
  4179. continue;
  4180. if (field.mDataIdx < 0)
  4181. lastTagId = -field.mDataIdx - 1;
  4182. }
  4183. isComprehensive = lastTagId == (int)handledCases.size() - 1;
  4184. }
  4185. else
  4186. {
  4187. for (auto& field : enumType->mFieldInstances)
  4188. {
  4189. auto fieldDef = field.GetFieldDef();
  4190. if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
  4191. {
  4192. if (field.mConstIdx != -1)
  4193. {
  4194. auto constant = enumType->mConstHolder->GetConstantById(field.mConstIdx);
  4195. isComprehensive &= handledCases.ContainsKey(constant->mInt64);
  4196. }
  4197. }
  4198. }
  4199. }
  4200. }
  4201. if (!isComprehensive)
  4202. {
  4203. BfAstNode* refNode = switchStmt->mSwitchToken;
  4204. Fail("Switch must be exhaustive, consider adding a default clause", switchStmt->mSwitchToken);
  4205. if ((switchStmt->mCloseBrace) && (mCompiler->IsAutocomplete()) && (mCompiler->mResolvePassData->mAutoComplete->CheckFixit((refNode))))
  4206. {
  4207. BfParserData* parser = refNode->GetSourceData()->ToParserData();
  4208. if (parser != NULL)
  4209. {
  4210. int fileLoc = switchStmt->mCloseBrace->GetSrcStart();
  4211. mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("default:\tdefault:|%s|%d||default:", parser->mFileName.c_str(), fileLoc).c_str()));
  4212. }
  4213. }
  4214. }
  4215. }
  4216. else
  4217. isComprehensive = false;
  4218. }
  4219. if (!hadConstMatch)
  4220. mBfIRBuilder->CreateBr(defaultBlock);
  4221. mBfIRBuilder->SetInsertPoint(switchBlock);
  4222. if (!hadConstIntVals)
  4223. {
  4224. if (switchStatement)
  4225. mBfIRBuilder->EraseInstFromParent(switchStatement);
  4226. mBfIRBuilder->CreateBr(noSwitchBlock);
  4227. }
  4228. if (switchStmt->mDefaultCase != NULL)
  4229. {
  4230. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, hadConstMatch);
  4231. mBfIRBuilder->AddBlock(defaultBlock);
  4232. mBfIRBuilder->SetInsertPoint(defaultBlock);
  4233. auto switchCase = switchStmt->mDefaultCase;
  4234. if (switchCase->mCodeBlock != NULL)
  4235. {
  4236. isComprehensive = true;
  4237. UpdateSrcPos(switchCase->mCodeBlock);
  4238. deferredLocalAssignDataVec[blockIdx].mScopeData = mCurMethodState->mCurScope;
  4239. deferredLocalAssignDataVec[blockIdx].ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
  4240. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignDataVec[blockIdx]);
  4241. mCurMethodState->mDeferredLocalAssignData->mVarIdBarrier = startingLocalVarId;
  4242. bool hadReturn = false;
  4243. VisitCodeBlock(switchCase->mCodeBlock, BfIRBlock(), endBlock, BfIRBlock(), true, &hadReturn, switchStmt->mLabelNode);
  4244. deferredLocalAssignDataVec[blockIdx].mHadReturn = hadReturn;
  4245. caseCount++;
  4246. if (!hadReturn)
  4247. allHadReturns = false;
  4248. }
  4249. }
  4250. else
  4251. {
  4252. mBfIRBuilder->AddBlock(defaultBlock);
  4253. mBfIRBuilder->SetInsertPoint(defaultBlock);
  4254. if (isComprehensive)
  4255. {
  4256. mBfIRBuilder->CreateUnreachable();
  4257. //TODO: This masks a bug in our backend
  4258. if (IsTargetingBeefBackend())
  4259. mBfIRBuilder->CreateBr(endBlock);
  4260. }
  4261. else
  4262. mBfIRBuilder->CreateBr(endBlock);
  4263. }
  4264. if (isComprehensive)
  4265. {
  4266. // Merge and apply deferred local assign data
  4267. // We only do this if there's a default case, otherwise we assume we may have missed a case
  4268. // that by definition had no local assigns
  4269. BfDeferredLocalAssignData* mergedDeferredLocalAssignData = NULL;
  4270. for (blockIdx = 0; blockIdx < (int)blocks.size(); blockIdx++)
  4271. {
  4272. auto deferredLocalAssignData = &deferredLocalAssignDataVec[blockIdx];
  4273. if (deferredLocalAssignData->mHadFallthrough)
  4274. continue;
  4275. if (mergedDeferredLocalAssignData == NULL)
  4276. mergedDeferredLocalAssignData = deferredLocalAssignData;
  4277. else
  4278. mergedDeferredLocalAssignData->SetIntersection(*deferredLocalAssignData);
  4279. }
  4280. if (mergedDeferredLocalAssignData != NULL)
  4281. mCurMethodState->ApplyDeferredLocalAssignData(*mergedDeferredLocalAssignData);
  4282. }
  4283. if ((caseCount > 0) && (allHadReturns) &&
  4284. ((hasDefaultCase) || (isComprehensive)))
  4285. {
  4286. mCurMethodState->SetHadReturn(true);
  4287. mCurMethodState->mLeftBlockUncond = true;
  4288. if ((!hasDefaultCase) && (!isComprehensive))
  4289. mBfIRBuilder->DeleteBlock(endBlock);
  4290. else
  4291. {
  4292. if (switchStmt->mCloseBrace != NULL)
  4293. UpdateSrcPos(switchStmt->mCloseBrace);
  4294. mBfIRBuilder->AddBlock(endBlock);
  4295. mBfIRBuilder->SetInsertPoint(endBlock);
  4296. mBfIRBuilder->CreateUnreachable();
  4297. }
  4298. }
  4299. else
  4300. {
  4301. if (switchStmt->mCloseBrace != NULL)
  4302. UpdateSrcPos(switchStmt->mCloseBrace);
  4303. mBfIRBuilder->AddBlock(endBlock);
  4304. mBfIRBuilder->SetInsertPoint(endBlock);
  4305. }
  4306. BfIRValue lifetimeExtendVal;
  4307. if (tryExtendValue)
  4308. {
  4309. if (localDef->mAddr)
  4310. lifetimeExtendVal = localDef->mAddr;
  4311. else
  4312. lifetimeExtendVal = localDef->mValue;
  4313. }
  4314. RestoreScopeState(); // newScope
  4315. RestoreScopeState(); // outerScope
  4316. if (lifetimeExtendVal)
  4317. mBfIRBuilder->CreateLifetimeExtend(lifetimeExtendVal);
  4318. ValueScopeEnd(valueScopeStartOuter);
  4319. }
  4320. static int gRetIdx = 0;
  4321. void BfModule::Visit(BfReturnStatement* returnStmt)
  4322. {
  4323. if ((mCurMethodInstance == NULL) || (mCurMethodState->mDisableReturns))
  4324. {
  4325. Fail("Unexpected return", returnStmt);
  4326. if (returnStmt->mExpression != NULL)
  4327. {
  4328. BfExprEvaluator exprEvaluator(this);
  4329. CreateValueFromExpression(exprEvaluator, returnStmt->mExpression);
  4330. }
  4331. return;
  4332. }
  4333. UpdateSrcPos(returnStmt);
  4334. EmitEnsureInstructionAt();
  4335. auto retType = mCurMethodInstance->mReturnType;
  4336. if (mCurMethodInstance->IsMixin())
  4337. retType = NULL;
  4338. bool inferReturnType = false;
  4339. if (mCurMethodState->mClosureState != NULL)
  4340. {
  4341. retType = mCurMethodState->mClosureState->mReturnType;
  4342. inferReturnType = (mCurMethodState->mClosureState->mReturnTypeInferState != BfReturnTypeInferState_None);
  4343. }
  4344. auto checkScope = mCurMethodState->mCurScope;
  4345. while (checkScope != NULL)
  4346. {
  4347. if (checkScope->mIsDeferredBlock)
  4348. {
  4349. Fail("Deferred blocks cannot contain 'return' statements", returnStmt);
  4350. if (returnStmt->mExpression != NULL)
  4351. {
  4352. BfExprEvaluator exprEvaluator(this);
  4353. CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, GetPrimitiveType(BfTypeCode_Var), BfEvalExprFlags_None);
  4354. }
  4355. return;
  4356. }
  4357. if (checkScope->mInInitBlock)
  4358. {
  4359. Fail("Initialization blocks cannot contain 'return' statements", returnStmt);
  4360. }
  4361. checkScope = checkScope->mPrevScope;
  4362. }
  4363. auto checkLocalAssignData = mCurMethodState->mDeferredLocalAssignData;
  4364. while (checkLocalAssignData != NULL)
  4365. {
  4366. if (checkLocalAssignData->mScopeData != NULL)
  4367. checkLocalAssignData->mLeftBlock = true;
  4368. checkLocalAssignData = checkLocalAssignData->mChainedAssignData;
  4369. }
  4370. if ((retType == NULL) && (!inferReturnType))
  4371. {
  4372. if (returnStmt->mExpression != NULL)
  4373. {
  4374. BfExprEvaluator exprEvaluator(this);
  4375. CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, GetPrimitiveType(BfTypeCode_Var), BfEvalExprFlags_None);
  4376. }
  4377. MarkScopeLeft(&mCurMethodState->mHeadScope);
  4378. return;
  4379. }
  4380. if (returnStmt->mExpression == NULL)
  4381. {
  4382. MarkScopeLeft(&mCurMethodState->mHeadScope);
  4383. if ((retType != NULL) && (retType->IsVoid()))
  4384. {
  4385. EmitReturn(BfTypedValue());
  4386. return;
  4387. }
  4388. Fail("Expected return value", returnStmt);
  4389. if (retType != NULL)
  4390. EmitReturn(GetDefaultTypedValue(retType));
  4391. else
  4392. EmitReturn(BfTypedValue());
  4393. return;
  4394. }
  4395. BfType* expectingReturnType = retType;
  4396. BfType* origType;
  4397. BfExprEvaluator exprEvaluator(this);
  4398. bool alreadyWritten = false;
  4399. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  4400. exprEvaluator.mReceivingValue = &mCurMethodState->mRetVal;
  4401. if (mCurMethodInstance->mMethodDef->mIsReadOnly)
  4402. exprEvaluator.mAllowReadOnlyReference = true;
  4403. if (inferReturnType)
  4404. expectingReturnType = NULL;
  4405. auto retValue = CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, expectingReturnType, BfEvalExprFlags_AllowRefExpr, &origType);
  4406. if ((retValue) && (inferReturnType))
  4407. {
  4408. if (mCurMethodState->mClosureState->mReturnType == NULL)
  4409. mCurMethodState->mClosureState->mReturnType = retValue.mType;
  4410. else
  4411. {
  4412. if ((retValue.mType == mCurMethodState->mClosureState->mReturnType) ||
  4413. (CanCast(retValue, mCurMethodState->mClosureState->mReturnType)))
  4414. {
  4415. // Leave as-is
  4416. }
  4417. else if (CanCast(GetFakeTypedValue(mCurMethodState->mClosureState->mReturnType), retValue.mType))
  4418. {
  4419. mCurMethodState->mClosureState->mReturnType = retValue.mType;
  4420. }
  4421. else
  4422. {
  4423. mCurMethodState->mClosureState->mReturnTypeInferState = BfReturnTypeInferState_Fail;
  4424. }
  4425. }
  4426. }
  4427. if ((retType == NULL) && (inferReturnType))
  4428. retType = mCurMethodState->mClosureState->mReturnType;
  4429. if (retType == NULL)
  4430. retType = GetPrimitiveType(BfTypeCode_None);
  4431. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  4432. alreadyWritten = exprEvaluator.mReceivingValue == NULL;
  4433. MarkScopeLeft(&mCurMethodState->mHeadScope);
  4434. if (!retValue)
  4435. {
  4436. AssertErrorState();
  4437. if ((expectingReturnType != NULL) && (!expectingReturnType->IsVoid()))
  4438. {
  4439. retValue = GetDefaultTypedValue(expectingReturnType, true);
  4440. }
  4441. else
  4442. {
  4443. EmitReturn(BfTypedValue());
  4444. return;
  4445. }
  4446. }
  4447. if (retValue.mType->IsVar())
  4448. {
  4449. EmitReturn(BfTypedValue());
  4450. }
  4451. else if (retValue.mType->IsVoid())
  4452. {
  4453. if (retType->IsVoid())
  4454. {
  4455. Warn(0, "Returning void value", returnStmt->mReturnToken);
  4456. EmitReturn(BfTypedValue());
  4457. }
  4458. }
  4459. else
  4460. {
  4461. if (retType->IsVoid())
  4462. {
  4463. expectingReturnType = NULL;
  4464. Fail("Attempting to return value from void method", returnStmt->mExpression);
  4465. EmitReturn(BfTypedValue());
  4466. return;
  4467. }
  4468. if ((origType != NULL) && (origType->IsStructOrStructPtr()) && (retValue.mType->IsObjectOrInterface()))
  4469. {
  4470. Fail(StrFormat("Stack boxing of type '%s' is not allowed on return statements. Use 'new box' to box on the heap.", TypeToString(origType).c_str()), returnStmt->mExpression);
  4471. }
  4472. if (!alreadyWritten)
  4473. EmitReturn(LoadOrAggregateValue(retValue));
  4474. else
  4475. EmitReturn(BfTypedValue());
  4476. }
  4477. }
  4478. void BfModule::Visit(BfYieldStatement* yieldStmt)
  4479. {
  4480. Fail("Yield not supported", yieldStmt);
  4481. }
  4482. void BfModule::Visit(BfBreakStatement* breakStmt)
  4483. {
  4484. bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin());
  4485. UpdateSrcPos(breakStmt);
  4486. mBfIRBuilder->CreateEnsureInstructionAt();
  4487. BfBreakData* breakData = mCurMethodState->mBreakData;
  4488. if (breakStmt->mLabel != NULL)
  4489. {
  4490. breakData = FindBreakData(breakStmt->mLabel);
  4491. }
  4492. else
  4493. {
  4494. while (breakData != NULL)
  4495. {
  4496. if (breakData->mIRBreakBlock)
  4497. break;
  4498. breakData = breakData->mPrevBreakData;
  4499. }
  4500. }
  4501. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  4502. {
  4503. BfScopeData* scope = NULL;
  4504. if (breakData != NULL)
  4505. scope = breakData->mScope;
  4506. if (auto identifer = BfNodeDynCast<BfIdentifierNode>(breakStmt->mLabel))
  4507. mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, breakStmt->mBreakNode, scope);
  4508. }
  4509. if ((breakData == NULL) || (!breakData->mIRBreakBlock))
  4510. {
  4511. if (inMixinDecl)
  4512. {
  4513. // Our mixin may just require that we're injected into a breakable scope
  4514. }
  4515. else
  4516. Fail("'break' not applicable in this block", breakStmt);
  4517. return;
  4518. }
  4519. if (mCurMethodState->mInDeferredBlock)
  4520. {
  4521. auto checkScope = mCurMethodState->mCurScope;
  4522. while (checkScope != NULL)
  4523. {
  4524. if (checkScope == breakData->mScope)
  4525. break;
  4526. if (checkScope->mIsDeferredBlock)
  4527. {
  4528. Fail("The break target crosses a deferred block boundary", breakStmt);
  4529. return;
  4530. }
  4531. checkScope = checkScope->mPrevScope;
  4532. }
  4533. }
  4534. auto checkLocalAssignData = mCurMethodState->mDeferredLocalAssignData;
  4535. while (checkLocalAssignData != NULL)
  4536. {
  4537. if ((checkLocalAssignData->mScopeData != NULL) && (checkLocalAssignData->mScopeData->mScopeDepth >= breakData->mScope->mScopeDepth))
  4538. {
  4539. checkLocalAssignData->mLeftBlock = true;
  4540. checkLocalAssignData->mHadBreak = true;
  4541. }
  4542. checkLocalAssignData = checkLocalAssignData->mChainedAssignData;
  4543. }
  4544. if (HasDeferredScopeCalls(breakData->mScope))
  4545. {
  4546. EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRBreakBlock);
  4547. }
  4548. else
  4549. {
  4550. mBfIRBuilder->CreateBr(breakData->mIRBreakBlock);
  4551. }
  4552. mCurMethodState->mLeftBlockUncond = true;
  4553. BfIRValue earliestValueScopeStart;
  4554. auto checkScope = mCurMethodState->mCurScope;
  4555. while (checkScope != NULL)
  4556. {
  4557. if (checkScope->mValueScopeStart)
  4558. earliestValueScopeStart = checkScope->mValueScopeStart;
  4559. if (checkScope == breakData->mScope)
  4560. break;
  4561. checkScope = checkScope->mPrevScope;
  4562. }
  4563. MarkScopeLeft(breakData->mScope);
  4564. ValueScopeEnd(earliestValueScopeStart);
  4565. auto checkBreakData = mCurMethodState->mBreakData;
  4566. while (true)
  4567. {
  4568. checkBreakData->mHadBreak = true;
  4569. if (checkBreakData == breakData)
  4570. break;
  4571. checkBreakData = checkBreakData->mPrevBreakData;
  4572. }
  4573. }
  4574. void BfModule::Visit(BfContinueStatement* continueStmt)
  4575. {
  4576. bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin());
  4577. UpdateSrcPos(continueStmt);
  4578. mBfIRBuilder->CreateEnsureInstructionAt();
  4579. // If we're in a switch, 'break' is valid but we need to continue looking outward for a 'continue' target
  4580. BfBreakData* breakData = mCurMethodState->mBreakData;
  4581. if (continueStmt->mLabel != NULL)
  4582. {
  4583. breakData = FindBreakData(continueStmt->mLabel);
  4584. if ((breakData != NULL) && (!breakData->mIRContinueBlock))
  4585. {
  4586. Fail(StrFormat("'continue' not applicable in '%s", continueStmt->mLabel->ToString().c_str()), continueStmt);
  4587. return;
  4588. }
  4589. }
  4590. else
  4591. {
  4592. while (breakData != NULL)
  4593. {
  4594. if (breakData->mIRContinueBlock)
  4595. break;
  4596. breakData = breakData->mPrevBreakData;
  4597. }
  4598. }
  4599. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  4600. {
  4601. BfScopeData* scope = NULL;
  4602. if (breakData != NULL)
  4603. scope = breakData->mScope;
  4604. if (auto identifer = BfNodeDynCast<BfIdentifierNode>(continueStmt->mLabel))
  4605. mCompiler->mResolvePassData->mAutoComplete->CheckLabel(identifer, continueStmt->mContinueNode, scope);
  4606. }
  4607. if ((breakData == NULL) || (!breakData->mIRContinueBlock))
  4608. {
  4609. if (inMixinDecl)
  4610. {
  4611. // Our mixin may just require that we're injected into a breakable scope
  4612. }
  4613. else
  4614. Fail("'Continue' not applicable in this block", continueStmt);
  4615. return;
  4616. }
  4617. BfIRValue earliestValueScopeStart;
  4618. // We don't want to close out our own scope, we want to close out any scopes that were opened after us
  4619. auto nextScope = mCurMethodState->mCurScope;
  4620. while (nextScope != NULL)
  4621. {
  4622. if (nextScope->mValueScopeStart)
  4623. earliestValueScopeStart = nextScope->mValueScopeStart;
  4624. if (nextScope->mPrevScope == breakData->mScope)
  4625. break;
  4626. nextScope = nextScope->mPrevScope;
  4627. }
  4628. if (breakData->mInnerValueScopeStart)
  4629. earliestValueScopeStart = breakData->mInnerValueScopeStart;
  4630. if (mCurMethodState->mInDeferredBlock)
  4631. {
  4632. auto checkScope = mCurMethodState->mCurScope;
  4633. while (checkScope != NULL)
  4634. {
  4635. if (checkScope == breakData->mScope)
  4636. break;
  4637. if (checkScope->mIsDeferredBlock)
  4638. {
  4639. Fail("The continue target crosses a deferred block boundary", continueStmt);
  4640. return;
  4641. }
  4642. checkScope = checkScope->mPrevScope;
  4643. }
  4644. }
  4645. if ((nextScope != NULL) && (HasDeferredScopeCalls(nextScope)))
  4646. {
  4647. EmitDeferredScopeCalls(true, nextScope, breakData->mIRContinueBlock);
  4648. }
  4649. else
  4650. {
  4651. mBfIRBuilder->CreateBr(breakData->mIRContinueBlock);
  4652. }
  4653. MarkScopeLeft(breakData->mScope);
  4654. ValueScopeEnd(earliestValueScopeStart);
  4655. mCurMethodState->mLeftBlockUncond = true;
  4656. if (!mCurMethodState->mInPostReturn)
  4657. mCurMethodState->mHadContinue = true;
  4658. }
  4659. void BfModule::Visit(BfFallthroughStatement* fallthroughStmt)
  4660. {
  4661. UpdateSrcPos(fallthroughStmt);
  4662. if ((mCurMethodState->mBreakData == NULL) || (!mCurMethodState->mBreakData->mIRFallthroughBlock))
  4663. {
  4664. Fail("'Fallthrough' not applicable in this block", fallthroughStmt);
  4665. return;
  4666. }
  4667. EmitDeferredScopeCalls(true, mCurMethodState->mBreakData->mScope, mCurMethodState->mBreakData->mIRFallthroughBlock);
  4668. mCurMethodState->mLeftBlockUncond = true; // Not really a return, but handled the same way
  4669. if (mCurMethodState->mDeferredLocalAssignData != NULL)
  4670. mCurMethodState->mDeferredLocalAssignData->mHadFallthrough = true;
  4671. }
  4672. void BfModule::Visit(BfUsingStatement* usingStmt)
  4673. {
  4674. UpdateSrcPos(usingStmt);
  4675. mCurMethodState->mInHeadScope = false;
  4676. BfScopeData newScope;
  4677. mCurMethodState->AddScope(&newScope);
  4678. NewScopeState();
  4679. if (usingStmt->mVariableDeclaration != NULL)
  4680. UpdateSrcPos(usingStmt->mVariableDeclaration);
  4681. BfTypedValue embeddedValue;
  4682. SizedArray<BfIRValue, 1> llvmArgs;
  4683. BfModuleMethodInstance moduleMethodInstance;
  4684. BfFunctionBindResult functionBindResult;
  4685. BfExprEvaluator exprEvaluator(this);
  4686. bool failed = false;
  4687. if (usingStmt->mVariableDeclaration == NULL)
  4688. {
  4689. AssertErrorState();
  4690. failed = true;
  4691. }
  4692. else if (usingStmt->mVariableDeclaration->mNameNode != NULL)
  4693. {
  4694. BfLocalVariable* localVar = HandleVariableDeclaration(usingStmt->mVariableDeclaration);
  4695. if (localVar == NULL)
  4696. {
  4697. AssertErrorState();
  4698. failed = true;
  4699. }
  4700. else
  4701. {
  4702. embeddedValue = exprEvaluator.LoadLocal(localVar);
  4703. }
  4704. //exprEvaluator.CheckModifyResult(embeddedValue, usingStmt->mVariableDeclaration->mNameNode,);
  4705. }
  4706. else
  4707. {
  4708. embeddedValue = CreateValueFromExpression(usingStmt->mVariableDeclaration->mInitializer);
  4709. if (!embeddedValue)
  4710. failed = true;
  4711. }
  4712. if (!failed)
  4713. {
  4714. auto iDisposableType = ResolveTypeDef(mCompiler->mIDisposableTypeDef)->ToTypeInstance();
  4715. auto dispMethod = GetMethodByName(iDisposableType, "Dispose");
  4716. if ((!dispMethod) || (!CanCast(embeddedValue, iDisposableType)))
  4717. {
  4718. Fail(StrFormat("Type '%s' must be implicitly convertible to 'System.IDisposable' for use in 'using' statement", TypeToString(embeddedValue.mType).c_str()), usingStmt->mVariableDeclaration);
  4719. failed = true;
  4720. }
  4721. else
  4722. {
  4723. bool mayBeNull = true;
  4724. if (embeddedValue.mType->IsStruct())
  4725. {
  4726. // It's possible that a struct can convert to an IDisposable through a conversion operator that CAN
  4727. // return null, so the only way we can know we are not null is if we are a struct that directly
  4728. // implements the interface
  4729. if (TypeIsSubTypeOf(embeddedValue.mType->ToTypeInstance(), iDisposableType))
  4730. mayBeNull = false;
  4731. }
  4732. exprEvaluator.mFunctionBindResult = &functionBindResult;
  4733. SizedArray<BfResolvedArg, 0> resolvedArgs;
  4734. BfMethodMatcher methodMatcher(usingStmt->mVariableDeclaration, this, dispMethod.mMethodInstance, resolvedArgs, BfMethodGenericArguments());
  4735. methodMatcher.CheckType(iDisposableType, embeddedValue, false);
  4736. methodMatcher.TryDevirtualizeCall(embeddedValue);
  4737. auto retVal = exprEvaluator.CreateCall(&methodMatcher, embeddedValue);
  4738. if (functionBindResult.mMethodInstance != NULL)
  4739. {
  4740. moduleMethodInstance = BfModuleMethodInstance(functionBindResult.mMethodInstance, functionBindResult.mFunc);
  4741. AddDeferredCall(moduleMethodInstance, functionBindResult.mIRArgs, mCurMethodState->mCurScope, NULL, false, mayBeNull);
  4742. }
  4743. }
  4744. }
  4745. if (usingStmt->mEmbeddedStatement == NULL)
  4746. {
  4747. AssertErrorState();
  4748. }
  4749. else
  4750. {
  4751. VisitEmbeddedStatement(usingStmt->mEmbeddedStatement);
  4752. }
  4753. RestoreScopeState();
  4754. }
  4755. void BfModule::Visit(BfDoStatement* doStmt)
  4756. {
  4757. UpdateSrcPos(doStmt);
  4758. auto bodyBB = mBfIRBuilder->CreateBlock("do.body", true);
  4759. auto endBB = mBfIRBuilder->CreateBlock("do.end");
  4760. BfScopeData scopeData;
  4761. if (doStmt->mLabelNode != NULL)
  4762. scopeData.mLabelNode = doStmt->mLabelNode->mLabel;
  4763. mCurMethodState->AddScope(&scopeData);
  4764. NewScopeState();
  4765. BfBreakData breakData;
  4766. breakData.mIRBreakBlock = endBB;
  4767. breakData.mScope = &scopeData;
  4768. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  4769. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  4770. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  4771. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
  4772. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  4773. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  4774. // We may have a call in the loop body
  4775. mCurMethodState->mMayNeedThisAccessCheck = true;
  4776. mBfIRBuilder->CreateBr(bodyBB);
  4777. mBfIRBuilder->SetInsertPoint(bodyBB);
  4778. VisitEmbeddedStatement(doStmt->mEmbeddedStatement);
  4779. prevDLA.Restore();
  4780. mCurMethodState->ApplyDeferredLocalAssignData(deferredLocalAssignData);
  4781. RestoreScopeState();
  4782. if (!mCurMethodState->mLeftBlockUncond)
  4783. mBfIRBuilder->CreateBr(endBB);
  4784. mCurMethodState->SetHadReturn(false);
  4785. mCurMethodState->mLeftBlockUncond = false;
  4786. mBfIRBuilder->AddBlock(endBB);
  4787. mBfIRBuilder->SetInsertPoint(endBB);
  4788. }
  4789. void BfModule::Visit(BfRepeatStatement* repeatStmt)
  4790. {
  4791. // if (repeatStmt->mCondition != NULL)
  4792. // UpdateSrcPos(repeatStmt->mCondition);
  4793. // else
  4794. UpdateSrcPos(repeatStmt);
  4795. if (repeatStmt->mRepeatToken->mToken == BfToken_Do)
  4796. {
  4797. Fail("Repeat block requires 'repeat' token", repeatStmt->mRepeatToken);
  4798. }
  4799. auto bodyBB = mBfIRBuilder->CreateBlock("repeat.body", true);
  4800. auto condBB = mBfIRBuilder->CreateBlock("repeat.cond");
  4801. auto endBB = mBfIRBuilder->CreateBlock("repeat.end");
  4802. BfScopeData scopeData;
  4803. // We set mIsLoop later
  4804. if (repeatStmt->mLabelNode != NULL)
  4805. scopeData.mLabelNode = repeatStmt->mLabelNode->mLabel;
  4806. mCurMethodState->AddScope(&scopeData);
  4807. NewScopeState();
  4808. BfBreakData breakData;
  4809. breakData.mIRContinueBlock = condBB;
  4810. breakData.mIRBreakBlock = endBB;
  4811. breakData.mScope = &scopeData;
  4812. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  4813. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  4814. // We may have a call in the loop body
  4815. mCurMethodState->mMayNeedThisAccessCheck = true;
  4816. mBfIRBuilder->CreateBr(bodyBB);
  4817. mBfIRBuilder->SetInsertPoint(bodyBB);
  4818. scopeData.mIsLoop = true;
  4819. VisitEmbeddedStatement(repeatStmt->mEmbeddedStatement);
  4820. if (!mCurMethodState->mLeftBlockUncond)
  4821. mBfIRBuilder->CreateBr(condBB);
  4822. mCurMethodState->SetHadReturn(false);
  4823. mCurMethodState->mLeftBlockUncond = false;
  4824. mCurMethodState->mLeftBlockCond = false;
  4825. mBfIRBuilder->AddBlock(condBB);
  4826. mBfIRBuilder->SetInsertPoint(condBB);
  4827. bool isInfiniteLoop = false;
  4828. if (repeatStmt->mCondition != NULL)
  4829. {
  4830. UpdateSrcPos(repeatStmt->mCondition);
  4831. auto checkVal = CreateValueFromExpression(repeatStmt->mCondition, GetPrimitiveType(BfTypeCode_Boolean));
  4832. if (checkVal)
  4833. {
  4834. if ((!breakData.mHadBreak) && (checkVal.mValue.IsConst()))
  4835. {
  4836. auto constVal = mBfIRBuilder->GetConstantById(checkVal.mValue.mId);
  4837. if (constVal->mTypeCode == BfTypeCode_Boolean)
  4838. isInfiniteLoop = constVal->mBool;
  4839. }
  4840. mBfIRBuilder->CreateCondBr(checkVal.mValue, bodyBB, endBB);
  4841. mBfIRBuilder->AddBlock(endBB);
  4842. mBfIRBuilder->SetInsertPoint(endBB);
  4843. }
  4844. }
  4845. RestoreScopeState();
  4846. if (isInfiniteLoop)
  4847. EmitDefaultReturn();
  4848. }
  4849. void BfModule::Visit(BfWhileStatement* whileStmt)
  4850. {
  4851. UpdateSrcPos(whileStmt);
  4852. bool prevHadReturn = mCurMethodState->mHadReturn;
  4853. auto condBB = mBfIRBuilder->CreateBlock("while.cond");
  4854. auto bodyBB = mBfIRBuilder->CreateBlock("while.body");
  4855. auto endBB = mBfIRBuilder->CreateBlock("while.end");
  4856. mCurMethodState->mInHeadScope = false;
  4857. BfScopeData scopeData;
  4858. scopeData.mScopeKind = BfScopeKind_StatementTarget_Conditional;
  4859. scopeData.mIsLoop = true;
  4860. if (whileStmt->mLabelNode != NULL)
  4861. scopeData.mLabelNode = whileStmt->mLabelNode->mLabel;
  4862. scopeData.mValueScopeStart = ValueScopeStart();
  4863. mCurMethodState->AddScope(&scopeData);
  4864. NewScopeState();
  4865. BfBreakData breakData;
  4866. breakData.mIRContinueBlock = condBB;
  4867. breakData.mIRBreakBlock = endBB;
  4868. breakData.mScope = &scopeData;
  4869. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  4870. breakData.mInnerValueScopeStart = scopeData.mValueScopeStart;
  4871. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  4872. mBfIRBuilder->AddBlock(condBB);
  4873. mBfIRBuilder->CreateBr(condBB);
  4874. mBfIRBuilder->SetInsertPoint(condBB);
  4875. BfTypedValue checkVal;
  4876. if (whileStmt->mCondition != NULL)
  4877. {
  4878. UpdateSrcPos(whileStmt->mCondition);
  4879. checkVal = CreateValueFromExpression(whileStmt->mCondition, GetPrimitiveType(BfTypeCode_Boolean));
  4880. }
  4881. if (!checkVal)
  4882. {
  4883. AssertErrorState();
  4884. checkVal = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_Boolean));
  4885. }
  4886. bool isInfiniteLoop = false;
  4887. bool isFalseLoop = false;
  4888. if (checkVal.mValue.IsConst())
  4889. {
  4890. mBfIRBuilder->CreateEnsureInstructionAt();
  4891. auto constVal = mBfIRBuilder->GetConstantById(checkVal.mValue.mId);
  4892. if (constVal->mTypeCode == BfTypeCode_Boolean)
  4893. {
  4894. isInfiniteLoop = constVal->mBool;
  4895. isFalseLoop = !isInfiniteLoop;
  4896. }
  4897. }
  4898. // We may have a call in the loop body
  4899. mCurMethodState->mMayNeedThisAccessCheck = true;
  4900. // For BeefBackend we continue to do CondBr because it helps our flow analysis and we optimize it anyway
  4901. if ((isInfiniteLoop) && (!IsTargetingBeefBackend()))
  4902. mBfIRBuilder->CreateBr(bodyBB);
  4903. else if (isFalseLoop)
  4904. mBfIRBuilder->CreateBr(endBB);
  4905. else
  4906. mBfIRBuilder->CreateCondBr(checkVal.mValue, bodyBB, endBB);
  4907. // Apply deferred local assign to mEmbeddedStatement and itrStmt
  4908. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  4909. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
  4910. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  4911. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  4912. deferredLocalAssignData.mIsUnconditional = isInfiniteLoop;
  4913. mBfIRBuilder->AddBlock(bodyBB);
  4914. mBfIRBuilder->SetInsertPoint(bodyBB);
  4915. if (whileStmt->mEmbeddedStatement != NULL)
  4916. {
  4917. if (isFalseLoop)
  4918. {
  4919. SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  4920. VisitEmbeddedStatement(whileStmt->mEmbeddedStatement);
  4921. }
  4922. else
  4923. VisitEmbeddedStatement(whileStmt->mEmbeddedStatement);
  4924. }
  4925. else
  4926. {
  4927. AssertErrorState();
  4928. }
  4929. if (breakData.mHadBreak)
  4930. {
  4931. isInfiniteLoop = false;
  4932. }
  4933. if ((!mCurMethodState->mLeftBlockUncond) && (!isFalseLoop))
  4934. {
  4935. mBfIRBuilder->CreateBr(condBB);
  4936. }
  4937. if (!isInfiniteLoop)
  4938. mCurMethodState->mHadReturn = prevHadReturn;
  4939. mCurMethodState->mLeftBlockUncond = false;
  4940. mCurMethodState->mLeftBlockCond = false;
  4941. mBfIRBuilder->AddBlock(endBB);
  4942. mBfIRBuilder->SetInsertPoint(endBB);
  4943. if (isFalseLoop)
  4944. {
  4945. mBfIRBuilder->EraseFromParent(bodyBB);
  4946. }
  4947. RestoreScopeState();
  4948. if ((isInfiniteLoop) && (mCurMethodInstance != NULL))
  4949. EmitDefaultReturn();
  4950. }
  4951. void BfModule::Visit(BfForStatement* forStmt)
  4952. {
  4953. auto autoComplete = mCompiler->GetAutoComplete();
  4954. if (autoComplete != NULL)
  4955. autoComplete->CheckIdentifier(forStmt->mForToken, true);
  4956. UpdateSrcPos(forStmt);
  4957. auto startBB = mBfIRBuilder->CreateBlock("for.start", true);
  4958. mBfIRBuilder->CreateBr(startBB);
  4959. mBfIRBuilder->SetInsertPoint(startBB);
  4960. BfScopeData scopeData;
  4961. scopeData.mIsLoop = true;
  4962. if (forStmt->mLabelNode != NULL)
  4963. scopeData.mLabelNode = forStmt->mLabelNode->mLabel;
  4964. scopeData.mCloseNode = forStmt;
  4965. scopeData.mValueScopeStart = ValueScopeStart();
  4966. mCurMethodState->AddScope(&scopeData);
  4967. NewScopeState();
  4968. for (auto initializer : forStmt->mInitializers)
  4969. {
  4970. VisitChild(initializer);
  4971. }
  4972. // We may have a call in the loop body
  4973. mCurMethodState->mMayNeedThisAccessCheck = true;
  4974. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  4975. auto condBB = mBfIRBuilder->CreateBlock("for.cond", true);
  4976. auto bodyBB = mBfIRBuilder->CreateBlock("for.body");
  4977. auto incBB = mBfIRBuilder->CreateBlock("for.inc");
  4978. auto endBB = mBfIRBuilder->CreateBlock("for.end");
  4979. BfBreakData breakData;
  4980. breakData.mIRContinueBlock = incBB;
  4981. breakData.mIRBreakBlock = endBB;
  4982. breakData.mScope = &scopeData;
  4983. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  4984. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  4985. mBfIRBuilder->CreateBr(condBB);
  4986. bool isInfiniteLoop = false;
  4987. mBfIRBuilder->SetInsertPoint(condBB);
  4988. if (forStmt->mCondition != NULL)
  4989. {
  4990. auto conditionValue = CreateValueFromExpression(forStmt->mCondition, boolType);
  4991. if (!conditionValue)
  4992. conditionValue = GetDefaultTypedValue(boolType);
  4993. auto constant = mBfIRBuilder->GetConstant(conditionValue.mValue);
  4994. if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean))
  4995. isInfiniteLoop = constant->mBool;
  4996. ValueScopeEnd(scopeData.mValueScopeStart);
  4997. mBfIRBuilder->CreateCondBr(conditionValue.mValue, bodyBB, endBB);
  4998. }
  4999. else
  5000. {
  5001. isInfiniteLoop = true;
  5002. mBfIRBuilder->CreateBr(bodyBB);
  5003. }
  5004. // Apply deferred local assign to mEmbeddedStatement and itrStmt
  5005. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  5006. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
  5007. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  5008. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  5009. mBfIRBuilder->AddBlock(bodyBB);
  5010. mBfIRBuilder->SetInsertPoint(bodyBB);
  5011. if (forStmt->mEmbeddedStatement != NULL)
  5012. {
  5013. VisitEmbeddedStatement(forStmt->mEmbeddedStatement);
  5014. }
  5015. if (!mCurMethodState->mLeftBlockUncond)
  5016. mBfIRBuilder->CreateBr(incBB);
  5017. mBfIRBuilder->AddBlock(incBB);
  5018. mBfIRBuilder->SetInsertPoint(incBB);
  5019. for (auto itrStmt : forStmt->mIterators)
  5020. {
  5021. VisitChild(itrStmt);
  5022. if ((mCurMethodState->mLeftBlockUncond) && (!mCurMethodState->mHadContinue) && (!mCurMethodState->mInPostReturn))
  5023. Warn(BfWarning_CS0162_UnreachableCode, "Unreachable code", itrStmt);
  5024. }
  5025. ValueScopeEnd(scopeData.mValueScopeStart);
  5026. mBfIRBuilder->CreateBr(condBB);
  5027. mBfIRBuilder->AddBlock(endBB);
  5028. mBfIRBuilder->SetInsertPoint(endBB);
  5029. // The 'return' may have been inside the block, which may not have been entered if preconditions were not met
  5030. mCurMethodState->SetHadReturn(false);
  5031. mCurMethodState->mLeftBlockUncond = false;
  5032. mCurMethodState->mLeftBlockCond = false;
  5033. if (breakData.mHadBreak)
  5034. isInfiniteLoop = false;
  5035. RestoreScopeState();
  5036. if (isInfiniteLoop)
  5037. EmitDefaultReturn();
  5038. }
  5039. void BfModule::DoForLess(BfForEachStatement* forEachStmt)
  5040. {
  5041. UpdateSrcPos(forEachStmt);
  5042. auto startBB = mBfIRBuilder->GetInsertBlock();
  5043. auto condBB = mBfIRBuilder->CreateBlock("forless.cond", true);
  5044. mBfIRBuilder->SetInsertPoint(condBB);
  5045. BfScopeData scopeData;
  5046. // We set mIsLoop later
  5047. if (forEachStmt->mLabelNode != NULL)
  5048. scopeData.mLabelNode = forEachStmt->mLabelNode->mLabel;
  5049. mCurMethodState->AddScope(&scopeData);
  5050. NewScopeState();
  5051. auto autoComplete = mCompiler->GetAutoComplete();
  5052. auto isLet = BfNodeDynCast<BfLetTypeReference>(forEachStmt->mVariableTypeRef) != 0;
  5053. auto isVar = BfNodeDynCast<BfVarTypeReference>(forEachStmt->mVariableTypeRef) != 0;
  5054. BfTypedValue target;
  5055. BfType* varType = NULL;
  5056. bool didInference = false;
  5057. if (isLet || isVar)
  5058. {
  5059. if (forEachStmt->mCollectionExpression != NULL)
  5060. target = CreateValueFromExpression(forEachStmt->mCollectionExpression);
  5061. if (target)
  5062. {
  5063. FixIntUnknown(target);
  5064. varType = target.mType;
  5065. }
  5066. if (autoComplete != NULL)
  5067. autoComplete->CheckVarResolution(forEachStmt->mVariableTypeRef, varType);
  5068. didInference = true;
  5069. }
  5070. else
  5071. {
  5072. varType = ResolveTypeRef(forEachStmt->mVariableTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
  5073. if (forEachStmt->mCollectionExpression != NULL)
  5074. target = CreateValueFromExpression(forEachStmt->mCollectionExpression, varType);
  5075. }
  5076. if (varType == NULL)
  5077. varType = GetPrimitiveType(BfTypeCode_IntPtr);
  5078. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  5079. deferredLocalAssignData.mIsIfCondition = true;
  5080. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, true);
  5081. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  5082. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  5083. deferredLocalAssignData.mIsIfCondition = false;
  5084. // The "extend chain" is only valid for the conditional -- since that expression may contain unconditionally executed and
  5085. // conditionally executed code (in the case of "(GetVal(out a) && GetVal(out b))" for example
  5086. mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
  5087. BfType* checkType = varType;
  5088. if (checkType->IsTypedPrimitive())
  5089. checkType = checkType->GetUnderlyingType();
  5090. if (!checkType->IsIntegral())
  5091. {
  5092. Fail(StrFormat("Cannot iterate over '%s' in for-less statements, only integer types are allowed", TypeToString(varType).c_str()), forEachStmt->mVariableTypeRef);
  5093. varType = GetPrimitiveType(BfTypeCode_IntPtr);
  5094. if (didInference)
  5095. target = GetDefaultTypedValue(varType);
  5096. }
  5097. PopulateType(varType, BfPopulateType_Data);
  5098. auto condEndBB = mBfIRBuilder->GetInsertBlock();
  5099. mBfIRBuilder->SetInsertPoint(startBB);
  5100. BfLocalVariable* localDef = new BfLocalVariable();
  5101. localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(forEachStmt->mVariableName);
  5102. localDef->mName = localDef->mNameNode->ToString();
  5103. localDef->mResolvedType = varType;
  5104. BfIRValue varInst;
  5105. if (!varType->IsValuelessType())
  5106. {
  5107. varInst = CreateAlloca(varType);
  5108. }
  5109. localDef->mAddr = varInst;
  5110. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  5111. localDef->mReadFromId = 0;
  5112. localDef->mIsReadOnly = isLet || (forEachStmt->mReadOnlyToken != NULL);
  5113. CheckVariableDef(localDef);
  5114. mBfIRBuilder->CreateStore(GetDefaultValue(varType), localDef->mAddr);
  5115. localDef->Init();
  5116. UpdateExprSrcPos(forEachStmt->mVariableName);
  5117. AddLocalVariableDef(localDef, true);
  5118. auto bodyBB = mBfIRBuilder->CreateBlock("forless.body");
  5119. auto incBB = mBfIRBuilder->CreateBlock("forless.inc");
  5120. auto endBB = mBfIRBuilder->CreateBlock("forless.end");
  5121. BfBreakData breakData;
  5122. breakData.mIRContinueBlock = incBB;
  5123. breakData.mIRBreakBlock = endBB;
  5124. breakData.mScope = &scopeData;
  5125. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  5126. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  5127. mBfIRBuilder->CreateBr(condBB);
  5128. mBfIRBuilder->SetInsertPoint(condEndBB);
  5129. if (forEachStmt->mCollectionExpression != NULL)
  5130. UpdateExprSrcPos(forEachStmt->mCollectionExpression);
  5131. BfIRValue conditionValue;
  5132. // We may have a call in the loop body
  5133. mCurMethodState->mMayNeedThisAccessCheck = true;
  5134. // Cond
  5135. auto valueScopeStart = ValueScopeStart();
  5136. auto localVal = mBfIRBuilder->CreateLoad(localDef->mAddr);
  5137. if (!target)
  5138. {
  5139. // Soldier on
  5140. target = GetDefaultTypedValue(varType);
  5141. }
  5142. if (forEachStmt->mInToken->mToken == BfToken_LessEquals)
  5143. conditionValue = mBfIRBuilder->CreateCmpLTE(localVal, target.mValue, varType->IsSigned());
  5144. else
  5145. conditionValue = mBfIRBuilder->CreateCmpLT(localVal, target.mValue, varType->IsSigned());
  5146. mBfIRBuilder->CreateCondBr(conditionValue, bodyBB, endBB);
  5147. ValueScopeEnd(valueScopeStart);
  5148. mBfIRBuilder->AddBlock(bodyBB);
  5149. mBfIRBuilder->SetInsertPoint(bodyBB);
  5150. // Body
  5151. scopeData.mIsLoop = true;
  5152. if (forEachStmt->mEmbeddedStatement != NULL)
  5153. {
  5154. VisitEmbeddedStatement(forEachStmt->mEmbeddedStatement);
  5155. }
  5156. // Inc
  5157. if (!mCurMethodState->mLeftBlockUncond)
  5158. {
  5159. mBfIRBuilder->CreateBr(incBB);
  5160. }
  5161. mBfIRBuilder->AddBlock(incBB);
  5162. mBfIRBuilder->SetInsertPoint(incBB);
  5163. if (forEachStmt->mCollectionExpression != NULL)
  5164. UpdateExprSrcPos(forEachStmt->mCollectionExpression);
  5165. auto one = GetConstValue(1, localDef->mResolvedType);
  5166. // We have to reload localVal before the inc, user logic could have changed it
  5167. localVal = mBfIRBuilder->CreateLoad(localDef->mAddr);
  5168. auto result = mBfIRBuilder->CreateAdd(localVal, one);
  5169. mBfIRBuilder->CreateStore(result, localDef->mAddr);
  5170. ValueScopeEnd(valueScopeStart);
  5171. mBfIRBuilder->CreateBr(condBB);
  5172. mBfIRBuilder->AddBlock(endBB);
  5173. mBfIRBuilder->SetInsertPoint(endBB);
  5174. // The 'return' may have been inside the block, which may not have been entered if preconditions were not met
  5175. mCurMethodState->SetHadReturn(false);
  5176. mCurMethodState->mLeftBlockUncond = false;
  5177. mCurMethodState->mLeftBlockCond = false;
  5178. bool definitelyExecuted = false;
  5179. if (target.mValue.IsConst())
  5180. {
  5181. auto constant = mBfIRBuilder->GetConstant(target.mValue);
  5182. if (constant->mInt32 > 0)
  5183. definitelyExecuted = true;
  5184. }
  5185. prevDLA.Restore();
  5186. if (definitelyExecuted)
  5187. mCurMethodState->ApplyDeferredLocalAssignData(deferredLocalAssignData);
  5188. RestoreScopeState();
  5189. }
  5190. void BfModule::Visit(BfForEachStatement* forEachStmt)
  5191. {
  5192. if ((forEachStmt->mInToken != NULL) &&
  5193. ((forEachStmt->mInToken->GetToken() == BfToken_LChevron) || (forEachStmt->mInToken->GetToken() == BfToken_LessEquals)))
  5194. {
  5195. DoForLess(forEachStmt);
  5196. return;
  5197. }
  5198. auto autoComplete = mCompiler->GetAutoComplete();
  5199. UpdateSrcPos(forEachStmt);
  5200. BfScopeData scopeData;
  5201. // We set mIsLoop after the non-looped initializations
  5202. scopeData.mValueScopeStart = ValueScopeStart();
  5203. mCurMethodState->AddScope(&scopeData);
  5204. NewScopeState();
  5205. bool isRefExpression = false;
  5206. BfExpression* collectionExpr = forEachStmt->mCollectionExpression;
  5207. if (auto unaryOpExpr = BfNodeDynCast<BfUnaryOperatorExpression>(collectionExpr))
  5208. {
  5209. if ((unaryOpExpr->mOp == BfUnaryOp_Ref) || (unaryOpExpr->mOp == BfUnaryOp_Mut))
  5210. {
  5211. isRefExpression = true;
  5212. collectionExpr = unaryOpExpr->mExpression;
  5213. }
  5214. }
  5215. BfTypedValue target;
  5216. if (collectionExpr != NULL)
  5217. target = CreateValueFromExpression(collectionExpr);
  5218. if (!target)
  5219. {
  5220. // Soldier on
  5221. target = BfTypedValue(GetDefaultValue(mContext->mBfObjectType), mContext->mBfObjectType);
  5222. }
  5223. bool isLet = (forEachStmt->mVariableTypeRef != NULL) && (forEachStmt->mVariableTypeRef->IsA<BfLetTypeReference>());
  5224. BfType* varType = NULL;
  5225. bool inferVarType = false;
  5226. if ((forEachStmt->mVariableTypeRef == NULL) || (forEachStmt->mVariableTypeRef->IsA<BfVarTypeReference>()) || (isLet))
  5227. {
  5228. if (target.mType->IsSizedArray())
  5229. {
  5230. varType = target.mType->GetUnderlyingType();
  5231. if (isRefExpression)
  5232. varType = CreateRefType(varType);
  5233. }
  5234. else if (target.mType->IsArray())
  5235. {
  5236. varType = target.mType->GetUnderlyingType();
  5237. if (isRefExpression)
  5238. varType = CreateRefType(varType);
  5239. }
  5240. else
  5241. inferVarType = true;
  5242. }
  5243. else
  5244. {
  5245. if (autoComplete != NULL)
  5246. autoComplete->CheckTypeRef(forEachStmt->mVariableTypeRef, false);
  5247. varType = ResolveTypeRef(forEachStmt->mVariableTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
  5248. }
  5249. if (varType == NULL)
  5250. varType = GetPrimitiveType(BfTypeCode_Var);
  5251. bool isArray = target.mType->IsArray();
  5252. bool isSizedArray = target.mType->IsSizedArray();
  5253. bool isVarEnumerator = target.mType->IsVar();
  5254. // Array
  5255. BfType* itrType;
  5256. BfTypedValue itr;
  5257. BfTypeInstance* itrInterface = NULL;
  5258. BfTypeInstance* refItrInterface = NULL;
  5259. if (isVarEnumerator)
  5260. varType = GetPrimitiveType(BfTypeCode_Var);
  5261. BfGenericParamInstance* genericParamInst = NULL;
  5262. if (target.mType->IsGenericParam())
  5263. {
  5264. genericParamInst = GetGenericParamInstance((BfGenericParamType*)target.mType);
  5265. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
  5266. {
  5267. varType = GetPrimitiveType(BfTypeCode_Var);
  5268. isVarEnumerator = true;
  5269. }
  5270. if (genericParamInst->mTypeConstraint != NULL)
  5271. {
  5272. if (genericParamInst->mTypeConstraint->IsVar())
  5273. {
  5274. varType = GetPrimitiveType(BfTypeCode_Var);
  5275. isVarEnumerator = true;
  5276. }
  5277. if (genericParamInst->mTypeConstraint->IsGenericTypeInstance())
  5278. {
  5279. auto genericConstraintType = (BfTypeInstance*)genericParamInst->mTypeConstraint;
  5280. if (genericConstraintType->IsInstanceOf(mCompiler->mSizedArrayTypeDef))
  5281. {
  5282. varType = genericConstraintType->mGenericTypeInfo->mTypeGenericArguments[0];
  5283. isVarEnumerator = true;
  5284. }
  5285. }
  5286. }
  5287. }
  5288. if (target.mType->IsConcreteInterfaceType())
  5289. target.mType = target.mType->GetUnderlyingType();
  5290. if (isArray || isSizedArray)
  5291. {
  5292. itrType = GetPrimitiveType(BfTypeCode_IntPtr);
  5293. BfIRValue itrInst = CreateAlloca(itrType);
  5294. itr = BfTypedValue(itrInst, itrType, true);
  5295. }
  5296. else if (isVarEnumerator)
  5297. {
  5298. // Generic method or mixin decl
  5299. }
  5300. else if ((!target.mType->IsTypeInstance()) && (genericParamInst == NULL))
  5301. {
  5302. Fail(StrFormat("Type '%s' cannot be used in enumeration", TypeToString(target.mType).c_str()), forEachStmt->mCollectionExpression);
  5303. }
  5304. else if (forEachStmt->mCollectionExpression != NULL)
  5305. {
  5306. auto targetTypeInstance = target.mType->ToTypeInstance();
  5307. itr = target;
  5308. bool hadGetEnumeratorType = false;
  5309. if (genericParamInst != NULL)
  5310. {
  5311. for (auto ifaceConstraint : genericParamInst->mInterfaceConstraints)
  5312. {
  5313. if (ifaceConstraint->IsInstanceOf(mCompiler->mGenericIEnumerableTypeDef))
  5314. {
  5315. if (targetTypeInstance != NULL)
  5316. {
  5317. targetTypeInstance = NULL;
  5318. break;
  5319. }
  5320. targetTypeInstance = ifaceConstraint->ToTypeInstance();
  5321. }
  5322. }
  5323. }
  5324. if (targetTypeInstance != NULL)
  5325. {
  5326. PopulateType(targetTypeInstance, BfPopulateType_DataAndMethods);
  5327. auto getEnumeratorMethod = GetMethodByName(targetTypeInstance, "GetEnumerator", 0, true);
  5328. if (!getEnumeratorMethod)
  5329. {
  5330. hadGetEnumeratorType = false;
  5331. }
  5332. else if (getEnumeratorMethod.mMethodInstance->mMethodDef->mIsStatic)
  5333. {
  5334. hadGetEnumeratorType = true;
  5335. Fail(StrFormat("Type '%s' does not contain a non-static 'GetEnumerator' method", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression);
  5336. }
  5337. else
  5338. {
  5339. if (getEnumeratorMethod.mMethodInstance->mMethodDef->mIsConcrete)
  5340. {
  5341. hadGetEnumeratorType = true;
  5342. if (genericParamInst != NULL)
  5343. {
  5344. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Concrete) == 0)
  5345. Fail(StrFormat("Iteration requires a concrete implementation of '%s', consider adding 'concrete' constraint to '%s'", TypeToString(targetTypeInstance).c_str(), genericParamInst->GetName().c_str()), forEachStmt->mCollectionExpression);
  5346. }
  5347. else
  5348. Fail(StrFormat("Iteration requires a concrete implementation of '%s'", TypeToString(targetTypeInstance).c_str()), forEachStmt->mCollectionExpression);
  5349. }
  5350. hadGetEnumeratorType = true;
  5351. BfExprEvaluator exprEvaluator(this);
  5352. SizedArray<BfIRValue, 1> args;
  5353. auto castedTarget = Cast(forEachStmt->mCollectionExpression, target, getEnumeratorMethod.mMethodInstance->GetOwner());
  5354. exprEvaluator.PushThis(forEachStmt->mCollectionExpression, castedTarget, getEnumeratorMethod.mMethodInstance, args);
  5355. itr = exprEvaluator.CreateCall(forEachStmt->mCollectionExpression, getEnumeratorMethod.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : getEnumeratorMethod.mFunc, false, args);
  5356. if (itr.mType->IsConcreteInterfaceType())
  5357. itr.mType = itr.mType->GetUnderlyingType();
  5358. }
  5359. }
  5360. if (itr)
  5361. {
  5362. PopulateType(itr.mType, BfPopulateType_DataAndMethods);
  5363. BfTypeInstance* genericItrInterface = NULL;
  5364. auto _CheckInterface = [&](BfTypeInstance* interface)
  5365. {
  5366. if (interface->IsInstanceOf(isRefExpression ? mCompiler->mGenericIRefEnumeratorTypeDef : mCompiler->mGenericIEnumeratorTypeDef))
  5367. {
  5368. if (genericItrInterface != NULL)
  5369. {
  5370. Fail(StrFormat("Type '%s' implements multiple %s<T> interfaces", TypeToString(itr.mType).c_str(), isRefExpression ? "IRefEnumerator" : "IEnumerator"), forEachStmt->mCollectionExpression);
  5371. }
  5372. itrInterface = interface;
  5373. genericItrInterface = itrInterface->ToGenericTypeInstance();
  5374. if (inferVarType)
  5375. {
  5376. varType = genericItrInterface->mGenericTypeInfo->mTypeGenericArguments[0];
  5377. if (isRefExpression)
  5378. {
  5379. if (varType->IsPointer())
  5380. varType = CreateRefType(varType->GetUnderlyingType());
  5381. }
  5382. }
  5383. }
  5384. };
  5385. auto enumeratorTypeInst = itr.mType->ToTypeInstance();
  5386. if (enumeratorTypeInst != NULL)
  5387. {
  5388. for (auto& interfaceRef : enumeratorTypeInst->mInterfaces)
  5389. {
  5390. BfTypeInstance* interface = interfaceRef.mInterfaceType;
  5391. _CheckInterface(interface);
  5392. }
  5393. if (enumeratorTypeInst->IsInstanceOf(isRefExpression ? mCompiler->mGenericIRefEnumeratorTypeDef : mCompiler->mGenericIEnumeratorTypeDef))
  5394. {
  5395. itrInterface = enumeratorTypeInst;
  5396. genericItrInterface = itrInterface->ToGenericTypeInstance();
  5397. if (inferVarType)
  5398. {
  5399. varType = genericItrInterface->mGenericTypeInfo->mTypeGenericArguments[0];
  5400. if (isRefExpression)
  5401. {
  5402. if (varType->IsPointer())
  5403. varType = CreateRefType(varType);
  5404. }
  5405. }
  5406. }
  5407. }
  5408. if ((genericItrInterface == NULL) && (genericParamInst != NULL))
  5409. {
  5410. for (auto interface : genericParamInst->mInterfaceConstraints)
  5411. _CheckInterface(interface);
  5412. }
  5413. if (genericItrInterface == NULL)
  5414. {
  5415. if (!hadGetEnumeratorType)
  5416. {
  5417. Fail(StrFormat("Type '%s' must contain a 'GetEnumerator' method or implement an IEnumerator<T> interface", TypeToString(target.mType).c_str()), forEachStmt->mCollectionExpression);
  5418. }
  5419. else
  5420. Fail(StrFormat("Enumerator type '%s' must implement an %s<T> interface", TypeToString(itr.mType).c_str(), isRefExpression ? "IRefEnumerator" : "IEnumerator"), forEachStmt->mCollectionExpression);
  5421. itrInterface = NULL;
  5422. itr = BfTypedValue();
  5423. }
  5424. else
  5425. {
  5426. itrInterface = genericItrInterface;
  5427. if (isRefExpression)
  5428. {
  5429. refItrInterface = itrInterface;
  5430. PopulateType(refItrInterface);
  5431. // Must IRefEnumeratorf<T> must include only IEnumerator<T>
  5432. // BF_ASSERT(refItrInterface->mInterfaces.size() == 1);
  5433. // if (refItrInterface->mInterfaces.size() == 1)
  5434. // itrInterface = refItrInterface->mInterfaces[0].mInterfaceType;
  5435. }
  5436. itr = MakeAddressable(itr);
  5437. itr = RemoveReadOnly(itr);
  5438. }
  5439. }
  5440. }
  5441. else
  5442. {
  5443. AssertErrorState();
  5444. }
  5445. PopulateType(varType, BfPopulateType_Data);
  5446. // Apply deferred local assign to mEmbeddedStatement and itrStmt
  5447. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  5448. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
  5449. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  5450. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  5451. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites);
  5452. if ((target.mType->IsSizedArray()) && (((BfSizedArrayType*)target.mType)->mElementCount == 0))
  5453. {
  5454. EmitEnsureInstructionAt();
  5455. mBfIRBuilder->mIgnoreWrites = true;
  5456. }
  5457. BfIdentifierNode* nameNode = NULL;
  5458. String variableName;
  5459. struct _TupleBind
  5460. {
  5461. BfIdentifierNode* mNameNode;
  5462. String mName;
  5463. BfType* mType;
  5464. BfLocalVariable* mVariable;
  5465. };
  5466. Array<_TupleBind> tupleBinds;
  5467. if (forEachStmt->mVariableName != NULL)
  5468. {
  5469. if (auto tupleExpr = BfNodeDynCast<BfTupleExpression>(forEachStmt->mVariableName))
  5470. {
  5471. CheckTupleVariableDeclaration(tupleExpr, varType);
  5472. if (varType->IsTuple())
  5473. {
  5474. auto tupleType = (BfTypeInstance*)varType;
  5475. for (int idx = 0; idx < BF_MIN((int)tupleExpr->mValues.size(), (int)tupleType->mFieldInstances.size()); idx++)
  5476. {
  5477. auto nameNode = tupleExpr->mValues[idx];
  5478. _TupleBind tupleBind;
  5479. tupleBind.mNameNode = BfNodeDynCast<BfIdentifierNode>(nameNode);
  5480. if ((tupleBind.mNameNode == NULL) && (nameNode != NULL))
  5481. {
  5482. Fail("Variable name expected", nameNode);
  5483. }
  5484. tupleBind.mName = nameNode->ToString();
  5485. tupleBind.mType = tupleType->mFieldInstances[idx].mResolvedType;
  5486. tupleBind.mVariable = NULL;
  5487. tupleBinds.Add(tupleBind);
  5488. if (idx == 0)
  5489. variableName = tupleBind.mName;
  5490. }
  5491. }
  5492. }
  5493. else
  5494. {
  5495. nameNode = BfNodeDynCast<BfIdentifierNode>(forEachStmt->mVariableName);
  5496. if (nameNode != NULL)
  5497. variableName = nameNode->ToString();
  5498. }
  5499. }
  5500. if (variableName.IsEmpty())
  5501. variableName = "_";
  5502. BfModuleMethodInstance getNextMethodInst;
  5503. BfType* nextEmbeddedType = NULL;
  5504. BfTypedValue nextResult;
  5505. if ((refItrInterface) || (itrInterface))
  5506. {
  5507. if (isRefExpression)
  5508. {
  5509. PopulateType(refItrInterface, BfPopulateType_Full_Force);
  5510. getNextMethodInst = GetMethodByName(refItrInterface, "GetNextRef");
  5511. }
  5512. else
  5513. {
  5514. PopulateType(itrInterface, BfPopulateType_Full_Force);
  5515. getNextMethodInst = GetMethodByName(itrInterface, "GetNext");
  5516. }
  5517. BF_ASSERT(getNextMethodInst);
  5518. nextResult = BfTypedValue(CreateAlloca(getNextMethodInst.mMethodInstance->mReturnType), getNextMethodInst.mMethodInstance->mReturnType, true);
  5519. if (nextResult.mType->IsGenericTypeInstance())
  5520. {
  5521. nextEmbeddedType = ((BfTypeInstance*)nextResult.mType)->mGenericTypeInfo->mTypeGenericArguments[0];
  5522. }
  5523. }
  5524. if (nextEmbeddedType == NULL)
  5525. nextEmbeddedType = GetPrimitiveType(BfTypeCode_Var);
  5526. BfLocalVariable* itrLocalDef = NULL;
  5527. // Iterator local def
  5528. if (itr)
  5529. {
  5530. BfLocalVariable* localDef = new BfLocalVariable();
  5531. itrLocalDef = localDef;
  5532. localDef->mNameNode = nameNode;
  5533. localDef->mName = variableName;
  5534. localDef->mResolvedType = itr.mType;
  5535. localDef->mAddr = itr.mValue;
  5536. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  5537. localDef->mReadFromId = 0;
  5538. localDef->Init();
  5539. UpdateSrcPos(forEachStmt);
  5540. CheckVariableDef(localDef);
  5541. AddLocalVariableDef(localDef, true);
  5542. }
  5543. BfIRValue varInst;
  5544. BfTypedValue varTypedVal;
  5545. bool needsValCopy = true;
  5546. // Local variable
  5547. {
  5548. if (!tupleBinds.IsEmpty())
  5549. {
  5550. BF_ASSERT(varType->IsTuple());
  5551. auto tupleType = (BfTypeInstance*)varType;
  5552. // Tuple binds
  5553. needsValCopy = false;
  5554. if (!nextResult)
  5555. {
  5556. varInst = CreateAlloca(varType);
  5557. varTypedVal = BfTypedValue(varInst, varType, true);
  5558. }
  5559. // Local
  5560. for (int idx = 0; idx < (int)tupleBinds.size(); idx++)
  5561. {
  5562. auto& tupleBind = tupleBinds[idx];
  5563. BfLocalVariable* localDef = new BfLocalVariable();
  5564. localDef->mNameNode = tupleBind.mNameNode;
  5565. localDef->mName = tupleBind.mName;
  5566. localDef->mResolvedType = tupleBind.mType;
  5567. if (!needsValCopy)
  5568. localDef->mResolvedType = CreateRefType(localDef->mResolvedType);
  5569. localDef->mAddr = CreateAlloca(localDef->mResolvedType);
  5570. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  5571. localDef->mReadFromId = 0;
  5572. if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
  5573. localDef->mIsReadOnly = true;
  5574. localDef->Init();
  5575. auto fieldInstance = &tupleType->mFieldInstances[idx];
  5576. if (fieldInstance->mDataIdx >= 0)
  5577. {
  5578. auto tuplePtrType = CreatePointerType(varType);
  5579. BfIRValue tuplePtr;
  5580. if (nextResult)
  5581. tuplePtr = mBfIRBuilder->CreateBitCast(nextResult.mValue, mBfIRBuilder->MapType(tuplePtrType));
  5582. else
  5583. tuplePtr = mBfIRBuilder->CreateBitCast(varInst, mBfIRBuilder->MapType(tuplePtrType));
  5584. auto valAddr = mBfIRBuilder->CreateInBoundsGEP(tuplePtr, 0, fieldInstance->mDataIdx);
  5585. mBfIRBuilder->CreateStore(valAddr, localDef->mAddr);
  5586. }
  5587. UpdateSrcPos(forEachStmt);
  5588. if ((itrLocalDef != NULL) && (idx == 0))
  5589. {
  5590. localDef->mLocalVarId = itrLocalDef->mLocalVarId;
  5591. localDef->mIsShadow = true;
  5592. }
  5593. else
  5594. {
  5595. CheckVariableDef(localDef);
  5596. }
  5597. AddLocalVariableDef(localDef, true, false, BfIRValue(), BfIRInitType_NotNeeded_AliveOnDecl);
  5598. }
  5599. }
  5600. else
  5601. {
  5602. // Normal case
  5603. if ((nextResult) && (varType->IsComposite()))
  5604. {
  5605. needsValCopy = false;
  5606. varType = CreateRefType(varType);
  5607. }
  5608. // Local
  5609. BfLocalVariable* localDef = new BfLocalVariable();
  5610. localDef->mNameNode = nameNode;
  5611. localDef->mName = variableName;
  5612. localDef->mResolvedType = varType;
  5613. varInst = CreateAlloca(varType);
  5614. localDef->mAddr = varInst;
  5615. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  5616. localDef->mReadFromId = 0;
  5617. if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
  5618. localDef->mIsReadOnly = true;
  5619. localDef->Init();
  5620. if (!needsValCopy)
  5621. {
  5622. auto valAddr = mBfIRBuilder->CreateBitCast(nextResult.mValue, mBfIRBuilder->MapType(varType));
  5623. mBfIRBuilder->CreateStore(valAddr, varInst);
  5624. }
  5625. UpdateSrcPos(forEachStmt);
  5626. if (itrLocalDef != NULL)
  5627. {
  5628. localDef->mLocalVarId = itrLocalDef->mLocalVarId;
  5629. localDef->mIsShadow = true;
  5630. }
  5631. else
  5632. {
  5633. CheckVariableDef(localDef);
  5634. }
  5635. AddLocalVariableDef(localDef, true, false, BfIRValue(), BfIRInitType_NotNeeded_AliveOnDecl);
  5636. varTypedVal = BfTypedValue(varInst, varType, true);
  5637. }
  5638. }
  5639. // Iterator
  5640. if (itr)
  5641. {
  5642. if ((!isArray) && (!isSizedArray))
  5643. {
  5644. BfFunctionBindResult functionBindResult;
  5645. BfExprEvaluator exprEvaluator(this);
  5646. exprEvaluator.mFunctionBindResult = &functionBindResult;
  5647. // Allow for "Dispose" not to exist
  5648. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  5649. BfResolvedArgs resolvedArgs;
  5650. exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_NoAutoComplete);
  5651. exprEvaluator.MatchMethod(forEachStmt->mCollectionExpression, NULL, itr, false, false, "Dispose", resolvedArgs, BfMethodGenericArguments());
  5652. if (functionBindResult.mMethodInstance != NULL)
  5653. {
  5654. BfModuleMethodInstance moduleMethodInstance;
  5655. moduleMethodInstance = BfModuleMethodInstance(functionBindResult.mMethodInstance, functionBindResult.mFunc);
  5656. AddDeferredCall(moduleMethodInstance, functionBindResult.mIRArgs, mCurMethodState->mCurScope);
  5657. }
  5658. }
  5659. }
  5660. BfScopeData innerScopeData;
  5661. if (forEachStmt->mLabelNode != NULL)
  5662. innerScopeData.mLabelNode = forEachStmt->mLabelNode->mLabel;
  5663. innerScopeData.mValueScopeStart = ValueScopeStart();
  5664. mCurMethodState->AddScope(&innerScopeData);
  5665. NewScopeState(true, false);
  5666. innerScopeData.mIsLoop = true;
  5667. if ((autoComplete != NULL) && (forEachStmt->mVariableTypeRef != NULL))
  5668. autoComplete->CheckVarResolution(forEachStmt->mVariableTypeRef, varType);
  5669. if (isArray || isSizedArray)
  5670. mBfIRBuilder->CreateStore(GetConstValue(0), itr.mValue);
  5671. auto valueScopeStartInner = ValueScopeStart();
  5672. // We may have a call in the loop body
  5673. mCurMethodState->mMayNeedThisAccessCheck = true;
  5674. auto condBB = mBfIRBuilder->CreateBlock("foreach.cond", true);
  5675. auto bodyBB = mBfIRBuilder->CreateBlock("foreach.body");
  5676. auto incBB = mBfIRBuilder->CreateBlock("foreach.inc");
  5677. auto endBB = mBfIRBuilder->CreateBlock("foreach.end");
  5678. BfBreakData breakData;
  5679. breakData.mIRContinueBlock = incBB;
  5680. breakData.mIRBreakBlock = endBB;
  5681. breakData.mScope = &innerScopeData;
  5682. breakData.mInnerValueScopeStart = valueScopeStartInner;
  5683. breakData.mPrevBreakData = mCurMethodState->mBreakData;
  5684. SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
  5685. mBfIRBuilder->CreateBr(condBB);
  5686. mBfIRBuilder->SetInsertPoint(condBB);
  5687. if (forEachStmt->mCollectionExpression != NULL)
  5688. UpdateExprSrcPos(forEachStmt->mCollectionExpression);
  5689. BfIRValue conditionValue;
  5690. if (isSizedArray) // if (i < lengthof(array)
  5691. {
  5692. auto itrVal = mBfIRBuilder->CreateLoad(itr.mValue);
  5693. auto arrayType = (BfSizedArrayType*)target.mType;
  5694. PopulateType(arrayType, BfPopulateType_DataAndMethods);
  5695. BfIRValue lengthVal = GetConstValue(arrayType->mElementCount);
  5696. conditionValue = mBfIRBuilder->CreateCmpLT(itrVal, lengthVal, true);
  5697. mBfIRBuilder->CreateCondBr(conditionValue, bodyBB, endBB);
  5698. ValueScopeEnd(valueScopeStartInner);
  5699. }
  5700. else if (isArray) // if (i < array.mLength)
  5701. {
  5702. auto itrVal = mBfIRBuilder->CreateLoad(itr.mValue);
  5703. auto arrayType = (BfArrayType*)target.mType;
  5704. PopulateType(arrayType);
  5705. auto arrayBaseValue = mBfIRBuilder->CreateBitCast(target.mValue, mBfIRBuilder->MapType(arrayType->mBaseType, BfIRPopulateType_Full));
  5706. int getLengthBitCount = arrayType->GetLengthBitCount();
  5707. BfIRValue lengthVal;
  5708. if (arrayType->mBaseType->mTypeFailed)
  5709. {
  5710. AssertErrorState();
  5711. if (getLengthBitCount == 64)
  5712. lengthVal = GetConstValue64(0);
  5713. else
  5714. lengthVal = GetConstValue32(0);
  5715. }
  5716. else
  5717. {
  5718. auto lengthValAddr = mBfIRBuilder->CreateInBoundsGEP(arrayBaseValue, 0, GetFieldDataIdx(arrayType->mBaseType, 0, "mLength"));
  5719. lengthVal = mBfIRBuilder->CreateLoad(lengthValAddr);
  5720. }
  5721. lengthVal = mBfIRBuilder->CreateNumericCast(lengthVal, true, BfTypeCode_IntPtr);
  5722. conditionValue = mBfIRBuilder->CreateCmpLT(itrVal, lengthVal, true);
  5723. mBfIRBuilder->CreateCondBr(conditionValue, bodyBB, endBB);
  5724. ValueScopeEnd(valueScopeStartInner);
  5725. }
  5726. else // if (itr.MoveNext())
  5727. {
  5728. if (!itr)
  5729. {
  5730. if (!isVarEnumerator)
  5731. AssertErrorState();
  5732. }
  5733. else
  5734. {
  5735. BfExprEvaluator exprEvaluator(this);
  5736. auto itrTypeInstance = itr.mType->ToTypeInstance();
  5737. SizedArray<BfResolvedArg, 0> resolvedArgs;
  5738. BfMethodMatcher methodMatcher(forEachStmt->mCollectionExpression, this, getNextMethodInst.mMethodInstance, resolvedArgs, BfMethodGenericArguments());
  5739. if (isRefExpression)
  5740. methodMatcher.CheckType(refItrInterface, itr, false);
  5741. else
  5742. methodMatcher.CheckType(itrInterface, itr, false);
  5743. methodMatcher.TryDevirtualizeCall(itr);
  5744. exprEvaluator.mReceivingValue = &nextResult;
  5745. auto retVal = exprEvaluator.CreateCall(&methodMatcher, itr);
  5746. if (exprEvaluator.mReceivingValue != NULL)
  5747. {
  5748. if (mIsComptimeModule)
  5749. {
  5750. retVal = LoadValue(retVal);
  5751. mBfIRBuilder->CreateStore(retVal.mValue, nextResult.mValue);
  5752. }
  5753. else
  5754. AssertErrorState();
  5755. }
  5756. if ((retVal) && (!retVal.mType->IsVar()))
  5757. {
  5758. auto i8Result = ExtractValue(nextResult, NULL, 2);
  5759. i8Result = LoadValue(i8Result);
  5760. BF_ASSERT(i8Result.mType == GetPrimitiveType(BfTypeCode_Int8));
  5761. conditionValue = mBfIRBuilder->CreateCmpEQ(i8Result.mValue, GetConstValue8(0));
  5762. }
  5763. else
  5764. conditionValue = GetDefaultValue(GetPrimitiveType(BfTypeCode_Boolean));
  5765. mBfIRBuilder->CreateCondBr(conditionValue, bodyBB, endBB);
  5766. ValueScopeEnd(valueScopeStartInner);
  5767. }
  5768. }
  5769. mBfIRBuilder->AddBlock(bodyBB);
  5770. mBfIRBuilder->SetInsertPoint(bodyBB);
  5771. if (!varTypedVal)
  5772. {
  5773. // Nothing to do...
  5774. }
  5775. else if (isSizedArray) // val = array[i]
  5776. {
  5777. auto itrVal = mBfIRBuilder->CreateLoad(itr.mValue);
  5778. auto arrayType = (BfSizedArrayType*)target.mType;
  5779. BfType* ptrType = CreatePointerType(arrayType->mElementType);
  5780. BfTypedValue arrayItem;
  5781. if (arrayType->mElementType->IsValuelessType())
  5782. {
  5783. arrayItem = GetDefaultTypedValue(arrayType->mElementType);
  5784. }
  5785. else
  5786. {
  5787. target = MakeAddressable(target);
  5788. arrayItem = BfTypedValue(CreateIndexedValue(arrayType->mElementType, target.mValue, itrVal, true), arrayType->mElementType, true);
  5789. if (isRefExpression)
  5790. arrayItem = BfTypedValue(arrayItem.mValue, CreateRefType(arrayItem.mType));
  5791. }
  5792. arrayItem = Cast(forEachStmt->mCollectionExpression, arrayItem, varType, BfCastFlags_Explicit);
  5793. if ((arrayItem) && (!arrayItem.mValue.IsFake()))
  5794. {
  5795. arrayItem = LoadValue(arrayItem);
  5796. if (arrayItem)
  5797. mBfIRBuilder->CreateStore(arrayItem.mValue, varInst);
  5798. }
  5799. }
  5800. else if (isArray) // val = array[i]
  5801. {
  5802. auto itrVal = mBfIRBuilder->CreateLoad(itr.mValue);
  5803. BfTypedValueExpression typedValueExpr;
  5804. typedValueExpr.Init(BfTypedValue(itrVal, itrType));
  5805. BfExprEvaluator exprEvaluator(this);
  5806. SizedArray<BfExpression*, 1> indices;
  5807. indices.push_back(&typedValueExpr);
  5808. BfSizedArray<BfExpression*> sizedArgExprs(indices);
  5809. BfResolvedArgs argValues(&sizedArgExprs);
  5810. exprEvaluator.ResolveArgValues(argValues);
  5811. bool boundsCheck = mCompiler->mOptions.mRuntimeChecks;
  5812. auto typeOptions = GetTypeOptions();
  5813. if (typeOptions != NULL)
  5814. boundsCheck = typeOptions->Apply(boundsCheck, BfOptionFlags_RuntimeChecks);
  5815. BfMethodMatcher methodMatcher(forEachStmt->mVariableName, this, "get__", argValues.mResolvedArgs, BfMethodGenericArguments());
  5816. methodMatcher.mMethodType = BfMethodType_PropertyGetter;
  5817. methodMatcher.CheckType(target.mType->ToTypeInstance(), target, false);
  5818. if (methodMatcher.mBestMethodDef == NULL)
  5819. {
  5820. Fail("Failed to find indexer method in array", forEachStmt);
  5821. }
  5822. else
  5823. {
  5824. methodMatcher.mCheckedKind = boundsCheck ? BfCheckedKind_Checked : BfCheckedKind_Unchecked;
  5825. BfTypedValue arrayItem = exprEvaluator.CreateCall(&methodMatcher, target);
  5826. if ((varInst) && (arrayItem))
  5827. {
  5828. if (isRefExpression)
  5829. arrayItem = BfTypedValue(arrayItem.mValue, CreateRefType(arrayItem.mType));
  5830. else if (!arrayItem.mType->IsComposite())
  5831. arrayItem = LoadValue(arrayItem);
  5832. arrayItem = Cast(forEachStmt->mCollectionExpression, arrayItem, varType, BfCastFlags_Explicit);
  5833. arrayItem = LoadValue(arrayItem);
  5834. if (arrayItem)
  5835. mBfIRBuilder->CreateStore(arrayItem.mValue, varInst);
  5836. }
  5837. }
  5838. }
  5839. else
  5840. {
  5841. if (!itr)
  5842. {
  5843. if (!isVarEnumerator)
  5844. AssertErrorState();
  5845. }
  5846. else if (mCompiler->IsAutocomplete())
  5847. {
  5848. // If we don't do this shortcut, we can end up creating temporary "boxed" objects
  5849. }
  5850. else
  5851. {
  5852. if (needsValCopy)
  5853. {
  5854. auto nextVal = BfTypedValue(mBfIRBuilder->CreateBitCast(nextResult.mValue, mBfIRBuilder->MapType(CreatePointerType(nextEmbeddedType))), nextEmbeddedType, true);
  5855. if (isRefExpression)
  5856. {
  5857. if (nextVal.mType->IsPointer())
  5858. nextVal = BfTypedValue(nextVal.mValue, CreateRefType(nextVal.mType->GetUnderlyingType()), true);
  5859. }
  5860. nextVal = Cast(forEachStmt->mCollectionExpression, nextVal, varType, BfCastFlags_Explicit);
  5861. nextVal = LoadValue(nextVal);
  5862. if ((nextVal) && (!nextVal.mType->IsValuelessType()))
  5863. mBfIRBuilder->CreateStore(nextVal.mValue, varInst);
  5864. }
  5865. }
  5866. }
  5867. if (forEachStmt->mEmbeddedStatement != NULL)
  5868. {
  5869. VisitEmbeddedStatement(forEachStmt->mEmbeddedStatement);
  5870. }
  5871. if (!mCurMethodState->mLeftBlockUncond)
  5872. {
  5873. ValueScopeEnd(valueScopeStartInner);
  5874. mBfIRBuilder->CreateBr(incBB);
  5875. }
  5876. mBfIRBuilder->AddBlock(incBB);
  5877. mBfIRBuilder->SetInsertPoint(incBB);
  5878. if (isArray || isSizedArray)
  5879. {
  5880. auto val = mBfIRBuilder->CreateLoad(itr.mValue);
  5881. auto result = mBfIRBuilder->CreateAdd(val, GetConstValue(1));
  5882. mBfIRBuilder->CreateStore(result, itr.mValue);
  5883. }
  5884. else
  5885. {
  5886. // Nothing to do
  5887. }
  5888. mBfIRBuilder->CreateBr(condBB);
  5889. mBfIRBuilder->AddBlock(endBB);
  5890. mBfIRBuilder->SetInsertPoint(endBB);
  5891. if ((itrLocalDef != NULL) && (itrLocalDef->mDbgVarInst) && (IsTargetingBeefBackend()))
  5892. {
  5893. // If this shadows another enumerator variable then we need to explicitly mark the end of this one
  5894. mBfIRBuilder->DbgLifetimeEnd(itrLocalDef->mDbgVarInst);
  5895. }
  5896. // The 'return' may have been inside the block, which may not have been entered if preconditions were not met
  5897. mCurMethodState->SetHadReturn(false);
  5898. mCurMethodState->mLeftBlockUncond = false;
  5899. mCurMethodState->mLeftBlockCond = false;
  5900. RestoreScopeState();
  5901. RestoreScopeState();
  5902. }
  5903. void BfModule::Visit(BfDeferStatement* deferStmt)
  5904. {
  5905. if (deferStmt->mTargetNode == NULL)
  5906. {
  5907. AssertErrorState();
  5908. return;
  5909. }
  5910. //TODO: Why in the world didn't we want to be able to step onto a defer statement?
  5911. // We only want the breakpoint to hit on execution of the defer, not on insertion of it
  5912. //SetAndRestoreValue<bool> prevSetIllegalSrcPos(mSetIllegalSrcPosition, true);
  5913. UpdateSrcPos(deferStmt);
  5914. EmitEnsureInstructionAt();
  5915. BfScopeData* scope = NULL;
  5916. if (deferStmt->mScopeToken != NULL)
  5917. {
  5918. if (deferStmt->mScopeToken->GetToken() == BfToken_Scope)
  5919. scope = mCurMethodState->mCurScope->GetTargetable();
  5920. else
  5921. scope = &mCurMethodState->mHeadScope;
  5922. }
  5923. else if (deferStmt->mScopeName != NULL)
  5924. scope = FindScope(deferStmt->mScopeName, true);
  5925. else
  5926. scope = mCurMethodState->mCurScope;
  5927. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  5928. {
  5929. auto targetIdentifier = BfNodeDynCast<BfIdentifierNode>(deferStmt->mScopeName);
  5930. if ((deferStmt->mScopeName == NULL) || (targetIdentifier != NULL))
  5931. mCompiler->mResolvePassData->mAutoComplete->CheckLabel(targetIdentifier, deferStmt->mColonToken, scope);
  5932. }
  5933. if ((scope == mCurMethodState->mCurScope) && (scope->mCloseNode == NULL))
  5934. {
  5935. auto parser = deferStmt->GetParser();
  5936. if ((parser != NULL) && (parser->mFileName.Contains('|')))
  5937. {
  5938. // Is emitted
  5939. }
  5940. else
  5941. Warn(0, "This defer will immediately execute. Consider specifying a wider scope target such as 'defer::'", deferStmt->mDeferToken);
  5942. }
  5943. if (auto block = BfNodeDynCast<BfBlock>(deferStmt->mTargetNode))
  5944. {
  5945. if (deferStmt->mBind != NULL)
  5946. {
  5947. Array<BfDeferredCapture> captures;
  5948. for (auto identifier : deferStmt->mBind->mParams)
  5949. {
  5950. BfDeferredCapture deferredCapture;
  5951. deferredCapture.mName = identifier->ToString();
  5952. deferredCapture.mValue = CreateValueFromExpression(identifier);
  5953. if (deferredCapture.mValue)
  5954. {
  5955. captures.push_back(deferredCapture);
  5956. }
  5957. }
  5958. AddDeferredBlock(block, scope, &captures);
  5959. }
  5960. else
  5961. AddDeferredBlock(block, scope);
  5962. }
  5963. else if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(deferStmt->mTargetNode))
  5964. {
  5965. BfExprEvaluator expressionEvaluator(this);
  5966. expressionEvaluator.mDeferCallRef = exprStmt->mExpression;
  5967. expressionEvaluator.mDeferScopeAlloc = scope;
  5968. expressionEvaluator.VisitChild(exprStmt->mExpression);
  5969. if (mCurMethodState->mPendingNullConditional != NULL)
  5970. FlushNullConditional(expressionEvaluator.mResult, true);
  5971. }
  5972. else if (auto deleteStmt = BfNodeDynCast<BfDeleteStatement>(deferStmt->mTargetNode))
  5973. {
  5974. if (deleteStmt->mExpression == NULL)
  5975. {
  5976. AssertErrorState();
  5977. return;
  5978. }
  5979. auto val = CreateValueFromExpression(deleteStmt->mExpression);
  5980. if (!val)
  5981. return;
  5982. if (mCompiler->IsAutocomplete())
  5983. return;
  5984. bool isGenericParam = false;
  5985. auto checkType = val.mType;
  5986. if (val.mType->IsGenericParam())
  5987. {
  5988. isGenericParam = true;
  5989. auto genericParamInst = GetGenericParamInstance((BfGenericParamType*)val.mType);
  5990. if (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Delete)
  5991. return;
  5992. if (genericParamInst->mTypeConstraint != NULL)
  5993. checkType = genericParamInst->mTypeConstraint;
  5994. }
  5995. bool isAppendDelete = false;
  5996. BfTypedValue customAllocator;
  5997. if (deleteStmt->mAllocExpr != NULL)
  5998. {
  5999. if (auto expr = BfNodeDynCast<BfExpression>(deleteStmt->mAllocExpr))
  6000. customAllocator = CreateValueFromExpression(expr);
  6001. else if (auto tokenNode = BfNodeDynCast<BfTokenNode>(deleteStmt->mAllocExpr))
  6002. {
  6003. if (tokenNode->mToken == BfToken_Append)
  6004. isAppendDelete = true;
  6005. }
  6006. }
  6007. auto internalType = ResolveTypeDef(mCompiler->mInternalTypeDef);
  6008. PopulateType(checkType);
  6009. if (checkType->IsVar())
  6010. return;
  6011. if ((!checkType->IsObjectOrInterface()) && (!checkType->IsPointer()))
  6012. {
  6013. VisitChild(deferStmt->mTargetNode);
  6014. Fail(StrFormat("Cannot delete a value of type '%s'", TypeToString(val.mType).c_str()), deferStmt->mTargetNode);
  6015. return;
  6016. }
  6017. if (isGenericParam)
  6018. return;
  6019. bool isDtorOnly = false;
  6020. if (customAllocator.mType == GetPrimitiveType(BfTypeCode_NullPtr))
  6021. {
  6022. if (!checkType->IsObjectOrInterface())
  6023. Warn(0, "Type '%' has no destructor, so delete:null has no effect", deleteStmt->mExpression);
  6024. }
  6025. else if (customAllocator)
  6026. {
  6027. BfFunctionBindResult functionBindResult;
  6028. functionBindResult.mWantsArgs = true;
  6029. auto customAllocTypeInst = customAllocator.mType->ToTypeInstance();
  6030. if ((checkType->IsObjectOrInterface()) && (customAllocTypeInst != NULL) && (customAllocTypeInst->mTypeDef->GetMethodByName("FreeObject") != NULL))
  6031. {
  6032. BfTypedValueExpression typedValueExpr;
  6033. typedValueExpr.Init(val);
  6034. typedValueExpr.mRefNode = deleteStmt->mAllocExpr;
  6035. BfExprEvaluator exprEvaluator(this);
  6036. SizedArray<BfExpression*, 2> argExprs;
  6037. argExprs.push_back(&typedValueExpr);
  6038. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  6039. BfResolvedArgs argValues(&sizedArgExprs);
  6040. exprEvaluator.ResolveArgValues(argValues);
  6041. exprEvaluator.mNoBind = true;
  6042. exprEvaluator.mFunctionBindResult = &functionBindResult;
  6043. exprEvaluator.MatchMethod(deleteStmt->mAllocExpr, NULL, customAllocator, false, false, "FreeObject", argValues, BfMethodGenericArguments());
  6044. }
  6045. else
  6046. {
  6047. auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  6048. auto ptrValue = BfTypedValue(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(voidPtrType)), voidPtrType);
  6049. BfTypedValueExpression typedValueExpr;
  6050. typedValueExpr.Init(ptrValue);
  6051. BfExprEvaluator exprEvaluator(this);
  6052. SizedArray<BfExpression*, 2> argExprs;
  6053. argExprs.push_back(&typedValueExpr);
  6054. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  6055. BfResolvedArgs argValues(&sizedArgExprs);
  6056. exprEvaluator.ResolveArgValues(argValues);
  6057. exprEvaluator.mNoBind = true;
  6058. exprEvaluator.mFunctionBindResult = &functionBindResult;
  6059. exprEvaluator.MatchMethod(deleteStmt->mAllocExpr, NULL, customAllocator, false, false, "Free", argValues, BfMethodGenericArguments());
  6060. }
  6061. if (functionBindResult.mMethodInstance != NULL)
  6062. {
  6063. AddDeferredCall(BfModuleMethodInstance(functionBindResult.mMethodInstance, functionBindResult.mFunc), functionBindResult.mIRArgs, scope, deleteStmt, true);
  6064. }
  6065. }
  6066. if (checkType->IsObjectOrInterface())
  6067. {
  6068. auto objectType = mContext->mBfObjectType;
  6069. PopulateType(objectType);
  6070. BfMethodInstance* methodInstance = objectType->mVirtualMethodTable[mCompiler->GetVTableMethodOffset() + 0].mImplementingMethod;
  6071. BF_ASSERT(methodInstance->mMethodDef->mName == "~this");
  6072. SizedArray<BfIRValue, 1> llvmArgs;
  6073. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(objectType)));
  6074. if (!customAllocator)
  6075. {
  6076. if ((mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!mIsComptimeModule))
  6077. {
  6078. auto moduleMethodInstance = GetInternalMethod("Dbg_MarkObjectDeleted");
  6079. AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
  6080. }
  6081. else
  6082. {
  6083. auto moduleMethodInstance = GetInternalMethod("Free");
  6084. SizedArray<BfIRValue, 1> llvmArgs;
  6085. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr)));
  6086. AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
  6087. }
  6088. }
  6089. auto moduleMethodInstance = GetMethodInstance(objectType, methodInstance->mMethodDef, BfTypeVector());
  6090. AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
  6091. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  6092. {
  6093. auto moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), (deleteStmt->mTargetTypeToken != NULL) ? "Dbg_ObjectPreCustomDelete" : "Dbg_ObjectPreDelete");
  6094. AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
  6095. }
  6096. }
  6097. else
  6098. {
  6099. if ((!customAllocator) && (!isAppendDelete))
  6100. {
  6101. val = LoadValue(val);
  6102. BfModuleMethodInstance moduleMethodInstance;
  6103. if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  6104. moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Dbg_RawFree");
  6105. else
  6106. moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), "Free");
  6107. SizedArray<BfIRValue, 1> llvmArgs;
  6108. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr)));
  6109. AddDeferredCall(moduleMethodInstance, llvmArgs, scope, deleteStmt, false, true);
  6110. }
  6111. }
  6112. }
  6113. else
  6114. {
  6115. AssertErrorState();
  6116. VisitChild(deferStmt->mTargetNode);
  6117. }
  6118. }
  6119. void BfModule::Visit(BfBlock* block)
  6120. {
  6121. VisitEmbeddedStatement(block);
  6122. }
  6123. void BfModule::Visit(BfUnscopedBlock* block)
  6124. {
  6125. VisitEmbeddedStatement(block, NULL, BfEmbeddedStatementFlags_Unscoped);
  6126. }
  6127. void BfModule::Visit(BfLabeledBlock* labeledBlock)
  6128. {
  6129. VisitEmbeddedStatement(labeledBlock);
  6130. }
  6131. void BfModule::Visit(BfRootNode* rootNode)
  6132. {
  6133. VisitMembers(rootNode);
  6134. }
  6135. void BfModule::Visit(BfInlineAsmStatement* asmStmt)
  6136. {
  6137. #if 0
  6138. enum RegClobberFlags //CDH TODO add support for mmx/xmm/fpst etc (how are these signified in LLVM? check LangRef inline asm docs clobber list info)
  6139. {
  6140. // please keep eax through edx in alphabetical order (grep $BYTEREGS for why)
  6141. REGCLOBBERF_EAX = (1 << 0),
  6142. REGCLOBBERF_EBX = (1 << 1),
  6143. REGCLOBBERF_ECX = (1 << 2),
  6144. REGCLOBBERF_EDX = (1 << 3),
  6145. REGCLOBBERF_ESI = (1 << 4),
  6146. REGCLOBBERF_EDI = (1 << 5),
  6147. REGCLOBBERF_ESP = (1 << 6),
  6148. REGCLOBBERF_EBP = (1 << 7),
  6149. REGCLOBBERF_XMM0 = (1 << 8),
  6150. REGCLOBBERF_XMM1 = (1 << 9),
  6151. REGCLOBBERF_XMM2 = (1 << 10),
  6152. REGCLOBBERF_XMM3 = (1 << 11),
  6153. REGCLOBBERF_XMM4 = (1 << 12),
  6154. REGCLOBBERF_XMM5 = (1 << 13),
  6155. REGCLOBBERF_XMM6 = (1 << 14),
  6156. REGCLOBBERF_XMM7 = (1 << 15),
  6157. REGCLOBBERF_FPST0 = (1 << 16),
  6158. REGCLOBBERF_FPST1 = (1 << 17),
  6159. REGCLOBBERF_FPST2 = (1 << 18),
  6160. REGCLOBBERF_FPST3 = (1 << 19),
  6161. REGCLOBBERF_FPST4 = (1 << 20),
  6162. REGCLOBBERF_FPST5 = (1 << 21),
  6163. REGCLOBBERF_FPST6 = (1 << 22),
  6164. REGCLOBBERF_FPST7 = (1 << 23),
  6165. REGCLOBBERF_MM0 = (1 << 24),
  6166. REGCLOBBERF_MM1 = (1 << 25),
  6167. REGCLOBBERF_MM2 = (1 << 26),
  6168. REGCLOBBERF_MM3 = (1 << 27),
  6169. REGCLOBBERF_MM4 = (1 << 28),
  6170. REGCLOBBERF_MM5 = (1 << 29),
  6171. REGCLOBBERF_MM6 = (1 << 30),
  6172. REGCLOBBERF_MM7 = (1 << 31),
  6173. };
  6174. const char* regClobberNames[] = { "eax", "ebx", "ecx", "edx", "esi", "edi", "esp", "ebp", nullptr }; // must be in same order as flags
  6175. unsigned long regClobberFlags = 0;
  6176. std::function<bool(const StringImpl&, bool)> matchRegFunc = [this, &regClobberNames, &regClobberFlags](const StringImpl& name, bool isClobber)
  6177. {
  6178. bool found = false;
  6179. int nameLen = name.length();
  6180. if (nameLen == 3)
  6181. {
  6182. if ((name[0] == 's') && (name[1] == 't') && (name[2] >= '0') && (name[2] <= '7'))
  6183. {
  6184. // st# regs (unparenthesized at this point)
  6185. if (isClobber)
  6186. regClobberFlags |= (REGCLOBBERF_FPST0 << (name[2] - '0'));
  6187. found = true;
  6188. }
  6189. else if ((name[0] == 'm') && (name[1] == 'm') && (name[2] >= '0') && (name[2] <= '7'))
  6190. {
  6191. // mm regs
  6192. if (isClobber)
  6193. regClobberFlags |= (REGCLOBBERF_MM0 << (name[2] - '0'));
  6194. found = true;
  6195. }
  6196. else
  6197. {
  6198. // dword regs
  6199. for (int iRegCheck = 0; regClobberNames[iRegCheck] != nullptr; ++iRegCheck)
  6200. {
  6201. if (!strcmp(name.c_str(), regClobberNames[iRegCheck]))
  6202. {
  6203. if (isClobber)
  6204. regClobberFlags |= (1 << iRegCheck);
  6205. found = true;
  6206. break;
  6207. }
  6208. }
  6209. }
  6210. }
  6211. else if (nameLen == 2)
  6212. {
  6213. // word & byte regs
  6214. for (int iRegCheck = 0; regClobberNames[iRegCheck] != nullptr; ++iRegCheck)
  6215. {
  6216. if (!strcmp(name.c_str(), regClobberNames[iRegCheck] + 1)) // skip leading 'e'
  6217. {
  6218. if (isClobber)
  6219. regClobberFlags |= (1 << iRegCheck);
  6220. found = true;
  6221. break;
  6222. }
  6223. }
  6224. if (!found)
  6225. {
  6226. // check for byte regs for eax through edx (e.g. al, ah, bl, bh....)
  6227. if ((nameLen == 2) && (name[0] >= 'a') && (name[0] <= 'd') && ((name[1] == 'l') || (name[1] == 'h')))
  6228. {
  6229. if (isClobber)
  6230. regClobberFlags |= (1 << (name[0] - 'a'));// $BYTEREGS this is why we want alphabetical order
  6231. found = true;
  6232. }
  6233. }
  6234. }
  6235. else if ((nameLen == 4) && (name[0] == 'x') && (name[1] == 'm') && (name[2] == 'm') && (name[3] >= '0') && (name[3] <= '7'))
  6236. {
  6237. // xmm regs
  6238. if (isClobber)
  6239. regClobberFlags |= (REGCLOBBERF_XMM0 << (name[3] - '0'));
  6240. found = true;
  6241. }
  6242. return found;
  6243. };
  6244. int asmInstCount = (int)asmStmt->mInstructions.size();
  6245. typedef std::map<String, int> StrToVarIndexMap;
  6246. StrToVarIndexMap strToVarIndexMap;
  6247. if (mCompiler->IsAutocomplete())
  6248. {
  6249. // auto-complete "fast-pass" just to eliminate unused/unassigned variable yellow warning flashes
  6250. for (int iInst=0; iInst<asmInstCount; ++iInst)
  6251. {
  6252. auto instNode = asmStmt->mInstructions[iInst];
  6253. BfInlineAsmInstruction::AsmInst& asmInst = instNode->mAsmInst;
  6254. bool hasLabel = !asmInst.mLabel.empty();
  6255. bool hasOpCode = !asmInst.mOpCode.empty();
  6256. if (hasLabel || hasOpCode) // check against blank lines
  6257. {
  6258. if (hasOpCode) // check against label-only lines (which still get written out, but don't do any other processing)
  6259. {
  6260. int argCount = (int)asmInst.mArgs.size();
  6261. for (int iArg=0; iArg<argCount; ++iArg)
  6262. {
  6263. BfInlineAsmInstruction::AsmArg* arg = &asmInst.mArgs[iArg];
  6264. if (arg->mType == BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg)
  6265. {
  6266. bool found = matchRegFunc(arg->mReg, false);
  6267. if (!found)
  6268. {
  6269. StrToVarIndexMap::iterator it = strToVarIndexMap.find(arg->mReg);
  6270. if (it == strToVarIndexMap.end())
  6271. {
  6272. for (int i = 0; i < (int) mCurMethodState->mLocals.size(); i++)
  6273. {
  6274. auto& checkLocal = mCurMethodState->mLocals[i];
  6275. if (checkLocal.mName == arg->mReg)
  6276. {
  6277. // if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
  6278. checkLocal.mIsReadFrom = true;
  6279. checkLocal.mAssignedKind = BfLocalVarAssignKind_Unconditional;
  6280. found = true;
  6281. break;
  6282. }
  6283. }
  6284. }
  6285. }
  6286. }
  6287. }
  6288. }
  6289. }
  6290. }
  6291. return;
  6292. }
  6293. int debugLocOffset = 0;
  6294. if (!asmStmt->mInstructions.empty())
  6295. debugLocOffset = asmStmt->mInstructions.front()->GetSrcStart() - asmStmt->GetSrcStart();
  6296. UpdateSrcPos(asmStmt, true, debugLocOffset);
  6297. mCurMethodState->mInHeadScope = false;
  6298. BfScopeData prevScope = mCurMethodState->mCurScope;
  6299. mCurMethodState->mCurScope->mPrevScope = &prevScope;
  6300. NewScopeState();
  6301. bool failed = false;
  6302. if (!mCpu)
  6303. mCpu = new Beefy::X86Cpu();
  6304. //const char* srcAsmText = "nop\nnop\n\n\nmov eax, i\ninc eax\nmov i, eax\n_emit 0x0F\n_emit 0xC7\n_emit 0xF0\n\n\nnop\nnop"; //CDH TODO extract from actual lexical text block
  6305. //const char* srcAsmText = "nop\nnop\n\n\nmov eax, i\ninc eax\nmov i, eax\nrdrand eax\n\n\nnop\nnop"; //CDH TODO extract from actual lexical text block
  6306. //String srcAsmTextStr(&asmStmt->mParser->mSrc[asmStmt->mSrcStart], asmStmt->mSrcEnd - asmStmt->mSrcStart);
  6307. //const char* srcAsmText = srcAsmTextStr.c_str();
  6308. String dstAsmText;
  6309. String constraintStr, clobberStr;
  6310. int constraintCount = 0;
  6311. bool hasMemoryClobber = false;
  6312. Array<Type*> paramTypes;
  6313. SizedArray<Value*, 1> llvmArgs;
  6314. int lastDebugLine = -1;
  6315. int curDebugLineDeltaValue = 0, curDebugLineDeltaRunCount = 0;
  6316. String debugLineSequenceStr;
  6317. int isFirstDebugLine = 1;
  6318. auto maybeEmitDebugLineRun = [&curDebugLineDeltaValue, &curDebugLineDeltaRunCount, &debugLineSequenceStr, &isFirstDebugLine]()
  6319. {
  6320. if (curDebugLineDeltaRunCount > 0)
  6321. {
  6322. for (int i=isFirstDebugLine; i<2; ++i)
  6323. {
  6324. int value = i ? curDebugLineDeltaValue : curDebugLineDeltaRunCount;
  6325. String encodedValue;
  6326. EncodeULEB32(value, encodedValue);
  6327. if (encodedValue.length() > 1)
  6328. debugLineSequenceStr += String("$") + encodedValue + "$";
  6329. else
  6330. debugLineSequenceStr += encodedValue;
  6331. }
  6332. curDebugLineDeltaRunCount = 0;
  6333. isFirstDebugLine = 0;
  6334. }
  6335. };
  6336. auto mangledLabelName = [&asmStmt](const StringImpl& labelName, int numericLabel) -> String
  6337. {
  6338. return StrFormat("%d", numericLabel);
  6339. //return String(".") + labelName;
  6340. //return StrFormat("%s_%p_%d", labelName.c_str(), asmStmt->mSource, asmStmt->mSrcStart); // suffix label name with location information to make it block-specific (since labels get external linkage)
  6341. };
  6342. typedef std::pair<String, int> LabelPair;
  6343. std::unordered_map<String, LabelPair> labelNames;
  6344. // pre-scan instructions for label names
  6345. for (int iInst=0; iInst<asmInstCount; ++iInst)
  6346. {
  6347. auto instNode = asmStmt->mInstructions[iInst];
  6348. BfInlineAsmInstruction::AsmInst& asmInst = instNode->mAsmInst;
  6349. if (!asmInst.mLabel.empty())
  6350. {
  6351. if (labelNames.find(asmInst.mLabel) != labelNames.end())
  6352. {
  6353. Fail(StrFormat("Label \"%s\" already defined in asm block", asmInst.mLabel.c_str()), instNode, true);
  6354. failed = true;
  6355. }
  6356. else
  6357. {
  6358. String mangledLabel(mangledLabelName(asmInst.mLabel, instNode->GetSrcStart()));
  6359. labelNames[asmInst.mLabel] = LabelPair(mangledLabel, instNode->GetSrcStart());
  6360. asmInst.mLabel = mangledLabel;
  6361. }
  6362. }
  6363. }
  6364. for (int iInst=0; iInst<asmInstCount; ++iInst)
  6365. {
  6366. auto instNode = asmStmt->mInstructions[iInst];
  6367. BfInlineAsmInstruction::AsmInst& asmInst = instNode->mAsmInst;
  6368. bool hasLabel = !asmInst.mLabel.empty();
  6369. bool hasOpCode = !asmInst.mOpCode.empty();
  6370. if (hasLabel || hasOpCode) // check against blank lines
  6371. {
  6372. if (hasOpCode) // check against label-only lines (which still get written out, but don't do any other processing)
  6373. {
  6374. int argCount = (int)asmInst.mArgs.size();
  6375. // reasonable defaults for clobber info
  6376. int clobberCount = 1; // destination is usually first arg in Intel syntax
  6377. bool mayClobberMem = true; // we only care about this when it gets turned to false by GetClobbersForMnemonic (no operand form of the instruction clobbers mem)
  6378. // pseudo-ops
  6379. if (asmInst.mOpCode == "_emit")
  6380. {
  6381. asmInst.mOpCode = ".byte";
  6382. }
  6383. else
  6384. {
  6385. Array<int> opcodes;
  6386. if (!mCpu->GetOpcodesForMnemonic(asmInst.mOpCode, opcodes))
  6387. {
  6388. Fail(StrFormat("Unrecognized instruction mnemonic \"%s\"", asmInst.mOpCode.c_str()), instNode, true);
  6389. failed = true;
  6390. }
  6391. else
  6392. {
  6393. Array<int> implicitClobbers;
  6394. mCpu->GetClobbersForMnemonic(asmInst.mOpCode, argCount, implicitClobbers, clobberCount, mayClobberMem);
  6395. for (int iClobberReg : implicitClobbers)
  6396. {
  6397. String regName = CPURegisters::GetRegisterName(iClobberReg);
  6398. std::transform(regName.begin(), regName.end(), regName.begin(), ::tolower);
  6399. matchRegFunc(regName, true);
  6400. }
  6401. }
  6402. }
  6403. String fakeLabel; // used when running label-using instructions through LLVM semantic pre-check
  6404. for (int iArg=0; iArg<argCount; ++iArg)
  6405. {
  6406. BfInlineAsmInstruction::AsmArg* arg = &asmInst.mArgs[iArg];
  6407. if (arg->mType == BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg)
  6408. {
  6409. bool isClobber = (iArg < clobberCount);
  6410. bool found = matchRegFunc(arg->mReg, isClobber);
  6411. if (!found)
  6412. {
  6413. StrToVarIndexMap::iterator it = strToVarIndexMap.find(arg->mReg);
  6414. if (it != strToVarIndexMap.end())
  6415. {
  6416. arg->mReg = StrFormat("$%d", it->second);
  6417. if (isClobber)
  6418. mayClobberMem = true;
  6419. found = true;
  6420. }
  6421. else
  6422. {
  6423. for (int i = 0; i < (int) mCurMethodState->mLocals.size(); i++)
  6424. {
  6425. auto& checkLocal = mCurMethodState->mLocals[i];
  6426. if (checkLocal.mName == arg->mReg)
  6427. {
  6428. BfIRValue testValue = checkLocal.mAddr;
  6429. llvmArgs.push_back(testValue);
  6430. paramTypes.push_back(testValue->getType());
  6431. arg->mReg = StrFormat("$%d", constraintCount);//CDH TODO does this need size qualifiers for "dword ptr $0" or whatever?
  6432. strToVarIndexMap[checkLocal.mName] = constraintCount;
  6433. constraintStr += "=*m,";
  6434. ++constraintCount;
  6435. if (isClobber)
  6436. mayClobberMem = true;
  6437. // if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
  6438. checkLocal.mIsReadFrom = true;
  6439. checkLocal.mAssignedKind = BfLocalVarAssignKind_Unconditional;
  6440. found = true;
  6441. break;
  6442. }
  6443. }
  6444. }
  6445. }
  6446. if (!found)
  6447. {
  6448. auto labelIt = labelNames.find(arg->mReg);
  6449. if (labelIt != labelNames.end())
  6450. {
  6451. arg->mReg = labelIt->second.first;
  6452. if (labelIt->second.second <= instNode->GetSrcStart())
  6453. {
  6454. fakeLabel = arg->mReg;
  6455. arg->mReg += "b";
  6456. }
  6457. else
  6458. arg->mReg += "f";
  6459. }
  6460. else
  6461. {
  6462. Fail(StrFormat("Unrecognized variable \"%s\"", arg->mReg.c_str()), instNode, true);
  6463. failed = true;
  6464. }
  6465. }
  6466. }
  6467. else if (arg->mType == BfInlineAsmInstruction::AsmArg::ARGTYPE_FloatReg)
  6468. {
  6469. //CDH individual reg clobber is probably insufficient for fp regs since it's stack-based; without deeper knowledge of how individual instructions
  6470. // manipulate the FP stack, the safest approach is to clobber all FP regs as soon as one of them is involved
  6471. //bool isClobber = (iArg == 0); // destination is first arg in Intel syntax
  6472. //bool found = matchRegFunc(StrFormat("st%d", arg->mInt), isClobber);
  6473. //BF_ASSERT(found);
  6474. for (int iRegCheck=0; iRegCheck<8; ++iRegCheck)
  6475. regClobberFlags |= (REGCLOBBERF_FPST0 << iRegCheck);
  6476. }
  6477. else if (arg->mType == BfInlineAsmInstruction::AsmArg::ARGTYPE_Memory)
  6478. {
  6479. bool isClobber = (iArg < clobberCount);
  6480. // check regs for clobber flags
  6481. /*
  6482. //CDH TODO do we need to set clobber flags for regs that are used *indirectly* like this? Actually I don't think so; commenting out for now
  6483. if (!arg->mReg.empty())
  6484. matchRegFunc(arg->mReg, isClobber);
  6485. if (!arg->mAdjReg.empty())
  6486. matchRegFunc(arg->mAdjReg, isClobber);
  6487. */
  6488. if (isClobber)
  6489. mayClobberMem = true;
  6490. if (!arg->mMemberSuffix.empty())
  6491. {
  6492. //CDH TODO add member support once I know the right way to look up struct member offsets. Once we know the offset,
  6493. // add it to arg->mInt, and set ARGMEMF_ImmediateDisp if it's not set already (member support is just used as an offset)
  6494. Fail("Member suffix syntax is not yet supported", instNode, true);
  6495. failed = true;
  6496. }
  6497. }
  6498. }
  6499. if (mayClobberMem)
  6500. hasMemoryClobber = true;
  6501. //debugLineSequenceStr += StrFormat("%d_", asmInst.mDebugLine);
  6502. int curDebugLine = asmInst.mDebugLine;
  6503. int debugLineDelta = (lastDebugLine > 0) ? curDebugLine - lastDebugLine : curDebugLine;
  6504. lastDebugLine = curDebugLine;
  6505. //String encodedDebugLineDelta;
  6506. //EncodeULEB32(debugLineDelta, encodedDebugLineDelta);
  6507. //debugLineSequenceStr += encodedDebugLineDelta + "_";
  6508. if (curDebugLineDeltaValue != debugLineDelta)
  6509. {
  6510. maybeEmitDebugLineRun();
  6511. curDebugLineDeltaValue = debugLineDelta;
  6512. }
  6513. ++curDebugLineDeltaRunCount;
  6514. // run instruction through LLVM for better semantic errors (can be slow in debug; feel free to comment out this scopeData if it's intolerable; the errors will still be caught at compile time)
  6515. //if (false)
  6516. {
  6517. BfInlineAsmInstruction::AsmInst tempAsmInst(asmInst);
  6518. tempAsmInst.mLabel = fakeLabel;
  6519. for (auto & arg : tempAsmInst.mArgs)
  6520. {
  6521. if ((arg.mType == BfInlineAsmInstruction::AsmArg::ARGTYPE_IntReg) && !arg.mReg.empty() && (arg.mReg[0] == '$'))
  6522. {
  6523. // if we've rewritten a local variable instruction arg to use a $-prefixed input, we can't pass that to LLVM
  6524. // at this stage as it won't recognize it; the actual compilation would have changed all these to use actual
  6525. // memory operand syntax first. However, those changes all work down in LLVM to printIntelMemReference inside
  6526. // of X86AsmPrinter.cpp, and that always results in a [bracketed] memory access string no matter what, which
  6527. // means for our semantic checking purposes here it's sufficient to just use "[eax]" for all such cases,
  6528. // rather than go through an even more expensive setup & teardown process to use the AsmPrinter itself.
  6529. arg.mType = BfInlineAsmInstruction::AsmArg::ARGTYPE_Memory;
  6530. arg.mMemFlags = BfInlineAsmInstruction::AsmArg::ARGMEMF_BaseReg;
  6531. arg.mReg = "eax";
  6532. }
  6533. }
  6534. String llvmError;
  6535. if (!mCpu->ParseInlineAsmInstructionLLVM(tempAsmInst.ToString(), llvmError))
  6536. {
  6537. Fail(StrFormat("Inline asm error: %s", llvmError.c_str()), instNode, true);
  6538. failed = true;
  6539. }
  6540. }
  6541. }
  6542. dstAsmText += asmInst.ToString();
  6543. dstAsmText += "\n";
  6544. }
  6545. }
  6546. maybeEmitDebugLineRun(); // leftovers
  6547. if (failed)
  6548. {
  6549. RestoreScopeState(&prevScope);
  6550. return;
  6551. }
  6552. // prepare constraints/clobbers
  6553. {
  6554. for (int iRegCheck = 0; regClobberNames[iRegCheck] != nullptr; ++iRegCheck)
  6555. {
  6556. if (regClobberFlags & (1 << iRegCheck))
  6557. clobberStr += StrFormat("~{%s},", regClobberNames[iRegCheck]);
  6558. }
  6559. for (int iRegCheck=0; iRegCheck<8; ++iRegCheck)
  6560. {
  6561. if (regClobberFlags & (REGCLOBBERF_XMM0 << iRegCheck))
  6562. clobberStr += StrFormat("~{xmm%d},", iRegCheck);
  6563. if (regClobberFlags & (REGCLOBBERF_FPST0 << iRegCheck))
  6564. clobberStr += StrFormat("~{fp%d},~{st(%d)},", iRegCheck, iRegCheck); // both fp# and st(#) are listed in X86RegisterInfo.td
  6565. if (regClobberFlags & (REGCLOBBERF_MM0 << iRegCheck))
  6566. clobberStr += StrFormat("~{mm%d},", iRegCheck);
  6567. }
  6568. // add wrapping instructions to preserve certain regs (e.g. ESI), due to LLVM bypassing register allocator when choosing a base register
  6569. //CDH TODO currently I'm only shielding against ESI stompage; people generally know not to mess with ESP & EBP, but ESI is still a "general" reg and should be allowed to be clobbered
  6570. //if (regClobberFlags & REGCLOBBERF_ESI)
  6571. //{
  6572. //CDH TODO Bah! This doesn't actually work, because if you do any local variable access after mutating ESI, the variable substitution could have generated a base address dependency
  6573. // on ESI which will not expect it to have changed, e.g. "mov esi, var\ninc esi\nmov var, esi\n" dies if "var" gets internally rewritten to "[esi + displacement]". What to do? Hmm.
  6574. //dstAsmText = String("push esi\n") + dstAsmText + String("pop esi\n");
  6575. //}
  6576. if (hasMemoryClobber)
  6577. clobberStr += "~{memory},";
  6578. clobberStr += "~{dirflag},~{fpsr},~{flags}";
  6579. constraintStr += clobberStr;
  6580. }
  6581. bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (!mCurMethodInstance->mIsUnspecialized) && (mHasFullDebugInfo);
  6582. if (wantsDIData)
  6583. {
  6584. static int sVarNum = 0;
  6585. String varName(StrFormat("__asmLines_%d.%s", ++sVarNum, debugLineSequenceStr.c_str()));
  6586. auto varType = GetPrimitiveType(BfTypeCode_Int32);
  6587. auto allocaInst = mBfIRBuilder->CreateAlloca(varType->mLLVMType, 0, varName + ".addr");
  6588. allocaInst->setAlignment(varType->mAlign);
  6589. //paramVar->mAddr = allocaInst;
  6590. auto varValue = GetConstValue(0, varType);
  6591. auto diVariable = mDIBuilder->createAutoVariable(mCurMethodState->mCurScope->mDIScope,
  6592. varName.c_str(), mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, varType->mDIType/*, true*/);
  6593. //auto varValue = llvm::ConstantInt::getTrue(*mLLVMContext);
  6594. //auto varValue = GetDefaultValue(varType);
  6595. //auto varValue = CreateGlobalConstValue(varName, llvm::ConstantInt::getTrue(*mLLVMContext), true);
  6596. //auto varValue = AllocGlobalVariable(*mIRModule, diType->getType(), false, GlobalValue::ExternalLinkage, llvm::ConstantInt::getTrue(*mLLVMContext), varName.c_str());
  6597. //auto diVariable = mDIBuilder->createGlobalVariable(mCurMethodState->mCurScope->mDIScope, varName.c_str(), "", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType, false, varValue);
  6598. //BasicBlock* block = mBfIRBuilder->GetInsertBlock();
  6599. //auto declareVar = mDIBuilder->insertDeclare(varValue, diVariable, mBfIRBuilder->GetInsertBlock());
  6600. auto declareVar = mDIBuilder->insertDeclare(allocaInst, diVariable, mDIBuilder->createExpression(),
  6601. mIRBuilder->getCurrentDebugLocation(), mBfIRBuilder->GetInsertBlock());
  6602. //auto declareVar = mDIBuilder->insertDbgValueIntrinsic(varValue, 0, diVariable, mBfIRBuilder->GetInsertBlock());
  6603. declareVar->setDebugLoc(mIRBuilder->getCurrentDebugLocation());
  6604. }
  6605. /*
  6606. BfIRValue testValue = NULL;
  6607. for (int i = 0; i < (int) mCurMethodState->mLocals.size(); i++)
  6608. {
  6609. auto& checkLocal = mCurMethodState->mLocals[i];
  6610. if (checkLocal.mName == "i")
  6611. {
  6612. testValue = checkLocal.mAddr;
  6613. break;
  6614. }
  6615. }
  6616. */
  6617. //BF_ASSERT((testValue != NULL) && "Need local variable \"i\"");
  6618. //if (testValue != NULL)
  6619. {
  6620. //Type* voidPtrType = Type::getInt8PtrTy(*mLLVMContext);
  6621. //if (mContext->mAsmObjectCheckFuncType == NULL)
  6622. //{
  6623. //Array<Type*> paramTypes;
  6624. //paramTypes.push_back(voidPtrType);
  6625. //mContext->mAsmObjectCheckFuncType = FunctionType::get(Type::getVoidTy(*mLLVMContext), paramTypes, false);
  6626. //}
  6627. FunctionType* funcType = FunctionType::get(Type::getVoidTy(*mLLVMContext), paramTypes, false);
  6628. //SizedArray<Value*, 1> llvmArgs;
  6629. //llvmArgs.push_back(testValue);
  6630. //CDH REMOVE NOTE
  6631. //generates IR (e.g.):
  6632. // call void asm sideeffect "#4\0Anop\0Anop\0Amovl %eax, %eax\0Anop\0Anop", "~{cc},~{dirflag},~{fpsr},~{flags},~{eax}"() #0, !dbg !492
  6633. static int asmIdx = 0;
  6634. asmIdx++;
  6635. String asmStr = StrFormat("#%d\n", asmIdx) +
  6636. //"nop\nnop\nmovl $0, %eax\nincl %eax\nmovl %eax, $0\nmovl $$0, %ecx\nmovl $$0, %esp\nnop\nnop";
  6637. //"nop\nnop\nmovl ($0), %eax\nincl %eax\nmovl %eax, ($0)\nmovl $$0, %ecx\nmovl $$0, %esp\nnop\nnop";
  6638. //"nop\nnop\nmovl %eax, %eax\nmovl $$0, %ecx\nmovl $$0, %esp\nnop\nnop";
  6639. //"nop\nnop\nmovl %eax, %eax\nnop\nnop";
  6640. //"nop\nnop\n.byte 0x0F\n.byte 0xC7\n.byte 0xF0\nmov eax, 7\nmov ecx, 0\ncpuid\nmov eax, dword ptr $0\ninc eax\nmov dword ptr $0, eax\nmov ecx, 0\nmov esp, 0\nnop\nnop"; // rdrand test
  6641. dstAsmText;
  6642. llvm::InlineAsm* inlineAsm = llvm::InlineAsm::get(funcType,
  6643. //asmStr.c_str(), "~{r},~{cc},~{dirflag},~{fpsr},~{flags},~{eax},~{memory},~{esi},~{esp}", true,
  6644. //asmStr.c_str(), "~{cc},~{dirflag},~{fpsr},~{flags},~{memory},~{ecx},~{esp}", true,
  6645. //DOES NOT WORK (mem not written back to from reg:
  6646. //asmStr.c_str(), "+r,~{cc},~{dirflag},~{fpsr},~{flags},~{memory},~{eax},~{ecx},~{esp}", true,
  6647. //asmStr.c_str(), "+rm,~{cc},~{dirflag},~{fpsr},~{flags},~{memory},~{eax},~{ecx},~{esp}", true,
  6648. asmStr.c_str(), constraintStr.c_str(), true,
  6649. false, /*llvm::InlineAsm::AD_ATT*/llvm::InlineAsm::AD_Intel);
  6650. llvm::CallInst* callInst = mIRBuilder->CreateCall(inlineAsm, llvmArgs);
  6651. //llvm::CallInst* callInst = mIRBuilder->CreateCall(inlineAsm);
  6652. callInst->addAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind);
  6653. }
  6654. RestoreScopeState(&prevScope);
  6655. #endif
  6656. }