BfStmtEvaluator.cpp 264 KB

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