BfCompiler.cpp 253 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196
  1. #pragma warning(disable:4996)
  2. #pragma warning(push)
  3. #pragma warning(disable:4800)
  4. #pragma warning(disable:4244)
  5. #pragma warning(disable:4141)
  6. #pragma warning(disable:4624)
  7. #pragma warning(disable:4146)
  8. #pragma warning(disable:4267)
  9. #pragma warning(disable:4291)
  10. #include "BeefySysLib/util/AllocDebug.h"
  11. #include "llvm/Support/Compiler.h"
  12. #include "BfCompiler.h"
  13. #include "BfSystem.h"
  14. #include "BfParser.h"
  15. #include "BfReducer.h"
  16. #include "BfExprEvaluator.h"
  17. #include "../Backend/BeLibManger.h"
  18. #include <fcntl.h>
  19. #include "BfConstResolver.h"
  20. #include "BfMangler.h"
  21. #include "BfDemangler.h"
  22. #include "BeefySysLib/util/PerfTimer.h"
  23. #include "BfSourceClassifier.h"
  24. #include "BfAutoComplete.h"
  25. #include "BfResolvePass.h"
  26. #include "BeefySysLib/util/BeefPerf.h"
  27. #include "../LLVMUtils.h"
  28. #pragma warning(pop)
  29. namespace llvm
  30. {
  31. extern bool DebugFlag;
  32. }
  33. #define SPLIT_CONTEXTS
  34. Beefy::BfCompiler* gBfCompiler = NULL;
  35. void pt(llvm::Type* t)
  36. {
  37. //Beefy::OutputDebugStrF("pv((llvm::Type*)%p)\n", t);
  38. Beefy::debug_ostream os;
  39. t->print(os);
  40. os << "\n";
  41. os << " isSized: " << t->isSized() << "\n";
  42. os.flush();
  43. if (auto pointerType = llvm::dyn_cast<llvm::PointerType>(t))
  44. {
  45. Beefy::OutputDebugStrF("Element: ");
  46. pt(pointerType->getElementType());
  47. }
  48. }
  49. void ppt(llvm::Type* t)
  50. {
  51. auto pointerType = llvm::dyn_cast<llvm::PointerType>(t);
  52. if (pointerType == NULL)
  53. {
  54. Beefy::OutputDebugStrF("Not a pointer type");
  55. return;
  56. }
  57. pt(pointerType->getElementType());
  58. }
  59. void pt(llvm::DINode* t)
  60. {
  61. Beefy::debug_ostream os;
  62. t->print(os);
  63. os << "\n";
  64. os.flush();
  65. }
  66. void pt(llvm::Value* v)
  67. {
  68. pt(v->getType());
  69. }
  70. void pv(const llvm::Value* v)
  71. {
  72. Beefy::debug_ostream os;
  73. v->print(os);
  74. os << "\n";
  75. os.flush();
  76. pt(v->getType());
  77. }
  78. void ppt(llvm::Value* v)
  79. {
  80. ppt(v->getType());
  81. }
  82. void pmd(llvm::Metadata* md)
  83. {
  84. Beefy::debug_ostream os;
  85. md->print(os);
  86. os << "\n";
  87. os.flush();
  88. }
  89. void pdl(llvm::DebugLoc& dl)
  90. {
  91. Beefy::debug_ostream os;
  92. dl.print(os);
  93. os << "\n";
  94. os.flush();
  95. }
  96. void pm(llvm::Module* module)
  97. {
  98. Beefy::debug_ostream os;
  99. module->print(os, NULL);
  100. os << "\n";
  101. os.flush();
  102. }
  103. void PrintUsers(llvm::MDNode* md)
  104. {
  105. /*Beefy::debug_ostream os;
  106. //auto val = llvm::ReplaceableMetadataImpl::get(*md);
  107. auto val = md->Context.getReplaceableUses();
  108. if (val == NULL)
  109. {
  110. os << "Not replaceable\n";
  111. }
  112. else
  113. {
  114. //md->print(os);
  115. typedef std::pair<void *, std::pair<llvm::MetadataTracking::OwnerTy, uint64_t>> UseTy;
  116. llvm::SmallVector<UseTy, 8> Uses(val->UseMap.begin(), val->UseMap.end());
  117. std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
  118. return L.second.second < R.second.second;
  119. });
  120. for (const auto &Pair : Uses)
  121. {
  122. auto Owner = Pair.second.first;
  123. os << Beefy::StrFormat(" %d %p %d\n", Pair.second.first.isNull(), Pair.first, Pair.second.second, Pair).c_str();
  124. }
  125. os << "\n";
  126. }
  127. os.flush();*/
  128. }
  129. void ptbf(Beefy::BfType* bfType)
  130. {
  131. Beefy::OutputDebugStrF("%s\n", bfType->GetModule()->TypeToString(bfType).c_str());
  132. }
  133. void pt(const Beefy::BfTypedValue& val)
  134. {
  135. Beefy::OutputDebugStrF("%s\n", val.mType->GetModule()->TypeToString(val.mType).c_str());
  136. }
  137. void pt(llvm::SmallVectorImpl<llvm::Value*>& llvmArgs)
  138. {
  139. Beefy::debug_ostream os;
  140. for (int i = 0; i < (int)llvmArgs.size(); i++)
  141. {
  142. if (i > 0)
  143. os << ", ";
  144. llvmArgs[i]->getType()->print(os);
  145. }
  146. os << "\n";
  147. os.flush();
  148. }
  149. void PrintUsers(llvm::Value* v)
  150. {
  151. for (auto user : v->users())
  152. {
  153. pt(user);
  154. }
  155. }
  156. /*void PrintFunc(Beefy::BfMethodInstance* methodInstance)
  157. {
  158. Beefy::debug_ostream os;
  159. methodInstance->mIRFunction.mLLVMValue->print(os);
  160. os << "\n";
  161. os.flush();
  162. }*/
  163. USING_NS_BF;
  164. using namespace llvm;
  165. int Beefy::BfWorkListEntry::sCurReqId = 0;
  166. GlobalVariable* AllocGlobalVariable(Module &M, Type *Ty, bool isConstant,
  167. GlobalValue::LinkageTypes Linkage, Constant *Initializer,
  168. const Twine &Name = "", GlobalVariable *InsertBefore = nullptr,
  169. GlobalValue::ThreadLocalMode tlm = GlobalValue::NotThreadLocal, unsigned AddressSpace = 0,
  170. bool isExternallyInitialized = false);
  171. #include "BeefySysLib/util/AllocDebug.h"
  172. //////////////////////////////////////////////////////////////////////////
  173. BfCompiler::HotData::~HotData()
  174. {
  175. for (auto& kv : mMethodMap)
  176. {
  177. auto hotMethod = kv.mValue;
  178. hotMethod->Clear();
  179. }
  180. for (auto& kv : mThisType)
  181. kv.mValue->Deref();
  182. for (auto& kv : mAllocation)
  183. kv.mValue->Deref();
  184. for (auto& kv : mDevirtualizedMethods)
  185. kv.mValue->Deref();
  186. for (auto& kv : mFuncPtrs)
  187. kv.mValue->Deref();
  188. for (auto& kv : mVirtualDecls)
  189. kv.mValue->Deref();
  190. for (auto& kv : mInnerMethods)
  191. kv.mValue->Deref();
  192. for (auto& kv : mMethodMap)
  193. kv.mValue->Deref();
  194. }
  195. template <typename TDict>
  196. static void DeleteUnused(TDict& dict)
  197. {
  198. auto itr = dict.begin();
  199. while (itr != dict.end())
  200. {
  201. auto val = itr->mValue;
  202. BF_ASSERT(val->mRefCount >= 1);
  203. if (val->mRefCount == 1)
  204. {
  205. val->Deref();
  206. itr = dict.Remove(itr);
  207. }
  208. else
  209. ++itr;
  210. }
  211. }
  212. template <typename TDict, typename TElement>
  213. static typename TDict::value_type AllocFromMap(TDict& dict, TElement* elem)
  214. {
  215. typename TDict::value_type* valuePtr;
  216. if (dict.TryAdd(elem, NULL, &valuePtr))
  217. {
  218. auto val = new typename std::remove_pointer<typename TDict::value_type>::type(elem);
  219. val->mRefCount++;
  220. *valuePtr = val;
  221. }
  222. return *valuePtr;
  223. }
  224. void BfCompiler::HotData::ClearUnused(bool isHotCompile)
  225. {
  226. BP_ZONE("BfCompiler::HotData::ClearUnused");
  227. DeleteUnused(mThisType);
  228. DeleteUnused(mAllocation);
  229. DeleteUnused(mDevirtualizedMethods);
  230. DeleteUnused(mVirtualDecls);
  231. DeleteUnused(mInnerMethods);
  232. if (isHotCompile)
  233. {
  234. // We need to keep all function pointer references ever, since we can't tell if we still reference them or not
  235. DeleteUnused(mFuncPtrs);
  236. }
  237. }
  238. BfHotThisType* BfCompiler::HotData::GetThisType(BfHotTypeVersion* hotVersion)
  239. {
  240. return AllocFromMap(mThisType, hotVersion);
  241. }
  242. BfHotAllocation* BfCompiler::HotData::GetAllocation(BfHotTypeVersion* hotVersion)
  243. {
  244. return AllocFromMap(mAllocation, hotVersion);
  245. }
  246. BfHotDevirtualizedMethod* BfCompiler::HotData::GetDevirtualizedMethod(BfHotMethod* hotMethod)
  247. {
  248. return AllocFromMap(mDevirtualizedMethods, hotMethod);
  249. }
  250. BfHotFunctionReference* BfCompiler::HotData::GetFunctionReference(BfHotMethod* hotMethod)
  251. {
  252. return AllocFromMap(mFuncPtrs, hotMethod);
  253. }
  254. BfHotInnerMethod* BfCompiler::HotData::GetInnerMethod(BfHotMethod* hotMethod)
  255. {
  256. return AllocFromMap(mInnerMethods, hotMethod);
  257. }
  258. BfHotVirtualDeclaration* BfCompiler::HotData::GetVirtualDeclaration(BfHotMethod* hotMethod)
  259. {
  260. return AllocFromMap(mVirtualDecls, hotMethod);
  261. }
  262. BfCompiler::HotState::~HotState()
  263. {
  264. }
  265. bool BfCompiler::HotState::HasPendingChanges(BfTypeInstance* type)
  266. {
  267. return (type->mHotTypeData != NULL) && (type->mHotTypeData->mPendingDataChange);
  268. }
  269. void BfCompiler::HotState::RemovePendingChanges(BfTypeInstance* type)
  270. {
  271. BF_ASSERT(type->mHotTypeData->mPendingDataChange);
  272. if (!type->mHotTypeData->mPendingDataChange)
  273. return;
  274. type->mHotTypeData->mPendingDataChange = false;
  275. bool didRemove = mPendingDataChanges.Remove(type->mTypeId);
  276. BF_ASSERT(didRemove);
  277. }
  278. BfCompiler::HotResolveData::~HotResolveData()
  279. {
  280. for (auto hotMethod : mActiveMethods)
  281. hotMethod->Deref();
  282. for (auto kv : mReachableMethods)
  283. kv.mKey->Deref();
  284. }
  285. //////////////////////////////////////////////////////////////////////////
  286. BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
  287. {
  288. //llvm::DebugFlag = true;
  289. memset(&mStats, 0, sizeof(mStats));
  290. mCompletionPct = 0;
  291. mCanceling = false;
  292. mIsResolveOnly = isResolveOnly;
  293. mResolvePassData = NULL;
  294. mPassInstance = NULL;
  295. mRevision = 0;
  296. mLastRevisionAborted = false;
  297. gBfCompiler = this;
  298. mSystem = bfSystem;
  299. mCurTypeId = 1;
  300. mTypeInitCount = 0;
  301. //mMaxInterfaceSlots = 16;
  302. mMaxInterfaceSlots = -1;
  303. mInterfaceSlotCountChanged = false;
  304. mHSPreserveIdx = 0;
  305. mCompileLogFP = NULL;
  306. mWantsDeferMethodDecls = false;
  307. mHadCancel = false;
  308. mCompileState = CompileState_None;
  309. //mMaxInterfaceSlots = 4;
  310. mContext = new BfContext(this);
  311. mHotData = NULL;
  312. mHotState = NULL;
  313. mHotResolveData = NULL;
  314. mArray1TypeDef = NULL;
  315. mArray2TypeDef = NULL;
  316. mArray3TypeDef = NULL;
  317. mArray4TypeDef = NULL;
  318. mSpanTypeDef = NULL;
  319. mAttributeTypeDef = NULL;
  320. mAttributeUsageAttributeTypeDef = NULL;
  321. mBfObjectTypeDef = NULL;
  322. mClassVDataTypeDef = NULL;
  323. mCLinkAttributeTypeDef = NULL;
  324. mCReprAttributeTypeDef = NULL;
  325. mNoDiscardAttributeTypeDef = NULL;
  326. mDisableObjectAccessChecksAttributeTypeDef = NULL;
  327. mDbgRawAllocDataTypeDef = NULL;
  328. mDeferredCallTypeDef = NULL;
  329. mDelegateTypeDef = NULL;
  330. mEnumTypeDef = NULL;
  331. mFriendAttributeTypeDef = NULL;
  332. mCheckedAttributeTypeDef = NULL;
  333. mUncheckedAttributeTypeDef = NULL;
  334. mFunctionTypeDef = NULL;
  335. mGCTypeDef = NULL;
  336. mGenericIEnumerableTypeDef = NULL;
  337. mGenericIEnumeratorTypeDef = NULL;
  338. mGenericIRefEnumeratorTypeDef = NULL;
  339. mInlineAttributeTypeDef = NULL;
  340. mInternalTypeDef = NULL;
  341. mIPrintableTypeDef = NULL;
  342. mLinkNameAttributeTypeDef = NULL;
  343. mMethodRefTypeDef = NULL;
  344. mNullableTypeDef = NULL;
  345. mOrderedAttributeTypeDef = NULL;
  346. mPointerTTypeDef = NULL;
  347. mPointerTypeDef = NULL;
  348. mReflectArrayType = NULL;
  349. mReflectFieldDataDef = NULL;
  350. mReflectFieldSplatDataDef = NULL;
  351. mReflectMethodDataDef = NULL;
  352. mReflectParamDataDef = NULL;
  353. mReflectPointerType = NULL;
  354. mReflectSizedArrayType = NULL;
  355. mReflectSpecializedGenericType = NULL;
  356. mReflectTypeInstanceTypeDef = NULL;
  357. mReflectUnspecializedGenericType = NULL;
  358. mSizedArrayTypeDef = NULL;
  359. mSkipAccessCheckAttributeTypeDef = NULL;
  360. mStaticInitAfterAttributeTypeDef = NULL;
  361. mStaticInitPriorityAttributeTypeDef = NULL;
  362. mStringTypeDef = NULL;
  363. mThreadStaticAttributeTypeDef = NULL;
  364. mTypeTypeDef = NULL;
  365. mUnboundAttributeTypeDef = NULL;
  366. mValueTypeTypeDef = NULL;
  367. mLastAutocompleteModule = NULL;
  368. }
  369. BfCompiler::~BfCompiler()
  370. {
  371. delete mContext;
  372. delete mHotData;
  373. delete mHotState;
  374. delete mHotResolveData;
  375. }
  376. bool BfCompiler::IsTypeAccessible(BfType* checkType, BfProject* curProject)
  377. {
  378. if (checkType->IsBoxed())
  379. return IsTypeAccessible(((BfBoxedType*)checkType)->mElementType, curProject);
  380. BfTypeInstance* typeInst = checkType->ToTypeInstance();
  381. if (typeInst != NULL)
  382. {
  383. if (checkType->IsTuple())
  384. {
  385. for (auto&& fieldInst : typeInst->mFieldInstances)
  386. {
  387. if (!IsTypeAccessible(fieldInst.mResolvedType, curProject))
  388. return false;
  389. }
  390. }
  391. auto genericTypeInst = typeInst->ToGenericTypeInstance();
  392. if (genericTypeInst != NULL)
  393. {
  394. for (auto genericArg : genericTypeInst->mTypeGenericArguments)
  395. if (!IsTypeAccessible(genericArg, curProject))
  396. return false;
  397. }
  398. return curProject->ContainsReference(typeInst->mTypeDef->mProject);
  399. }
  400. if (checkType->IsPointer())
  401. return IsTypeAccessible(((BfPointerType*)checkType)->mElementType, curProject);
  402. if (checkType->IsRef())
  403. return IsTypeAccessible(((BfPointerType*)checkType)->mElementType, curProject);
  404. return true;
  405. }
  406. bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject)
  407. {
  408. if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
  409. return IsTypeAccessible(checkType, curProject);
  410. BfTypeInstance* typeInst = checkType->ToTypeInstance();
  411. if (typeInst != NULL)
  412. {
  413. if ((typeInst->mTypeDef->mProject != NULL) && (typeInst->mTypeDef->mProject != curProject))
  414. {
  415. if (typeInst->mTypeDef->mProject->mTargetType == BfTargetType_BeefDynLib)
  416. return false;
  417. }
  418. if (checkType->IsInterface())
  419. return typeInst->mIsReified;
  420. //TODO: We could check to see if this project has any reified specialized instances...
  421. if (checkType->IsUnspecializedType())
  422. return typeInst->mIsReified;
  423. if (checkType->IsTuple())
  424. {
  425. for (auto&& fieldInst : typeInst->mFieldInstances)
  426. {
  427. if (!IsTypeUsed(fieldInst.mResolvedType, curProject))
  428. return false;
  429. }
  430. }
  431. auto genericTypeInst = typeInst->ToGenericTypeInstance();
  432. if (genericTypeInst != NULL)
  433. {
  434. for (auto genericArg : genericTypeInst->mTypeGenericArguments)
  435. if (!IsTypeUsed(genericArg, curProject))
  436. return false;
  437. }
  438. auto module = typeInst->GetModule();
  439. if (module == NULL)
  440. return true;
  441. return curProject->mUsedModules.Contains(module);
  442. }
  443. if (checkType->IsPointer())
  444. return IsTypeUsed(((BfPointerType*)checkType)->mElementType, curProject);
  445. if (checkType->IsRef())
  446. return IsTypeUsed(((BfPointerType*)checkType)->mElementType, curProject);
  447. return true;
  448. }
  449. bool BfCompiler::IsModuleAccessible(BfModule* module, BfProject* curProject)
  450. {
  451. for (auto checkType : module->mOwnedTypeInstances)
  452. {
  453. if (!IsTypeAccessible(checkType, curProject))
  454. return false;
  455. }
  456. return curProject->ContainsReference(module->mProject);
  457. }
  458. void BfCompiler::FixVDataHash(BfModule* bfModule)
  459. {
  460. // We recreate the actual vdata hash now that we're done creating new string literals
  461. /*for (auto context : mContexts)
  462. HASH128_MIXIN(bfModule->mDataHash, bfModule->mHighestUsedStringId);*/
  463. }
  464. void BfCompiler::CheckModuleStringRefs(BfModule* module, BfVDataModule* vdataModule, int lastModuleRevision, HashSet<int>& foundStringIds, HashSet<int>& dllNameSet, Array<BfMethodInstance*>& dllMethods, Array<BfCompiler::StringValueEntry>& stringValueEntries)
  465. {
  466. for (int stringId : module->mStringPoolRefs)
  467. {
  468. if (foundStringIds.Add(stringId))
  469. {
  470. BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId];
  471. if (IsHotCompile())
  472. {
  473. if (vdataModule->mDefinedStrings.Contains(stringId))
  474. continue;
  475. }
  476. StringValueEntry stringEntry;
  477. stringEntry.mId = stringId;
  478. vdataModule->mDefinedStrings.Add(stringId);
  479. stringEntry.mStringVal = vdataModule->CreateStringObjectValue(stringPoolEntry.mString, stringId, true);
  480. stringValueEntries.Add(stringEntry);
  481. CompileLog("String %d %s\n", stringId, stringPoolEntry.mString.c_str());
  482. }
  483. }
  484. for (auto dllNameId : module->mImportFileNames)
  485. dllNameSet.Add(dllNameId);
  486. for (auto& dllImportEntry : module->mDllImportEntries)
  487. dllMethods.push_back(dllImportEntry.mMethodInstance);
  488. auto altModule = module->mNextAltModule;
  489. while (altModule != NULL)
  490. {
  491. CheckModuleStringRefs(altModule, vdataModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
  492. altModule = altModule->mNextAltModule;
  493. }
  494. for (auto& specModulePair : module->mSpecializedMethodModules)
  495. CheckModuleStringRefs(specModulePair.mValue, vdataModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
  496. }
  497. void BfCompiler::HashModuleVData(BfModule* module, HashContext& vdataHash)
  498. {
  499. BP_ZONE("BfCompiler::HashModuleVData");
  500. if (module->mStringPoolRefs.size() > 0)
  501. {
  502. module->mStringPoolRefs.Sort([](int lhs, int rhs) { return lhs < rhs; });
  503. vdataHash.Mixin(&module->mStringPoolRefs[0], (int)module->mStringPoolRefs.size() * (int)sizeof(int));
  504. }
  505. if (module->mImportFileNames.size() > 0)
  506. {
  507. module->mImportFileNames.Sort([](int lhs, int rhs) { return lhs < rhs; });
  508. vdataHash.Mixin(&module->mImportFileNames[0], (int)module->mImportFileNames.size() * (int)sizeof(int));
  509. }
  510. auto altModule = module->mNextAltModule;
  511. while (altModule != NULL)
  512. {
  513. HashModuleVData(altModule, vdataHash);
  514. altModule = altModule->mNextAltModule;
  515. }
  516. for (auto& specModulePair : module->mSpecializedMethodModules)
  517. {
  518. HashModuleVData(specModulePair.mValue, vdataHash);
  519. }
  520. }
  521. BfIRFunction BfCompiler::CreateLoadSharedLibraries(BfVDataModule* bfModule, Array<BfMethodInstance*>& dllMethods)
  522. {
  523. BfIRType nullPtrType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
  524. BfIRType nullPtrPtrType = bfModule->mBfIRBuilder->MapType(bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)));
  525. BfIRType voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None));
  526. SmallVector<BfIRType, 2> paramTypes;
  527. auto loadSharedLibrariesFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
  528. auto loadSharedLibFunc = bfModule->mBfIRBuilder->CreateFunction(loadSharedLibrariesFuncType, BfIRLinkageType_External, "BfLoadSharedLibraries");
  529. bfModule->mBfIRBuilder->SetActiveFunction(loadSharedLibFunc);
  530. auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  531. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  532. HashSet<int> dllNameSet;
  533. auto internalType = bfModule->ResolveTypeDef(mInternalTypeDef);
  534. bfModule->PopulateType(internalType);
  535. auto getSharedProcAddressInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "GetSharedProcAddressInto");
  536. auto loadSharedLibraryProc = bfModule->GetMethodByName(internalType->ToTypeInstance(), "LoadSharedLibraryInto");
  537. BF_ASSERT(getSharedProcAddressInstance);
  538. BF_ASSERT(loadSharedLibraryProc);
  539. if (!getSharedProcAddressInstance)
  540. {
  541. bfModule->Fail("Missing Internal.GetSharedProcAddressInto");
  542. return loadSharedLibFunc;
  543. }
  544. if (!loadSharedLibraryProc)
  545. {
  546. bfModule->Fail("Missing Internal.LoadSharedLibraryInto");
  547. return loadSharedLibFunc;
  548. }
  549. Dictionary<int, BfIRValue> dllHandleMap;
  550. for (auto methodInstance : dllMethods)
  551. {
  552. auto typeInstance = methodInstance->GetOwner();
  553. auto methodDef = methodInstance->mMethodDef;
  554. BF_ASSERT(methodInstance->GetCustomAttributes() != NULL);
  555. for (auto customAttr : methodInstance->GetCustomAttributes()->mAttributes)
  556. {
  557. if (customAttr.mType->mTypeDef->mFullName.ToString() == "System.ImportAttribute")
  558. {
  559. bool doCLink = false;
  560. bool undecorated = false;
  561. BfCallingConvention callingConvention = methodDef->mCallingConvention;
  562. for (auto fieldSet : customAttr.mSetField)
  563. {
  564. BfFieldDef* fieldDef = fieldSet.mFieldRef;
  565. if (fieldDef->mName == "CLink")
  566. {
  567. auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
  568. if (constant != NULL)
  569. doCLink = constant->mBool;
  570. }
  571. if (fieldDef->mName == "Undecorated")
  572. {
  573. auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
  574. if (constant != NULL)
  575. undecorated = constant->mBool;
  576. }
  577. if (fieldDef->mName == "CallingConvention")
  578. {
  579. auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
  580. if (constant != NULL)
  581. {
  582. int callingConventionVal = (int)constant->mInt32;
  583. if ((callingConventionVal == 3) || (callingConventionVal == 1))
  584. callingConvention = BfCallingConvention_Stdcall;
  585. else if (callingConventionVal == 2)
  586. callingConvention = BfCallingConvention_Cdecl;
  587. }
  588. }
  589. }
  590. if (customAttr.mCtorArgs.size() == 1)
  591. {
  592. auto fileNameArg = customAttr.mCtorArgs[0];
  593. int strNum = 0;
  594. auto constant = typeInstance->mConstHolder->GetConstant(fileNameArg);
  595. if (constant != NULL)
  596. {
  597. if (constant->IsNull())
  598. continue; // Invalid
  599. strNum = constant->mInt32;
  600. }
  601. else
  602. {
  603. strNum = bfModule->GetStringPoolIdx(fileNameArg, typeInstance->mConstHolder);
  604. }
  605. BfIRValue dllHandleVar;
  606. if (!dllHandleMap.TryGetValue(strNum, &dllHandleVar))
  607. {
  608. String dllHandleName = StrFormat("bf_hs_preserve@dllHandle%d", strNum);
  609. dllHandleVar = bfModule->mBfIRBuilder->CreateGlobalVariable(nullPtrType, false, BfIRLinkageType_External,
  610. bfModule->GetDefaultValue(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)), dllHandleName);
  611. BfIRValue namePtr = bfModule->GetStringCharPtr(strNum);
  612. SmallVector<BfIRValue, 1> args;
  613. args.push_back(namePtr);
  614. args.push_back(dllHandleVar);
  615. BfIRValue dllHandleValue = bfModule->mBfIRBuilder->CreateCall(loadSharedLibraryProc.mFunc, args);
  616. dllHandleMap[strNum] = dllHandleVar;
  617. }
  618. String methodImportName;
  619. if (undecorated)
  620. {
  621. methodImportName = methodInstance->mMethodDef->mName;
  622. }
  623. else if (doCLink)
  624. {
  625. methodImportName = methodInstance->mMethodDef->mName;
  626. if ((mSystem->mPtrSize == 4) && (callingConvention == BfCallingConvention_Stdcall))
  627. {
  628. int argSize = (int)methodDef->mParams.size() * mSystem->mPtrSize;
  629. methodImportName = StrFormat("_%s$%d", methodImportName.c_str(), argSize);
  630. }
  631. }
  632. else
  633. BfMangler::Mangle(methodImportName, GetMangleKind(), methodInstance);
  634. BfIRValue methodNameValue = bfModule->mBfIRBuilder->CreateGlobalStringPtr(methodImportName);
  635. //auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
  636. //auto globalVarPtr = bfModule->mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, nullPtrPtrType);
  637. auto func = bfModule->CreateDllImportGlobalVar(methodInstance, false);
  638. auto globalVarPtr = bfModule->mBfIRBuilder->CreateBitCast(func, nullPtrPtrType);
  639. BfSizedVector<BfIRValue, 2> args;
  640. args.push_back(bfModule->mBfIRBuilder->CreateLoad(dllHandleVar));
  641. args.push_back(methodNameValue);
  642. args.push_back(globalVarPtr);
  643. BfIRValue dllFuncValVoidPtr = bfModule->mBfIRBuilder->CreateCall(getSharedProcAddressInstance.mFunc, args);
  644. }
  645. }
  646. }
  647. }
  648. bfModule->mBfIRBuilder->CreateRetVoid();
  649. return loadSharedLibFunc;
  650. }
  651. void BfCompiler::GetTestMethods(BfVDataModule* bfModule, Array<TestMethod>& testMethods, HashContext& vdataHashCtx)
  652. {
  653. vdataHashCtx.Mixin(0xBEEF0001); // Marker
  654. auto _CheckMethod = [&](BfTypeInstance* typeInstance, BfMethodInstance* methodInstance)
  655. {
  656. auto project = typeInstance->mTypeDef->mProject;
  657. if (project->mTargetType != BfTargetType_BeefTest)
  658. return;
  659. if (project != bfModule->mProject)
  660. return;
  661. bool isTest = false;
  662. if ((methodInstance->GetCustomAttributes() != NULL) &&
  663. (methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
  664. isTest = true;
  665. if (!isTest)
  666. return;
  667. if (!methodInstance->mMethodDef->mIsStatic)
  668. {
  669. bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it is not static", bfModule->MethodToString(methodInstance).c_str()),
  670. methodInstance->mMethodDef->GetRefNode());
  671. bfModule->mHadBuildError = true;
  672. return;
  673. }
  674. if (methodInstance->GetParamCount() > 0)
  675. {
  676. if ((methodInstance->GetParamInitializer(0) == NULL) &&
  677. (methodInstance->GetParamKind(0) != BfParamKind_Params))
  678. {
  679. bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it contains parameters without defaults", bfModule->MethodToString(methodInstance).c_str()),
  680. methodInstance->mMethodDef->GetRefNode());
  681. bfModule->mHadBuildError = true;
  682. return;
  683. }
  684. }
  685. BF_ASSERT(typeInstance->IsReified());
  686. TestMethod testMethod;
  687. testMethod.mMethodInstance = methodInstance;
  688. testMethods.Add(testMethod);
  689. if (!bfModule->mProject->mUsedModules.Contains(typeInstance->mModule))
  690. bfModule->mProject->mUsedModules.Add(typeInstance->mModule);
  691. vdataHashCtx.Mixin(methodInstance->GetOwner()->mTypeId);
  692. vdataHashCtx.Mixin(methodInstance->mMethodDef->mIdx);
  693. };
  694. for (auto type : mContext->mResolvedTypes)
  695. {
  696. auto typeInstance = type->ToTypeInstance();
  697. if (typeInstance == NULL)
  698. continue;
  699. for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
  700. {
  701. if (methodInstanceGroup.mDefault != NULL)
  702. {
  703. _CheckMethod(typeInstance, methodInstanceGroup.mDefault);
  704. }
  705. }
  706. }
  707. }
  708. void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& testMethods, BfIRValue& retValue)
  709. {
  710. for (auto& testMethod : testMethods)
  711. {
  712. auto methodInstance = testMethod.mMethodInstance;
  713. auto typeInstance = methodInstance->GetOwner();
  714. testMethod.mName += bfModule->TypeToString(typeInstance);
  715. testMethod.mName += ".";
  716. testMethod.mName += methodInstance->mMethodDef->mName;
  717. testMethod.mName += "\t";
  718. auto testAttribute = methodInstance->GetCustomAttributes()->Get(mTestAttributeTypeDef);
  719. for (auto& field : testAttribute->mSetField)
  720. {
  721. auto constant = typeInstance->mConstHolder->GetConstant(field.mParam.mValue);
  722. if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean) && (constant->mBool))
  723. {
  724. BfFieldDef* fieldDef = field.mFieldRef;
  725. if (fieldDef->mName == "ShouldFail")
  726. {
  727. testMethod.mName += "Sf";
  728. }
  729. else if (fieldDef->mName == "Profile")
  730. {
  731. testMethod.mName += "Pr";
  732. }
  733. else if (fieldDef->mName == "Ignore")
  734. {
  735. testMethod.mName += "Ig";
  736. }
  737. }
  738. }
  739. bfModule->UpdateSrcPos(methodInstance->mMethodDef->GetRefNode(), (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
  740. testMethod.mName += StrFormat("\t%s\t%d\t%d", bfModule->mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), bfModule->mCurFilePosition.mCurLine, bfModule->mCurFilePosition.mCurColumn);
  741. }
  742. std::stable_sort(testMethods.begin(), testMethods.end(),
  743. [](const TestMethod& lhs, const TestMethod& rhs)
  744. {
  745. return lhs.mName < rhs.mName;
  746. });
  747. String methodData;
  748. for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
  749. {
  750. String& methodName = testMethods[methodIdx].mName;
  751. if (!methodData.IsEmpty())
  752. methodData += "\n";
  753. methodData += methodName;
  754. }
  755. //////////////////////////////////////////////////////////////////////////
  756. auto testInitMethod = bfModule->GetInternalMethod("Test_Init");
  757. auto testQueryMethod = bfModule->GetInternalMethod("Test_Query");
  758. auto testFinishMethod = bfModule->GetInternalMethod("Test_Finish");
  759. auto char8PtrType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Char8));
  760. BfIRType strCharType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)methodData.length() + 1);
  761. BfIRValue strConstant = bfModule->mBfIRBuilder->CreateConstString(methodData);
  762. BfIRValue gv = bfModule->mBfIRBuilder->CreateGlobalVariable(strCharType,
  763. true, BfIRLinkageType_External,
  764. strConstant, "__bfTestData");
  765. BfIRValue strPtrVal = bfModule->mBfIRBuilder->CreateBitCast(gv, bfModule->mBfIRBuilder->MapType(char8PtrType));
  766. SizedArray<BfIRValue, 4> irArgs;
  767. irArgs.Add(strPtrVal);
  768. bfModule->mBfIRBuilder->CreateCall(testInitMethod.mFunc, irArgs);
  769. BfIRBlock testHeadBlock = bfModule->mBfIRBuilder->CreateBlock("testHead");
  770. BfIRBlock testEndBlock = bfModule->mBfIRBuilder->CreateBlock("testEnd");
  771. bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
  772. bfModule->mBfIRBuilder->AddBlock(testHeadBlock);
  773. bfModule->mBfIRBuilder->SetInsertPoint(testHeadBlock);
  774. irArgs.clear();
  775. auto testVal = bfModule->mBfIRBuilder->CreateCall(testQueryMethod.mFunc, irArgs);
  776. auto switchVal = bfModule->mBfIRBuilder->CreateSwitch(testVal, testEndBlock, (int)testMethods.size());
  777. for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
  778. {
  779. auto methodInstance = testMethods[methodIdx].mMethodInstance;
  780. String& methodName = testMethods[methodIdx].mName;
  781. auto testBlock = bfModule->mBfIRBuilder->CreateBlock(StrFormat("test%d", methodIdx));
  782. bfModule->mBfIRBuilder->AddSwitchCase(switchVal, bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodIdx), testBlock);
  783. bfModule->mBfIRBuilder->AddBlock(testBlock);
  784. bfModule->mBfIRBuilder->SetInsertPoint(testBlock);
  785. auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
  786. irArgs.clear();
  787. if (methodInstance->GetParamCount() > 0)
  788. {
  789. if (methodInstance->GetParamKind(0) == BfParamKind_Params)
  790. {
  791. auto paramType = methodInstance->GetParamType(0);
  792. auto paramTypeInst = paramType->ToTypeInstance();
  793. BfTypedValue paramVal = BfTypedValue(bfModule->mBfIRBuilder->CreateAlloca(bfModule->mBfIRBuilder->MapTypeInst(paramTypeInst)), paramType);
  794. bfModule->InitTypeInst(paramVal, NULL, false, BfIRValue());
  795. //TODO: Assert 'length' var is at slot 1
  796. auto arrayBits = bfModule->mBfIRBuilder->CreateBitCast(paramVal.mValue, bfModule->mBfIRBuilder->MapType(paramTypeInst->mBaseType));
  797. auto addr = bfModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1);
  798. auto storeInst = bfModule->mBfIRBuilder->CreateAlignedStore(bfModule->GetConstValue(0), addr, 4);
  799. irArgs.Add(paramVal.mValue);
  800. }
  801. else
  802. {
  803. for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++)
  804. {
  805. irArgs.Add(methodInstance->mDefaultValues[defaultIdx]);
  806. }
  807. }
  808. }
  809. BfExprEvaluator exprEvaluator(bfModule);
  810. exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
  811. bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
  812. }
  813. bfModule->mBfIRBuilder->AddBlock(testEndBlock);
  814. bfModule->mBfIRBuilder->SetInsertPoint(testEndBlock);
  815. irArgs.clear();
  816. bfModule->mBfIRBuilder->CreateCall(testFinishMethod.mFunc, irArgs);
  817. retValue = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
  818. }
  819. void BfCompiler::CreateVData(BfVDataModule* bfModule)
  820. {
  821. bool isHotCompile = IsHotCompile();
  822. if ((isHotCompile) && (bfModule->mProject != mOptions.mHotProject))
  823. return;
  824. BP_ZONE("BfCompiler::CreateVData");
  825. BfLogSysM("CreateVData %s\n", bfModule->mProject->mName.c_str());
  826. CompileLog("CreateVData %s\n", bfModule->mProject->mName.c_str());
  827. bfModule->mProject->mUsedModules.Add(bfModule);
  828. auto project = bfModule->mProject;
  829. auto vdataContext = bfModule->mContext;
  830. BF_ASSERT(bfModule->mModuleName == "vdata");
  831. //////////////////////////////////////////////////////////////////////////
  832. // Create types we'll need for vdata, so we won't change the vdata hash afterward
  833. bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
  834. ///
  835. auto typeDefType = bfModule->ResolveTypeDef(mTypeTypeDef)->ToTypeInstance();
  836. if (!typeDefType)
  837. return;
  838. BF_ASSERT(typeDefType != NULL);
  839. vdataContext->mBfTypeType = typeDefType->ToTypeInstance();
  840. auto typeInstanceDefType = bfModule->ResolveTypeDef(mReflectTypeInstanceTypeDef);
  841. if (!typeInstanceDefType)
  842. return;
  843. auto typeInstanceDefTypeInstance = typeInstanceDefType->ToTypeInstance();
  844. auto typeDef = mSystem->FindTypeDef("System.ClassVData");
  845. BF_ASSERT(typeDef != NULL);
  846. auto bfClassVDataType = bfModule->ResolveTypeDef(typeDef)->ToTypeInstance();
  847. vdataContext->mBfClassVDataPtrType = bfModule->CreatePointerType(bfClassVDataType);
  848. //////////////////////////////////////////////////////////////////////////
  849. int numEntries = 0;
  850. int numConcreteTypes = 0;
  851. Array<BfType*> orderedTypes;
  852. for (auto type : mContext->mResolvedTypes)
  853. {
  854. numEntries++;
  855. BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
  856. if (!type->IsReified())
  857. continue;
  858. orderedTypes.Add(type);
  859. CompileLog("TypeId:%d %s\n", type->mTypeId, bfModule->TypeToString(type).c_str());
  860. if ((type != NULL) && (type->IsObjectOrInterface()))
  861. {
  862. numConcreteTypes++;
  863. auto typeInst = type->ToTypeInstance();
  864. if (typeInst->mModule == NULL)
  865. {
  866. BF_ASSERT(mPassInstance->HasFailed());
  867. continue;
  868. }
  869. }
  870. }
  871. {
  872. BP_ZONE("BfCompiler::CreateVData sort orderedTypes");
  873. orderedTypes.Sort([](BfType* lhs, BfType* rhs)
  874. {
  875. return lhs->mTypeId < rhs->mTypeId;
  876. });
  877. }
  878. BfLogSysM("TypeEntries: %d ConcreteTypes: %d\n", numEntries, numConcreteTypes);
  879. HashContext vdataHashCtx;
  880. //vdataHashCtx.mDbgViz = true;
  881. vdataHashCtx.Mixin(bfModule->mProject->mVDataConfigHash);
  882. Array<TestMethod> testMethods;
  883. if (project->mTargetType == BfTargetType_BeefTest)
  884. GetTestMethods(bfModule, testMethods, vdataHashCtx);
  885. Array<BfType*> vdataTypeList;
  886. std::multimap<String, BfTypeInstance*> sortedStaticInitMap;
  887. std::multimap<String, BfTypeInstance*> sortedStaticDtorMap;
  888. std::multimap<String, BfTypeInstance*> sortedStaticMarkMap;
  889. std::multimap<String, BfTypeInstance*> sortedStaticTLSMap;
  890. HashSet<BfModule*> usedModuleSet;
  891. vdataHashCtx.MixinStr(project->mStartupObject);
  892. vdataHashCtx.Mixin(project->mTargetType);
  893. for (auto type : orderedTypes)
  894. {
  895. if ((type == NULL) /*|| (type->IsUnspecializedType()*/)
  896. continue;
  897. if (type->IsTemporary())
  898. continue;
  899. if ((type->IsGenericParam()) || (type->IsUnspecializedTypeVariation()))
  900. continue;
  901. auto typeInst = type->ToTypeInstance();
  902. if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
  903. continue;
  904. if (!IsTypeUsed(type, project))
  905. continue;
  906. vdataTypeList.push_back(type);
  907. vdataHashCtx.Mixin(type->mTypeId);
  908. BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
  909. if ((type != NULL) && (typeInst != NULL))
  910. {
  911. auto module = typeInst->mModule;
  912. if (module == NULL)
  913. continue;
  914. if (type->IsInterface())
  915. vdataHashCtx.Mixin(typeInst->mSlotNum);
  916. if (!module->mIsScratchModule)
  917. {
  918. BF_ASSERT(module->mIsReified);
  919. if (usedModuleSet.Add(module))
  920. {
  921. CompileLog("UsedModule %p %s\n", module, module->mModuleName.c_str());
  922. HashModuleVData(module, vdataHashCtx);
  923. }
  924. }
  925. vdataHashCtx.Mixin(typeInst->mTypeDef->mSignatureHash);
  926. for (auto iface : typeInst->mInterfaces)
  927. {
  928. vdataHashCtx.Mixin(iface.mInterfaceType->mTypeId);
  929. vdataHashCtx.Mixin(iface.mDeclaringType->mTypeCode);
  930. vdataHashCtx.Mixin(iface.mDeclaringType->mProject);
  931. }
  932. if (!typeInst->IsUnspecializedType())
  933. {
  934. for (auto& methodInstGroup : typeInst->mMethodInstanceGroups)
  935. {
  936. bool isImplementedAndReified = (methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) &&
  937. (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mIsUnspecialized);
  938. vdataHashCtx.Mixin(isImplementedAndReified);
  939. }
  940. }
  941. // Could be necessary if a base type in another project adds new virtual methods (for example)
  942. auto baseType = typeInst->mBaseType;
  943. while (baseType != NULL)
  944. {
  945. vdataHashCtx.Mixin(baseType->mTypeDef->mSignatureHash);
  946. baseType = baseType->mBaseType;
  947. }
  948. if (module->mProject != bfModule->mProject)
  949. {
  950. if ((module->mProject != NULL) && (module->mProject->mTargetType == BfTargetType_BeefDynLib))
  951. continue;
  952. }
  953. if (typeInst->mHasStaticInitMethod)
  954. sortedStaticInitMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
  955. else if (typeInst->mHasStaticDtorMethod) // Only store types not already in the static init map
  956. sortedStaticDtorMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
  957. if ((typeInst->mHasStaticMarkMethod) && (mOptions.mEnableRealtimeLeakCheck))
  958. sortedStaticMarkMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
  959. if ((typeInst->mHasTLSFindMethod) && (mOptions.mEnableRealtimeLeakCheck))
  960. sortedStaticTLSMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
  961. }
  962. }
  963. int lastModuleRevision = bfModule->mRevision;
  964. Val128 vdataHash = vdataHashCtx.Finish128();
  965. bool wantsRebuild = vdataHash != bfModule->mDataHash;
  966. if (bfModule->mHadBuildError)
  967. wantsRebuild = true;
  968. // If we did one of those 'hot compile' partial vdata builds, now build the whole thing
  969. if ((!IsHotCompile()) && (bfModule->mHadHotObjectWrites))
  970. wantsRebuild = true;
  971. if (mOptions.mHotProject != NULL)
  972. {
  973. HashContext vdataHashCtxEx;
  974. vdataHashCtxEx.Mixin(mOptions.mHotProject->mName);
  975. vdataHashCtxEx.Mixin((int)mHotState->mNewlySlottedTypeIds.size());
  976. for (auto typeId : mHotState->mNewlySlottedTypeIds)
  977. vdataHashCtxEx.Mixin(typeId);
  978. vdataHashCtxEx.Mixin((int)mHotState->mSlotDefineTypeIds.size());
  979. for (auto typeId : mHotState->mSlotDefineTypeIds)
  980. vdataHashCtxEx.Mixin(typeId);
  981. Val128 vdataHashEx = vdataHashCtxEx.Finish128();
  982. if (mHotState->mVDataHashEx.IsZero())
  983. {
  984. if (!mHotState->mNewlySlottedTypeIds.IsEmpty())
  985. wantsRebuild = true;
  986. if (!mHotState->mSlotDefineTypeIds.IsEmpty())
  987. wantsRebuild = true;
  988. }
  989. else
  990. {
  991. if (vdataHashEx != mHotState->mVDataHashEx)
  992. wantsRebuild = true;
  993. }
  994. mHotState->mVDataHashEx = vdataHashEx;
  995. }
  996. if ((wantsRebuild) || (bfModule->mIsModuleMutable))
  997. {
  998. bfModule->StartNewRevision();
  999. if (bfModule->mAwaitingInitFinish)
  1000. bfModule->FinishInit();
  1001. }
  1002. // We add the string hash into vdata hash later
  1003. bfModule->mDataHash = vdataHash;//vdataPreStringHash;
  1004. // This handles "no StartNewRevision" 'else' case, but also handles if vdata failed to complete from a previous compilation
  1005. if (!bfModule->mIsModuleMutable)
  1006. {
  1007. CompileLog("VData unchanged, skipping\n");
  1008. return;
  1009. }
  1010. BfTypeInstance* stringType = bfModule->ResolveTypeDef(mStringTypeDef, BfPopulateType_Data)->ToTypeInstance();
  1011. BfTypeInstance* reflectSpecializedTypeInstance = bfModule->ResolveTypeDef(mReflectSpecializedGenericType)->ToTypeInstance();
  1012. BfTypeInstance* reflectUnspecializedTypeInstance = bfModule->ResolveTypeDef(mReflectUnspecializedGenericType)->ToTypeInstance();
  1013. BfTypeInstance* reflectArrayTypeInstance = bfModule->ResolveTypeDef(mReflectArrayType)->ToTypeInstance();
  1014. bool madeBfTypeData = false;
  1015. bool needsTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
  1016. bool needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType");
  1017. bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName");
  1018. bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern"));
  1019. Dictionary<int, int> usedStringIdMap;
  1020. HashSet<BfType*> reflectTypeSet;
  1021. reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
  1022. reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
  1023. reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
  1024. reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
  1025. SmallVector<BfIRValue, 256> typeDataVector;
  1026. for (auto type : vdataTypeList)
  1027. {
  1028. if (type->IsTypeAlias())
  1029. continue;
  1030. if (type->IsTypeInstance())
  1031. BF_ASSERT(!type->IsIncomplete());
  1032. auto typeInst = type->ToTypeInstance();
  1033. if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
  1034. continue;
  1035. bool needsTypeData = (needsTypeList) || ((type->IsObject()) && (needsObjectTypeData));
  1036. bool forceReflectFields = false;
  1037. if (bfModule->mProject->mReferencedTypeData.Contains(type))
  1038. {
  1039. needsTypeData = true;
  1040. if (type->IsEnum())
  1041. forceReflectFields = true;
  1042. }
  1043. bool needsVData = (type->IsObject()) && (typeInst->mHasBeenInstantiated);
  1044. BfIRValue typeVariable;
  1045. if ((needsTypeData) || (needsVData))
  1046. {
  1047. if (reflectTypeSet.Contains(type))
  1048. {
  1049. needsTypeData = true;
  1050. needsVData = true;
  1051. }
  1052. typeVariable = bfModule->CreateTypeData(type, usedStringIdMap, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
  1053. }
  1054. type->mDirty = false;
  1055. if (needsTypeList)
  1056. {
  1057. int typeId = type->mTypeId;
  1058. if (typeId == -1)
  1059. continue;
  1060. if (typeId >= (int)typeDataVector.size())
  1061. typeDataVector.resize(typeId + 1);
  1062. typeDataVector[typeId] = typeVariable;
  1063. }
  1064. }
  1065. for (int typeId = 0; typeId < (int)typeDataVector.size(); typeId++)
  1066. {
  1067. if (!typeDataVector[typeId])
  1068. typeDataVector[typeId] = bfModule->GetDefaultValue(typeDefType);
  1069. }
  1070. // We only need 'sTypes' if we actually reference it
  1071. //
  1072. {
  1073. auto typeDefPtrType = bfModule->CreatePointerType(typeDefType);
  1074. StringT<128> typesVariableName;
  1075. BfMangler::MangleStaticFieldName(typesVariableName, GetMangleKind(), typeDefType->ToTypeInstance(), "sTypes", typeDefPtrType);
  1076. auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(typeDefType), (int)typeDataVector.size());
  1077. auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, typeDataVector);
  1078. BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_External,
  1079. typeDataConst, typesVariableName);
  1080. }
  1081. HashSet<int> foundStringIds;
  1082. for (int stringId : bfModule->mStringPoolRefs)
  1083. foundStringIds.Add(stringId);
  1084. Array<BfModule*> orderedUsedModules;
  1085. for (auto module : usedModuleSet)
  1086. orderedUsedModules.push_back(module);
  1087. std::sort(orderedUsedModules.begin(), orderedUsedModules.end(), [] (BfModule* lhs, BfModule* rhs)
  1088. {
  1089. return lhs->mModuleName < rhs->mModuleName;
  1090. });
  1091. Array<BfMethodInstance*> dllMethods;
  1092. Array<BfIRValue> forceLinkValues;
  1093. HashSet<int> dllNameSet;
  1094. Array<BfCompiler::StringValueEntry> stringValueEntries;
  1095. for (auto module : orderedUsedModules)
  1096. {
  1097. CheckModuleStringRefs(module, bfModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
  1098. if ((module->mHasForceLinkMarker) &&
  1099. ((!isHotCompile) || (module->mHadHotObjectWrites)))
  1100. forceLinkValues.Add(bfModule->CreateForceLinkMarker(module, NULL));
  1101. }
  1102. if (!forceLinkValues.IsEmpty())
  1103. {
  1104. auto elemType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Int8));
  1105. auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(elemType), (int)forceLinkValues.size());
  1106. auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, forceLinkValues);
  1107. BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_Internal,
  1108. typeDataConst, "FORCELINK_MODULES");
  1109. }
  1110. // Generate strings array
  1111. {
  1112. if (!needsStringLiteralList)
  1113. {
  1114. stringValueEntries.Clear();
  1115. }
  1116. std::sort(stringValueEntries.begin(), stringValueEntries.end(),
  1117. [](const StringValueEntry& lhs, const StringValueEntry& rhs)
  1118. {
  1119. return lhs.mId < rhs.mId;
  1120. });
  1121. auto stringPtrType = bfModule->CreatePointerType(stringType);
  1122. auto stringPtrIRType = bfModule->mBfIRBuilder->MapTypeInstPtr(stringType);
  1123. StringT<128> stringsVariableName;
  1124. BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sStringLiterals", stringPtrType);
  1125. Array<BfIRValue> stringList;
  1126. stringList.Add(bfModule->mBfIRBuilder->CreateConstNull(stringPtrIRType));
  1127. for (auto& stringValueEntry : stringValueEntries)
  1128. stringList.Add(stringValueEntry.mStringVal);
  1129. stringList.Add(bfModule->mBfIRBuilder->CreateConstNull(stringPtrIRType));
  1130. BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)stringList.size());
  1131. auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
  1132. auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
  1133. if (bfModule->mBfIRBuilder->DbgHasInfo())
  1134. {
  1135. auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size());
  1136. bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar);
  1137. }
  1138. }
  1139. // Generate string ID array
  1140. {
  1141. auto stringType = bfModule->ResolveTypeDef(mStringTypeDef, BfPopulateType_Data)->ToTypeInstance();
  1142. auto stringPtrType = bfModule->CreatePointerType(stringType);
  1143. auto stringPtrIRType = bfModule->mBfIRBuilder->MapTypeInstPtr(stringType);
  1144. StringT<128> stringsVariableName;
  1145. BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType);
  1146. Array<BfIRValue> stringList;
  1147. stringList.Resize(usedStringIdMap.size());
  1148. for (auto& kv : usedStringIdMap)
  1149. {
  1150. stringList[kv.mValue] = bfModule->mStringObjectPool[kv.mKey];
  1151. }
  1152. BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)usedStringIdMap.size());
  1153. auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
  1154. auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
  1155. if (bfModule->mBfIRBuilder->DbgHasInfo())
  1156. {
  1157. auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size());
  1158. bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar);
  1159. }
  1160. }
  1161. BfIRFunction loadSharedLibFunc = CreateLoadSharedLibraries(bfModule, dllMethods);
  1162. BfIRType nullPtrType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
  1163. BfIRType voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None));
  1164. BfIRType int32Type = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_Int32));
  1165. struct _StaticInitEntry
  1166. {
  1167. int mPriority;
  1168. BfTypeInstance* mTypeInstance;
  1169. };
  1170. Array<_StaticInitEntry> staticInitList;
  1171. // Populate staticInitList
  1172. {
  1173. Dictionary<int, BfTypeInstance*> pendingIDToInstanceMap;
  1174. HashSet<BfTypeInstance*> handledTypes;
  1175. BfType* staticInitPriorityAttributeType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStaticInitPriorityAttributeTypeDef);
  1176. BfType* staticInitAfterAttributeType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStaticInitAfterAttributeTypeDef);
  1177. bool forceAdd = false;
  1178. for (int pass = 0; true; pass++)
  1179. {
  1180. bool hadAdd = false;
  1181. for (auto& mapEntry : sortedStaticInitMap)
  1182. {
  1183. auto typeInst = mapEntry.second;
  1184. if ((typeInst != NULL) && (!typeInst->IsUnspecializedType()) && (typeInst->mHasStaticInitMethod))
  1185. {
  1186. if (pass == 0)
  1187. {
  1188. int priority = 0;
  1189. bool hadInitAfterAttribute = false;
  1190. if (typeInst->mCustomAttributes != NULL)
  1191. {
  1192. for (auto& customAttr : typeInst->mCustomAttributes->mAttributes)
  1193. {
  1194. if (customAttr.mType == staticInitAfterAttributeType)
  1195. hadInitAfterAttribute = true;
  1196. if (customAttr.mType == staticInitPriorityAttributeType)
  1197. {
  1198. if (customAttr.mCtorArgs.size() == 1)
  1199. {
  1200. auto constant = typeInst->mConstHolder->GetConstant(customAttr.mCtorArgs[0]);
  1201. if (constant != NULL)
  1202. priority = constant->mInt32;
  1203. }
  1204. }
  1205. }
  1206. }
  1207. if (!hadInitAfterAttribute)
  1208. {
  1209. staticInitList.push_back({ priority, typeInst });
  1210. mapEntry.second = NULL;
  1211. }
  1212. else
  1213. {
  1214. pendingIDToInstanceMap.TryAdd(typeInst->mTypeId, typeInst);
  1215. }
  1216. }
  1217. else
  1218. {
  1219. if (pendingIDToInstanceMap.ContainsKey(typeInst->mTypeId))
  1220. {
  1221. bool doAdd = true;
  1222. if (!forceAdd)
  1223. {
  1224. for (auto& customAttr : typeInst->mCustomAttributes->mAttributes)
  1225. {
  1226. if (customAttr.mType == staticInitAfterAttributeType)
  1227. {
  1228. if (customAttr.mCtorArgs.size() == 0)
  1229. {
  1230. doAdd = false;
  1231. }
  1232. else
  1233. {
  1234. auto ctorArg = customAttr.mCtorArgs[0];
  1235. auto constant = typeInst->mConstHolder->GetConstant(ctorArg);
  1236. if (constant != NULL)
  1237. {
  1238. int refTypeId = constant->mInt32;
  1239. if (pendingIDToInstanceMap.ContainsKey(refTypeId))
  1240. doAdd = false;
  1241. }
  1242. }
  1243. }
  1244. }
  1245. }
  1246. if (doAdd)
  1247. {
  1248. staticInitList.push_back({ 0, typeInst });
  1249. pendingIDToInstanceMap.Remove(typeInst->mTypeId);
  1250. hadAdd = true;
  1251. }
  1252. }
  1253. }
  1254. }
  1255. }
  1256. if (pass == 0)
  1257. {
  1258. std::sort(staticInitList.begin(), staticInitList.end(),
  1259. [](const _StaticInitEntry& lhs, const _StaticInitEntry& rhs)
  1260. {
  1261. return lhs.mPriority > rhs.mPriority;
  1262. });
  1263. }
  1264. if ((pass > 0) && (!hadAdd) && (pendingIDToInstanceMap.size() > 0)) // Circular ref?
  1265. forceAdd = true;
  1266. if (pendingIDToInstanceMap.size() == 0)
  1267. break;
  1268. }
  1269. }
  1270. // We want to call DTORS in reverse order from CTORS
  1271. Array<BfTypeInstance*> dtorList;
  1272. for (intptr idx = staticInitList.size() - 1; idx >= 0; idx--)
  1273. {
  1274. auto typeInst = staticInitList[idx].mTypeInstance;
  1275. if (typeInst->mHasStaticDtorMethod)
  1276. {
  1277. dtorList.push_back(typeInst);
  1278. }
  1279. }
  1280. for (auto itr = sortedStaticDtorMap.rbegin(); itr != sortedStaticDtorMap.rend(); itr++)
  1281. {
  1282. auto typeInst = itr->second;
  1283. dtorList.push_back(typeInst);
  1284. }
  1285. /// Generate "BfCallAllStaticDtors"
  1286. BfIRFunction dtorFunc;
  1287. {
  1288. SmallVector<BfIRType, 2> paramTypes;
  1289. auto dtorFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
  1290. dtorFunc = bfModule->mBfIRBuilder->CreateFunction(dtorFuncType, BfIRLinkageType_External, "BfCallAllStaticDtors");
  1291. bfModule->mBfIRBuilder->SetActiveFunction(dtorFunc);
  1292. auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  1293. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  1294. for (auto typeInst : dtorList)
  1295. {
  1296. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  1297. {
  1298. auto methodInstance = methodGroup.mDefault;
  1299. if ((methodInstance != NULL) &&
  1300. (methodInstance->mMethodDef->mIsStatic) &&
  1301. (methodInstance->mMethodDef->mMethodType == BfMethodType_Dtor) &&
  1302. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  1303. {
  1304. if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
  1305. continue;
  1306. if (methodInstance->mHotMethod != NULL)
  1307. methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
  1308. auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
  1309. bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
  1310. }
  1311. }
  1312. }
  1313. bfModule->mBfIRBuilder->CreateRetVoid();
  1314. }
  1315. // Generate "main"
  1316. if (!IsHotCompile())
  1317. {
  1318. BfIRFunctionType mainFuncType;
  1319. BfIRFunction mainFunc;
  1320. if ((project->mTargetType == BfTargetType_BeefConsoleApplication) || (project->mTargetType == BfTargetType_BeefTest))
  1321. {
  1322. SmallVector<BfIRType, 2> paramTypes;
  1323. paramTypes.push_back(int32Type);
  1324. paramTypes.push_back(nullPtrType);
  1325. mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
  1326. mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "main");
  1327. }
  1328. else if (project->mTargetType == BfTargetType_BeefDynLib)
  1329. {
  1330. SmallVector<BfIRType, 4> paramTypes;
  1331. paramTypes.push_back(nullPtrType); // hinstDLL
  1332. paramTypes.push_back(int32Type); // fdwReason
  1333. paramTypes.push_back(nullPtrType); // lpvReserved
  1334. mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
  1335. mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "DllMain");
  1336. if (mSystem->mPtrSize == 4)
  1337. bfModule->mBfIRBuilder->SetFuncCallingConv(mainFunc, BfIRCallingConv_StdCall);
  1338. }
  1339. else if (project->mTargetType == BfTargetType_BeefWindowsApplication)
  1340. {
  1341. SmallVector<BfIRType, 4> paramTypes;
  1342. paramTypes.push_back(nullPtrType); // hInstance
  1343. paramTypes.push_back(nullPtrType); // hPrevInstance
  1344. paramTypes.push_back(nullPtrType); // lpCmdLine
  1345. paramTypes.push_back(int32Type); // nCmdShow
  1346. mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
  1347. mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "WinMain");
  1348. if (mSystem->mPtrSize == 4)
  1349. bfModule->mBfIRBuilder->SetFuncCallingConv(mainFunc, BfIRCallingConv_StdCall);
  1350. }
  1351. else
  1352. {
  1353. SmallVector<BfIRType, 2> paramTypes;
  1354. paramTypes.push_back(int32Type);
  1355. paramTypes.push_back(nullPtrType);
  1356. mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
  1357. mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "BeefMain");
  1358. }
  1359. bfModule->mBfIRBuilder->SetActiveFunction(mainFunc);
  1360. auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  1361. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  1362. #ifndef BF_PLATFORM_WINDOWS
  1363. {
  1364. SmallVector<BfIRType, 2> paramTypes;
  1365. paramTypes.push_back(int32Type);
  1366. paramTypes.push_back(nullPtrType);
  1367. auto setCmdLineFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
  1368. auto setCmdLineFunc = bfModule->mBfIRBuilder->CreateFunction(setCmdLineFuncType, BfIRLinkageType_External, "BfpSystem_SetCommandLine");
  1369. SmallVector<BfIRValue, 2> args;
  1370. args.push_back(bfModule->mBfIRBuilder->GetArgument(0));
  1371. args.push_back(bfModule->mBfIRBuilder->GetArgument(1));
  1372. bfModule->mBfIRBuilder->CreateCall(setCmdLineFunc, args);
  1373. }
  1374. #endif
  1375. BfIRBlock initSkipBlock;
  1376. if (project->mTargetType == BfTargetType_BeefDynLib)
  1377. {
  1378. auto initBlock = bfModule->mBfIRBuilder->CreateBlock("doInit", false);
  1379. initSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipInit", false);
  1380. auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1));
  1381. bfModule->mBfIRBuilder->CreateCondBr(cmpResult, initBlock, initSkipBlock);
  1382. bfModule->mBfIRBuilder->AddBlock(initBlock);
  1383. bfModule->mBfIRBuilder->SetInsertPoint(initBlock);
  1384. }
  1385. // Do the LoadLibrary calls below priority 100
  1386. bool didSharedLibLoad = false;
  1387. auto _CheckSharedLibLoad = [&]()
  1388. {
  1389. if (!didSharedLibLoad)
  1390. {
  1391. bfModule->mBfIRBuilder->CreateCall(loadSharedLibFunc, SmallVector<BfIRValue, 0>());
  1392. didSharedLibLoad = true;
  1393. }
  1394. };
  1395. for (auto& staticInitEntry : staticInitList)
  1396. {
  1397. if (staticInitEntry.mPriority < 100)
  1398. _CheckSharedLibLoad();
  1399. auto typeInst = staticInitEntry.mTypeInstance;
  1400. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  1401. {
  1402. auto methodInstance = methodGroup.mDefault;
  1403. if ((methodInstance != NULL) &&
  1404. (methodInstance->mMethodDef->mIsStatic) &&
  1405. (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor) &&
  1406. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  1407. {
  1408. if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
  1409. continue;
  1410. auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
  1411. if (methodInstance->mHotMethod != NULL)
  1412. methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
  1413. bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
  1414. }
  1415. }
  1416. }
  1417. _CheckSharedLibLoad();
  1418. if (initSkipBlock)
  1419. {
  1420. bfModule->mBfIRBuilder->CreateBr(initSkipBlock);
  1421. bfModule->mBfIRBuilder->AddBlock(initSkipBlock);
  1422. bfModule->mBfIRBuilder->SetInsertPoint(initSkipBlock);
  1423. }
  1424. BfIRValue retValue;
  1425. if ((project->mTargetType == BfTargetType_BeefConsoleApplication) || (project->mTargetType == BfTargetType_BeefWindowsApplication))
  1426. {
  1427. bool hadRet = false;
  1428. String entryClassName = project->mStartupObject;
  1429. typeDef = mSystem->FindTypeDef(entryClassName, 0, bfModule->mProject);
  1430. if (typeDef != NULL)
  1431. {
  1432. auto type = bfModule->ResolveTypeDef(typeDef);
  1433. BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
  1434. if (type != NULL)
  1435. {
  1436. BfType* stringType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStringTypeDef);
  1437. BfType* int32Type = bfModule->GetPrimitiveType(BfTypeCode_Int32);
  1438. BfType* intType = bfModule->GetPrimitiveType(BfTypeCode_IntPtr);
  1439. BfType* voidType = bfModule->GetPrimitiveType(BfTypeCode_None);
  1440. bool hadValidMainMethod = false;
  1441. BfModuleMethodInstance moduleMethodInst;
  1442. for (auto methodDef : typeDef->mMethods)
  1443. {
  1444. if (methodDef->mName == "Main")
  1445. {
  1446. hadValidMainMethod = true;
  1447. moduleMethodInst = bfModule->GetMethodInstanceAtIdx(type->ToTypeInstance(), methodDef->mIdx);
  1448. if (!methodDef->mIsStatic)
  1449. {
  1450. mPassInstance->Fail("Main method must be static", methodDef->GetRefNode());
  1451. hadValidMainMethod = false;
  1452. }
  1453. if ((moduleMethodInst.mMethodInstance->mReturnType != int32Type) &&
  1454. (moduleMethodInst.mMethodInstance->mReturnType != intType) &&
  1455. (moduleMethodInst.mMethodInstance->mReturnType != voidType))
  1456. {
  1457. mPassInstance->Fail("Main method must return void, int, or int32", methodDef->GetRefNode());
  1458. hadValidMainMethod = false;
  1459. }
  1460. if (moduleMethodInst.mMethodInstance->GetParamCount() == 0)
  1461. {
  1462. // No params
  1463. }
  1464. else
  1465. {
  1466. auto paramType = moduleMethodInst.mMethodInstance->GetParamType(0);
  1467. if ((moduleMethodInst.mMethodInstance->GetParamCount() != 1) || (!paramType->IsArray()) || (paramType->GetUnderlyingType() != stringType))
  1468. {
  1469. mPassInstance->Fail("Main method must be declared with either no parameters or a single String[] parameter", methodDef->GetRefNode());
  1470. hadValidMainMethod = false;
  1471. }
  1472. }
  1473. }
  1474. }
  1475. if (moduleMethodInst)
  1476. {
  1477. if (hadValidMainMethod)
  1478. {
  1479. bool hasArgs = moduleMethodInst.mMethodInstance->GetParamCount() != 0;
  1480. BfIRType intType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_IntPtr));
  1481. BfIRType int32Type = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_Int32));
  1482. // Create BeefEntry thunk
  1483. SmallVector<BfIRType, 1> paramTypes;
  1484. if (hasArgs)
  1485. {
  1486. paramTypes.push_back(bfModule->mBfIRBuilder->MapType(moduleMethodInst.mMethodInstance->GetParamType(0)));
  1487. }
  1488. BfIRFunctionType thunkFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
  1489. BfIRFunction thunkMainFunc = bfModule->mBfIRBuilder->CreateFunction(thunkFuncType, BfIRLinkageType_External, "BeefMain");
  1490. bfModule->mBfIRBuilder->SetActiveFunction(thunkMainFunc);
  1491. auto thunkEntryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  1492. bfModule->mBfIRBuilder->SetInsertPoint(thunkEntryBlock);
  1493. SmallVector<BfIRValue, 1> args;
  1494. if (hasArgs)
  1495. args.push_back(bfModule->mBfIRBuilder->GetArgument(0));
  1496. auto methodInstance = moduleMethodInst.mMethodInstance;
  1497. if (methodInstance->mHotMethod != NULL)
  1498. methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
  1499. auto retVal = bfModule->mBfIRBuilder->CreateCall(moduleMethodInst.mFunc, args);
  1500. if (moduleMethodInst.mMethodInstance->mReturnType->IsVoid())
  1501. {
  1502. bfModule->mBfIRBuilder->CreateRet(bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0));
  1503. }
  1504. else
  1505. {
  1506. retVal = bfModule->mBfIRBuilder->CreateNumericCast(retVal, true, BfTypeCode_Int32);
  1507. bfModule->mBfIRBuilder->CreateRet(retVal);
  1508. }
  1509. hadRet = true;
  1510. auto internalType = bfModule->ResolveTypeDef(mInternalTypeDef);
  1511. args.clear();
  1512. // Call BeefEntry thunk
  1513. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  1514. if (hasArgs)
  1515. {
  1516. auto createParamsMethodInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "CreateParamsArray");
  1517. auto callValue = bfModule->mBfIRBuilder->CreateCall(createParamsMethodInstance.mFunc, SmallVector<BfIRValue, 0>());
  1518. args.push_back(callValue);
  1519. }
  1520. retValue = bfModule->mBfIRBuilder->CreateCall(thunkMainFunc, args);
  1521. if (hasArgs)
  1522. {
  1523. auto deleteStringArrayMethodInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "DeleteStringArray");
  1524. bfModule->mBfIRBuilder->CreateCall(deleteStringArrayMethodInstance.mFunc, args);
  1525. }
  1526. }
  1527. }
  1528. else
  1529. {
  1530. mPassInstance->Fail(StrFormat("Unable to find Main method in class '%s'", entryClassName.c_str()));
  1531. }
  1532. }
  1533. }
  1534. else
  1535. {
  1536. if (entryClassName.empty())
  1537. mPassInstance->Fail(StrFormat("No entry point class specified for executable in project '%s'", project->mName.c_str()));
  1538. else
  1539. mPassInstance->Fail(StrFormat("Unable to find entry point class '%s' in project '%s'", entryClassName.c_str(), project->mName.c_str()));
  1540. bfModule->mHadBuildError = true;
  1541. }
  1542. if (!hadRet)
  1543. retValue = bfModule->GetConstValue32(0);
  1544. }
  1545. else if (project->mTargetType == BfTargetType_BeefDynLib)
  1546. {
  1547. retValue = bfModule->GetConstValue32(1);
  1548. }
  1549. if (project->mTargetType == BfTargetType_BeefTest)
  1550. EmitTestMethod(bfModule, testMethods, retValue);
  1551. BfIRBlock deinitSkipBlock;
  1552. if (project->mTargetType == BfTargetType_BeefDynLib)
  1553. {
  1554. auto deinitBlock = bfModule->mBfIRBuilder->CreateBlock("doDeinit", false);
  1555. deinitSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipDeinit", false);
  1556. auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0));
  1557. bfModule->mBfIRBuilder->CreateCondBr(cmpResult, deinitBlock, deinitSkipBlock);
  1558. bfModule->mBfIRBuilder->AddBlock(deinitBlock);
  1559. bfModule->mBfIRBuilder->SetInsertPoint(deinitBlock);
  1560. }
  1561. bfModule->mBfIRBuilder->CreateCall(dtorFunc, SizedArray<BfIRValue, 0>());
  1562. BfModuleMethodInstance shutdownMethod = bfModule->GetInternalMethod("Shutdown");
  1563. if (shutdownMethod)
  1564. {
  1565. bfModule->mBfIRBuilder->CreateCall(shutdownMethod.mFunc, SizedArray<BfIRValue, 0>());
  1566. }
  1567. if (deinitSkipBlock)
  1568. {
  1569. bfModule->mBfIRBuilder->CreateBr(deinitSkipBlock);
  1570. bfModule->mBfIRBuilder->AddBlock(deinitSkipBlock);
  1571. bfModule->mBfIRBuilder->SetInsertPoint(deinitSkipBlock);
  1572. }
  1573. if (retValue)
  1574. bfModule->mBfIRBuilder->CreateRet(retValue);
  1575. else
  1576. bfModule->mBfIRBuilder->CreateRetVoid();
  1577. if ((mOptions.mAllowHotSwapping) && (bfModule->mHasFullDebugInfo))
  1578. {
  1579. auto int8Type = bfModule->GetPrimitiveType(BfTypeCode_Int8);
  1580. int dataSize = 16*1024;
  1581. auto irArrType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(int8Type), dataSize);
  1582. String name = "__BFTLS_EXTRA";
  1583. auto irVal = bfModule->mBfIRBuilder->CreateGlobalVariable(irArrType, false, BfIRLinkageType_External, bfModule->mBfIRBuilder->CreateConstStructZero(irArrType), name, true);
  1584. BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize);
  1585. bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, NULL, 0, dbgArrayType, false, irVal);
  1586. }
  1587. }
  1588. // Generate "System.GC.MarkAllStaticMembers"
  1589. auto gcType = vdataContext->mUnreifiedModule->ResolveTypeDef(mGCTypeDef);
  1590. if (bfModule->IsMethodImplementedAndReified(gcType->ToTypeInstance(), "MarkAllStaticMembers"))
  1591. {
  1592. bfModule->PopulateType(gcType);
  1593. auto moduleMethodInstance = bfModule->GetMethodByName(gcType->ToTypeInstance(), "MarkAllStaticMembers");
  1594. bfModule->mBfIRBuilder->SetActiveFunction(moduleMethodInstance.mFunc);
  1595. if (!moduleMethodInstance)
  1596. {
  1597. bfModule->Fail("Internal error: System.GC doesn't contain MarkAllStaticMembers method");
  1598. }
  1599. else
  1600. {
  1601. auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  1602. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  1603. for (auto& mapEntry : sortedStaticMarkMap)
  1604. {
  1605. auto typeInst = mapEntry.second;
  1606. if (typeInst->IsUnspecializedType())
  1607. continue;
  1608. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  1609. {
  1610. auto methodInstance = methodGroup.mDefault;
  1611. if ((methodInstance != NULL) &&
  1612. (methodInstance->mMethodDef->mIsStatic) &&
  1613. (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) &&
  1614. (methodInstance->mMethodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) &&
  1615. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  1616. {
  1617. if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
  1618. continue;
  1619. auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
  1620. if (methodInstance->mHotMethod != NULL)
  1621. methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
  1622. bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
  1623. }
  1624. }
  1625. }
  1626. bfModule->mBfIRBuilder->CreateRetVoid();
  1627. }
  1628. }
  1629. // Generate "System.GC.FindAllTLSMembers"
  1630. if (bfModule->IsMethodImplementedAndReified(gcType->ToTypeInstance(), "FindAllTLSMembers"))
  1631. {
  1632. bfModule->PopulateType(gcType);
  1633. auto moduleMethodInstance = bfModule->GetMethodByName(gcType->ToTypeInstance(), "FindAllTLSMembers");
  1634. bfModule->mBfIRBuilder->SetActiveFunction(moduleMethodInstance.mFunc);
  1635. if (!moduleMethodInstance)
  1636. {
  1637. bfModule->Fail("Internal error: System.GC doesn't contain FindAllTLSMembers method");
  1638. }
  1639. else
  1640. {
  1641. auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
  1642. bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
  1643. for (auto& mapEntry : sortedStaticTLSMap)
  1644. {
  1645. auto typeInst = mapEntry.second;
  1646. if (typeInst->IsUnspecializedType())
  1647. continue;
  1648. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  1649. {
  1650. auto methodInstance = methodGroup.mDefault;
  1651. if ((methodInstance != NULL) &&
  1652. (methodInstance->mMethodDef->mIsStatic) &&
  1653. (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) &&
  1654. (methodInstance->mMethodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS) &&
  1655. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  1656. {
  1657. if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
  1658. continue;
  1659. auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
  1660. bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
  1661. }
  1662. }
  1663. }
  1664. bfModule->mBfIRBuilder->CreateRetVoid();
  1665. }
  1666. }
  1667. if (bfModule->mHadBuildError)
  1668. {
  1669. bfModule->mDataHash = 0;
  1670. }
  1671. }
  1672. // This method clears out unused generic types AFTER compilation of reified types has occurred
  1673. void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
  1674. {
  1675. BP_ZONE("BfCompiler::UpdateDependencyMap");
  1676. BfLogSysM("Compiler::UpdateDependencyMap %d\n", deleteUnusued);
  1677. bool madeFullPass = true;
  1678. if (mCanceling)
  1679. madeFullPass = false;
  1680. if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
  1681. madeFullPass = false;
  1682. // Remove old data in dependency maps, and find types which don't have any references (direct or indirect)
  1683. // to a non-generic type and remove them
  1684. for (int pass = 0; true; pass++)
  1685. {
  1686. // This assert can fail if we have a dependency error, where deleting a type causes a dependent type
  1687. // to be rebuilt
  1688. BF_ASSERT(pass < 100);
  1689. bool foundNew = false;
  1690. for (auto type : mContext->mResolvedTypes)
  1691. {
  1692. if (type != NULL)
  1693. {
  1694. auto depType = type->ToDependedType();
  1695. auto typeInst = type->ToTypeInstance();
  1696. if (depType != NULL)
  1697. {
  1698. extern BfModule* gLastCreatedModule;
  1699. for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr)
  1700. {
  1701. auto dependentType = itr->mKey;
  1702. if (dependentType->IsIncomplete())
  1703. {
  1704. BF_ASSERT(dependentType->IsDeleting() || dependentType->IsOnDemand() || !dependentType->HasBeenReferenced() || !madeFullPass || dependentType->IsSpecializedByAutoCompleteMethod());
  1705. }
  1706. }
  1707. // Not combined with previous loop because PopulateType could modify typeInst->mDependencyMap
  1708. for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end();)
  1709. {
  1710. auto dependentType = itr->mKey;
  1711. auto depTypeInst = dependentType->ToTypeInstance();
  1712. auto& depData = itr->mValue;
  1713. bool isInvalidVersion = (dependentType->mRevision > depData.mRevision) && (deleteUnusued) && (madeFullPass);
  1714. //TODO: Just to cause crash if dependentType is deleted
  1715. bool isIncomplete = dependentType->IsIncomplete();
  1716. if ((isInvalidVersion) && (!dependentType->IsDeleting()))
  1717. {
  1718. if (!dependentType->HasBeenReferenced())
  1719. {
  1720. BfLogSysM("Skipping remove of old dependent %p from %p\n", dependentType, typeInst);
  1721. //BF_ASSERT(dependentType->IsGenericTypeInstance());
  1722. // We have a pending type rebuild but we're not sure whether we're being deleted or not yet...
  1723. ++itr;
  1724. continue;
  1725. }
  1726. }
  1727. if ((dependentType->IsDeleting()) || (isInvalidVersion))
  1728. {
  1729. // If we're deleting the type, OR the dependency of the type has been removed.
  1730. // We detect a removed dependency by the dependent type changing but the dependency revision
  1731. // is older than the dependent type.
  1732. BfLogSysM("Removing old dependent %p from %p\n", dependentType, typeInst);
  1733. itr = depType->mDependencyMap.erase(itr);
  1734. }
  1735. else
  1736. {
  1737. // There needs to be more usage than just being used as part of the method specialization's MethodGenericArg.
  1738. // Keep in mind that actually invoking a generic method creates a DependencyFlag_LocalUsage dependency. The
  1739. // DependencyFlag_MethodGenericArg is just used by the owner during creation of the method specialization
  1740. bool isDependentUsage =
  1741. (depData.mFlags != BfDependencyMap::DependencyFlag_UnspecializedType) &&
  1742. (depData.mFlags != BfDependencyMap::DependencyFlag_MethodGenericArg);
  1743. // We need to consider specialized generic types separately, to remove unused specializations
  1744. if (typeInst != NULL)
  1745. {
  1746. if ((depTypeInst != NULL) && (typeInst->mLastNonGenericUsedRevision != mRevision) && (isDependentUsage) &&
  1747. ((!dependentType->IsGenericTypeInstance()) || (dependentType->IsUnspecializedType()) || (depTypeInst->mLastNonGenericUsedRevision == mRevision)))
  1748. {
  1749. typeInst->mLastNonGenericUsedRevision = mRevision;
  1750. foundNew = true;
  1751. if (!typeInst->HasBeenReferenced())
  1752. mContext->AddTypeToWorkList(typeInst);
  1753. }
  1754. }
  1755. ++itr;
  1756. }
  1757. }
  1758. if ((!depType->IsGenericTypeInstance() && (!depType->IsBoxed())) ||
  1759. (depType->IsUnspecializedType()) ||
  1760. ((typeInst != NULL) && (typeInst->mLastNonGenericUsedRevision == mRevision)))
  1761. {
  1762. if ((depType->mRebuildFlags & BfTypeRebuildFlag_AwaitingReference) != 0)
  1763. {
  1764. mContext->MarkAsReferenced(depType);
  1765. }
  1766. }
  1767. }
  1768. }
  1769. }
  1770. if (mCanceling)
  1771. madeFullPass = false;
  1772. if (!madeFullPass)
  1773. {
  1774. // We can't delete types based on the dependency map when we're canceling, because we may still
  1775. // have items in the work queues (particularly the mMethodWorkList) that will create
  1776. // new dependencies -- things may unduly be thought to be deleted.
  1777. return;
  1778. }
  1779. if (foundNew)
  1780. {
  1781. // This will work through generic method specializations for the types referenced above, clearing out AwaitingReference flags for
  1782. // newly-referenced generics, and queuing up their method specializations as well
  1783. didWork |= DoWorkLoop(false, false);
  1784. }
  1785. else if (deleteUnusued)
  1786. {
  1787. // Work queues should be empty if we're not canceling
  1788. BF_ASSERT(mContext->mPopulateTypeWorkList.size() == 0);
  1789. BF_ASSERT(mContext->mMethodWorkList.size() == 0);
  1790. // We need to use a delete queue because we trigger a RebuildType for dependent types,
  1791. // but we need to make sure we don't rebuild any types that may be next in line for
  1792. // deletion, so we must set BfTypeRebuildFlag_DeleteQueued first to avoid that
  1793. Array<BfDependedType*> deleteQueue;
  1794. // We bubble out
  1795. for (auto type : mContext->mResolvedTypes)
  1796. {
  1797. auto depType = type->ToDependedType();
  1798. // Delete if we're a generic
  1799. if ((depType != NULL) && (!depType->IsDeleting()))
  1800. {
  1801. auto typeInst = depType->ToTypeInstance();
  1802. bool wantDelete = false;
  1803. if (typeInst != NULL)
  1804. {
  1805. wantDelete = (typeInst->mLastNonGenericUsedRevision != mRevision) &&
  1806. (typeInst->IsGenericTypeInstance() || typeInst->IsBoxed()) && (!typeInst->IsUnspecializedType());
  1807. }
  1808. wantDelete |= (depType->IsOnDemand()) && (depType->mDependencyMap.IsEmpty());
  1809. if (wantDelete)
  1810. {
  1811. deleteQueue.push_back(depType);
  1812. depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_DeleteQueued);
  1813. foundNew = true;
  1814. }
  1815. }
  1816. }
  1817. for (auto depType : deleteQueue)
  1818. {
  1819. BfLogSysM("Deleting type from deleteQueue in UpdateDependencyMap %p\n", depType);
  1820. mContext->DeleteType(depType, true);
  1821. }
  1822. if (deleteQueue.size() != 0)
  1823. {
  1824. mContext->UpdateAfterDeletingTypes();
  1825. }
  1826. }
  1827. if (!foundNew)
  1828. break;
  1829. }
  1830. #ifdef _DEBUG
  1831. if (deleteUnusued)
  1832. {
  1833. for (auto type : mContext->mResolvedTypes)
  1834. {
  1835. // This flag should be handled by now
  1836. BF_ASSERT((type->mRebuildFlags & BfTypeRebuildFlag_AwaitingReference) == 0);
  1837. }
  1838. }
  1839. #endif
  1840. BP_ZONE("UpdateDependencyMap QueuedSpecializedMethodRebuildTypes");
  1841. HashSet<BfTypeInstance*> specializerSet;
  1842. for (auto rebuildType : mContext->mQueuedSpecializedMethodRebuildTypes)
  1843. {
  1844. if (rebuildType->mRevision != mRevision)
  1845. {
  1846. mContext->RebuildType(rebuildType);
  1847. rebuildType->mRebuildFlags = (BfTypeRebuildFlags)(rebuildType->mRebuildFlags | BfTypeRebuildFlag_SpecializedMethodRebuild);
  1848. for (auto& dep : rebuildType->mDependencyMap)
  1849. {
  1850. auto depType = dep.mKey;
  1851. auto& depData = dep.mValue;
  1852. auto depTypeInst = depType->ToTypeInstance();
  1853. if (depTypeInst == NULL)
  1854. continue;
  1855. if ((depData.mFlags & BfDependencyMap::DependencyFlag_Calls) != 0)
  1856. {
  1857. specializerSet.Add(depTypeInst);
  1858. }
  1859. }
  1860. }
  1861. }
  1862. for (auto depType : specializerSet)
  1863. {
  1864. mContext->QueueMethodSpecializations(depType, true);
  1865. }
  1866. for (auto rebuildType : mContext->mQueuedSpecializedMethodRebuildTypes)
  1867. {
  1868. rebuildType->mRebuildFlags = (BfTypeRebuildFlags)(rebuildType->mRebuildFlags & ~BfTypeRebuildFlag_SpecializedMethodRebuild);
  1869. }
  1870. mContext->mQueuedSpecializedMethodRebuildTypes.Clear();
  1871. }
  1872. // When we are unsure of whether an old generic instance will survive, we RebuildType but don't put it in any worklist.
  1873. // One of three things happens:
  1874. // 1) It gets built on demand
  1875. // 2) It gets deleted in UpdateDependencyMap
  1876. // 3) It stays undefined and we need to build it here
  1877. void BfCompiler::ProcessPurgatory(bool reifiedOnly)
  1878. {
  1879. BP_ZONE("BfCompiler::ProcessPuragory");
  1880. while (true)
  1881. {
  1882. mContext->RemoveInvalidWorkItems();
  1883. //for (auto type : mGenericInstancePurgatory)
  1884. for (int i = 0; i < (int)mGenericInstancePurgatory.size(); i++)
  1885. {
  1886. auto type = mGenericInstancePurgatory[i];
  1887. if ((reifiedOnly) && (!type->IsReified()))
  1888. continue;
  1889. if (!type->IsDeleting())
  1890. {
  1891. auto module = type->GetModule();
  1892. if (module != NULL)
  1893. module->PopulateType(type, BfPopulateType_Full);
  1894. }
  1895. if (reifiedOnly)
  1896. {
  1897. mGenericInstancePurgatory.RemoveAtFast(i);
  1898. i--;
  1899. }
  1900. }
  1901. if (!reifiedOnly)
  1902. mGenericInstancePurgatory.Clear();
  1903. int prevPurgatorySize = (int)mGenericInstancePurgatory.size();
  1904. mContext->ProcessWorkList(reifiedOnly, reifiedOnly);
  1905. if (prevPurgatorySize == (int)mGenericInstancePurgatory.size())
  1906. break;
  1907. }
  1908. }
  1909. bool BfCompiler::VerifySlotNums()
  1910. {
  1911. BP_ZONE("BfCompiler::VerifySlotNums");
  1912. SmallVector<BfTypeInstance*, 16> isSlotUsed;
  1913. for (auto type : mContext->mResolvedTypes)
  1914. {
  1915. if (!type->IsReified())
  1916. continue;
  1917. auto typeInst = type->ToTypeInstance();
  1918. if (typeInst == NULL)
  1919. continue;
  1920. if (typeInst->IsUnspecializedType())
  1921. continue;
  1922. if (typeInst->IsInterface())
  1923. {
  1924. if (typeInst->mSlotNum == -2)
  1925. continue; // Not used
  1926. if ((typeInst->mVirtualMethodTableSize > 0) && (typeInst->mSlotNum == -1))
  1927. {
  1928. // Slot not assigned yet
  1929. return false;
  1930. }
  1931. continue;
  1932. }
  1933. isSlotUsed.clear();
  1934. isSlotUsed.resize(mMaxInterfaceSlots);
  1935. auto checkType = typeInst;
  1936. while (checkType != NULL)
  1937. {
  1938. for (auto iface : checkType->mInterfaces)
  1939. {
  1940. int slotNum = iface.mInterfaceType->mSlotNum;
  1941. if (slotNum >= 0)
  1942. {
  1943. if ((isSlotUsed[slotNum] != NULL) && (isSlotUsed[slotNum] != iface.mInterfaceType))
  1944. return false; // Collision
  1945. isSlotUsed[slotNum] = iface.mInterfaceType;
  1946. }
  1947. }
  1948. checkType = checkType->mBaseType;
  1949. }
  1950. }
  1951. return true;
  1952. }
  1953. bool BfCompiler::QuickGenerateSlotNums()
  1954. {
  1955. /*SmallVector<bool, 16> isSlotUsed;
  1956. for (auto globalTypeEntry : mResolvedTypes)
  1957. {
  1958. BfType* type = globalTypeEntry->mType;
  1959. auto typeInst = type->ToTypeInstance();
  1960. if (typeInst == NULL)
  1961. continue;
  1962. if (typeInst->IsInterface())
  1963. {
  1964. if ((typeInst->mVirtualMethodTableSize > 0) && (typeInst->mSlotNum == -1))
  1965. {
  1966. // Slot not assigned yet
  1967. return false;
  1968. }
  1969. continue;
  1970. }
  1971. }
  1972. return VerifySlotNums();*/
  1973. // Implement later
  1974. return false;
  1975. }
  1976. class BfSlotEntry
  1977. {
  1978. public:
  1979. BfTypeInstance* mTypeInstance;
  1980. int mRefCount;
  1981. Array<BfTypeInstance*> mConcurrentRefs;
  1982. };
  1983. typedef std::pair<BfTypeInstance*, BfTypeInstance*> InterfacePair;
  1984. typedef Dictionary<BfTypeInstance*, BfSlotEntry*> SlotEntryMap;
  1985. static BfSlotEntry* GetSlotEntry(SlotEntryMap& slotEntryMap, BfTypeInstance* typeInst)
  1986. {
  1987. BF_ASSERT(typeInst->IsReified());
  1988. BfSlotEntry** slotEntryPtr = NULL;
  1989. if (!slotEntryMap.TryAdd(typeInst, NULL, &slotEntryPtr))
  1990. return *slotEntryPtr;
  1991. BfSlotEntry* slotEntry = new BfSlotEntry();
  1992. slotEntry->mTypeInstance = typeInst;
  1993. slotEntry->mRefCount = 0;
  1994. //insertPair.first->second = slotEntry;
  1995. *slotEntryPtr = slotEntry;
  1996. return slotEntry;
  1997. }
  1998. static InterfacePair MakeInterfacePair(BfTypeInstance* iface1, BfTypeInstance* iface2)
  1999. {
  2000. if (iface1->mTypeId < iface2->mTypeId)
  2001. return InterfacePair(iface1, iface2);
  2002. return InterfacePair(iface2, iface1);
  2003. }
  2004. struct InterfacePairHash
  2005. {
  2006. size_t operator()(const InterfacePair& val) const
  2007. {
  2008. return (((size_t)val.first) >> 2) ^ ((size_t)val.second);
  2009. }
  2010. };
  2011. bool BfCompiler::SlowGenerateSlotNums()
  2012. {
  2013. BP_ZONE("BfCompiler::SlowGenerateSlotNums");
  2014. SlotEntryMap ifaceUseMap;
  2015. std::unordered_set<InterfacePair, InterfacePairHash> concurrentInterfaceSet;
  2016. HashSet<BfTypeInstance*> foundIFaces;
  2017. if (mMaxInterfaceSlots < 0)
  2018. {
  2019. mMaxInterfaceSlots = 0;
  2020. }
  2021. bool isHotCompile = IsHotCompile();
  2022. for (auto type : mContext->mResolvedTypes)
  2023. {
  2024. if (!type->IsReified())
  2025. continue;
  2026. auto typeInst = type->ToTypeInstance();
  2027. if (typeInst == NULL)
  2028. continue;
  2029. if (typeInst->IsUnspecializedType())
  2030. continue;
  2031. if (typeInst->IsInterface())
  2032. {
  2033. if (typeInst->mSlotNum == -2) // Not needed
  2034. continue;
  2035. if (!isHotCompile) // Hot compiles cannot remap slot numbers
  2036. typeInst->mSlotNum = -1;
  2037. if (typeInst->mVirtualMethodTableSize > 0)
  2038. {
  2039. GetSlotEntry(ifaceUseMap, typeInst);
  2040. }
  2041. continue;
  2042. }
  2043. foundIFaces.Clear();
  2044. auto checkTypeInst = typeInst;
  2045. while (checkTypeInst != NULL)
  2046. {
  2047. for (auto iface : checkTypeInst->mInterfaces)
  2048. {
  2049. auto interfaceType = iface.mInterfaceType;
  2050. if (interfaceType->mSlotNum == -2)
  2051. continue; // Not needed
  2052. if ((isHotCompile) && (interfaceType->mSlotNum == -1))
  2053. checkTypeInst->mDirty = true; // We're about to slot an interface here
  2054. if (interfaceType->mVirtualMethodTableSize > 0)
  2055. {
  2056. BfSlotEntry* slotEntry = GetSlotEntry(ifaceUseMap, interfaceType);
  2057. slotEntry->mRefCount++;
  2058. foundIFaces.Add(iface.mInterfaceType);
  2059. }
  2060. }
  2061. checkTypeInst = checkTypeInst->mBaseType;
  2062. }
  2063. for (auto itr1 = foundIFaces.begin(); itr1 != foundIFaces.end(); ++itr1)
  2064. {
  2065. auto itr2 = itr1;
  2066. ++itr2;
  2067. for ( ; itr2 != foundIFaces.end(); ++itr2)
  2068. {
  2069. auto iface1 = *itr1;
  2070. auto iface2 = *itr2;
  2071. InterfacePair ifacePair = MakeInterfacePair(iface1, iface2);
  2072. if (concurrentInterfaceSet.insert(ifacePair).second)
  2073. {
  2074. BfSlotEntry* entry1 = GetSlotEntry(ifaceUseMap, iface1);
  2075. BfSlotEntry* entry2 = GetSlotEntry(ifaceUseMap, iface2);
  2076. entry1->mConcurrentRefs.push_back(iface2);
  2077. entry2->mConcurrentRefs.push_back(iface1);
  2078. }
  2079. }
  2080. }
  2081. }
  2082. Array<BfSlotEntry*> sortedIfaceUseMap;
  2083. for (auto& entry : ifaceUseMap)
  2084. {
  2085. if (!isHotCompile)
  2086. BF_ASSERT(entry.mValue->mTypeInstance->mSlotNum == -1);
  2087. sortedIfaceUseMap.push_back(entry.mValue);
  2088. }
  2089. std::sort(sortedIfaceUseMap.begin(), sortedIfaceUseMap.end(), [] (BfSlotEntry* lhs, BfSlotEntry* rhs)
  2090. {
  2091. if (lhs->mRefCount != rhs->mRefCount)
  2092. return lhs->mRefCount > rhs->mRefCount;
  2093. return lhs->mTypeInstance->mTypeId < rhs->mTypeInstance->mTypeId;
  2094. });
  2095. bool failed = false;
  2096. SmallVector<bool, 16> isSlotUsed;
  2097. for (auto slotEntry : sortedIfaceUseMap)
  2098. {
  2099. BfTypeInstance* iface = slotEntry->mTypeInstance;
  2100. if (iface->mSlotNum >= 0)
  2101. {
  2102. BF_ASSERT(isHotCompile);
  2103. continue;
  2104. }
  2105. isSlotUsed.clear();
  2106. if (mMaxInterfaceSlots > 0)
  2107. isSlotUsed.resize(mMaxInterfaceSlots);
  2108. BF_ASSERT(iface->mSlotNum == -1);
  2109. BF_ASSERT(iface->IsInterface());
  2110. for (auto iface2 : slotEntry->mConcurrentRefs)
  2111. {
  2112. int slotNum2 = iface2->mSlotNum;
  2113. if (slotNum2 != -1)
  2114. isSlotUsed[slotNum2] = true;
  2115. }
  2116. for (int checkSlot = 0; checkSlot < mMaxInterfaceSlots; checkSlot++)
  2117. {
  2118. if (!isSlotUsed[checkSlot])
  2119. {
  2120. iface->mSlotNum = checkSlot;
  2121. break;
  2122. }
  2123. }
  2124. if (iface->mSlotNum == -1)
  2125. {
  2126. if (isHotCompile)
  2127. {
  2128. failed = true;
  2129. mPassInstance->Fail("Interface slot numbering overflow. Restart the program or revert changes.");
  2130. break;
  2131. }
  2132. iface->mSlotNum = mMaxInterfaceSlots;
  2133. if (mOptions.mIncrementalBuild)
  2134. {
  2135. // Allocate more than enough interface slots
  2136. mMaxInterfaceSlots += 3;
  2137. }
  2138. else
  2139. mMaxInterfaceSlots++;
  2140. // failed = true;
  2141. // mPassInstance->Fail(StrFormat("Interface slot numbering overflow, increase the maximum slot number from '%d'", mMaxInterfaceSlots));
  2142. // break;
  2143. }
  2144. // if (iface->mSlotNum == -1)
  2145. // {
  2146. // failed = true;
  2147. // mPassInstance->Fail(StrFormat("Interface slot numbering overflow, increase the maximum slot number from '%d'", mMaxInterfaceSlots));
  2148. // break;
  2149. // }
  2150. if (isHotCompile)
  2151. {
  2152. mHotState->mNewlySlottedTypeIds.Add(iface->mTypeId);
  2153. mHotState->mSlotDefineTypeIds.Add(iface->mTypeId);
  2154. }
  2155. }
  2156. if (!failed)
  2157. {
  2158. bool success = VerifySlotNums();
  2159. if (!success)
  2160. {
  2161. BF_DBG_FATAL("Failed!");
  2162. }
  2163. }
  2164. for (auto& entry : ifaceUseMap)
  2165. delete entry.mValue;
  2166. return true;
  2167. }
  2168. void BfCompiler::GenerateSlotNums()
  2169. {
  2170. BP_ZONE("BfCompiler::GenerateSlotNums");
  2171. if (mMaxInterfaceSlots < 0)
  2172. {
  2173. if (mOptions.mIncrementalBuild)
  2174. mMaxInterfaceSlots = 3;
  2175. else
  2176. mMaxInterfaceSlots = 0;
  2177. }
  2178. bool isHotCompile = IsHotCompile();
  2179. for (auto type : mContext->mResolvedTypes)
  2180. {
  2181. if (!type->IsInterface())
  2182. continue;
  2183. auto typeInstance = type->ToTypeInstance();
  2184. if ((typeInstance->mSlotNum <= 0) || (!isHotCompile))
  2185. {
  2186. if (mContext->mReferencedIFaceSlots.Contains(typeInstance))
  2187. {
  2188. if (typeInstance->mSlotNum == -2)
  2189. typeInstance->mSlotNum = -1;
  2190. }
  2191. else
  2192. typeInstance->mSlotNum = -2; // Not needed
  2193. }
  2194. }
  2195. if (VerifySlotNums())
  2196. return;
  2197. if (!QuickGenerateSlotNums())
  2198. SlowGenerateSlotNums();
  2199. BfLogSysM("GenerateSlotNums mMaxInterfaceSlots: %d\n", mMaxInterfaceSlots);
  2200. }
  2201. void BfCompiler::GenerateDynCastData()
  2202. {
  2203. BP_ZONE("BfCompiler::GenerateDynCastData");
  2204. Array<int> firstDerivedIds;
  2205. Array<int> nextSiblingIds;
  2206. firstDerivedIds.Resize(mCurTypeId);
  2207. nextSiblingIds.Resize(mCurTypeId);
  2208. for (auto type : mContext->mResolvedTypes)
  2209. {
  2210. if (type->IsBoxed())
  2211. continue;
  2212. auto typeInst = type->ToTypeInstance();
  2213. if (typeInst == NULL)
  2214. continue;
  2215. if (typeInst->mBaseType == NULL)
  2216. continue;
  2217. int baseId = typeInst->mBaseType->mTypeId;
  2218. int firstDerivedId = firstDerivedIds[baseId];
  2219. nextSiblingIds[typeInst->mTypeId] = firstDerivedIds[baseId];
  2220. firstDerivedIds[baseId] = typeInst->mTypeId;
  2221. }
  2222. int curInheritanceId = 1;
  2223. std::function<void(BfTypeInstance*)> _AddTypeInfo = [&](BfTypeInstance* typeInst)
  2224. {
  2225. if (typeInst->mInheritanceId != curInheritanceId)
  2226. {
  2227. typeInst->mInheritanceId = curInheritanceId;
  2228. typeInst->mDirty = true;
  2229. }
  2230. curInheritanceId++;
  2231. int childId = firstDerivedIds[typeInst->mTypeId];
  2232. while (childId != 0)
  2233. {
  2234. auto childType = mContext->mTypes[childId]->ToTypeInstance();
  2235. _AddTypeInfo(childType);
  2236. childId = nextSiblingIds[childId];
  2237. }
  2238. int inheritanceCount = curInheritanceId - typeInst->mInheritanceId - 1;
  2239. if (typeInst->mInheritanceCount != inheritanceCount)
  2240. {
  2241. typeInst->mInheritanceCount = inheritanceCount;
  2242. typeInst->mDirty = true;
  2243. }
  2244. };
  2245. _AddTypeInfo(mContext->mBfObjectType);
  2246. auto valueTypeInst = mContext->mScratchModule->ResolveTypeDef(mValueTypeTypeDef)->ToTypeInstance();
  2247. _AddTypeInfo(valueTypeInst);
  2248. }
  2249. void BfCompiler::UpdateRevisedTypes()
  2250. {
  2251. BP_ZONE("BfCompiler::UpdateRevisedTypes");
  2252. // See if we have any name conflicts and remove those
  2253. auto typeDefItr = mSystem->mTypeDefs.begin();
  2254. while (typeDefItr != mSystem->mTypeDefs.end())
  2255. {
  2256. auto typeDef = *typeDefItr;
  2257. auto origTypeDef = typeDef;
  2258. if (typeDef->mNextRevision != NULL)
  2259. typeDef = typeDef->mNextRevision;
  2260. if (typeDef->mDupDetectedRevision == mRevision)
  2261. {
  2262. ++typeDefItr;
  2263. continue;
  2264. }
  2265. typeDef->mDupDetectedRevision = -1;
  2266. if ((typeDef->mIsCombinedPartial) || (typeDef->mDefState == BfTypeDef::DefState_Deleted) || (typeDef->mTypeCode == BfTypeCode_Extension))
  2267. {
  2268. ++typeDefItr;
  2269. continue;
  2270. }
  2271. bool removedElement = false;
  2272. auto nextTypeDefItr = typeDefItr;
  2273. nextTypeDefItr.MoveToNextHashMatch();
  2274. while (nextTypeDefItr)
  2275. {
  2276. auto nextTypeDef = *nextTypeDefItr;
  2277. if (nextTypeDef->mNextRevision != NULL)
  2278. nextTypeDef = nextTypeDef->mNextRevision;
  2279. if ((nextTypeDef->mIsCombinedPartial) || (nextTypeDef->mDefState == BfTypeDef::DefState_Deleted) || (nextTypeDef->mTypeCode == BfTypeCode_Extension) ||
  2280. (typeDef->mFullName != nextTypeDef->mFullName) || (typeDef->mGenericParamDefs.size() != nextTypeDef->mGenericParamDefs.size()))
  2281. {
  2282. nextTypeDefItr.MoveToNextHashMatch();
  2283. continue;
  2284. }
  2285. if ((typeDef->mIsPartial) && (nextTypeDef->mIsPartial) &&
  2286. (!typeDef->IsGlobalsContainer()) &&
  2287. (typeDef->mProject != nextTypeDef->mProject))
  2288. {
  2289. BfTypeDef* typeA = NULL;
  2290. BfTypeDef* typeB = NULL;
  2291. BfError* error = NULL;
  2292. if (typeDef->mProject->ReferencesOrReferencedBy(nextTypeDef->mProject))
  2293. {
  2294. typeA = typeDef;
  2295. typeB = nextTypeDef;
  2296. }
  2297. else if (nextTypeDef->mProject->ReferencesOrReferencedBy(typeDef->mProject))
  2298. {
  2299. typeA = nextTypeDef;
  2300. typeB = typeDef;
  2301. }
  2302. if (typeA != NULL)
  2303. {
  2304. error = mPassInstance->Fail(StrFormat("Partial type in project '%s' cannot extend a type from a referenced project", typeA->mProject->mName.c_str()).c_str(),
  2305. typeA->mTypeDeclaration->mNameNode);
  2306. mPassInstance->MoreInfo(StrFormat("Previous definition in project '%s'", typeB->mProject->mName.c_str()),
  2307. typeB->mTypeDeclaration->mNameNode);
  2308. }
  2309. if (error != NULL)
  2310. error->mIsPersistent = true;
  2311. }
  2312. if (((!typeDef->mIsPartial) || (!nextTypeDef->mIsPartial)) &&
  2313. (!typeDef->IsGlobalsContainer()) && (!nextTypeDef->IsGlobalsContainer()) &&
  2314. (typeDef->mProject->ReferencesOrReferencedBy(nextTypeDef->mProject)))
  2315. {
  2316. nextTypeDef->mDupDetectedRevision = mRevision;
  2317. BfError* error = NULL;
  2318. /*if ((typeDef->mIsPartial) && (typeDef->mTypeCode != BfTypeCode_Extension))
  2319. {
  2320. error = mPassInstance->Fail("Missing 'partial' modifier; another partial definition of this type exists", nextTypeDef->mTypeDeclaration->mNameNode);
  2321. mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
  2322. }
  2323. else if ((nextTypeDef->mIsPartial) && (nextTypeDef->mTypeCode != BfTypeCode_Extension))
  2324. {
  2325. error = mPassInstance->Fail("Missing 'partial' modifier; another partial definition of this type exists", typeDef->mTypeDeclaration->mNameNode);
  2326. mPassInstance->MoreInfo("Previous definition", nextTypeDef->mTypeDeclaration->mNameNode);
  2327. }
  2328. else */if (nextTypeDef->mOuterType != NULL)
  2329. {
  2330. error = mPassInstance->Fail(StrFormat("The type '%s.%s' already has a definition for '%s'", nextTypeDef->mOuterType->mNamespace.ToString().c_str(), nextTypeDef->mOuterType->mName->mString.mPtr,
  2331. nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
  2332. mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
  2333. }
  2334. else if (!nextTypeDef->mNamespace.IsEmpty())
  2335. {
  2336. error = mPassInstance->Fail(StrFormat("The namespace '%s' already has a definition for '%s'", nextTypeDef->mNamespace.ToString().c_str(),
  2337. nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
  2338. mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
  2339. }
  2340. else
  2341. {
  2342. error = mPassInstance->Fail(StrFormat("The global namespace already has a definition for '%s'",
  2343. nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
  2344. mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
  2345. }
  2346. if (error != NULL)
  2347. error->mIsPersistent = true;
  2348. }
  2349. nextTypeDefItr.MoveToNextHashMatch();
  2350. }
  2351. ++typeDefItr;
  2352. }
  2353. mContext->PreUpdateRevisedTypes();
  2354. // If we missed out on required types previously, now we should be 'okay'
  2355. mInInvalidState = false;
  2356. // We can't do any yields in here - the compiler state is invalid from the time we inject a new
  2357. // typedef revision up until we finish the associated RebuildType
  2358. int compositeBucket = 0;
  2359. // These are "extension" defs that were unmatched last run through
  2360. Array<BfTypeDef*> prevSoloExtensions;
  2361. mSystem->mTypeDefs.CheckRehash();
  2362. // Process the typedefs one bucket at a time. When we are combining extensions or partials (globals) into a single definition then
  2363. // we will be making multiple passes over the bucket that contains that name
  2364. for (int bucketIdx = 0; bucketIdx < mSystem->mTypeDefs.mHashSize; bucketIdx++)
  2365. {
  2366. bool hadPartials = false;
  2367. bool hadChanges = false;
  2368. if (mSystem->mTypeDefs.mHashHeads == NULL)
  2369. break;
  2370. // Partials combiner
  2371. auto outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2372. while (outerTypeDefEntry != NULL)
  2373. {
  2374. auto outerTypeDef = outerTypeDefEntry->mValue;
  2375. if (outerTypeDef->mDefState == BfTypeDef::DefState_Deleted)
  2376. {
  2377. hadChanges = true;
  2378. outerTypeDefEntry = outerTypeDefEntry->mNext;
  2379. continue;
  2380. }
  2381. if (outerTypeDef->mNextRevision != NULL)
  2382. hadChanges = true;
  2383. BfTypeDefMap::Entry* rootTypeDefEntry = NULL;
  2384. BfTypeDef* rootTypeDef = NULL;
  2385. BfTypeDef* compositeTypeDef = NULL;
  2386. auto latestOuterTypeDef = outerTypeDef->GetLatest();
  2387. if ((outerTypeDef->mTypeCode == BfTypeCode_Extension) && (!outerTypeDef->mIsPartial))
  2388. {
  2389. prevSoloExtensions.Add(outerTypeDef);
  2390. outerTypeDef->mIsPartial = true;
  2391. }
  2392. if ((outerTypeDef->mIsPartial) || (outerTypeDef->mIsCombinedPartial))
  2393. {
  2394. // Initialize mPartialUsed flags
  2395. if (!hadPartials)
  2396. {
  2397. auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2398. while (checkTypeDefEntry != NULL)
  2399. {
  2400. auto checkTypeDef = checkTypeDefEntry->mValue;
  2401. if ((checkTypeDefEntry->mHash == outerTypeDefEntry->mHash) &&
  2402. (checkTypeDef->NameEquals(outerTypeDef)))
  2403. {
  2404. checkTypeDef->mPartialUsed = false;
  2405. }
  2406. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2407. }
  2408. hadPartials = true;
  2409. }
  2410. }
  2411. if ((outerTypeDef->mTypeCode == BfTypeCode_Extension) && (!outerTypeDef->mPartialUsed))
  2412. {
  2413. // Find root type, and we assume the composite type follows this
  2414. auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2415. while (checkTypeDefEntry != NULL)
  2416. {
  2417. auto checkTypeDef = checkTypeDefEntry->mValue;
  2418. if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||
  2419. (checkTypeDef->mIsCombinedPartial) ||
  2420. (checkTypeDef->mTypeCode == BfTypeCode_Extension) ||
  2421. (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
  2422. (checkTypeDef->mPartialUsed) ||
  2423. (!checkTypeDef->NameEquals(outerTypeDef)) ||
  2424. (checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()) ||
  2425. (!outerTypeDef->mProject->ContainsReference(checkTypeDef->mProject)))
  2426. {
  2427. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2428. continue;
  2429. }
  2430. rootTypeDef = checkTypeDef;
  2431. rootTypeDefEntry = checkTypeDefEntry;
  2432. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2433. }
  2434. }
  2435. else if ((outerTypeDef->mIsExplicitPartial) && (!outerTypeDef->mPartialUsed))
  2436. {
  2437. // For explicit partials there is no 'root type' so we just use the first explicit partial
  2438. rootTypeDef = outerTypeDef;
  2439. rootTypeDefEntry = outerTypeDefEntry;
  2440. // Find composite type, there is no explicit position for this
  2441. auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2442. while (checkTypeDefEntry != NULL)
  2443. {
  2444. auto checkTypeDef = checkTypeDefEntry->mValue;
  2445. if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||
  2446. (!checkTypeDef->mIsCombinedPartial) ||
  2447. (checkTypeDef->mPartialUsed) ||
  2448. (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
  2449. (!checkTypeDef->NameEquals(outerTypeDef)) ||
  2450. (checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()) ||
  2451. (outerTypeDef->mProject != checkTypeDef->mProject))
  2452. {
  2453. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2454. continue;
  2455. }
  2456. compositeTypeDef = checkTypeDef;
  2457. if (compositeTypeDef->mNextRevision != NULL)
  2458. {
  2459. // This is an old 'next revision'
  2460. delete compositeTypeDef->mNextRevision;
  2461. compositeTypeDef->mNextRevision = NULL;
  2462. }
  2463. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2464. }
  2465. }
  2466. // Now find extensions to apply to the rootTypeDef
  2467. if (rootTypeDef != NULL)
  2468. {
  2469. bool partialsHadChanges = false;
  2470. bool hadSignatureChange = false;
  2471. bool compositeIsNew = false;
  2472. if (compositeTypeDef == NULL)
  2473. {
  2474. if ((rootTypeDef->mIsExplicitPartial) || (rootTypeDefEntry->mNext == NULL) || (!rootTypeDefEntry->mNext->mValue->mIsCombinedPartial))
  2475. {
  2476. compositeTypeDef = new BfTypeDef();
  2477. compositeTypeDef->mSystem = rootTypeDef->mSystem;
  2478. compositeTypeDef->mProject = rootTypeDef->mProject;
  2479. compositeTypeDef->mName = rootTypeDef->mName;
  2480. compositeTypeDef->mName->mRefCount++;
  2481. mSystem->TrackName(compositeTypeDef);
  2482. compositeTypeDef->mNameEx = rootTypeDef->mNameEx;
  2483. compositeTypeDef->mNameEx->Ref();
  2484. compositeTypeDef->mProtection = rootTypeDef->mProtection;
  2485. compositeTypeDef->mNamespace = rootTypeDef->mNamespace;
  2486. compositeTypeDef->mTypeCode = BfTypeCode_Extension;
  2487. compositeTypeDef->mFullName = rootTypeDef->mFullName;
  2488. compositeTypeDef->mFullNameEx = rootTypeDef->mFullNameEx;
  2489. compositeTypeDef->mIsCombinedPartial = true;
  2490. // if (rootTypeDef->IsGlobalsContainer())
  2491. // {
  2492. // //NOP;
  2493. // auto didAdd = mSystem->mGlobalsMap.TryAdd(rootTypeDef->mNamespace, compositeTypeDef);
  2494. // BF_ASSERT(didAdd);
  2495. // }
  2496. for (auto prevGenericParam : rootTypeDef->mGenericParamDefs)
  2497. {
  2498. BfGenericParamDef* copiedGenericParam = new BfGenericParamDef();
  2499. *copiedGenericParam = *prevGenericParam;
  2500. compositeTypeDef->mGenericParamDefs.Add(copiedGenericParam);
  2501. }
  2502. mSystem->mTypeDefs.AddAfter(compositeTypeDef, rootTypeDefEntry);
  2503. // compositeTypeDef->mNext = rootTypeDef->mNext;
  2504. // rootTypeDef->mNext = compositeTypeDef;
  2505. partialsHadChanges = true;
  2506. hadSignatureChange = true;
  2507. compositeIsNew = true;
  2508. BfLogSysM("Creating compositeTypeDef %p\n", compositeTypeDef);
  2509. }
  2510. else
  2511. {
  2512. BF_ASSERT(rootTypeDefEntry->mNext->mValue->NameEquals(rootTypeDef));
  2513. compositeTypeDef = rootTypeDefEntry->mNext->mValue;
  2514. if (compositeTypeDef->mNextRevision != NULL)
  2515. {
  2516. // This is an old 'next revision'
  2517. delete compositeTypeDef->mNextRevision;
  2518. compositeTypeDef->mNextRevision = NULL;
  2519. }
  2520. }
  2521. }
  2522. // Collect the partials
  2523. BfSizedVector<BfTypeDef*, 8> typeParts;
  2524. typeParts.push_back(rootTypeDef);
  2525. auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2526. while (checkTypeDefEntry != NULL)
  2527. {
  2528. auto checkTypeDef = checkTypeDefEntry->mValue;
  2529. bool isValidProject;
  2530. if (rootTypeDef->mIsExplicitPartial)
  2531. isValidProject = rootTypeDef->mProject == checkTypeDef->mProject;
  2532. else
  2533. isValidProject = checkTypeDef->mProject->ContainsReference(rootTypeDef->mProject);
  2534. if (checkTypeDef != rootTypeDef)
  2535. {
  2536. if ((checkTypeDef->mIsCombinedPartial) ||
  2537. (!checkTypeDef->mIsPartial) ||
  2538. (checkTypeDef->mPartialUsed) ||
  2539. (!checkTypeDef->NameEquals(rootTypeDef)) ||
  2540. (checkTypeDef->mGenericParamDefs.size() != rootTypeDef->mGenericParamDefs.size()) ||
  2541. (!isValidProject))
  2542. {
  2543. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2544. continue;
  2545. }
  2546. }
  2547. compositeTypeDef->mPartialUsed = true;
  2548. checkTypeDef->mPartialUsed = true;
  2549. if (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted)
  2550. {
  2551. partialsHadChanges = true;
  2552. hadSignatureChange = true;
  2553. }
  2554. else
  2555. {
  2556. if (checkTypeDef != rootTypeDef)
  2557. typeParts.push_back(checkTypeDef);
  2558. if (checkTypeDef->mNextRevision != NULL)
  2559. {
  2560. partialsHadChanges = true;
  2561. BF_ASSERT(checkTypeDef->mNextRevision->mGenericParamDefs.size() == rootTypeDef->mGenericParamDefs.size());
  2562. //mSystem->InjectNewRevision(checkTypeDef);
  2563. //BF_ASSERT(checkTypeDef->mGenericParamDefs.size() == rootTypeDef->mGenericParamDefs.size());
  2564. }
  2565. else if (checkTypeDef->mDefState == BfTypeDef::DefState_New)
  2566. partialsHadChanges = true;
  2567. }
  2568. checkTypeDefEntry = checkTypeDefEntry->mNext;
  2569. }
  2570. // Set this down here, because the InjectNewRevision will clear this flag
  2571. rootTypeDef->mIsPartial = true;
  2572. if (partialsHadChanges)
  2573. {
  2574. BF_ASSERT(compositeTypeDef->mNextRevision == NULL);
  2575. mSystem->VerifyTypeDef(compositeTypeDef);
  2576. for (auto checkTypeDef : typeParts)
  2577. {
  2578. mSystem->VerifyTypeDef(checkTypeDef);
  2579. // Apply any def state that is more conservative
  2580. if (checkTypeDef->mDefState == BfTypeDef::DefState_Signature_Changed)
  2581. compositeTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
  2582. else if (checkTypeDef->mDefState == BfTypeDef::DefState_InlinedInternals_Changed)
  2583. {
  2584. if (compositeTypeDef->mDefState != BfTypeDef::DefState_Signature_Changed)
  2585. compositeTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed;
  2586. }
  2587. else if (checkTypeDef->mDefState == BfTypeDef::DefState_Internals_Changed)
  2588. {
  2589. if ((compositeTypeDef->mDefState != BfTypeDef::DefState_Signature_Changed) &&
  2590. (compositeTypeDef->mDefState != BfTypeDef::DefState_InlinedInternals_Changed))
  2591. compositeTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed;
  2592. }
  2593. BF_ASSERT(checkTypeDef->mIsPartial);
  2594. if (checkTypeDef->mNextRevision != NULL)
  2595. {
  2596. mSystem->VerifyTypeDef(checkTypeDef->mNextRevision);
  2597. mSystem->InjectNewRevision(checkTypeDef);
  2598. }
  2599. checkTypeDef->mIsPartial = true;
  2600. checkTypeDef->mDefState = BfTypeDef::DefState_Defined;
  2601. mSystem->AddToCompositePartial(mPassInstance, compositeTypeDef, checkTypeDef);
  2602. }
  2603. mSystem->FinishCompositePartial(compositeTypeDef);
  2604. if (!compositeIsNew)
  2605. {
  2606. if (compositeTypeDef->mNextRevision != NULL)
  2607. {
  2608. BF_ASSERT(compositeTypeDef->mPartials.size() != 0);
  2609. }
  2610. }
  2611. // We use the root typedef's namespace search for the composite, but this should only be
  2612. // used for cases where we CANNOT specify a typeref on an extension. IE: custom attributes
  2613. // for a type can only be added on the root typedef. If this changes then we need to make
  2614. // sure that we attach a definingType to attributes
  2615. for (auto name : compositeTypeDef->mNamespaceSearch)
  2616. mSystem->ReleaseAtomComposite(name);
  2617. compositeTypeDef->mNamespaceSearch = rootTypeDef->mNamespaceSearch;
  2618. for (auto name : compositeTypeDef->mNamespaceSearch)
  2619. mSystem->RefAtomComposite(name);
  2620. if (rootTypeDef != NULL)
  2621. compositeTypeDef->mNamespaceSearch = rootTypeDef->mNamespaceSearch;
  2622. else
  2623. compositeTypeDef->mNamespaceSearch.Clear();
  2624. //BfLogSysM("Composite type %p updating. isNew: %d\n", compositeTypeDef, compositeIsNew);
  2625. if (compositeIsNew)
  2626. {
  2627. compositeTypeDef->mDefState = BfTypeDef::DefState_New;
  2628. mSystem->InjectNewRevision(compositeTypeDef);
  2629. // Reset 'New' state
  2630. compositeTypeDef->mDefState = BfTypeDef::DefState_New;
  2631. }
  2632. else if (hadSignatureChange)
  2633. compositeTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
  2634. if (compositeTypeDef->mDefState == BfTypeDef::DefState_Defined)
  2635. {
  2636. // No changes, just inject
  2637. mSystem->InjectNewRevision(compositeTypeDef);
  2638. }
  2639. /*if (compositeTypeDef->mTypeCode == BfTypeCode_Extension)
  2640. {
  2641. BF_ASSERT(rootTypeDef == NULL);
  2642. compositeTypeDef->mTypeCode = BfTypeCode_Object;
  2643. }*/
  2644. auto latestCompositeTypeDef = compositeTypeDef->GetLatest();
  2645. if (latestCompositeTypeDef->mTypeCode == BfTypeCode_Extension)
  2646. {
  2647. BF_ASSERT(rootTypeDef == NULL);
  2648. latestCompositeTypeDef->mTypeCode = BfTypeCode_Object;
  2649. }
  2650. BfLogSysM("Partial combined type typedef %p updated from parser %p\n", compositeTypeDef, latestCompositeTypeDef->mTypeDeclaration->GetSourceData());
  2651. }
  2652. }
  2653. outerTypeDefEntry = outerTypeDefEntry->mNext;
  2654. }
  2655. // Handle unused partials, apply any new revisions, process pending deletes
  2656. if ((hadPartials) || (hadChanges))
  2657. {
  2658. BfTypeDef* checkMasterTypeDef = NULL;
  2659. BfTypeDef* deletedCombinedPartial = NULL;
  2660. outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
  2661. while (outerTypeDefEntry != NULL)
  2662. {
  2663. auto outerTypeDef = outerTypeDefEntry->mValue;
  2664. auto nextTypeDefEntry = outerTypeDefEntry->mNext;
  2665. if ((outerTypeDef->mIsPartial) && (!outerTypeDef->mIsExplicitPartial) && (outerTypeDef->mTypeCode != BfTypeCode_Extension) &&
  2666. (nextTypeDefEntry != NULL) && (!nextTypeDefEntry->mValue->mPartialUsed))
  2667. {
  2668. // This is a root type that we've removed all extensions from, so now we go back to treating it as the actual definition
  2669. // instead of using the composite that immediately follows it
  2670. BF_ASSERT(outerTypeDef->mTypeCode != BfTypeCode_Extension);
  2671. outerTypeDef->mIsPartial = false;
  2672. outerTypeDef->mPartialIdx = -1;
  2673. }
  2674. if (outerTypeDef->mDefState == BfTypeDef::DefState_Deleted)
  2675. {
  2676. BfLogSysM("UpdateRevisedTypes deleting type %p\n", outerTypeDef);
  2677. outerTypeDef->mDefState = BfTypeDef::DefState_Deleted;
  2678. mSystem->RemoveTypeDef(outerTypeDef);
  2679. }
  2680. else if (!outerTypeDef->mPartialUsed)
  2681. {
  2682. if (outerTypeDef->mIsCombinedPartial)
  2683. {
  2684. BfLogSysM("UpdateRevisedTypes deleting combinedPartial type %p\n", outerTypeDef);
  2685. deletedCombinedPartial = outerTypeDef;
  2686. outerTypeDef->mDefState = BfTypeDef::DefState_Deleted;
  2687. mSystem->RemoveTypeDef(outerTypeDef);
  2688. }
  2689. else if (outerTypeDef->mTypeCode == BfTypeCode_Extension)
  2690. {
  2691. auto error = mPassInstance->Fail(StrFormat("Unable to find root type definition for extension '%s'", outerTypeDef->GetLatest()->mFullName.ToString().c_str()),
  2692. outerTypeDef->GetLatest()->mTypeDeclaration->mNameNode);
  2693. if (error != NULL)
  2694. error->mIsPersistent = true;
  2695. if (outerTypeDef->mIsPartial)
  2696. {
  2697. // Allow this typeDef be a full solo type by itself
  2698. outerTypeDef->mIsPartial = false;
  2699. if (outerTypeDef->mNextRevision != NULL)
  2700. outerTypeDef->mNextRevision->mIsPartial = false;
  2701. if (outerTypeDef->mPartialIdx != -1)
  2702. {
  2703. outerTypeDef->mPartialIdx = -1;
  2704. outerTypeDef->mDefState = BfTypeDef::DefState_New;
  2705. }
  2706. }
  2707. }
  2708. }
  2709. if (outerTypeDef->mDefState != BfTypeDef::DefState_Deleted)
  2710. checkMasterTypeDef = outerTypeDef;
  2711. if ((deletedCombinedPartial != NULL) && (checkMasterTypeDef != NULL) &&
  2712. (deletedCombinedPartial->NameEquals(checkMasterTypeDef)))
  2713. {
  2714. // Remap nested types to their master typeDef
  2715. for (auto nestedType : deletedCombinedPartial->mNestedTypes)
  2716. {
  2717. nestedType->mOuterType = checkMasterTypeDef;
  2718. }
  2719. deletedCombinedPartial = NULL;
  2720. checkMasterTypeDef = NULL;
  2721. }
  2722. outerTypeDefEntry = nextTypeDefEntry;
  2723. }
  2724. }
  2725. }
  2726. for (auto typeDef : prevSoloExtensions)
  2727. {
  2728. // If this got added to a composite partial then delete the previous solo type
  2729. if (typeDef->mIsPartial)
  2730. {
  2731. BfLogSysM("Solo partial going back to normal partial %p\n", typeDef);
  2732. typeDef->mIsPartial = false;
  2733. auto type = mContext->mScratchModule->ResolveTypeDef(typeDef, BfPopulateType_Identity);
  2734. mContext->DeleteType(type);
  2735. typeDef->mIsPartial = true;
  2736. }
  2737. }
  2738. mContext->UpdateRevisedTypes();
  2739. mContext->VerifyTypeLookups();
  2740. if (mStats.mTypesDeleted != 0)
  2741. mContext->UpdateAfterDeletingTypes();
  2742. mContext->RemoveInvalidWorkItems();
  2743. for (auto typeDef : mSystem->mTypeDefs)
  2744. {
  2745. auto latestTypeDef = typeDef->GetLatest();
  2746. if ((latestTypeDef->mOuterType != NULL) && (latestTypeDef->mOuterType->mIsPartial))
  2747. latestTypeDef->mOuterType = mSystem->GetOuterTypeNonPartial(latestTypeDef);
  2748. }
  2749. mSystem->mNeedsTypesHandledByCompiler = false;
  2750. //TODO:
  2751. //Sleep(300);
  2752. //mSystem->CheckLockYield();
  2753. }
  2754. BfTypeDef* BfCompiler::GetArrayTypeDef(int dimensions)
  2755. {
  2756. BF_ASSERT(dimensions <= 4);
  2757. if (dimensions == 1)
  2758. return mArray1TypeDef;
  2759. if (dimensions == 2)
  2760. return mArray2TypeDef;
  2761. if (dimensions == 3)
  2762. return mArray3TypeDef;
  2763. return mArray4TypeDef;
  2764. }
  2765. void BfCompiler::VisitAutocompleteExteriorIdentifiers()
  2766. {
  2767. for (auto checkNode : mResolvePassData->mExteriorAutocompleteCheckNodes)
  2768. {
  2769. bool isUsingDirective = false;
  2770. BfIdentifierNode* checkIdentifier = NULL;
  2771. if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(checkNode))
  2772. {
  2773. checkIdentifier = usingDirective->mNamespace;
  2774. }
  2775. else if (auto usingDirective = BfNodeDynCast<BfUsingStaticDirective>(checkNode))
  2776. {
  2777. if (usingDirective->mTypeRef != NULL)
  2778. {
  2779. BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL);
  2780. SetAndRestoreValue<BfTypeInstance*> prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL);
  2781. mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, NULL);
  2782. if (mResolvePassData->mAutoComplete != NULL)
  2783. mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, isUsingDirective);
  2784. continue;
  2785. }
  2786. }
  2787. else
  2788. checkIdentifier = BfNodeDynCast<BfIdentifierNode>(checkNode);
  2789. if (checkIdentifier == NULL)
  2790. continue;
  2791. if (mResolvePassData->mAutoComplete != NULL)
  2792. mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
  2793. if ((checkIdentifier->IsFromParser(mResolvePassData->mParser)) && (mResolvePassData->mSourceClassifier != NULL))
  2794. {
  2795. if (isUsingDirective)
  2796. {
  2797. while (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier))
  2798. {
  2799. mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
  2800. checkIdentifier = qualifiedNameNode->mLeft;
  2801. }
  2802. if (checkIdentifier != NULL)
  2803. mResolvePassData->mSourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
  2804. }
  2805. }
  2806. }
  2807. mResolvePassData->mExteriorAutocompleteCheckNodes.Clear();
  2808. }
  2809. void BfCompiler::VisitSourceExteriorNodes()
  2810. {
  2811. BP_ZONE("BfCompiler::VisitSourceExteriorNodes");
  2812. String str;
  2813. Array<BfAtom*> namespaceParts;
  2814. Array<BfAstNode*> srcNodes;
  2815. std::function<bool(BfAstNode*)> _AddName = [&](BfAstNode* node)
  2816. {
  2817. if (auto qualifiedName = BfNodeDynCast<BfQualifiedNameNode>(node))
  2818. {
  2819. if (!_AddName(qualifiedName->mLeft))
  2820. return false;
  2821. if (!_AddName(qualifiedName->mRight))
  2822. return false;
  2823. }
  2824. else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(node))
  2825. {
  2826. srcNodes.Add(identifier);
  2827. str.Clear();
  2828. identifier->ToString(str);
  2829. auto atom = mSystem->FindAtom(str);
  2830. if (atom == NULL)
  2831. {
  2832. String prevNamespace;
  2833. for (auto part : namespaceParts)
  2834. {
  2835. if (!prevNamespace.IsEmpty())
  2836. prevNamespace += ".";
  2837. prevNamespace += part->mString;
  2838. }
  2839. if (prevNamespace.IsEmpty())
  2840. mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", str.c_str()), identifier);
  2841. else
  2842. mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", str.c_str(), prevNamespace.c_str()), identifier);
  2843. return false;
  2844. }
  2845. namespaceParts.Add(atom);
  2846. }
  2847. return true;
  2848. };
  2849. auto _CheckParser = [&](BfParser* parser)
  2850. {
  2851. if (parser->mNextRevision != NULL)
  2852. parser = parser->mNextRevision;
  2853. if (parser->mAwaitingDelete)
  2854. return;
  2855. if (parser->mParserData->mExteriorNodesCheckIdx == mSystem->mTypeMapVersion)
  2856. return;
  2857. bool failed = false;
  2858. for (auto node : parser->mParserData->mExteriorNodes)
  2859. {
  2860. if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(node))
  2861. {
  2862. srcNodes.Clear();
  2863. namespaceParts.Clear();
  2864. bool success = _AddName(usingDirective->mNamespace);
  2865. for (int i = 0; i < (int)namespaceParts.size(); i++)
  2866. {
  2867. BfAtomComposite checkNamespace;
  2868. checkNamespace.mParts = &namespaceParts[0];
  2869. checkNamespace.mSize = i + 1;
  2870. if (!mSystem->ContainsNamespace(checkNamespace, parser->mProject))
  2871. {
  2872. failed = true;
  2873. BfAtomComposite prevNamespace;
  2874. prevNamespace.mParts = &namespaceParts[0];
  2875. prevNamespace.mSize = i;
  2876. if (i == 0)
  2877. mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", namespaceParts[i]->mString.ToString().c_str()), srcNodes[i]);
  2878. else
  2879. mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", namespaceParts[i]->mString.ToString().c_str(), prevNamespace.ToString().c_str()), srcNodes[i]);
  2880. break;
  2881. }
  2882. }
  2883. }
  2884. else if (auto usingDirective = BfNodeDynCast<BfUsingStaticDirective>(node))
  2885. {
  2886. if (usingDirective->mTypeRef != NULL)
  2887. {
  2888. BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL);
  2889. SetAndRestoreValue<BfTypeInstance*> prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL);
  2890. mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, NULL);
  2891. if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
  2892. mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false);
  2893. return;
  2894. }
  2895. }
  2896. }
  2897. if (!failed)
  2898. parser->mParserData->mExteriorNodesCheckIdx = mSystem->mTypeMapVersion;
  2899. };
  2900. if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
  2901. {
  2902. _CheckParser(mResolvePassData->mParser);
  2903. }
  2904. else
  2905. {
  2906. for (auto parser : mSystem->mParsers)
  2907. {
  2908. _CheckParser(parser);
  2909. }
  2910. }
  2911. }
  2912. void BfCompiler::ProcessAutocompleteTempType()
  2913. {
  2914. BP_ZONE_F("BfCompiler::ProcessAutocompleteTempType %d", mResolvePassData->mResolveType);
  2915. String& autoCompleteResultString = *gTLStrReturn.Get();
  2916. autoCompleteResultString.clear();
  2917. if (mContext->mBfObjectType == NULL)
  2918. return; // Not initialized yet
  2919. auto module = mContext->mScratchModule;
  2920. auto autoComplete = mResolvePassData->mAutoComplete;
  2921. BfLogSysM("ProcessAutocompleteTempType %d\n", autoComplete->mResolveType);
  2922. SetAndRestoreValue<bool> prevCanceling(mCanceling, false);
  2923. BF_ASSERT(mResolvePassData->mAutoComplete->mDefMethod == NULL);
  2924. if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
  2925. {
  2926. for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
  2927. {
  2928. String typeName = tempTypeDef->ToString();
  2929. BfLogSysM("BfResolveType_GetNavigationData TypeDef:%p %s\n", tempTypeDef, typeName.c_str());
  2930. auto refNode = tempTypeDef->GetRefNode();
  2931. if ((refNode != NULL) && (!tempTypeDef->IsGlobalsContainer()))
  2932. {
  2933. if (!autoCompleteResultString.empty())
  2934. autoCompleteResultString += "\n";
  2935. String typeName = BfTypeUtils::TypeToString(tempTypeDef, BfTypeNameFlag_OmitNamespace);
  2936. module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
  2937. autoCompleteResultString += typeName;
  2938. if (tempTypeDef->mTypeCode == BfTypeCode_Object)
  2939. autoCompleteResultString += "\tclass";
  2940. else if (tempTypeDef->mTypeCode == BfTypeCode_Enum)
  2941. autoCompleteResultString += "\tenum";
  2942. else if (tempTypeDef->mTypeCode == BfTypeCode_Struct)
  2943. autoCompleteResultString += "\tstruct";
  2944. else if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
  2945. autoCompleteResultString += "\ttypealias";
  2946. else
  2947. autoCompleteResultString += "\t";
  2948. autoCompleteResultString += StrFormat("\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
  2949. }
  2950. String methodText;
  2951. for (auto methodDef : tempTypeDef->mMethods)
  2952. {
  2953. if (((methodDef->mMethodType == BfMethodType_Normal) || (methodDef->mMethodType == BfMethodType_Operator) ||
  2954. (methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_Dtor) ||
  2955. (methodDef->mMethodType == BfMethodType_Mixin)) &&
  2956. (methodDef->mMethodDeclaration != NULL))
  2957. {
  2958. methodText = methodDef->ToString();
  2959. if (typeName != "@")
  2960. methodText = typeName + "." + methodText;
  2961. if (!autoCompleteResultString.empty())
  2962. autoCompleteResultString += "\n";
  2963. auto methodDeclaration = methodDef->GetMethodDeclaration();
  2964. BfAstNode* refNode = methodDeclaration;
  2965. if (methodDeclaration->mBody != NULL)
  2966. refNode = methodDeclaration->mBody;
  2967. else if (methodDeclaration->mNameNode != NULL)
  2968. refNode = methodDeclaration->mNameNode;
  2969. module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
  2970. methodText += StrFormat("\tmethod\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
  2971. autoCompleteResultString += methodText;
  2972. }
  2973. }
  2974. for (auto propDef : tempTypeDef->mProperties)
  2975. {
  2976. auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(propDef->mFieldDeclaration);
  2977. if ((propDeclaration == NULL) || (propDeclaration->mNameNode == NULL))
  2978. continue;
  2979. String propText = propDef->mName;
  2980. if (typeName != "@")
  2981. propText = typeName + "." + propText;
  2982. if (!autoCompleteResultString.empty())
  2983. autoCompleteResultString += "\n";
  2984. BfAstNode* refNode = propDeclaration->mNameNode;
  2985. module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
  2986. propText += StrFormat("\tproperty\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
  2987. autoCompleteResultString += propText;
  2988. }
  2989. }
  2990. module->CleanupFileInstances();
  2991. return;
  2992. }
  2993. if (autoComplete->mResolveType == BfResolveType_GetCurrentLocation)
  2994. {
  2995. for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
  2996. {
  2997. String typeName = tempTypeDef->mNamespace.ToString();
  2998. if (!typeName.empty())
  2999. typeName += ".";
  3000. typeName += tempTypeDef->ToString();
  3001. autoCompleteResultString = typeName;
  3002. int cursorPos = mResolvePassData->mParser->mCursorIdx;
  3003. for (auto methodDef : tempTypeDef->mMethods)
  3004. {
  3005. BfAstNode* defNode = methodDef->mMethodDeclaration;
  3006. if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
  3007. defNode = propertyDeclaration;
  3008. if ((defNode != NULL) &&
  3009. (defNode->Contains(cursorPos)))
  3010. {
  3011. String methodText = methodDef->ToString();
  3012. if (typeName != "@")
  3013. methodText = typeName + "." + methodText;
  3014. autoCompleteResultString = methodText;
  3015. break;
  3016. }
  3017. }
  3018. }
  3019. module->CleanupFileInstances();
  3020. return;
  3021. }
  3022. // >>> VisitExteriorIdentifiers
  3023. mResolvePassData->mAutoComplete->SetModule(module);
  3024. {
  3025. SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, NULL);
  3026. BP_ZONE("VisitExteriorIdentifiers");
  3027. VisitAutocompleteExteriorIdentifiers();
  3028. }
  3029. VisitSourceExteriorNodes();
  3030. BfTypeDef* tempTypeDef = NULL;
  3031. for (auto checkTempType : mResolvePassData->mAutoCompleteTempTypes)
  3032. {
  3033. if (mResolvePassData->mAutoComplete->IsAutocompleteNode(checkTempType->mTypeDeclaration))
  3034. {
  3035. tempTypeDef = checkTempType;
  3036. mContext->HandleChangedTypeDef(tempTypeDef, true);
  3037. }
  3038. }
  3039. if (tempTypeDef == NULL)
  3040. {
  3041. GenerateAutocompleteInfo();
  3042. BfLogSysM("ProcessAutocompleteTempType - no tempTypeDef\n");
  3043. return;
  3044. }
  3045. if (tempTypeDef->mProject->mDisabled)
  3046. {
  3047. BfLogSysM("ProcessAutocompleteTempType - project disabled\n");
  3048. return;
  3049. }
  3050. SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, NULL);
  3051. BfTypeState typeState;
  3052. typeState.mCurTypeDef = tempTypeDef;
  3053. SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
  3054. BfTypeDef* actualTypeDef = NULL;
  3055. auto typeName = tempTypeDef->mFullName;
  3056. int wantNumGenericParams = (int)tempTypeDef->mGenericParamDefs.size();
  3057. auto actualTypeDefItr = mSystem->mTypeDefs.TryGet(typeName);
  3058. while (actualTypeDefItr)
  3059. {
  3060. auto checkTypeDef = *actualTypeDefItr;
  3061. if ((!checkTypeDef->mIsPartial) /*&& (checkTypeDef->mTypeCode != BfTypeCode_Extension)*/ &&
  3062. ((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension)))
  3063. {
  3064. if ((checkTypeDef->NameEquals(tempTypeDef)) && (checkTypeDef->mIsCombinedPartial) &&
  3065. (checkTypeDef->mGenericParamDefs.size() == tempTypeDef->mGenericParamDefs.size()) &&
  3066. (tempTypeDef->mProject->ContainsReference(checkTypeDef->mProject)))
  3067. {
  3068. actualTypeDef = mSystem->FilterDeletedTypeDef(checkTypeDef);
  3069. break;
  3070. }
  3071. if ((checkTypeDef->mGenericParamDefs.size() == wantNumGenericParams) &&
  3072. (FileNameEquals(tempTypeDef->mSource->mSourceData->ToParserData()->mFileName, checkTypeDef->mSource->mSourceData->ToParserData()->mFileName)) &&
  3073. (tempTypeDef->mProject == checkTypeDef->mProject))
  3074. {
  3075. actualTypeDef = mSystem->FilterDeletedTypeDef(checkTypeDef);
  3076. break;
  3077. }
  3078. }
  3079. actualTypeDefItr.MoveToNextHashMatch();
  3080. }
  3081. if ((actualTypeDef == NULL) || (actualTypeDef->mTypeDeclaration == NULL))
  3082. {
  3083. auto autoComplete = mResolvePassData->mAutoComplete;
  3084. if (autoComplete->IsAutocompleteNode(tempTypeDef->mTypeDeclaration->mNameNode))
  3085. {
  3086. BfIdentifierNode* nameNode = tempTypeDef->mTypeDeclaration->mNameNode;
  3087. if (tempTypeDef->mTypeCode == BfTypeCode_Extension)
  3088. {
  3089. autoComplete->AddTopLevelNamespaces(nameNode);
  3090. autoComplete->AddTopLevelTypes(nameNode);
  3091. autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
  3092. autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
  3093. }
  3094. }
  3095. //mResolvePassData->mSourceClassifier->MarkSkipped(tempTypeDef->mTypeDeclaration);
  3096. GenerateAutocompleteInfo();
  3097. return;
  3098. }
  3099. if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
  3100. {
  3101. mResolvePassData->mSourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
  3102. }
  3103. BfTypeInstance* typeInst;
  3104. {
  3105. BP_ZONE("ProcessAutocompleteTempType.ResolveTypeDef");
  3106. typeInst = (BfTypeInstance*)module->ResolveTypeDef(actualTypeDef, BfPopulateType_IdentityNoRemapAlias);
  3107. if ((typeInst != NULL) && (typeInst->IsIncomplete()))
  3108. module->PopulateType(typeInst, BfPopulateType_Full);
  3109. }
  3110. if (typeInst == NULL)
  3111. {
  3112. return;
  3113. }
  3114. BF_ASSERT((typeInst->mSize != -1) || (typeInst->IsTypeAlias()));
  3115. #ifdef _DEBUG
  3116. if ((typeInst->mModule != NULL) && (!typeInst->mModule->mIsScratchModule))
  3117. mLastAutocompleteModule = typeInst->mModule;
  3118. #endif
  3119. SetAndRestoreValue<BfTypeInstance*> prevType(module->mCurTypeInstance, typeInst);
  3120. typeState.mTypeInstance = typeInst;
  3121. BfGenericExtensionEntry* genericExEntry = NULL;
  3122. bool hadTempExtensionInfo = false;
  3123. if ((tempTypeDef->IsExtension()) && (actualTypeDef->mIsCombinedPartial) && (typeInst->IsGenericTypeInstance()))
  3124. {
  3125. // Add to our extension info map and then take it out at the end...
  3126. auto genericTypeInst = (BfGenericTypeInstance*)typeInst;
  3127. module->BuildGenericExtensionInfo(genericTypeInst, tempTypeDef);
  3128. genericTypeInst->mGenericExtensionInfo->mExtensionMap.TryGetValue(tempTypeDef, &genericExEntry);
  3129. BF_ASSERT(genericExEntry != NULL);
  3130. hadTempExtensionInfo = true;
  3131. }
  3132. if ((typeInst->IsUnspecializedType()) || (!typeInst->IsGenericTypeInstance()))
  3133. {
  3134. auto autoComplete = mResolvePassData->mAutoComplete;
  3135. if (autoComplete->IsAutocompleteNode(tempTypeDef->mTypeDeclaration->mNameNode))
  3136. {
  3137. BfIdentifierNode* nameNode;
  3138. nameNode = tempTypeDef->mTypeDeclaration->mNameNode;
  3139. if ((actualTypeDef->mIsCombinedPartial) && (tempTypeDef->mTypeCode == BfTypeCode_Extension))
  3140. {
  3141. autoComplete->AddTopLevelNamespaces(tempTypeDef->mTypeDeclaration->mNameNode);
  3142. autoComplete->AddTopLevelTypes(tempTypeDef->mTypeDeclaration->mNameNode);
  3143. autoComplete->SetDefinitionLocation(actualTypeDef->mTypeDeclaration->mNameNode);
  3144. }
  3145. else
  3146. autoComplete->SetDefinitionLocation(nameNode);
  3147. autoComplete->mDefType = actualTypeDef;
  3148. autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
  3149. autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
  3150. }
  3151. }
  3152. if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
  3153. {
  3154. auto typeAliasDecl = (BfTypeAliasDeclaration*)tempTypeDef->mTypeDeclaration;
  3155. if (typeAliasDecl->mAliasToType != NULL)
  3156. {
  3157. autoComplete->CheckTypeRef(typeAliasDecl->mAliasToType, false);
  3158. module->ResolveTypeRef(typeAliasDecl->mAliasToType);
  3159. }
  3160. }
  3161. // Save and restore mFieldResolveReentrys, we could fire off autocomplete while resolving a field
  3162. SetAndRestoreValue<decltype (module->mContext->mFieldResolveReentrys)> prevTypeResolveReentry(module->mContext->mFieldResolveReentrys);
  3163. module->mContext->mFieldResolveReentrys.Clear();
  3164. if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
  3165. {
  3166. BfAttributeTargets attrTarget;
  3167. if (tempTypeDef->mIsDelegate)
  3168. attrTarget = BfAttributeTargets_Delegate;
  3169. else if (typeInst->IsEnum())
  3170. attrTarget = BfAttributeTargets_Enum;
  3171. else if (typeInst->IsInterface())
  3172. attrTarget = BfAttributeTargets_Interface;
  3173. else if (typeInst->IsStruct())
  3174. attrTarget = BfAttributeTargets_Struct;
  3175. else
  3176. attrTarget = BfAttributeTargets_Class;
  3177. auto customAttrs = module->GetCustomAttributes(tempTypeDef->mTypeDeclaration->mAttributes, attrTarget);
  3178. delete customAttrs;
  3179. }
  3180. for (int genericParamIdx = 0; genericParamIdx < (int)tempTypeDef->mGenericParamDefs.size(); genericParamIdx++)
  3181. {
  3182. auto genericParamDef = tempTypeDef->mGenericParamDefs[genericParamIdx];
  3183. auto genericParamInstance = new BfGenericTypeParamInstance(tempTypeDef, genericParamIdx);
  3184. module->ResolveGenericParamConstraints(genericParamInstance, tempTypeDef->mGenericParamDefs, genericParamIdx);
  3185. delete genericParamInstance;
  3186. for (auto nameNode : genericParamDef->mNameNodes)
  3187. module->HandleTypeGenericParamRef(nameNode, tempTypeDef, genericParamIdx);
  3188. }
  3189. for (auto fieldDef : tempTypeDef->mFields)
  3190. {
  3191. BP_ZONE("ProcessAutocompleteTempType.CheckField");
  3192. auto fieldDecl = fieldDef->mFieldDeclaration;
  3193. if (BfNodeIsA<BfPropertyDeclaration>(fieldDecl))
  3194. continue; // Don't process auto-generated property fields
  3195. if (fieldDef->mTypeRef != NULL)
  3196. module->ResolveTypeRef(fieldDef->mTypeRef);
  3197. mResolvePassData->mAutoComplete->CheckTypeRef(fieldDef->mTypeRef, true);
  3198. BfFieldDef* actualFieldDef = NULL;
  3199. for (auto checkFieldDef : actualTypeDef->mFields)
  3200. {
  3201. if ((checkFieldDef->mName == fieldDef->mName) &&
  3202. (checkFieldDef->mIsConst == fieldDef->mIsConst) &&
  3203. (checkFieldDef->mIsStatic == fieldDef->mIsStatic))
  3204. {
  3205. actualFieldDef = checkFieldDef;
  3206. }
  3207. }
  3208. if ((autoComplete->mIsGetDefinition) && (fieldDef->mFieldDeclaration != NULL) && (autoComplete->IsAutocompleteNode(fieldDef->mFieldDeclaration->mNameNode)))
  3209. {
  3210. for (int i = 0; i < (int)actualTypeDef->mFields.size(); i++)
  3211. {
  3212. auto actualFieldDef = actualTypeDef->mFields[i];
  3213. if (actualFieldDef->mName == fieldDef->mName)
  3214. {
  3215. autoComplete->mDefType = actualTypeDef;
  3216. autoComplete->mDefField = actualFieldDef;
  3217. autoComplete->SetDefinitionLocation(fieldDef->mFieldDeclaration->mNameNode);
  3218. autoComplete->mInsertStartIdx = fieldDef->mFieldDeclaration->mNameNode->GetSrcStart();
  3219. autoComplete->mInsertEndIdx = fieldDef->mFieldDeclaration->mNameNode->GetSrcEnd();
  3220. break;
  3221. }
  3222. }
  3223. }
  3224. if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
  3225. {
  3226. auto customAttrs = module->GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Field);
  3227. delete customAttrs;
  3228. }
  3229. if (fieldDef->mIsConst)
  3230. {
  3231. module->ResolveConstField(typeInst, NULL, fieldDef);
  3232. }
  3233. if (fieldDef->mInitializer == NULL)
  3234. {
  3235. if (BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef))
  3236. {
  3237. if (fieldDef->mInitializer == NULL)
  3238. mPassInstance->Fail("Implicitly-typed fields must be initialized", fieldDef->mFieldDeclaration);
  3239. }
  3240. }
  3241. }
  3242. auto checkTypeDef = tempTypeDef;
  3243. while (checkTypeDef != NULL)
  3244. {
  3245. for (auto baseType : checkTypeDef->mBaseTypes)
  3246. {
  3247. autoComplete->CheckTypeRef(baseType, false);
  3248. module->ResolveTypeRef(baseType);
  3249. }
  3250. checkTypeDef = checkTypeDef->mOuterType;
  3251. }
  3252. for (auto propDef : tempTypeDef->mProperties)
  3253. {
  3254. if ((propDef->mFieldDeclaration != NULL) && (propDef->mFieldDeclaration->mAttributes != NULL))
  3255. {
  3256. auto customAttrs = module->GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
  3257. delete customAttrs;
  3258. }
  3259. auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(propDef->mFieldDeclaration);
  3260. if (propDeclaration != NULL)
  3261. autoComplete->CheckProperty(propDeclaration);
  3262. module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
  3263. if ((autoComplete->mIsGetDefinition) && (propDef->mFieldDeclaration != NULL) && (autoComplete->IsAutocompleteNode(propDef->mFieldDeclaration->mNameNode)))
  3264. {
  3265. auto checkType = typeInst;
  3266. while (checkType != NULL)
  3267. {
  3268. for (auto checkProp : checkType->mTypeDef->mProperties)
  3269. {
  3270. if (checkProp->mName == propDef->mName)
  3271. {
  3272. auto checkPropDeclaration = BfNodeDynCast<BfPropertyDeclaration>(checkProp->mFieldDeclaration);
  3273. if ((checkPropDeclaration->mVirtualSpecifier == NULL) || (checkPropDeclaration->mVirtualSpecifier->GetToken() == BfToken_Virtual))
  3274. {
  3275. autoComplete->SetDefinitionLocation(checkPropDeclaration->mNameNode);
  3276. autoComplete->mDefType = checkType->mTypeDef;
  3277. autoComplete->mDefProp = checkProp;
  3278. checkType = NULL;
  3279. break;
  3280. }
  3281. }
  3282. }
  3283. if (checkType != NULL)
  3284. checkType = checkType->mBaseType;
  3285. }
  3286. }
  3287. }
  3288. Array<BfMethodInstance*> methodInstances;
  3289. for (auto methodDef : tempTypeDef->mMethods)
  3290. {
  3291. auto methodDeclaration = methodDef->GetMethodDeclaration();
  3292. if (methodDeclaration != NULL)
  3293. autoComplete->CheckMethod(methodDeclaration, false);
  3294. if (!methodDef->mWantsBody)
  3295. {
  3296. if (methodDeclaration != NULL)
  3297. {
  3298. if (methodDeclaration->mAttributes != NULL)
  3299. {
  3300. auto customAttrs = module->GetCustomAttributes(methodDeclaration->mAttributes, (methodDef->mMethodType == BfMethodType_Ctor) ? BfAttributeTargets_Constructor : BfAttributeTargets_Method);
  3301. delete customAttrs;
  3302. }
  3303. }
  3304. else if (auto methodPropertyDeclaration = methodDef->GetPropertyMethodDeclaration())
  3305. {
  3306. if (methodPropertyDeclaration->mAttributes != NULL)
  3307. {
  3308. auto customAttrs = module->GetCustomAttributes(methodPropertyDeclaration->mAttributes, BfAttributeTargets_Method);
  3309. delete customAttrs;
  3310. }
  3311. }
  3312. continue;
  3313. }
  3314. BP_ZONE("ProcessAutocompleteTempType.CheckMethod");
  3315. BfMethodInstanceGroup methodInstanceGroup;
  3316. methodInstanceGroup.mOwner = typeInst;
  3317. methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  3318. BfMethodInstance* methodInstance = new BfMethodInstance();
  3319. methodInstances.push_back(methodInstance);
  3320. methodInstance->mMethodDef = methodDef;
  3321. methodInstance->mMethodInstanceGroup = &methodInstanceGroup;
  3322. methodInstance->mIsAutocompleteMethod = true;
  3323. for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
  3324. {
  3325. auto genericParamType = module->GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
  3326. methodInstance->GetMethodInfoEx()->mMethodGenericArguments.push_back(genericParamType);
  3327. auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
  3328. methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
  3329. //module->ResolveGenericParamConstraints(genericParamInstance, methodDef->mGenericParams[genericParamIdx]);
  3330. }
  3331. SetAndRestoreValue<BfFilePosition> prevFilePos(module->mCurFilePosition);
  3332. SetAndRestoreValue<BfMethodInstance*> prevMethodInst(module->mCurMethodInstance, methodInstance);
  3333. module->DoMethodDeclaration(methodDeclaration, true);
  3334. module->mIncompleteMethodCount++;
  3335. module->ProcessMethod(methodInstance);
  3336. if (methodInstance->mIRFunction)
  3337. {
  3338. BfLogSysM("Autocomplete removing IRFunction %d\n", methodInstance->mIRFunction.mId);
  3339. module->mBfIRBuilder->Func_DeleteBody(methodInstance->mIRFunction);
  3340. module->mBfIRBuilder->Func_EraseFromParent(methodInstance->mIRFunction);
  3341. }
  3342. }
  3343. if ((mResolvePassData->mAutoComplete->mDefType == actualTypeDef) && (mResolvePassData->mAutoComplete->mDefMethod != NULL))
  3344. {
  3345. BfMethodDef* tempDefMethod = NULL;
  3346. for (auto checkMethod : tempTypeDef->mMethods)
  3347. {
  3348. if (checkMethod == mResolvePassData->mAutoComplete->mDefMethod)
  3349. tempDefMethod = checkMethod;
  3350. }
  3351. if (tempDefMethod != NULL)
  3352. {
  3353. BfMethodDef* actualReplaceMethodDef = NULL;
  3354. for (auto checkMethodDef : actualTypeDef->mMethods)
  3355. {
  3356. if ((checkMethodDef->mMethodType == tempDefMethod->mMethodType) &&
  3357. (checkMethodDef->mMethodDeclaration != NULL) && (tempDefMethod->mMethodDeclaration != NULL) &&
  3358. (checkMethodDef->mMethodDeclaration->GetSrcStart() == tempDefMethod->mMethodDeclaration->GetSrcStart()))
  3359. actualReplaceMethodDef = checkMethodDef;
  3360. }
  3361. if (actualReplaceMethodDef == NULL)
  3362. {
  3363. autoComplete->mDefType = NULL;
  3364. autoComplete->mDefField = NULL;
  3365. autoComplete->mDefProp = NULL;
  3366. autoComplete->mReplaceLocalId = -1;
  3367. autoComplete->mDefMethod = NULL;
  3368. }
  3369. else
  3370. autoComplete->mDefMethod = actualReplaceMethodDef;
  3371. }
  3372. }
  3373. if (hadTempExtensionInfo)
  3374. {
  3375. auto genericTypeInst = (BfGenericTypeInstance*)typeInst;
  3376. genericTypeInst->mGenericExtensionInfo->mExtensionMap.Remove(tempTypeDef);
  3377. }
  3378. for (auto checkNode : mResolvePassData->mExteriorAutocompleteCheckNodes)
  3379. {
  3380. BP_ZONE("ProcessAutocompleteTempType.CheckIdentifier");
  3381. bool isUsingDirective = false;
  3382. BfIdentifierNode* checkIdentifier = NULL;
  3383. if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(checkNode))
  3384. {
  3385. isUsingDirective = true;
  3386. checkIdentifier = usingDirective->mNamespace;
  3387. }
  3388. else
  3389. checkIdentifier = BfNodeDynCast<BfIdentifierNode>(checkNode);
  3390. mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
  3391. }
  3392. GenerateAutocompleteInfo();
  3393. for (auto methodInstance : methodInstances)
  3394. delete methodInstance;
  3395. methodInstances.Clear();
  3396. module->CleanupFileInstances();
  3397. module->ClearConstData();
  3398. BfLogSysM("ProcessAutocompleteTempType end\n");
  3399. }
  3400. BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReference* typeRef)
  3401. {
  3402. //auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration,
  3403. //(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_AllowGenericTypeParamConstValue));
  3404. auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowRef);
  3405. if ((resolvedType != NULL) && (resolvedType->IsTypeInstance()))
  3406. {
  3407. auto typeInst = resolvedType->ToTypeInstance();
  3408. //TODO: Did we need this?
  3409. // The ResolveTypeRef call already does mResolvePassData->HandleTypeReference, so we were adding double entries
  3410. //mResolvePassData->HandleTypeReference(typeRef, typeInst->mTypeDef);
  3411. }
  3412. return resolvedType;
  3413. }
  3414. void BfCompiler::AddDepsToRebuildTypeList(BfTypeInstance* replaceTypeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList)
  3415. {
  3416. for (auto& dep : replaceTypeInst->mDependencyMap)
  3417. {
  3418. auto depType = dep.mKey;
  3419. auto depTypeInst = depType->ToTypeInstance();
  3420. if (depTypeInst == NULL)
  3421. continue;
  3422. if (mResolvePassData->mParser != NULL)
  3423. {
  3424. // Only find references within the current file
  3425. if (!depTypeInst->mTypeDef->HasSource(mResolvePassData->mParser))
  3426. continue;
  3427. }
  3428. bool allowRebuild = ((!depTypeInst->IsGenericTypeInstance()) ||
  3429. ((depTypeInst->IsUnspecializedType()) && (!depTypeInst->IsUnspecializedTypeVariation())));
  3430. if ((depTypeInst->IsClosure()) || (depTypeInst->IsConcreteInterfaceType()) || (depTypeInst->IsRetTypeType()))
  3431. allowRebuild = false;
  3432. if (allowRebuild)
  3433. rebuildTypeInstList.Add(depTypeInst);
  3434. }
  3435. }
  3436. void BfCompiler::GetSymbolReferences()
  3437. {
  3438. BfLogSysM("GetSymbolReferences\n");
  3439. if (mInInvalidState)
  3440. return; // Don't even try
  3441. auto context = mContext;
  3442. if (context->mBfObjectType == NULL)
  3443. return; // Not initialized yet
  3444. auto module = context->mScratchModule;
  3445. if (mResolvePassData->mAutoComplete != NULL)
  3446. mResolvePassData->mAutoComplete->SetModule(module);
  3447. const char* strPtr = mResolvePassData->mQueuedReplaceTypeDef.c_str();
  3448. BfTypeDef* typeDef = mSystem->FindTypeDefEx(strPtr);
  3449. if ((typeDef == NULL) || (typeDef->mTypeDeclaration == NULL))
  3450. return;
  3451. mResolvePassData->mSymbolReferenceTypeDef = typeDef;
  3452. auto replaceType = module->ResolveTypeDef(typeDef, BfPopulateType_IdentityNoRemapAlias);
  3453. module->PopulateType(replaceType);
  3454. auto replaceTypeInst = replaceType->ToTypeInstance();
  3455. HashSet<BfTypeInstance*> rebuildTypeInstList;
  3456. if (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Local)
  3457. {
  3458. AddDepsToRebuildTypeList(replaceTypeInst, rebuildTypeInstList);
  3459. // For generic types, add all references from all specialized versions
  3460. if (replaceTypeInst->IsGenericTypeInstance())
  3461. {
  3462. for (auto type : mContext->mResolvedTypes)
  3463. {
  3464. auto typeInst = type->ToTypeInstance();
  3465. if ((typeInst != replaceTypeInst) && (typeInst != NULL) && (typeInst->mTypeDef == typeDef))
  3466. AddDepsToRebuildTypeList(typeInst, rebuildTypeInstList);
  3467. }
  3468. }
  3469. }
  3470. rebuildTypeInstList.Add(replaceTypeInst);
  3471. //TODO: Did we need this to be rebuildTypeInst->mModule??? Why?
  3472. //auto rebuildModule = rebuildTypeInst->mModule;
  3473. auto rebuildModule = context->mScratchModule;
  3474. auto _CheckAttributes = [&](BfAttributeDirective* attrib, BfTypeDef* declaringType)
  3475. {
  3476. if ((mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Type) &&
  3477. (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Field) &&
  3478. (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Property))
  3479. return;
  3480. while (attrib != NULL)
  3481. {
  3482. String attrName = attrib->mAttributeTypeRef->ToString();
  3483. BfType* attrType = NULL;
  3484. BfAtomComposite nameComposite;
  3485. if (mSystem->ParseAtomComposite(attrName + "Attribute", nameComposite))
  3486. {
  3487. BfTypeDef* attrTypeDef = module->FindTypeDefRaw(nameComposite, 0, replaceTypeInst, declaringType, NULL);
  3488. if (attrTypeDef != NULL)
  3489. {
  3490. mResolvePassData->HandleTypeReference(attrib->mAttributeTypeRef, attrTypeDef);
  3491. attrTypeDef->PopulateMemberSets();
  3492. for (auto argExpr : attrib->mArguments)
  3493. {
  3494. if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(argExpr))
  3495. {
  3496. auto propName = assignExpr->mLeft->ToString();
  3497. BfMemberSetEntry* propDefEntry;
  3498. if (attrTypeDef->mPropertySet.TryGetWith(propName, &propDefEntry))
  3499. {
  3500. mResolvePassData->HandlePropertyReference(assignExpr->mLeft, attrTypeDef, (BfPropertyDef*)propDefEntry->mMemberDef);
  3501. }
  3502. else if (attrTypeDef->mFieldSet.TryGetWith(propName, &propDefEntry))
  3503. {
  3504. mResolvePassData->HandleFieldReference(assignExpr->mLeft, attrTypeDef, (BfFieldDef*)propDefEntry->mMemberDef);
  3505. }
  3506. }
  3507. }
  3508. }
  3509. }
  3510. attrib = attrib->mNextAttribute;
  3511. }
  3512. };
  3513. for (auto rebuildTypeInst : rebuildTypeInstList)
  3514. {
  3515. auto context = mContext;
  3516. auto module = context->mScratchModule;
  3517. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, rebuildTypeInst);
  3518. SetAndRestoreValue<bool> prevIgnoreErrors(module->mIgnoreErrors, true);
  3519. // Run through base types for type renames
  3520. auto typeDef = rebuildTypeInst->mTypeDef;
  3521. if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mNameNode != NULL))
  3522. {
  3523. if (typeDef->mIsCombinedPartial)
  3524. {
  3525. for (auto checkTypeDef : typeDef->mPartials)
  3526. {
  3527. auto nameNode = checkTypeDef->mTypeDeclaration->mNameNode;
  3528. if ((mResolvePassData->mParser == NULL) || (nameNode->IsFromParser(mResolvePassData->mParser)))
  3529. mResolvePassData->HandleTypeReference(nameNode, typeDef);
  3530. if (checkTypeDef->IsExtension())
  3531. {
  3532. if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type)
  3533. {
  3534. BfTypeState typeState;
  3535. typeState.mCurTypeDef = checkTypeDef;
  3536. SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
  3537. for (auto baseTypeRef : checkTypeDef->mBaseTypes)
  3538. CheckSymbolReferenceTypeRef(module, baseTypeRef);
  3539. for (auto genericParam : checkTypeDef->mGenericParamDefs)
  3540. {
  3541. for (auto constraint : genericParam->mInterfaceConstraints)
  3542. module->ResolveTypeRef(constraint, BfPopulateType_Identity);
  3543. }
  3544. }
  3545. }
  3546. }
  3547. }
  3548. else
  3549. {
  3550. mResolvePassData->HandleTypeReference(typeDef->mTypeDeclaration->mNameNode, typeDef);
  3551. }
  3552. }
  3553. if (!typeDef->mPartials.IsEmpty())
  3554. {
  3555. for (auto partialDef : typeDef->mPartials)
  3556. {
  3557. if ((partialDef->mTypeDeclaration != NULL) && (partialDef->mTypeDeclaration->mAttributes != NULL))
  3558. _CheckAttributes(partialDef->mTypeDeclaration->mAttributes, typeDef);
  3559. }
  3560. }
  3561. else
  3562. {
  3563. if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mAttributes != NULL))
  3564. _CheckAttributes(typeDef->mTypeDeclaration->mAttributes, typeDef);
  3565. }
  3566. if (auto typeAliasDeclaration = BfNodeDynCast<BfTypeAliasDeclaration>(typeDef->mTypeDeclaration))
  3567. {
  3568. CheckSymbolReferenceTypeRef(module, typeAliasDeclaration->mAliasToType);
  3569. }
  3570. if (mResolvePassData != NULL)
  3571. {
  3572. if (rebuildTypeInst->IsGenericTypeInstance())
  3573. {
  3574. auto genericTypeInstance = (BfGenericTypeInstance*)rebuildTypeInst;
  3575. for (int genericParamIdx = 0; genericParamIdx < (int)genericTypeInstance->mTypeGenericArguments.size(); genericParamIdx++)
  3576. {
  3577. BfGenericTypeParamInstance genericParamInstance(genericTypeInstance->mTypeDef, genericParamIdx);
  3578. auto genericParamDef = typeDef->mGenericParamDefs[genericParamIdx];
  3579. //BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, genericParamIdx);
  3580. if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam)
  3581. {
  3582. for (auto nameNode : genericParamDef->mNameNodes)
  3583. if (nameNode != NULL)
  3584. mResolvePassData->HandleTypeGenericParam(nameNode, typeDef, genericParamIdx);
  3585. }
  3586. rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, typeDef->mGenericParamDefs, genericParamIdx);
  3587. }
  3588. }
  3589. }
  3590. if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type)
  3591. {
  3592. for (auto baseTypeRef : typeDef->mBaseTypes)
  3593. CheckSymbolReferenceTypeRef(module, baseTypeRef);
  3594. }
  3595. BfTypeState typeState;
  3596. SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
  3597. if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Property)
  3598. {
  3599. for (auto propDef : typeDef->mProperties)
  3600. {
  3601. BfPropertyDef* checkPropDef = propDef;
  3602. BfTypeInstance* checkTypeInst = rebuildTypeInst;
  3603. typeState.mCurTypeDef = propDef->mDeclaringType;
  3604. module->GetBasePropertyDef(checkPropDef, checkTypeInst);
  3605. if (propDef->mFieldDeclaration != NULL)
  3606. mResolvePassData->HandlePropertyReference(propDef->mFieldDeclaration->mNameNode, checkTypeInst->mTypeDef, checkPropDef);
  3607. }
  3608. }
  3609. if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field)
  3610. {
  3611. for (auto fieldDef : typeDef->mFields)
  3612. {
  3613. if (fieldDef->mFieldDeclaration != NULL)
  3614. {
  3615. typeState.mCurTypeDef = fieldDef->mDeclaringType;
  3616. mResolvePassData->HandleFieldReference(fieldDef->mFieldDeclaration->mNameNode, typeDef, fieldDef);
  3617. }
  3618. }
  3619. }
  3620. for (auto& fieldInst : rebuildTypeInst->mFieldInstances)
  3621. {
  3622. auto fieldDef = fieldInst.GetFieldDef();
  3623. if (fieldDef != NULL)
  3624. {
  3625. typeState.mCurTypeDef = fieldDef->mDeclaringType;
  3626. if (fieldDef->mTypeRef != NULL)
  3627. CheckSymbolReferenceTypeRef(module, fieldDef->mTypeRef);
  3628. if ((fieldDef->mIsConst) && (fieldDef->mInitializer != NULL))
  3629. {
  3630. BfConstResolver constResolver(module);
  3631. constResolver.Resolve(fieldDef->mInitializer);
  3632. }
  3633. if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
  3634. _CheckAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mDeclaringType);
  3635. }
  3636. }
  3637. for (auto& propDef : rebuildTypeInst->mTypeDef->mProperties)
  3638. {
  3639. typeState.mCurTypeDef = propDef->mDeclaringType;
  3640. if (propDef->mTypeRef != NULL)
  3641. CheckSymbolReferenceTypeRef(module, propDef->mTypeRef);
  3642. }
  3643. if (rebuildModule == NULL)
  3644. continue;
  3645. rebuildModule->EnsureIRBuilder();
  3646. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance2(rebuildModule->mCurTypeInstance, rebuildTypeInst);
  3647. for (auto& methodInstGroup : rebuildTypeInst->mMethodInstanceGroups)
  3648. {
  3649. // Run through all methods
  3650. bool isDefault = true;
  3651. BfMethodInstanceGroup::MapType::iterator methodItr;
  3652. if (methodInstGroup.mMethodSpecializationMap != NULL)
  3653. methodItr = methodInstGroup.mMethodSpecializationMap->begin();
  3654. while (true)
  3655. {
  3656. BfMethodInstance* rebuildMethodInstance;
  3657. if (isDefault)
  3658. {
  3659. rebuildMethodInstance = methodInstGroup.mDefault;
  3660. if (rebuildMethodInstance == NULL)
  3661. break;
  3662. isDefault = false;
  3663. }
  3664. else
  3665. {
  3666. //TODO: Why did we process specialized methods?
  3667. // This caused renaming of types picking up 'T' usage from generic methods
  3668. break;
  3669. // if (methodInstGroup.mMethodSpecializationMap == NULL)
  3670. // break;
  3671. // if (methodItr == methodInstGroup.mMethodSpecializationMap->end())
  3672. // break;
  3673. // rebuildMethodInstance = methodItr->mValue;
  3674. // ++methodItr;
  3675. }
  3676. if ((rebuildMethodInstance->mIsUnspecializedVariation) || (rebuildMethodInstance->IsSpecializedGenericMethod()))
  3677. continue;
  3678. SetAndRestoreValue<BfMethodInstance*> prevTypeInstance(rebuildModule->mCurMethodInstance, rebuildMethodInstance);
  3679. auto methodDef = rebuildMethodInstance->mMethodDef;
  3680. auto methodDeclaration = methodDef->GetMethodDeclaration();
  3681. typeState.mCurTypeDef = methodDef->mDeclaringType;
  3682. if ((methodDeclaration != NULL) && (methodDeclaration->mAttributes != NULL))
  3683. _CheckAttributes(methodDeclaration->mAttributes, methodDef->mDeclaringType);
  3684. if ((mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type) ||
  3685. (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_MethodGenericParam) ||
  3686. (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam))
  3687. {
  3688. if (methodDef->mExplicitInterface != NULL)
  3689. CheckSymbolReferenceTypeRef(rebuildModule, methodDef->mExplicitInterface);
  3690. for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
  3691. {
  3692. auto param = methodDef->mParams[paramIdx];
  3693. CheckSymbolReferenceTypeRef(rebuildModule, param->mTypeRef);
  3694. }
  3695. if (methodDef->mReturnTypeRef != NULL)
  3696. CheckSymbolReferenceTypeRef(rebuildModule, methodDef->mReturnTypeRef);
  3697. }
  3698. if (rebuildMethodInstance->mIgnoreBody)
  3699. {
  3700. auto methodDeclaration = methodDef->GetMethodDeclaration();
  3701. if (methodDeclaration != NULL)
  3702. mResolvePassData->HandleMethodReference(methodDeclaration->mNameNode, typeDef, methodDef);
  3703. for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
  3704. {
  3705. auto param = methodDef->mParams[paramIdx];
  3706. if (param->mParamDeclaration != NULL)
  3707. {
  3708. if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(param->mParamDeclaration->mNameNode))
  3709. mResolvePassData->HandleLocalReference(identifierNode, rebuildTypeInst->mTypeDef, rebuildMethodInstance->mMethodDef, paramIdx + 1);
  3710. else if (auto tupleExprNode = BfNodeDynCast<BfTupleExpression>(param->mParamDeclaration->mNameNode))
  3711. {
  3712. for (int fieldIdx = 0; fieldIdx < (int)tupleExprNode->mValues.size(); fieldIdx++)
  3713. {
  3714. if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(tupleExprNode->mValues[fieldIdx]))
  3715. mResolvePassData->HandleLocalReference(identifierNode, rebuildTypeInst->mTypeDef, rebuildMethodInstance->mMethodDef, paramIdx + 1);
  3716. }
  3717. }
  3718. }
  3719. }
  3720. }
  3721. else
  3722. {
  3723. for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
  3724. {
  3725. auto param = methodDef->mParams[paramIdx];
  3726. if ((param->mParamDeclaration != NULL) && (param->mParamDeclaration->mInitializer != NULL))
  3727. {
  3728. auto paramType = rebuildMethodInstance->GetParamType(paramIdx);
  3729. BfConstResolver constResolver(rebuildModule);
  3730. constResolver.Resolve(param->mParamDeclaration->mInitializer, paramType);
  3731. }
  3732. }
  3733. if (rebuildMethodInstance->mHasBeenProcessed)
  3734. {
  3735. if (rebuildMethodInstance->mIRFunction)
  3736. rebuildModule->mBfIRBuilder->Func_DeleteBody(rebuildMethodInstance->mIRFunction);
  3737. rebuildMethodInstance->mHasBeenProcessed = false;
  3738. rebuildModule->mIncompleteMethodCount++;
  3739. }
  3740. else
  3741. {
  3742. if ((rebuildModule->mIncompleteMethodCount == 0) && (!rebuildModule->mIsScratchModule))
  3743. {
  3744. BF_FATAL("Shouldn't be processing this method");
  3745. }
  3746. }
  3747. for (int genericParamIdx = 0; genericParamIdx < (int)rebuildMethodInstance->GetNumGenericArguments(); genericParamIdx++)
  3748. {
  3749. BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, genericParamIdx);
  3750. auto genericParamDef = methodDef->mGenericParams[genericParamIdx];
  3751. if (mResolvePassData != NULL)
  3752. {
  3753. for (auto nameNode : genericParamDef->mNameNodes)
  3754. if (nameNode != NULL)
  3755. mResolvePassData->HandleMethodGenericParam(nameNode, typeDef, methodDef, genericParamIdx);
  3756. }
  3757. rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, methodDef->mGenericParams, genericParamIdx);
  3758. }
  3759. rebuildModule->ProcessMethod(rebuildMethodInstance);
  3760. }
  3761. }
  3762. }
  3763. }
  3764. }
  3765. void BfCompiler::UpdateCompletion()
  3766. {
  3767. if (mIsResolveOnly)
  3768. return;
  3769. float typeScale = 10.0f;
  3770. float methodScale = 1.0f;
  3771. float queueModuleScale = 50.0f;
  3772. float genModuleScale = 50.0f;
  3773. mCodeGen.UpdateStats();
  3774. BF_ASSERT(mCodeGen.mQueuedCount >= mCodeGen.mCompletionCount);
  3775. BF_ASSERT(mStats.mModulesFinished <= mStats.mModulesStarted);
  3776. BF_ASSERT(mCodeGen.mCompletionCount <= mStats.mModulesStarted);
  3777. float numerator = ((mStats.mQueuedTypesProcessed * typeScale) + //(mStats.mMethodsProcessed * methodScale) +
  3778. (mStats.mModulesFinished * queueModuleScale) + (mCodeGen.mCompletionCount * genModuleScale));
  3779. float divisor = ((mStats.mTypesQueued * typeScale) + //(mStats.mMethodsQueued * methodScale) +
  3780. (mStats.mModulesStarted * queueModuleScale) + (mStats.mReifiedModuleCount * genModuleScale));
  3781. float checkPct = 0;
  3782. if (divisor > 0)
  3783. {
  3784. checkPct = numerator / divisor;
  3785. BF_ASSERT(checkPct >= 0);
  3786. if (checkPct > mCompletionPct)
  3787. mCompletionPct = checkPct;
  3788. }
  3789. else
  3790. mCompletionPct = 0;
  3791. if (!mHadCancel)
  3792. BF_ASSERT(mCompletionPct <= 1.0f);
  3793. if (mCompletionPct > 1.0f)
  3794. mCompletionPct = 1.0f;
  3795. }
  3796. void BfCompiler::MarkStringPool(BfModule* module)
  3797. {
  3798. for (int stringId : module->mStringPoolRefs)
  3799. {
  3800. BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId];
  3801. stringPoolEntry.mLastUsedRevision = mRevision;
  3802. }
  3803. /*if (module->mOptModule != NULL)
  3804. MarkStringPool(module->mOptModule);*/
  3805. auto altModule = module->mNextAltModule;
  3806. while (altModule != NULL)
  3807. {
  3808. MarkStringPool(altModule);
  3809. altModule = altModule->mNextAltModule;
  3810. }
  3811. for (auto& specModulePair : module->mSpecializedMethodModules)
  3812. MarkStringPool(specModulePair.mValue);
  3813. }
  3814. void BfCompiler::ClearUnusedStringPoolEntries()
  3815. {
  3816. BF_ASSERT(!IsHotCompile());
  3817. for (auto module : mContext->mModules)
  3818. {
  3819. MarkStringPool(module);
  3820. }
  3821. for (auto itr = mContext->mStringObjectIdMap.begin(); itr != mContext->mStringObjectIdMap.end(); )
  3822. {
  3823. int strId = itr->mKey;
  3824. BfStringPoolEntry& stringPoolEntry = itr->mValue;
  3825. if (stringPoolEntry.mLastUsedRevision != mRevision)
  3826. {
  3827. CompileLog("Clearing unused string: %d %s\n", itr->mKey, stringPoolEntry.mString.c_str());
  3828. mContext->mStringObjectPool.Remove(stringPoolEntry.mString);
  3829. itr = mContext->mStringObjectIdMap.Remove(itr);
  3830. }
  3831. else
  3832. ++itr;
  3833. }
  3834. }
  3835. void BfCompiler::ClearBuildCache()
  3836. {
  3837. mCodeGen.ClearBuildCache();
  3838. for (auto project : mSystem->mProjects)
  3839. {
  3840. String libPath = mOutputDirectory + "/" + project->mName + "/" + project->mName + "__.lib";
  3841. BfpFile_Delete(libPath.c_str(), NULL);
  3842. }
  3843. }
  3844. int BfCompiler::GetDynCastVDataCount()
  3845. {
  3846. int dynElements = 1 + mMaxInterfaceSlots;
  3847. return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
  3848. }
  3849. bool BfCompiler::IsAutocomplete()
  3850. {
  3851. return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL);
  3852. }
  3853. BfAutoComplete* BfCompiler::GetAutoComplete()
  3854. {
  3855. if (mResolvePassData != NULL)
  3856. return mResolvePassData->mAutoComplete;
  3857. return NULL;
  3858. }
  3859. bool BfCompiler::IsHotCompile()
  3860. {
  3861. return mOptions.mHotProject != NULL;
  3862. }
  3863. bool BfCompiler::IsSkippingExtraResolveChecks()
  3864. {
  3865. return mIsResolveOnly && !mOptions.mExtraResolveChecks;
  3866. }
  3867. int BfCompiler::GetVTableMethodOffset()
  3868. {
  3869. if (mOptions.mHasVDataExtender)
  3870. return 1;
  3871. return 0;
  3872. }
  3873. bool BfCompiler::DoWorkLoop(bool onlyReifiedTypes, bool onlyReifiedMethods)
  3874. {
  3875. bool hadAnyWork = false;
  3876. while (true)
  3877. {
  3878. bool didWork = false;
  3879. didWork |= mContext->ProcessWorkList(onlyReifiedTypes, onlyReifiedMethods);
  3880. if (!didWork)
  3881. break;
  3882. hadAnyWork = true;
  3883. }
  3884. return hadAnyWork;
  3885. }
  3886. BfMangler::MangleKind BfCompiler::GetMangleKind()
  3887. {
  3888. if (mOptions.mToolsetType == BfToolsetType_GNU)
  3889. return BfMangler::MangleKind_GNU;
  3890. return (mSystem->mPtrSize == 8) ? BfMangler::MangleKind_Microsoft_64 : BfMangler::MangleKind_Microsoft_32;
  3891. }
  3892. //////////////////////////////////////////////////////////////////////////
  3893. int ArrTest()
  3894. {
  3895. //SizedArray<int, 8> intArr;
  3896. //Array<int> intArr;
  3897. //std::vector<int> intArr;
  3898. BfSizedVector<int, 8> intArr;
  3899. //int val = intArr.GetLastSafe();
  3900. intArr.push_back(123);
  3901. intArr.pop_back();
  3902. intArr.push_back(234);
  3903. intArr.push_back(345);
  3904. //intArr.push_back(567);
  3905. //auto itr = std::find(intArr.begin(), intArr.end(), 234);
  3906. //intArr.erase(itr);
  3907. for (auto itr = intArr.begin(); itr != intArr.end(); )
  3908. {
  3909. if (*itr == 234)
  3910. itr = intArr.erase(itr);
  3911. else
  3912. itr++;
  3913. }
  3914. return (int)intArr.size();
  3915. //intArr.RemoveAt(2);
  3916. }
  3917. //////////////////////////////////////////////////////////////////////////
  3918. void BfCompiler::PopulateReified()
  3919. {
  3920. BP_ZONE("PopulateReified");
  3921. BfContext* context = mContext;
  3922. bool hasTests = mSystem->HasTestProjects();
  3923. Array<BfMethodInstance*> impChainHeadMethods;
  3924. // Types can pull in new dependencies, so fully populate types until they stop
  3925. bool reifiedOnly = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
  3926. while (true)
  3927. {
  3928. BP_ZONE("Compile_PopulateTypes");
  3929. int startTypeInitCount = mTypeInitCount;
  3930. bool didWork = false;
  3931. BfLogSysM("PopulateReified iteration start\n");
  3932. int typeCount = 0;
  3933. for (auto type : context->mResolvedTypes)
  3934. {
  3935. auto module = type->GetModule();
  3936. typeCount++;
  3937. if (module == NULL)
  3938. continue;
  3939. if (!type->IsReified())
  3940. {
  3941. // On compiles, only handle reified types in this loop. This fixes cases where our first instance of a dependent type
  3942. // is found to be unreified and then we have to reify it later. It's not an error, just a compile perf issue
  3943. continue;
  3944. }
  3945. // We have to not populate generic type instances because that may force us to populate a type that SHOULD be deleted
  3946. if ((type->IsIncomplete()) && (type->IsTypeInstance()) && (!type->IsGenericTypeInstance()))
  3947. {
  3948. mSystem->CheckLockYield();
  3949. module->PopulateType(type, BfPopulateType_Full);
  3950. }
  3951. auto typeInst = type->ToTypeInstance();
  3952. if ((typeInst != NULL) && (typeInst->IsGenericTypeInstance()) && (!typeInst->IsUnspecializedType()))
  3953. {
  3954. auto unspecializedType = module->GetUnspecializedTypeInstance(typeInst);
  3955. if (!unspecializedType->mIsReified)
  3956. unspecializedType->mIsReified = true;
  3957. }
  3958. // Check reifications forced by virtuals or interfaces
  3959. if ((!mIsResolveOnly) && (typeInst != NULL) && (typeInst->mIsReified) && (typeInst->IsObject()) && (!typeInst->IsUnspecializedType())
  3960. && (typeInst->mHasBeenInstantiated) && (!typeInst->IsIncomplete()))
  3961. {
  3962. // If we have chained methods, make sure we implement the chain members if the chain head is implemented and reified
  3963. if (typeInst->mTypeDef->mIsCombinedPartial)
  3964. {
  3965. bool hasUnimpChainMembers = false;
  3966. impChainHeadMethods.Clear();
  3967. for (auto& methodInstanceGroup : typeInst->mMethodInstanceGroups)
  3968. {
  3969. auto methodInstance = methodInstanceGroup.mDefault;
  3970. if (methodInstance == NULL)
  3971. continue;
  3972. if (methodInstance->mChainType == BfMethodChainType_ChainHead)
  3973. {
  3974. if (methodInstance->IsReifiedAndImplemented())
  3975. impChainHeadMethods.Add(methodInstance);
  3976. }
  3977. else if (methodInstance->mChainType == BfMethodChainType_ChainMember)
  3978. {
  3979. if (!methodInstance->IsReifiedAndImplemented())
  3980. hasUnimpChainMembers = true;
  3981. }
  3982. else if ((methodInstance->mChainType == BfMethodChainType_None) && (methodInstance->mMethodDef->IsDefaultCtor()))
  3983. {
  3984. if (!methodInstance->IsReifiedAndImplemented())
  3985. hasUnimpChainMembers = true;
  3986. }
  3987. }
  3988. if ((hasUnimpChainMembers) && (!impChainHeadMethods.IsEmpty()))
  3989. {
  3990. for (auto& methodInstanceGroup : typeInst->mMethodInstanceGroups)
  3991. {
  3992. auto methodInstance = methodInstanceGroup.mDefault;
  3993. if (methodInstance == NULL)
  3994. continue;
  3995. bool forceMethod = false;
  3996. if (methodInstance->mChainType == BfMethodChainType_ChainMember)
  3997. {
  3998. if (!methodInstance->IsReifiedAndImplemented())
  3999. {
  4000. for (auto impMethodInstance : impChainHeadMethods)
  4001. {
  4002. if (typeInst->mModule->CompareMethodSignatures(methodInstance, impMethodInstance))
  4003. {
  4004. forceMethod = true;
  4005. }
  4006. }
  4007. }
  4008. }
  4009. else if (methodInstance->mMethodDef->IsDefaultCtor())
  4010. {
  4011. if (!methodInstance->IsReifiedAndImplemented())
  4012. forceMethod = true;
  4013. }
  4014. if (forceMethod)
  4015. {
  4016. typeInst->mModule->GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, BfTypeVector(),
  4017. (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass));
  4018. }
  4019. }
  4020. }
  4021. }
  4022. // If we have any virtual methods overrides that are unreified but the declaring virtual method is reified then we also need to reify
  4023. for (auto&& vEntry : typeInst->mVirtualMethodTable)
  4024. {
  4025. if ((vEntry.mDeclaringMethod.mTypeInstance == NULL) ||
  4026. (vEntry.mDeclaringMethod.mTypeInstance->IsIncomplete()) ||
  4027. (vEntry.mImplementingMethod.mTypeInstance == NULL) ||
  4028. (vEntry.mImplementingMethod.mTypeInstance->IsIncomplete()))
  4029. continue;
  4030. BfMethodInstance* declaringMethod = vEntry.mDeclaringMethod;
  4031. if (declaringMethod == NULL)
  4032. continue;
  4033. if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented()))
  4034. {
  4035. BfMethodInstance* implMethod = vEntry.mImplementingMethod;
  4036. if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
  4037. {
  4038. didWork = true;
  4039. typeInst->mModule->GetMethodInstance(implMethod);
  4040. }
  4041. }
  4042. }
  4043. for (auto& ifaceTypeInst : typeInst->mInterfaces)
  4044. {
  4045. auto ifaceInst = ifaceTypeInst.mInterfaceType;
  4046. int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
  4047. int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
  4048. auto declTypeDef = ifaceTypeInst.mDeclaringType;
  4049. for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++)
  4050. {
  4051. auto ifaceMethodInst = ifaceInst->mMethodInstanceGroups[iMethodIdx].mDefault;
  4052. if ((ifaceMethodInst == NULL) || (!ifaceMethodInst->IsReifiedAndImplemented()))
  4053. continue;
  4054. auto implMethodRef = &typeInst->mInterfaceMethodTable[iMethodIdx + startIdx].mMethodRef;
  4055. BfMethodInstance* implMethod = *implMethodRef;
  4056. if (implMethod == NULL)
  4057. continue;
  4058. if (!implMethod->IsReifiedAndImplemented())
  4059. {
  4060. didWork = true;
  4061. typeInst->mModule->GetMethodInstance(implMethod);
  4062. }
  4063. }
  4064. }
  4065. }
  4066. }
  4067. BfLogSysM("PopulateReified iteration done\n");
  4068. didWork |= DoWorkLoop(reifiedOnly, reifiedOnly);
  4069. if (reifiedOnly)
  4070. didWork |= DoWorkLoop(false, reifiedOnly);
  4071. if (startTypeInitCount != mTypeInitCount)
  4072. didWork = true;
  4073. if (didWork)
  4074. continue;
  4075. // We get everything on the first pass through
  4076. if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
  4077. break;
  4078. if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_SkipUnused)
  4079. break;
  4080. if (startTypeInitCount == mTypeInitCount)
  4081. break;
  4082. }
  4083. }
  4084. void BfCompiler::HotCommit()
  4085. {
  4086. mHotState->mCommittedHotCompileIdx = mOptions.mHotCompileIdx;
  4087. for (auto type : mContext->mResolvedTypes)
  4088. {
  4089. auto typeInst = type->ToTypeInstance();
  4090. if (typeInst == NULL)
  4091. continue;
  4092. if (typeInst->mHotTypeData == NULL)
  4093. continue;
  4094. for (int typeIdx = (int)typeInst->mHotTypeData->mTypeVersions.size() - 1; typeIdx >= 0; typeIdx--)
  4095. {
  4096. auto hotVersion = typeInst->mHotTypeData->mTypeVersions[typeIdx];
  4097. if (hotVersion->mCommittedHotCompileIdx != -1)
  4098. break;
  4099. hotVersion->mCommittedHotCompileIdx = mHotState->mCommittedHotCompileIdx;
  4100. if ((!hotVersion->mInterfaceMapping.IsEmpty()) && (typeIdx > 0))
  4101. {
  4102. auto hotVersionHead = typeInst->mHotTypeData->GetLatestVersionHead();
  4103. if ((hotVersionHead != hotVersion) && (hotVersionHead->mDataHash == hotVersion->mDataHash))
  4104. {
  4105. // When we have a slot failure, the data hash will match but we actually do need to use the new mInterfaceMapping entries
  4106. // So we copy them over to the
  4107. hotVersionHead->mInterfaceMapping = hotVersion->mInterfaceMapping;
  4108. }
  4109. }
  4110. }
  4111. }
  4112. }
  4113. void BfCompiler::HotResolve_Start(HotResolveFlags flags)
  4114. {
  4115. BfLogSysM("BfCompiler::HotResolve_Start\n");
  4116. delete mHotResolveData;
  4117. mHotResolveData = new HotResolveData();
  4118. mHotResolveData->mFlags = flags;
  4119. mHotResolveData->mHotTypeIdFlags.Resize(mCurTypeId);
  4120. mHotResolveData->mReasons.Resize(mCurTypeId);
  4121. if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
  4122. {
  4123. HotResolve_AddReachableMethod("BfCallAllStaticDtors");
  4124. for (auto& kv : mHotData->mFuncPtrs)
  4125. {
  4126. auto funcRef = kv.mValue;
  4127. HotResolve_AddReachableMethod(funcRef->mMethod, HotTypeFlag_FuncPtr, true);
  4128. }
  4129. }
  4130. }
  4131. bool BfCompiler::HotResolve_AddReachableMethod(BfHotMethod* hotMethod, HotTypeFlags flags, bool devirtualized, bool forceProcess)
  4132. {
  4133. HotReachableData* hotReachableData;
  4134. if (mHotResolveData->mReachableMethods.TryAdd(hotMethod, NULL, &hotReachableData))
  4135. {
  4136. hotMethod->mRefCount++;
  4137. }
  4138. else
  4139. {
  4140. hotReachableData->mTypeFlags = (HotTypeFlags)(hotReachableData->mTypeFlags | flags);
  4141. if ((!devirtualized) && (!hotReachableData->mHadNonDevirtualizedCall))
  4142. {
  4143. hotReachableData->mHadNonDevirtualizedCall = true;
  4144. if (!forceProcess)
  4145. return true;
  4146. }
  4147. if (!forceProcess)
  4148. return false;
  4149. }
  4150. hotReachableData->mTypeFlags = (HotTypeFlags)(hotReachableData->mTypeFlags | flags);
  4151. if (!devirtualized)
  4152. hotReachableData->mHadNonDevirtualizedCall = true;
  4153. for (auto hotDepData : hotMethod->mReferences)
  4154. {
  4155. if (hotDepData->mDataKind == BfHotDepDataKind_ThisType)
  4156. {
  4157. auto hotThisType = (BfHotThisType*)hotDepData;
  4158. auto hotTypeVersion = hotThisType->mTypeVersion;
  4159. HotTypeFlags hotTypeFlags = mHotResolveData->mHotTypeIdFlags[hotTypeVersion->mTypeId];
  4160. bool isAllocated = (hotTypeFlags & (HotTypeFlag_Heap | HotTypeFlag_CanAllocate)) != 0;
  4161. if (!isAllocated)
  4162. {
  4163. if (mHotResolveData->mDeferredThisCheckMethods.Add(hotMethod))
  4164. {
  4165. return true;
  4166. }
  4167. else
  4168. {
  4169. return false;
  4170. }
  4171. }
  4172. else
  4173. {
  4174. mHotResolveData->mDeferredThisCheckMethods.Remove(hotMethod);
  4175. }
  4176. }
  4177. else if (hotDepData->mDataKind == BfHotDepDataKind_Allocation)
  4178. {
  4179. auto hotAllocation = (BfHotAllocation*)hotDepData;
  4180. auto hotTypeVersion = hotAllocation->mTypeVersion;
  4181. HotResolve_ReportType(hotTypeVersion, flags, hotMethod);
  4182. HotResolve_ReportType(hotTypeVersion, HotTypeFlag_CanAllocate, hotMethod);
  4183. }
  4184. else if (hotDepData->mDataKind == BfHotDepDataKind_TypeVersion)
  4185. {
  4186. auto hotTypeVersion = (BfHotTypeVersion*)hotDepData;
  4187. HotResolve_ReportType(hotTypeVersion, flags, hotMethod);
  4188. }
  4189. else if (hotDepData->mDataKind == BfHotDepDataKind_Method)
  4190. {
  4191. auto checkMethod = (BfHotMethod*)hotDepData;
  4192. HotResolve_AddReachableMethod(checkMethod, flags, false);
  4193. }
  4194. else if (hotDepData->mDataKind == BfHotDepDataKind_DevirtualizedMethod)
  4195. {
  4196. auto checkMethod = (BfHotDevirtualizedMethod*)hotDepData;
  4197. HotResolve_AddReachableMethod(checkMethod->mMethod, flags, true);
  4198. }
  4199. else if (hotDepData->mDataKind == BfHotDepDataKind_DupMethod)
  4200. {
  4201. auto checkMethod = (BfHotDupMethod*)hotDepData;
  4202. HotResolve_AddReachableMethod(checkMethod->mMethod, flags, true);
  4203. }
  4204. }
  4205. return true;
  4206. }
  4207. void BfCompiler::HotResolve_AddReachableMethod(const StringImpl& methodName)
  4208. {
  4209. BfLogSysM("HotResolve_AddReachableMethod %s\n", methodName.c_str());
  4210. String mangledName = methodName;
  4211. BfHotMethod** hotMethodPtr;
  4212. if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
  4213. {
  4214. BfLogSysM("Hot method not found\n");
  4215. return;
  4216. }
  4217. BfHotMethod* hotMethod = *hotMethodPtr;
  4218. while (hotMethod->mPrevVersion != NULL)
  4219. {
  4220. if (hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx != -1)
  4221. break;
  4222. hotMethod = hotMethod->mPrevVersion;
  4223. }
  4224. HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_ActiveFunction, true);
  4225. }
  4226. void BfCompiler::HotResolve_AddActiveMethod(BfHotMethod* hotMethod)
  4227. {
  4228. if (mHotResolveData->mActiveMethods.Add(hotMethod))
  4229. {
  4230. hotMethod->mRefCount++;
  4231. }
  4232. // We don't need to mark reachable methods unless we had data changes
  4233. if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
  4234. {
  4235. HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_ActiveFunction, true);
  4236. }
  4237. if ((hotMethod->mFlags & BfHotDepDataFlag_HasDup) != 0)
  4238. {
  4239. for (auto depData : hotMethod->mReferences)
  4240. {
  4241. if (depData->mDataKind != BfHotDepDataKind_DupMethod)
  4242. continue;
  4243. auto hotDupMethod = (BfHotDupMethod*)depData;
  4244. HotResolve_AddActiveMethod(hotDupMethod->mMethod);
  4245. }
  4246. }
  4247. }
  4248. void BfCompiler::HotResolve_AddActiveMethod(const StringImpl& methodName)
  4249. {
  4250. BfLogSysM("HotResolve_AddActiveMethod %s\n", methodName.c_str());
  4251. String mangledName;
  4252. int hotCompileIdx = 0;
  4253. int tabIdx = (int)methodName.IndexOf('\t');
  4254. if (tabIdx != -1)
  4255. {
  4256. mangledName = methodName.Substring(0, tabIdx);
  4257. hotCompileIdx = atoi(methodName.c_str() + tabIdx + 1);
  4258. }
  4259. else
  4260. mangledName = methodName;
  4261. bool isDelegateRef = false;
  4262. BfHotMethod** hotMethodPtr;
  4263. if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
  4264. {
  4265. BfLogSysM("Hot method not found\n");
  4266. return;
  4267. }
  4268. BfHotMethod* hotMethod = *hotMethodPtr;
  4269. while (hotMethod->mPrevVersion != NULL)
  4270. {
  4271. if ((hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx != -1) && (hotCompileIdx < hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx))
  4272. break;
  4273. hotMethod = hotMethod->mPrevVersion;
  4274. }
  4275. HotResolve_AddActiveMethod(hotMethod);
  4276. }
  4277. void BfCompiler::HotResolve_AddDelegateMethod(const StringImpl& methodName)
  4278. {
  4279. BfLogSysM("HotResolve_HotResolve_AddDelegateMethod %s\n", methodName.c_str());
  4280. String mangledName = methodName;
  4281. BfHotMethod** hotMethodPtr;
  4282. if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
  4283. {
  4284. BfLogSysM("Hot method not found\n");
  4285. return;
  4286. }
  4287. BfHotMethod* hotMethod = *hotMethodPtr;
  4288. HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_Delegate, true);
  4289. }
  4290. void BfCompiler::HotResolve_ReportType(BfHotTypeVersion* hotTypeVersion, HotTypeFlags flags, BfHotDepData* reason)
  4291. {
  4292. auto& flagsRef = mHotResolveData->mHotTypeFlags[hotTypeVersion];
  4293. if (flagsRef == (flagsRef | flags))
  4294. return;
  4295. flagsRef = (HotTypeFlags)(flags | flagsRef);
  4296. bool applyFlags = true;
  4297. if ((flags & (BfCompiler::HotTypeFlag_ActiveFunction | BfCompiler::HotTypeFlag_Delegate | BfCompiler::HotTypeFlag_FuncPtr)) != 0)
  4298. {
  4299. applyFlags = (hotTypeVersion->mCommittedHotCompileIdx != -1) && (mHotState->mPendingDataChanges.Contains(hotTypeVersion->mTypeId));
  4300. if ((!applyFlags) && (hotTypeVersion->mCommittedHotCompileIdx != -1))
  4301. applyFlags = mHotState->mPendingFailedSlottings.Contains(hotTypeVersion->mTypeId);
  4302. if (applyFlags)
  4303. {
  4304. if (reason != NULL)
  4305. mHotResolveData->mReasons[hotTypeVersion->mTypeId] = reason;
  4306. }
  4307. }
  4308. if (applyFlags)
  4309. {
  4310. auto& flagsIdRef = mHotResolveData->mHotTypeIdFlags[hotTypeVersion->mTypeId];
  4311. flagsIdRef = (HotTypeFlags)(flags | flagsIdRef);
  4312. }
  4313. BfLogSysM("HotResolve_ReportType %p %s Flags:%X DeclHotIdx:%d\n", hotTypeVersion, mContext->TypeIdToString(hotTypeVersion->mTypeId).c_str(), flags, hotTypeVersion->mDeclHotCompileIdx);
  4314. for (auto member : hotTypeVersion->mMembers)
  4315. {
  4316. HotResolve_ReportType(member, flags, reason);
  4317. }
  4318. }
  4319. void BfCompiler::HotResolve_ReportType(int typeId, HotTypeFlags flags)
  4320. {
  4321. if ((uint)typeId >= mHotResolveData->mHotTypeIdFlags.size())
  4322. {
  4323. BF_DBG_FATAL("Invalid typeId");
  4324. return;
  4325. }
  4326. if (mHotResolveData->mHotTypeIdFlags[typeId] == (mHotResolveData->mHotTypeIdFlags[typeId] | flags))
  4327. return;
  4328. auto hotTypeData = mContext->GetHotTypeData(typeId);
  4329. if (hotTypeData != NULL)
  4330. {
  4331. auto hotTypeVersion = hotTypeData->GetTypeVersion(mHotState->mCommittedHotCompileIdx);
  4332. BF_ASSERT(hotTypeVersion != NULL);
  4333. if (hotTypeVersion != NULL)
  4334. HotResolve_ReportType(hotTypeVersion, flags, NULL);
  4335. }
  4336. mHotResolveData->mHotTypeIdFlags[typeId] = (HotTypeFlags)(flags | mHotResolveData->mHotTypeIdFlags[typeId]);
  4337. }
  4338. String BfCompiler::HotResolve_Finish()
  4339. {
  4340. BfLogSysM("HotResolve_Finish\n");
  4341. if (mHotState == NULL)
  4342. {
  4343. // It's possible we did a HotCompile with no file changes and therefore didn't actually do a compile
  4344. return "";
  4345. }
  4346. String result;
  4347. if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
  4348. {
  4349. BF_ASSERT(!mHotState->mPendingDataChanges.IsEmpty() || !mHotState->mPendingFailedSlottings.IsEmpty());
  4350. }
  4351. else
  4352. {
  4353. BF_ASSERT(mHotState->mPendingDataChanges.IsEmpty() && mHotState->mPendingFailedSlottings.IsEmpty());
  4354. }
  4355. if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
  4356. {
  4357. auto _AddUsedType = [&](BfTypeDef* typeDef)
  4358. {
  4359. auto type = mContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef);
  4360. if (type != NULL)
  4361. HotResolve_ReportType(type->mTypeId, BfCompiler::HotTypeFlag_Heap);
  4362. };
  4363. // We have some types that can be allocated in a read-only section- pretend they are on the heap
  4364. _AddUsedType(mReflectTypeInstanceTypeDef);
  4365. _AddUsedType(mStringTypeDef);
  4366. // Find any virtual method overrides that may have been called.
  4367. // These can cause new reachable virtual methods to be called, which may take more than one iteration to fully resolve
  4368. for (int methodPass = 0; true; methodPass++)
  4369. {
  4370. bool didWork = false;
  4371. for (auto hotMethod : mHotResolveData->mDeferredThisCheckMethods)
  4372. {
  4373. if (HotResolve_AddReachableMethod(hotMethod, BfCompiler::HotTypeFlag_ActiveFunction, true, true))
  4374. didWork = true;
  4375. }
  4376. HotTypeFlags typeFlags = HotTypeFlag_None;
  4377. for (auto& kv : mHotData->mMethodMap)
  4378. {
  4379. String& methodName = kv.mKey;
  4380. auto hotMethod = kv.mValue;
  4381. bool doCall = false;
  4382. bool forceAdd = false;
  4383. if (mHotResolveData->mReachableMethods.ContainsKey(hotMethod))
  4384. continue;
  4385. for (auto ref : hotMethod->mReferences)
  4386. {
  4387. if (ref->mDataKind == BfHotDepDataKind_ThisType)
  4388. continue;
  4389. if (ref->mDataKind != BfHotDepDataKind_VirtualDecl)
  4390. break;
  4391. auto hotVirtualDecl = (BfHotVirtualDeclaration*)ref;
  4392. HotReachableData* hotReachableData;
  4393. if (mHotResolveData->mReachableMethods.TryGetValue(hotVirtualDecl->mMethod, &hotReachableData))
  4394. {
  4395. if (hotReachableData->mHadNonDevirtualizedCall)
  4396. {
  4397. typeFlags = hotReachableData->mTypeFlags;
  4398. doCall = true;
  4399. }
  4400. }
  4401. }
  4402. if (!doCall)
  4403. {
  4404. if ((hotMethod->mFlags & BfHotDepDataFlag_AlwaysCalled) != 0)
  4405. {
  4406. typeFlags = BfCompiler::HotTypeFlag_ActiveFunction;
  4407. doCall = true;
  4408. }
  4409. }
  4410. if (doCall)
  4411. {
  4412. if (HotResolve_AddReachableMethod(hotMethod, typeFlags, true, forceAdd))
  4413. didWork = true;
  4414. }
  4415. }
  4416. if (!didWork)
  4417. break;
  4418. }
  4419. int errorCount = 0;
  4420. for (int typeId = 0; typeId < (int)mHotResolveData->mHotTypeIdFlags.size(); typeId++)
  4421. {
  4422. auto flags = mHotResolveData->mHotTypeIdFlags[typeId];
  4423. if (flags == 0)
  4424. continue;
  4425. auto type = mContext->mTypes[typeId];
  4426. Dictionary<BfHotMethod*, String*> methodNameMap;
  4427. if ((flags > BfCompiler::HotTypeFlag_UserNotUsed) &&
  4428. ((mHotState->mPendingDataChanges.Contains(typeId)) || (mHotState->mPendingFailedSlottings.Contains(typeId))))
  4429. {
  4430. bool isBadTypeUsed = false;
  4431. if ((flags & HotTypeFlag_Heap) != 0)
  4432. isBadTypeUsed = true;
  4433. else if ((flags & (HotTypeFlag_ActiveFunction | HotTypeFlag_Delegate | HotTypeFlag_FuncPtr)) != 0)
  4434. {
  4435. // If we detect an old version being used, it's only an issue if this type can actually be allocated
  4436. if ((flags & HotTypeFlag_CanAllocate) != 0)
  4437. {
  4438. isBadTypeUsed = true;
  4439. }
  4440. }
  4441. if (isBadTypeUsed)
  4442. {
  4443. bool reasonIsActiveMethod = false;
  4444. String methodReason;
  4445. auto reason = mHotResolveData->mReasons[typeId];
  4446. if ((reason != NULL) && (reason->mDataKind == BfHotDepDataKind_Method))
  4447. {
  4448. auto hotMethod = (BfHotMethod*)reason;
  4449. reasonIsActiveMethod = mHotResolveData->mActiveMethods.Contains(hotMethod);
  4450. if (methodNameMap.IsEmpty())
  4451. {
  4452. for (auto& kv : mHotData->mMethodMap)
  4453. {
  4454. auto hotMethod = kv.mValue;
  4455. while (hotMethod != NULL)
  4456. {
  4457. methodNameMap[hotMethod] = &kv.mKey;
  4458. hotMethod = hotMethod->mPrevVersion;
  4459. }
  4460. }
  4461. }
  4462. String** strPtr;
  4463. if (methodNameMap.TryGetValue(hotMethod, &strPtr))
  4464. {
  4465. methodReason += BfDemangler::Demangle((**strPtr), DbgLanguage_Beef, BfDemangler::Flag_BeefFixed);
  4466. }
  4467. }
  4468. errorCount++;
  4469. if (errorCount >= 1000)
  4470. {
  4471. result += "\n (more errors)...";
  4472. break;
  4473. }
  4474. if (!result.IsEmpty())
  4475. result += "\n";
  4476. result += "'";
  4477. result += mContext->TypeIdToString(typeId);
  4478. result += "'";
  4479. if ((flags & BfCompiler::HotTypeFlag_Heap) != 0)
  4480. result += " allocated on the heap";
  4481. else if ((flags & BfCompiler::HotTypeFlag_ActiveFunction) != 0)
  4482. {
  4483. if (reasonIsActiveMethod)
  4484. result += StrFormat(" used by active method '%s'", methodReason.c_str());
  4485. else if (!methodReason.IsEmpty())
  4486. result += StrFormat(" previous data version used by deleted method '%s', reachable by an active method", methodReason.c_str());
  4487. else
  4488. result += " previous data version used by a deleted method reachable by an active method";
  4489. }
  4490. else if ((flags & BfCompiler::HotTypeFlag_Delegate) != 0)
  4491. {
  4492. if (!methodReason.IsEmpty())
  4493. result += StrFormat(" previous data version used by deleted method '%s', reachable by a delegate", methodReason.c_str());
  4494. else
  4495. result += " previous data version used by a deleted method reachable by a delegate";
  4496. }
  4497. else if ((flags & BfCompiler::HotTypeFlag_FuncPtr) != 0)
  4498. {
  4499. if (!methodReason.IsEmpty())
  4500. result += StrFormat(" previous data version used by deleted method '%s', reachable by a function pointer", methodReason.c_str());
  4501. else
  4502. result += " previous data version used by a deleted method reachable by a function pointer";
  4503. }
  4504. else if ((flags & BfCompiler::HotTypeFlag_UserUsed) != 0)
  4505. result += " stated as used by the program";
  4506. }
  4507. }
  4508. String typeName = mContext->TypeIdToString(typeId);
  4509. BfLogSysM(" %d %s %02X\n", typeId, typeName.c_str(), flags);
  4510. }
  4511. if (result.IsEmpty())
  4512. {
  4513. for (auto typeId : mHotState->mPendingDataChanges)
  4514. {
  4515. auto type = mContext->mTypes[typeId];
  4516. auto typeInstance = type->ToTypeInstance();
  4517. BF_ASSERT(typeInstance->mHotTypeData->mPendingDataChange);
  4518. typeInstance->mHotTypeData->mPendingDataChange = false;
  4519. typeInstance->mHotTypeData->mHadDataChange = true;
  4520. typeInstance->mHotTypeData->mVTableOrigLength = -1;
  4521. typeInstance->mHotTypeData->mOrigInterfaceMethodsLength = -1;
  4522. BfLogSysM("Pending data change applied to type %p\n", typeInstance);
  4523. }
  4524. mHotState->mPendingDataChanges.Clear();
  4525. mHotState->mPendingFailedSlottings.Clear();
  4526. }
  4527. }
  4528. ClearOldHotData();
  4529. if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
  4530. {
  4531. for (int pass = 0; pass < 2; pass++)
  4532. {
  4533. bool wantsReachable = pass == 0;
  4534. Array<String> methodList;
  4535. for (auto& kv : mHotData->mMethodMap)
  4536. {
  4537. auto hotMethod = kv.mValue;
  4538. bool reachable = mHotResolveData->mReachableMethods.ContainsKey(hotMethod);
  4539. if (reachable != wantsReachable)
  4540. continue;
  4541. String methodName;
  4542. methodName += BfDemangler::Demangle(kv.mKey, DbgLanguage_Beef, BfDemangler::Flag_BeefFixed);
  4543. methodName += " - ";
  4544. methodName += kv.mKey;
  4545. methodList.Add(methodName);
  4546. }
  4547. methodList.Sort([](const String& lhs, const String& rhs) { return lhs < rhs; });
  4548. for (auto& methodName : methodList)
  4549. BfLogSysM("%s: %s\n", wantsReachable ? "Reachable" : "Unreachable", methodName.c_str());
  4550. }
  4551. }
  4552. delete mHotResolveData;
  4553. mHotResolveData = NULL;
  4554. return result;
  4555. }
  4556. void BfCompiler::ClearOldHotData()
  4557. {
  4558. if (mHotData == NULL)
  4559. return;
  4560. // TODO: Get rid of old hot data during hot compiles, too
  4561. // if (IsHotCompile())
  4562. // return;
  4563. BP_ZONE("BfCompiler::ClearOldHotData");
  4564. bool isHotCompile = IsHotCompile();
  4565. auto itr = mHotData->mMethodMap.begin();
  4566. while (itr != mHotData->mMethodMap.end())
  4567. {
  4568. String& methodName = itr->mKey;
  4569. auto hotMethod = itr->mValue;
  4570. bool doDelete = false;
  4571. // If a previous version of a method is not currently active then it should be impossible to ever reach it
  4572. while (hotMethod->mPrevVersion != NULL)
  4573. {
  4574. auto prevMethod = hotMethod->mPrevVersion;
  4575. if (prevMethod->mRefCount > 1)
  4576. {
  4577. BF_ASSERT((mHotResolveData != NULL) && (mHotResolveData->mActiveMethods.Contains(prevMethod)));
  4578. break;
  4579. }
  4580. hotMethod->mPrevVersion = prevMethod->mPrevVersion;
  4581. prevMethod->mPrevVersion = NULL;
  4582. prevMethod->Deref();
  4583. }
  4584. BF_ASSERT(hotMethod->mRefCount >= 1);
  4585. if (hotMethod->mPrevVersion == NULL)
  4586. {
  4587. if (hotMethod->mRefCount <= 1)
  4588. {
  4589. doDelete = true;
  4590. }
  4591. else if ((!isHotCompile) && ((hotMethod->mFlags & (BfHotDepDataFlag_IsBound | BfHotDepDataFlag_RetainMethodWithoutBinding)) == 0))
  4592. {
  4593. doDelete = true;
  4594. }
  4595. }
  4596. bool doRemove = doDelete;
  4597. if ((hotMethod->mFlags & BfHotDepDataFlag_HasDup) != 0)
  4598. {
  4599. bool hasDupMethod = false;
  4600. for (int idx = 0; idx < (int)hotMethod->mReferences.size(); idx++)
  4601. {
  4602. auto depData = hotMethod->mReferences[idx];
  4603. if (depData->mDataKind == BfHotDepDataKind_DupMethod)
  4604. {
  4605. auto dupMethod = (BfHotDupMethod*)depData;
  4606. if (doDelete)
  4607. {
  4608. doRemove = false;
  4609. dupMethod->mMethod->mRefCount++;
  4610. itr->mValue = dupMethod->mMethod;
  4611. }
  4612. else
  4613. {
  4614. if ((dupMethod->mMethod->mRefCount == 1) ||
  4615. ((!IsHotCompile()) && (dupMethod->mMethod->mFlags & BfHotDepDataFlag_IsBound) == 0))
  4616. {
  4617. dupMethod->Deref();
  4618. hotMethod->mReferences.RemoveAt(idx);
  4619. idx--;
  4620. }
  4621. }
  4622. }
  4623. }
  4624. }
  4625. if (doDelete)
  4626. {
  4627. BfLogSysM("Deleting hot method %p %s\n", hotMethod, methodName.c_str());
  4628. //BF_ASSERT(hotMethod->mRefCount == 1);
  4629. hotMethod->Clear();
  4630. hotMethod->Deref();
  4631. if (doRemove)
  4632. itr = mHotData->mMethodMap.Remove(itr);
  4633. }
  4634. else
  4635. ++itr;
  4636. }
  4637. mHotData->ClearUnused(IsHotCompile());
  4638. for (auto type : mContext->mResolvedTypes)
  4639. {
  4640. auto typeInst = type->ToTypeInstance();
  4641. if (typeInst == NULL)
  4642. continue;
  4643. if (typeInst->mHotTypeData == NULL)
  4644. continue;
  4645. bool foundCommittedVersion = false;
  4646. auto latestVersionHead = typeInst->mHotTypeData->GetLatestVersionHead();
  4647. for (int typeIdx = (int)typeInst->mHotTypeData->mTypeVersions.size() - 1; typeIdx >= 0; typeIdx--)
  4648. {
  4649. auto hotVersion = typeInst->mHotTypeData->mTypeVersions[typeIdx];
  4650. if (hotVersion == latestVersionHead)
  4651. {
  4652. // We have to keep the latest version head -- otherwise we would lose vdata and interface mapping data
  4653. continue;
  4654. }
  4655. if ((!foundCommittedVersion) && (mHotState != NULL) && (hotVersion->mDeclHotCompileIdx <= mHotState->mCommittedHotCompileIdx))
  4656. {
  4657. // Don't remove the latest committed version
  4658. foundCommittedVersion = true;
  4659. }
  4660. else if (hotVersion->mRefCount == 1)
  4661. {
  4662. typeInst->mHotTypeData->mTypeVersions.RemoveAt(typeIdx);
  4663. hotVersion->Deref();
  4664. BF_ASSERT(typeInst->mHotTypeData->mTypeVersions.size() > 0);
  4665. }
  4666. }
  4667. }
  4668. }
  4669. void BfCompiler::CompileReified()
  4670. {
  4671. BP_ZONE("Compile_ResolveTypeDefs");
  4672. for (auto typeDef : mSystem->mTypeDefs)
  4673. {
  4674. mSystem->CheckLockYield();
  4675. if (mCanceling)
  4676. {
  4677. BfLogSysM("Canceling from Compile typeDef loop\n");
  4678. break;
  4679. }
  4680. if (typeDef->mProject->mDisabled)
  4681. continue;
  4682. if (typeDef->mIsPartial)
  4683. continue;
  4684. bool isAlwaysInclude = typeDef->mIsAlwaysInclude;
  4685. if (typeDef->mProject->IsTestProject())
  4686. {
  4687. for (auto methodDef : typeDef->mMethods)
  4688. {
  4689. auto methodDeclaration = methodDef->GetMethodDeclaration();
  4690. if ((methodDeclaration != NULL) && (methodDeclaration->mAttributes != NULL) &&
  4691. (methodDeclaration->mAttributes->Contains("Test")))
  4692. isAlwaysInclude = true;
  4693. }
  4694. }
  4695. //TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check?
  4696. if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude))
  4697. continue;
  4698. auto scratchModule = mContext->mScratchModule;
  4699. scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
  4700. }
  4701. if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
  4702. {
  4703. for (auto project : mSystem->mProjects)
  4704. {
  4705. String entryClassName = project->mStartupObject;
  4706. auto typeDef = mSystem->FindTypeDef(entryClassName, 0, project);
  4707. if (typeDef != NULL)
  4708. {
  4709. typeDef->mIsAlwaysInclude = true;
  4710. auto resolvedType = mContext->mScratchModule->ResolveTypeDef(typeDef);
  4711. if (resolvedType != NULL)
  4712. {
  4713. auto resolvedTypeInst = resolvedType->ToTypeInstance();
  4714. if (resolvedTypeInst != NULL)
  4715. {
  4716. auto module = resolvedTypeInst->GetModule();
  4717. if (!module->mIsReified)
  4718. module->ReifyModule();
  4719. mContext->mScratchModule->PopulateType(resolvedType, BfPopulateType_Full);
  4720. BfMemberSetEntry* memberSetEntry;
  4721. if (resolvedTypeInst->mTypeDef->mMethodSet.TryGetWith(String("Main"), &memberSetEntry))
  4722. {
  4723. BfMethodDef* methodDef = (BfMethodDef*)memberSetEntry->mMemberDef;
  4724. while (methodDef != NULL)
  4725. {
  4726. auto moduleMethodInstance = mContext->mScratchModule->GetMethodInstanceAtIdx(resolvedTypeInst, methodDef->mIdx);
  4727. auto methodInstance = moduleMethodInstance.mMethodInstance;
  4728. if (methodInstance->GetParamCount() != 0)
  4729. {
  4730. mContext->mScratchModule->GetInternalMethod("CreateParamsArray");
  4731. mContext->mScratchModule->GetInternalMethod("DeleteStringArray");
  4732. }
  4733. methodDef = methodDef->mNextWithSameName;
  4734. }
  4735. }
  4736. }
  4737. }
  4738. }
  4739. }
  4740. }
  4741. PopulateReified();
  4742. }
  4743. bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
  4744. {
  4745. BP_ZONE("BfCompiler::Compile");
  4746. if (!mOptions.mErrorString.IsEmpty())
  4747. {
  4748. mPassInstance->Fail(mOptions.mErrorString);
  4749. return false;
  4750. }
  4751. {
  4752. String hotSwapErrors;
  4753. String toolsetErrors;
  4754. for (auto project : mSystem->mProjects)
  4755. {
  4756. if (project->mDisabled)
  4757. continue;
  4758. if (project->mCodeGenOptions.mLTOType != BfLTOType_None)
  4759. {
  4760. if (mOptions.mAllowHotSwapping)
  4761. {
  4762. if (!hotSwapErrors.IsEmpty())
  4763. hotSwapErrors += ", ";
  4764. hotSwapErrors += project->mName;
  4765. }
  4766. if (mOptions.mToolsetType != BfToolsetType_LLVM)
  4767. {
  4768. if (!toolsetErrors.IsEmpty())
  4769. toolsetErrors += ", ";
  4770. toolsetErrors += project->mName;
  4771. }
  4772. }
  4773. }
  4774. if (!hotSwapErrors.IsEmpty())
  4775. mPassInstance->Fail(StrFormat("Hot compilation cannot be used when LTO is enabled in '%s'. Consider setting 'Workspace/Beef/Debug/Enable Hot Compilation' to 'No'.", hotSwapErrors.c_str()));
  4776. if (!toolsetErrors.IsEmpty())
  4777. mPassInstance->Fail(StrFormat("The Workspace Toolset must be set to 'LLVM' in order to use LTO in '%s'. Consider changing 'Workspace/General/Toolset' to 'LLVM'.", toolsetErrors.c_str()));
  4778. }
  4779. //
  4780. {
  4781. String attribName;
  4782. mAttributeTypeOptionMap.Clear();
  4783. for (int typeOptionsIdx = 0; typeOptionsIdx < (int)mSystem->mTypeOptions.size(); typeOptionsIdx++)
  4784. {
  4785. auto& typeOptions = mSystem->mTypeOptions[typeOptionsIdx];
  4786. for (auto& attributeFilter : typeOptions.mAttributeFilters)
  4787. {
  4788. attribName = attributeFilter;
  4789. attribName += "Attribute";
  4790. Array<int>* arrPtr = NULL;
  4791. mAttributeTypeOptionMap.TryAdd(attribName, NULL, &arrPtr);
  4792. arrPtr->Add(typeOptionsIdx);
  4793. }
  4794. }
  4795. }
  4796. // Inc revision for next run through Compile
  4797. mRevision++;
  4798. BfLogSysM("Compile Start. Revision: %d\n", mRevision);
  4799. if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
  4800. mContext->mUnreifiedModule->mIsReified = true;
  4801. else
  4802. mContext->mUnreifiedModule->mIsReified = false;
  4803. if (mOptions.mAllowHotSwapping)
  4804. {
  4805. if (mHotData == NULL)
  4806. {
  4807. mHotData = new HotData();
  4808. mHotData->mCompiler = this;
  4809. }
  4810. }
  4811. else
  4812. {
  4813. delete mHotData;
  4814. mHotData = NULL;
  4815. }
  4816. if (IsHotCompile())
  4817. {
  4818. if (!mOptions.mAllowHotSwapping)
  4819. {
  4820. mPassInstance->Fail("Hot Compilation is not enabled");
  4821. return true;
  4822. }
  4823. if (mHotState == NULL)
  4824. {
  4825. mHotState = new HotState();
  4826. mHotState->mHotProject = mOptions.mHotProject;
  4827. }
  4828. else
  4829. {
  4830. // It should be impossible to switch hot projects without a non-hot compile between them
  4831. BF_ASSERT(mHotState->mHotProject == mOptions.mHotProject);
  4832. }
  4833. }
  4834. else
  4835. {
  4836. for (auto& kv : mContext->mSavedTypeDataMap)
  4837. {
  4838. auto savedTypeData = kv.mValue;
  4839. delete savedTypeData->mHotTypeData;
  4840. savedTypeData->mHotTypeData = NULL;
  4841. }
  4842. delete mHotState;
  4843. mHotState = NULL;
  4844. // This will get rid of any old method data so we don't have any more mPrevVersions
  4845. ClearOldHotData();
  4846. }
  4847. int prevUnfinishedModules = mStats.mModulesStarted - mStats.mModulesFinished;
  4848. mCompletionPct = 0;
  4849. memset(&mStats, 0, sizeof(mStats));
  4850. mCodeGen.ClearResults();
  4851. mCodeGen.ResetStats();
  4852. mStats.mModulesStarted = prevUnfinishedModules;
  4853. if ((mLastRevisionAborted) && (!mIsResolveOnly))
  4854. {
  4855. auto _AddCount = [&](BfModule* module)
  4856. {
  4857. if (module->mAddedToCount)
  4858. {
  4859. if (module->mIsReified)
  4860. mStats.mReifiedModuleCount++;
  4861. }
  4862. };
  4863. for (auto mainModule : mContext->mModules)
  4864. {
  4865. _AddCount(mainModule);
  4866. for (auto specKV : mainModule->mSpecializedMethodModules)
  4867. {
  4868. _AddCount(specKV.mValue);
  4869. }
  4870. }
  4871. }
  4872. if (IsHotCompile())
  4873. {
  4874. mContext->EnsureHotMangledVirtualMethodNames();
  4875. }
  4876. mOutputDirectory = outputDirectory;
  4877. mSystem->StartYieldSection();
  4878. mCanceling = false;
  4879. mSystem->CheckLockYield();
  4880. #ifdef WANT_COMPILE_LOG
  4881. if (!mIsResolveOnly)
  4882. {
  4883. mCompileLogFP = fopen(StrFormat("compile%d.txt", mRevision).c_str(), "wb");
  4884. }
  4885. #endif
  4886. BfTypeDef* typeDef;
  4887. BfLogSysM("UpdateRevisedTypes Revision %d. ResolvePass:%d CursorIdx:%d\n", mRevision, mIsResolveOnly,
  4888. ((mResolvePassData == NULL) || (mResolvePassData->mParser == NULL)) ? - 1 : mResolvePassData->mParser->mCursorIdx);
  4889. mCompileState = CompileState_Normal;
  4890. UpdateRevisedTypes();
  4891. // We need to defer processing the graveyard until here, because mLookupResults contain atom references so we need to make sure
  4892. // those aren't deleted until we can properly handle it.
  4893. mSystem->ProcessAtomGraveyard();
  4894. BpEnter("Compile_Start");
  4895. bool hasRequiredTypes = true;
  4896. //HashSet<BfTypeDef*> internalTypeDefs;
  4897. auto _GetRequiredType = [&](const StringImpl& typeName, int genericArgCount = 0)
  4898. {
  4899. auto typeDef = mSystem->FindTypeDef(typeName, genericArgCount);
  4900. if (typeDef == NULL)
  4901. {
  4902. mPassInstance->Fail(StrFormat("Unable to find system type: %s", typeName.c_str()));
  4903. hasRequiredTypes = false;
  4904. }
  4905. return typeDef;
  4906. };
  4907. mArray1TypeDef = _GetRequiredType("System.Array1");
  4908. mArray2TypeDef = _GetRequiredType("System.Array2");
  4909. mArray3TypeDef = _GetRequiredType("System.Array3");
  4910. mArray4TypeDef = _GetRequiredType("System.Array4");
  4911. mSpanTypeDef = _GetRequiredType("System.Span", 1);
  4912. mAttributeTypeDef = _GetRequiredType("System.Attribute");
  4913. mAttributeUsageAttributeTypeDef = _GetRequiredType("System.AttributeUsageAttribute");
  4914. mBfObjectTypeDef = _GetRequiredType("System.Object");
  4915. mClassVDataTypeDef = _GetRequiredType("System.ClassVData");
  4916. mCLinkAttributeTypeDef = _GetRequiredType("System.CLinkAttribute");
  4917. mCReprAttributeTypeDef = _GetRequiredType("System.CReprAttribute");
  4918. mNoDiscardAttributeTypeDef = _GetRequiredType("System.NoDiscardAttribute");
  4919. mDisableObjectAccessChecksAttributeTypeDef = _GetRequiredType("System.DisableObjectAccessChecksAttribute");
  4920. mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData");
  4921. mDeferredCallTypeDef = _GetRequiredType("System.DeferredCall");
  4922. mDelegateTypeDef = _GetRequiredType("System.Delegate");
  4923. mEnumTypeDef = _GetRequiredType("System.Enum");
  4924. mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
  4925. mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
  4926. mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute");
  4927. mFunctionTypeDef = _GetRequiredType("System.Function");
  4928. mGCTypeDef = _GetRequiredType("System.GC");
  4929. mGenericIEnumerableTypeDef = _GetRequiredType("System.Collections.Generic.IEnumerable");
  4930. mGenericIEnumeratorTypeDef = _GetRequiredType("System.Collections.Generic.IEnumerator");
  4931. mGenericIRefEnumeratorTypeDef = _GetRequiredType("System.Collections.Generic.IRefEnumerator");
  4932. mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
  4933. mInternalTypeDef = _GetRequiredType("System.Internal");
  4934. mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
  4935. mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
  4936. mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);
  4937. mNullableTypeDef = _GetRequiredType("System.Nullable");
  4938. mOrderedAttributeTypeDef = _GetRequiredType("System.OrderedAttribute");
  4939. mPointerTTypeDef = _GetRequiredType("System.Pointer", 1);
  4940. mPointerTypeDef = _GetRequiredType("System.Pointer", 0);
  4941. mReflectArrayType = _GetRequiredType("System.Reflection.ArrayType");
  4942. mReflectFieldDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldData");
  4943. mReflectFieldSplatDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldSplatData");
  4944. mReflectMethodDataDef = _GetRequiredType("System.Reflection.TypeInstance.MethodData");
  4945. mReflectParamDataDef = _GetRequiredType("System.Reflection.TypeInstance.ParamData");
  4946. mReflectPointerType = _GetRequiredType("System.Reflection.PointerType");
  4947. mReflectSizedArrayType = _GetRequiredType("System.Reflection.SizedArrayType");
  4948. mReflectSpecializedGenericType = _GetRequiredType("System.Reflection.SpecializedGenericType");
  4949. mReflectTypeInstanceTypeDef = _GetRequiredType("System.Reflection.TypeInstance");
  4950. mReflectUnspecializedGenericType = _GetRequiredType("System.Reflection.UnspecializedGenericType");
  4951. mSizedArrayTypeDef = _GetRequiredType("System.SizedArray", 2);
  4952. mSkipAccessCheckAttributeTypeDef = _GetRequiredType("System.SkipAccessCheckAttribute");
  4953. mStaticInitAfterAttributeTypeDef = _GetRequiredType("System.StaticInitAfterAttribute");
  4954. mStaticInitPriorityAttributeTypeDef = _GetRequiredType("System.StaticInitPriorityAttribute");
  4955. mStringTypeDef = _GetRequiredType("System.String");
  4956. mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
  4957. mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
  4958. mTypeTypeDef = _GetRequiredType("System.Type");
  4959. mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
  4960. mValueTypeTypeDef = _GetRequiredType("System.ValueType");
  4961. for (int i = 0; i < BfTypeCode_Length; i++)
  4962. mContext->mPrimitiveStructTypes[i] = NULL;
  4963. if (!hasRequiredTypes)
  4964. {
  4965. // Force rebuilding
  4966. mInInvalidState = true;
  4967. mOptions.mForceRebuildIdx++;
  4968. return true;
  4969. }
  4970. mSystem->CheckLockYield();
  4971. VisitSourceExteriorNodes();
  4972. //BF_ASSERT(hasRequiredTypes);
  4973. if (!mIsResolveOnly)
  4974. {
  4975. HashSet<BfModule*> foundVDataModuleSet;
  4976. for (auto bfProject : mSystem->mProjects)
  4977. {
  4978. if (bfProject->mDisabled)
  4979. continue;
  4980. if ((mBfObjectTypeDef != NULL) && (!bfProject->ContainsReference(mBfObjectTypeDef->mProject)))
  4981. {
  4982. mPassInstance->Fail(StrFormat("Project '%s' must reference core library '%s'", bfProject->mName.c_str(), mBfObjectTypeDef->mProject->mName.c_str()));
  4983. }
  4984. if ((bfProject->mTargetType != BfTargetType_BeefConsoleApplication) && (bfProject->mTargetType != BfTargetType_BeefWindowsApplication) &&
  4985. (bfProject->mTargetType != BfTargetType_BeefDynLib) &&
  4986. (bfProject->mTargetType != BfTargetType_C_ConsoleApplication) && (bfProject->mTargetType != BfTargetType_C_WindowsApplication) &&
  4987. (bfProject->mTargetType != BfTargetType_BeefTest))
  4988. continue;
  4989. if (bfProject->mTargetType == BfTargetType_BeefTest)
  4990. {
  4991. // Force internal test methods
  4992. auto bfModule = mContext->mScratchModule;
  4993. bfModule->GetInternalMethod("Test_Init");
  4994. bfModule->GetInternalMethod("Test_Query");
  4995. bfModule->GetInternalMethod("Test_Finish");
  4996. }
  4997. bool found = false;
  4998. for (auto module : mVDataModules)
  4999. {
  5000. if (module->mProject == bfProject)
  5001. {
  5002. found = true;
  5003. foundVDataModuleSet.Add(module);
  5004. //module->StartNewRevision();
  5005. }
  5006. }
  5007. if (!found)
  5008. {
  5009. auto module = new BfVDataModule(mContext);
  5010. module->mProject = bfProject;
  5011. module->Init();
  5012. module->FinishInit();
  5013. module->mIsSpecialModule = true;
  5014. BF_ASSERT(!mContext->mLockModules);
  5015. mContext->mModules.push_back(module);
  5016. mVDataModules.push_back(module);
  5017. foundVDataModuleSet.Add(module);
  5018. }
  5019. }
  5020. // Remove old vdata
  5021. for (int moduleIdx = 0; moduleIdx < (int) mVDataModules.size(); moduleIdx++)
  5022. {
  5023. auto module = mVDataModules[moduleIdx];
  5024. if (!foundVDataModuleSet.Contains(module))
  5025. {
  5026. delete module;
  5027. mVDataModules.erase(mVDataModules.begin() + moduleIdx);
  5028. moduleIdx--;
  5029. mContext->mModules.Remove(module);
  5030. }
  5031. }
  5032. }
  5033. if (mIsResolveOnly)
  5034. VisitAutocompleteExteriorIdentifiers();
  5035. if (!hasRequiredTypes)
  5036. {
  5037. BfLogSysM("Missing required types\n");
  5038. }
  5039. mStats.mTypesQueued = 0;
  5040. mStats.mMethodsQueued = 0;
  5041. mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size();
  5042. mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size();
  5043. if (hasRequiredTypes)
  5044. {
  5045. mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef, BfPopulateType_Full);
  5046. mContext->RemapObject();
  5047. mSystem->CheckLockYield();
  5048. mWantsDeferMethodDecls = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
  5049. CompileReified();
  5050. mWantsDeferMethodDecls = false;
  5051. }
  5052. BpLeave();
  5053. BpEnter("Compile_End");
  5054. {
  5055. BP_ZONE("ProcessingLiveness");
  5056. for (auto type : mContext->mResolvedTypes)
  5057. {
  5058. auto depType = type->ToDependedType();
  5059. if (depType != NULL)
  5060. depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_AwaitingReference);
  5061. }
  5062. bool didWork = false;
  5063. UpdateDependencyMap(mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_ResolveUnused, didWork);
  5064. if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
  5065. {
  5066. // If UpdateDependencyMap caused methods to be reified, then we need to run PopulateReified again-
  5067. // because those methods may be virtual and we need to reify overrides (for example).
  5068. // We use the DoWorkLoop result to determine if there were actually any changes from UpdateDependencyMap
  5069. if (didWork)
  5070. {
  5071. PopulateReified();
  5072. }
  5073. }
  5074. }
  5075. if (hasRequiredTypes)
  5076. ProcessPurgatory(true);
  5077. // Mark used modules
  5078. if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!mCanceling))
  5079. {
  5080. bool hadActualTarget = false;
  5081. if (!mIsResolveOnly)
  5082. {
  5083. SizedArray<BfModule*, 32> requiredModules;
  5084. for (auto typeDef : mSystem->mTypeDefs)
  5085. {
  5086. if ((typeDef->mIsAlwaysInclude) && (!typeDef->mIsPartial))
  5087. {
  5088. auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef);
  5089. if (requiredType != NULL)
  5090. {
  5091. auto requiredModule = requiredType->GetModule();
  5092. if (requiredModule != NULL)
  5093. requiredModules.push_back(requiredModule);
  5094. }
  5095. }
  5096. }
  5097. mContext->mReferencedIFaceSlots.Clear();
  5098. bool hasTests = false;
  5099. for (auto project : mSystem->mProjects)
  5100. {
  5101. if (project->mTargetType == BfTargetType_BeefTest)
  5102. hasTests = true;
  5103. project->mUsedModules.Clear();
  5104. project->mReferencedTypeData.Clear();
  5105. if (project->mDisabled)
  5106. continue;
  5107. if (project->mTargetType == BfTargetType_BeefLib)
  5108. continue;
  5109. hadActualTarget = true;
  5110. for (auto requiredModule : requiredModules)
  5111. {
  5112. mContext->MarkUsedModules(project, requiredModule);
  5113. }
  5114. String entryClassName = project->mStartupObject;
  5115. typeDef = mSystem->FindTypeDef(entryClassName, 0, project);
  5116. if (typeDef != NULL)
  5117. {
  5118. auto startupType = mContext->mScratchModule->ResolveTypeDef(typeDef);
  5119. if (startupType != NULL)
  5120. {
  5121. auto startupTypeInst = startupType->ToTypeInstance();
  5122. if (startupTypeInst != NULL)
  5123. {
  5124. mContext->MarkUsedModules(project, startupTypeInst->GetModule());
  5125. }
  5126. }
  5127. }
  5128. if (hasTests)
  5129. {
  5130. for (auto type : mContext->mResolvedTypes)
  5131. {
  5132. auto typeInstance = type->ToTypeInstance();
  5133. if ((typeInstance != NULL) &&
  5134. (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest))
  5135. {
  5136. bool typeHasTest = false;
  5137. for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
  5138. {
  5139. if (methodInstanceGroup.mDefault != NULL)
  5140. {
  5141. auto methodInstance = methodInstanceGroup.mDefault;
  5142. if ((methodInstance->GetCustomAttributes() != NULL) &&
  5143. (methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
  5144. {
  5145. typeHasTest = true;
  5146. }
  5147. }
  5148. }
  5149. if (typeHasTest)
  5150. mContext->MarkUsedModules(typeInstance->mTypeDef->mProject, typeInstance->mModule);
  5151. }
  5152. }
  5153. }
  5154. }
  5155. // Leave types reified when hot compiling
  5156. if ((!IsHotCompile()) && (hadActualTarget))
  5157. mContext->TryUnreifyModules();
  5158. }
  5159. }
  5160. // Generate slot nums
  5161. if ((!mIsResolveOnly) && (hasRequiredTypes) && (!mCanceling))
  5162. {
  5163. if ((!IsHotCompile()) || (mHotState->mHasNewInterfaceTypes))
  5164. {
  5165. int prevSlotCount = mMaxInterfaceSlots;
  5166. GenerateSlotNums();
  5167. if ((prevSlotCount != -1) && (prevSlotCount != mMaxInterfaceSlots))
  5168. {
  5169. mInterfaceSlotCountChanged = true;
  5170. }
  5171. if (mHotState != NULL)
  5172. mHotState->mHasNewInterfaceTypes = false;
  5173. }
  5174. }
  5175. // Resolve unused types
  5176. if ((mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_ResolveUnused) && (!mCanceling))
  5177. {
  5178. // Finish off any outstanding modules so we can code generate in parallel with handling the unreified stuff
  5179. for (auto module : mContext->mModules)
  5180. {
  5181. if (!module->mIsSpecialModule)
  5182. {
  5183. if ((module->mIsReified) && (module->mIsModuleMutable))
  5184. {
  5185. module->Finish();
  5186. }
  5187. }
  5188. }
  5189. DoWorkLoop();
  5190. BfLogSysM("Compile QueueUnused\n");
  5191. mCompileState = BfCompiler::CompileState_Unreified;
  5192. BpLeave();
  5193. BpEnter("Compile_QueueUnused");
  5194. while (true)
  5195. {
  5196. BP_ZONE("Compile_QueueUnused");
  5197. bool queuedMoreMethods = false;
  5198. int startTypeInitCount = mTypeInitCount;
  5199. for (auto typeDef : mSystem->mTypeDefs)
  5200. {
  5201. mSystem->CheckLockYield();
  5202. if (mCanceling)
  5203. {
  5204. BfLogSysM("Canceling from Compile typeDef loop\n");
  5205. break;
  5206. }
  5207. if (typeDef->mProject->mDisabled)
  5208. continue;
  5209. if (typeDef->mIsPartial)
  5210. continue;
  5211. if (typeDef->mTypeCode == BfTypeCode_Extension)
  5212. continue;
  5213. mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
  5214. }
  5215. for (auto type : mContext->mResolvedTypes)
  5216. {
  5217. auto module = type->GetModule();
  5218. if (module == NULL)
  5219. continue;
  5220. if ((type->IsIncomplete()) && (type->IsTypeInstance()) && (!type->IsSpecializedType()))
  5221. {
  5222. mSystem->CheckLockYield();
  5223. module->PopulateType(type, BfPopulateType_Full);
  5224. }
  5225. auto typeInst = type->ToTypeInstance();
  5226. if (typeInst == NULL)
  5227. continue;
  5228. if (typeInst->IsUnspecializedTypeVariation())
  5229. continue;
  5230. if (!typeInst->IsSpecializedType())
  5231. {
  5232. // Find any remaining methods for unreified processing
  5233. for (auto&& methodInstGroup : typeInst->mMethodInstanceGroups)
  5234. {
  5235. if ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
  5236. (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference))
  5237. {
  5238. queuedMoreMethods = true;
  5239. if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mIsForeignMethodDef))
  5240. {
  5241. mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodInstGroup.mDefault->mMethodDef, BfTypeVector(),
  5242. (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
  5243. }
  5244. else
  5245. mContext->mUnreifiedModule->GetMethodInstance(typeInst, typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx], BfTypeVector(),
  5246. (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
  5247. }
  5248. }
  5249. }
  5250. }
  5251. if ((!queuedMoreMethods) && (startTypeInitCount == mTypeInitCount))
  5252. break;
  5253. DoWorkLoop();
  5254. }
  5255. bool didWork = false;
  5256. UpdateDependencyMap(true, didWork);
  5257. DoWorkLoop();
  5258. mCompileState = BfCompiler::CompileState_Normal;
  5259. }
  5260. else
  5261. {
  5262. DoWorkLoop();
  5263. }
  5264. if (hasRequiredTypes)
  5265. ProcessPurgatory(false);
  5266. // Old Mark used modules
  5267. if ((!mIsResolveOnly) && (hasRequiredTypes))
  5268. {
  5269. // if ((!mPassInstance->HasFailed()) && (!mCanceling))
  5270. // {
  5271. // if ((!IsHotCompile()) || (mHotState->mHasNewInterfaceTypes))
  5272. // {
  5273. // GenerateSlotNums();
  5274. // if (mHotState != NULL)
  5275. // mHotState->mHasNewInterfaceTypes = false;
  5276. // }
  5277. // }
  5278. if ((!mPassInstance->HasFailed()) && (!mCanceling))
  5279. {
  5280. if (!mOptions.mAllowHotSwapping)
  5281. {
  5282. GenerateDynCastData();
  5283. mContext->ProcessWorkList(false, false);
  5284. }
  5285. mCompileState = BfCompiler::CompileState_VData;
  5286. for (auto vdataModule : mVDataModules)
  5287. CreateVData(vdataModule);
  5288. for (auto vdataModule : mVDataModules)
  5289. FixVDataHash(vdataModule);
  5290. mCompileState = BfCompiler::CompileState_Normal;
  5291. }
  5292. // Don't clear out unused string pool entries while we are hot swapping, because we want string literals
  5293. // to still be the same pointer if it's erased and then put back
  5294. if ((!IsHotCompile()) && (!mCanceling))
  5295. ClearUnusedStringPoolEntries();
  5296. mContext->UpdateAfterDeletingTypes();
  5297. }
  5298. // We need to check the specialized errors before writing out modules --
  5299. // this call is responsible for deleting dead method specializations that contained errors, or for setting
  5300. // the mHadBuildErrors on the module if there was a method specialization error that didn't die
  5301. mContext->CheckSpecializedErrorData();
  5302. mContext->Finish();
  5303. if ((!mIsResolveOnly) && (!IsHotCompile()))
  5304. ClearOldHotData();
  5305. mPassInstance->TryFlushDeferredError();
  5306. BpLeave();
  5307. BpEnter("Compile_Finish");
  5308. //TODO:!!
  5309. //mCanceling = true;
  5310. String moduleListStr;
  5311. int numModulesWritten = 0;
  5312. if ((hasRequiredTypes) && (!mCanceling))
  5313. {
  5314. if (!mIsResolveOnly)
  5315. {
  5316. int idx = 0;
  5317. BF_ASSERT(mContext->mMethodWorkList.IsEmpty());
  5318. //bfContext->mLockModules = true;
  5319. for (int moduleIdx = 0; moduleIdx < (int)mContext->mModules.size(); moduleIdx++)
  5320. {
  5321. //bool clearModule = false;
  5322. auto mainModule = mContext->mModules[moduleIdx];
  5323. BfModule* bfModule = mainModule;
  5324. if (bfModule->mIsReified)
  5325. {
  5326. auto itr = mainModule->mSpecializedMethodModules.begin();
  5327. while (true)
  5328. {
  5329. if (bfModule->mIsModuleMutable)
  5330. {
  5331. //clearModule = true;
  5332. // Note that Finish will just return immediately if we have errors, we don't write out modules with errors
  5333. // The 'mLastModuleWrittenRevision' will not be updated in the case.
  5334. bfModule->Finish();
  5335. mainModule->mRevision = std::max(mainModule->mRevision, bfModule->mRevision);
  5336. }
  5337. if (bfModule->mLastModuleWrittenRevision == mRevision)
  5338. {
  5339. if (!moduleListStr.empty())
  5340. moduleListStr += ", ";
  5341. moduleListStr += bfModule->mModuleName;
  5342. numModulesWritten++;
  5343. }
  5344. if (bfModule->mParentModule != NULL)
  5345. {
  5346. for (auto&& fileName : bfModule->mOutFileNames)
  5347. {
  5348. if (!mainModule->mOutFileNames.Contains(fileName))
  5349. mainModule->mOutFileNames.push_back(fileName);
  5350. }
  5351. }
  5352. if (bfModule->mNextAltModule != NULL)
  5353. {
  5354. bfModule = bfModule->mNextAltModule;
  5355. }
  5356. else
  5357. {
  5358. if (itr == mainModule->mSpecializedMethodModules.end())
  5359. break;
  5360. bfModule = itr->mValue;
  5361. ++itr;
  5362. }
  5363. }
  5364. }
  5365. mainModule->ClearModule();
  5366. }
  5367. //bfContext->mLockModules = false;
  5368. }
  5369. else
  5370. {
  5371. bool isTargeted = (mResolvePassData != NULL) && (mResolvePassData->mParser != NULL);
  5372. if (!isTargeted)
  5373. {
  5374. for (auto bfModule : mContext->mModules)
  5375. {
  5376. if (bfModule->mIsModuleMutable)
  5377. {
  5378. bfModule->Finish();
  5379. bfModule->mRevision = std::max(bfModule->mRevision, bfModule->mRevision);
  5380. bfModule->ClearModuleData();
  5381. }
  5382. }
  5383. }
  5384. }
  5385. }
  5386. /*if (!moduleListStr.empty())
  5387. mPassInstance->OutputLine(StrFormat("%d modules generated: %s", numModulesWritten, moduleListStr.c_str()));*/
  5388. //CompileLog("%d object files written: %s\n", numModulesWritten, moduleListStr.c_str());
  5389. //printf("Compile done, waiting for finish\n");
  5390. while (true)
  5391. {
  5392. if (!hasRequiredTypes)
  5393. break;
  5394. if (mCanceling)
  5395. mCodeGen.Cancel();
  5396. bool isDone = mCodeGen.Finish();
  5397. UpdateCompletion();
  5398. if (isDone)
  5399. break;
  5400. }
  5401. mCodeGen.ProcessErrors(mPassInstance, mCanceling);
  5402. // This has to happen after codegen because we may delete modules that are referenced in codegen
  5403. mContext->Cleanup();
  5404. if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling))
  5405. {
  5406. // Only save 'saved type data' for temporarily-deleted types like on-demand types.
  5407. // If we don't reuse it within a compilation pass then we put those IDs up to be
  5408. // reused later. We don't do this for hot reloading because there are cases like
  5409. // a user renaming a type that we want to allow him to be able to undo and then
  5410. // hot-recompile successfully.
  5411. for (auto& kv : mContext->mSavedTypeDataMap)
  5412. {
  5413. auto savedTypeData = kv.mValue;
  5414. mTypeIdFreeList.Add(savedTypeData->mTypeId);
  5415. delete savedTypeData;
  5416. }
  5417. mContext->mSavedTypeDataMap.Clear();
  5418. mContext->mSavedTypeData.Clear();
  5419. }
  5420. #ifdef BF_PLATFORM_WINDOWS
  5421. if (!mIsResolveOnly)
  5422. {
  5423. for (auto mainModule : mContext->mModules)
  5424. {
  5425. BfModule* bfModule = mainModule;
  5426. if (bfModule->mIsReified)
  5427. {
  5428. for (auto outFileName : bfModule->mOutFileNames)
  5429. {
  5430. if (outFileName.mModuleWritten)
  5431. BeLibManager::Get()->AddUsedFileName(outFileName.mFileName);
  5432. }
  5433. }
  5434. }
  5435. BeLibManager::Get()->Finish();
  5436. }
  5437. #endif
  5438. int numObjFilesWritten = 0;
  5439. for (auto& fileEntry : mCodeGen.mCodeGenFiles)
  5440. {
  5441. if (!fileEntry.mWasCached)
  5442. numObjFilesWritten++;
  5443. }
  5444. mPassInstance->OutputLine(StrFormat(":low %d module%s built, %d object file%s generated",
  5445. numModulesWritten, (numModulesWritten != 1) ? "s" : "",
  5446. numObjFilesWritten, (numObjFilesWritten != 1) ? "s" : ""));
  5447. BpLeave();
  5448. mPassInstance->WriteErrorSummary();
  5449. if ((mCanceling) && (!mIsResolveOnly))
  5450. {
  5451. mPassInstance->Fail("Build canceled");
  5452. mContext->CancelWorkItems();
  5453. CompileLog("Compile canceled\n");
  5454. }
  5455. BfLogSysM("TypesPopulated:%d MethodsDeclared:%d MethodsProcessed:%d Canceled? %d\n", mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
  5456. UpdateCompletion();
  5457. if ((!mIsResolveOnly) && (!mPassInstance->HasFailed()) && (!mCanceling))
  5458. {
  5459. //BF_ASSERT(mCompletionPct >= 0.99999f);
  5460. }
  5461. if (mCompileLogFP != NULL)
  5462. {
  5463. fclose(mCompileLogFP);
  5464. mCompileLogFP = NULL;
  5465. }
  5466. UpdateCompletion();
  5467. mStats.mTotalTypes = mContext->mResolvedTypes.mCount;
  5468. String compileInfo;
  5469. if (mIsResolveOnly)
  5470. compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, mResolvePassData->mParser != NULL);
  5471. compileInfo += StrFormat("TotalTypes:%d\nTypesPopulated:%d\nMethodsDeclared:%d\nMethodsProcessed:%d\nCanceled? %d\n", mStats.mTotalTypes, mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
  5472. compileInfo += StrFormat("TypesPopulated:%d\n", mStats.mTypesPopulated);
  5473. compileInfo += StrFormat("MethodDecls:%d\nMethodsProcessed:%d\nModulesStarted:%d\nModulesFinished:%d\n", mStats.mMethodDeclarations, mStats.mMethodsProcessed, mStats.mModulesFinished);
  5474. BpEvent("CompileDone", compileInfo.c_str());
  5475. if (mHotState != NULL)
  5476. {
  5477. for (auto& fileEntry : mCodeGen.mCodeGenFiles)
  5478. {
  5479. if (fileEntry.mWasCached)
  5480. continue;
  5481. mHotState->mQueuedOutFiles.Add(fileEntry);
  5482. }
  5483. if (!mPassInstance->HasFailed())
  5484. {
  5485. // Clear these out when we know we've compiled without error
  5486. mHotState->mNewlySlottedTypeIds.Clear();
  5487. mHotState->mSlotDefineTypeIds.Clear();
  5488. }
  5489. }
  5490. mCompileState = BfCompiler::CompileState_None;
  5491. // extern MemReporter gBEMemReporter;
  5492. // extern int gBEMemReporterSize;
  5493. // gBEMemReporter.Report();
  5494. // int memReporterSize = gBEMemReporterSize;
  5495. mLastRevisionAborted = mCanceling || !hasRequiredTypes;
  5496. bool didCancel = mCanceling && hasRequiredTypes;
  5497. mCanceling = false;
  5498. return !didCancel;
  5499. }
  5500. bool BfCompiler::Compile(const StringImpl& outputDirectory)
  5501. {
  5502. bool success = DoCompile(outputDirectory);
  5503. if (!success)
  5504. return false;
  5505. if (mPassInstance->HasFailed())
  5506. return true;
  5507. if (!mInterfaceSlotCountChanged)
  5508. return true;
  5509. BfLogSysM("Interface slot count increased. Rebuilding relevant modules.\n");
  5510. mPassInstance->OutputLine("Interface slot count increased. Rebuilding relevant modules.");
  5511. // Recompile with the increased slot count
  5512. success = DoCompile(outputDirectory);
  5513. BF_ASSERT(!mInterfaceSlotCountChanged);
  5514. return success;
  5515. }
  5516. void BfCompiler::ClearResults()
  5517. {
  5518. BP_ZONE("BfCompiler::ClearResults");
  5519. mCodeGen.ClearResults();
  5520. }
  5521. // Can should still leave the system in a state such that we when we save as much progress as possible while
  5522. // still leaving the system in a state that the next attempt at compile will resume with a valid state
  5523. // Canceling will still process the pending PopulateType calls but may leave items in the method worklist.
  5524. // Note that Cancel is an async request to cancel
  5525. void BfCompiler::Cancel()
  5526. {
  5527. mCanceling = true;
  5528. mHadCancel = true;
  5529. BfLogSysM("BfCompiler::Cancel\n");
  5530. BpEvent("BfCompiler::Cancel", "");
  5531. }
  5532. //#define WANT_COMPILE_LOG
  5533. void BfCompiler::CompileLog(const char* fmt ...)
  5534. {
  5535. #ifdef WANT_COMPILE_LOG
  5536. if (mCompileLogFP == NULL)
  5537. return;
  5538. //static int lineNum = 0;
  5539. //lineNum++;
  5540. va_list argList;
  5541. va_start(argList, fmt);
  5542. String aResult = vformat(fmt, argList);
  5543. va_end(argList);
  5544. //aResult = StrFormat("%d ", lineNum) + aResult;
  5545. fwrite(aResult.c_str(), 1, aResult.length(), mCompileLogFP);
  5546. #endif
  5547. }
  5548. void BfCompiler::ReportMemory(MemReporter* memReporter)
  5549. {
  5550. AutoCrit crit(mSystem->mDataLock);
  5551. {
  5552. AutoMemReporter autoMemReporter(memReporter, "Context");
  5553. mContext->ReportMemory(memReporter);
  5554. }
  5555. for (auto type : mContext->mResolvedTypes)
  5556. {
  5557. AutoMemReporter autoMemReporter(memReporter, "Types");
  5558. type->ReportMemory(memReporter);
  5559. }
  5560. for (auto module : mContext->mModules)
  5561. {
  5562. AutoMemReporter autoMemReporter(memReporter, "Modules");
  5563. module->ReportMemory(memReporter);
  5564. }
  5565. {
  5566. AutoMemReporter autoMemReporter(memReporter, "ScratchModule");
  5567. mContext->mScratchModule->ReportMemory(memReporter);
  5568. }
  5569. for (auto vdataModule : mVDataModules)
  5570. {
  5571. AutoMemReporter autoMemReporter(memReporter, "VDataModules");
  5572. vdataModule->ReportMemory(memReporter);
  5573. }
  5574. if (mHotData != NULL)
  5575. {
  5576. AutoMemReporter autoMemReporter(memReporter, "HotData");
  5577. memReporter->Add(sizeof(HotData));
  5578. memReporter->AddMap(mHotData->mMethodMap);
  5579. for (auto& kv : mHotData->mMethodMap)
  5580. {
  5581. memReporter->AddStr(kv.mKey);
  5582. memReporter->Add(sizeof(BfHotMethod));
  5583. memReporter->AddVec(kv.mValue->mReferences);
  5584. }
  5585. }
  5586. if (mHotState != NULL)
  5587. {
  5588. AutoMemReporter autoMemReporter(memReporter, "HotState");
  5589. memReporter->Add(sizeof(HotState));
  5590. memReporter->AddVec(mHotState->mQueuedOutFiles, false);
  5591. memReporter->AddHashSet(mHotState->mSlotDefineTypeIds, false);
  5592. memReporter->AddHashSet(mHotState->mPendingDataChanges, false);
  5593. memReporter->AddMap(mHotState->mDeletedTypeNameMap, false);
  5594. for (auto& kv : mHotState->mDeletedTypeNameMap)
  5595. {
  5596. memReporter->AddStr(kv.mKey, false);
  5597. }
  5598. }
  5599. }
  5600. //////////////////////////////////////////////////////////////////////////
  5601. void BfCompiler::GenerateAutocompleteInfo()
  5602. {
  5603. BP_ZONE("BfCompiler::GetAutocompleteInfo");
  5604. String& autoCompleteResultString = *gTLStrReturn.Get();
  5605. autoCompleteResultString.Clear();
  5606. auto _GetDocString = [&](BfCommentNode* commentNode, StringImpl& docString)
  5607. {
  5608. commentNode->ToString(docString);
  5609. for (int i = 0; i < (int)docString.length(); i++)
  5610. {
  5611. char c = docString[i];
  5612. if (c == '\n')
  5613. docString[i] = '\x3';
  5614. }
  5615. };
  5616. auto bfModule = mResolvePassData->mAutoComplete->mModule;
  5617. if (bfModule != NULL)
  5618. {
  5619. auto autoComplete = mResolvePassData->mAutoComplete;
  5620. if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
  5621. return; // Already handled
  5622. if (autoComplete->mResolveType == BfResolveType_GetVarType)
  5623. {
  5624. autoCompleteResultString = autoComplete->mVarTypeName;
  5625. return;
  5626. }
  5627. if (autoComplete->mUncertain)
  5628. autoCompleteResultString += "uncertain\n";
  5629. if (autoComplete->mDefaultSelection.length() != 0)
  5630. autoCompleteResultString += StrFormat("select\t%s\n", autoComplete->mDefaultSelection.c_str());
  5631. auto _EncodeTypeDef = [] (BfTypeDef* typeDef)
  5632. {
  5633. String typeName = typeDef->mProject->mName + ":" + typeDef->mFullName.ToString();
  5634. if (!typeDef->mGenericParamDefs.IsEmpty())
  5635. typeName += StrFormat("`%d", (int)typeDef->mGenericParamDefs.size());
  5636. return typeName;
  5637. };
  5638. if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
  5639. {
  5640. if (autoComplete->mDefTypeGenericParamIdx != -1)
  5641. {
  5642. autoCompleteResultString += StrFormat("typeGenericParam\t%d\n", autoComplete->mDefTypeGenericParamIdx);
  5643. autoCompleteResultString += StrFormat("typeRef\t%s\n", _EncodeTypeDef(autoComplete->mDefType).c_str());
  5644. }
  5645. else if (autoComplete->mDefMethodGenericParamIdx != -1)
  5646. {
  5647. autoCompleteResultString += StrFormat("methodGenericParam\t%d\n", autoComplete->mDefMethodGenericParamIdx);
  5648. autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
  5649. }
  5650. else if ((autoComplete->mReplaceLocalId != -1) && (autoComplete->mDefMethod != NULL))
  5651. {
  5652. autoCompleteResultString += StrFormat("localId\t%d\n", autoComplete->mReplaceLocalId);
  5653. autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
  5654. }
  5655. else if (autoComplete->mDefField != NULL)
  5656. {
  5657. autoCompleteResultString += StrFormat("fieldRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefField->mIdx);
  5658. }
  5659. else if (autoComplete->mDefProp != NULL)
  5660. {
  5661. autoCompleteResultString += StrFormat("propertyRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefProp->mIdx);
  5662. }
  5663. else if (autoComplete->mDefMethod != NULL)
  5664. {
  5665. if (autoComplete->mDefMethod->mMethodType == BfMethodType_Ctor)
  5666. autoCompleteResultString += StrFormat("ctorRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
  5667. else
  5668. autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
  5669. }
  5670. else if (autoComplete->mDefType != NULL)
  5671. {
  5672. autoCompleteResultString += StrFormat("typeRef\t%s\n", _EncodeTypeDef(autoComplete->mDefType).c_str());
  5673. }
  5674. if (autoComplete->mInsertEndIdx > 0)
  5675. {
  5676. if (mResolvePassData->mParser->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
  5677. autoComplete->mInsertEndIdx--;
  5678. }
  5679. }
  5680. const char* wantsDocEntry = NULL;
  5681. if (!autoComplete->mDocumentationEntryName.IsEmpty())
  5682. wantsDocEntry = autoComplete->mDocumentationEntryName.c_str();
  5683. if (autoComplete->mInsertStartIdx != -1)
  5684. {
  5685. autoCompleteResultString += StrFormat("insertRange\t%d %d\n", autoComplete->mInsertStartIdx, autoComplete->mInsertEndIdx);
  5686. }
  5687. if ((autoComplete->mDefMethod == NULL) && (autoComplete->mGetDefinitionNode == NULL) && (autoComplete->mIsGetDefinition) && (autoComplete->mMethodMatchInfo != NULL))
  5688. {
  5689. // Take loc from methodMatchInfo
  5690. if (autoComplete->mMethodMatchInfo->mInstanceList.size() > 0)
  5691. {
  5692. int bestIdx = autoComplete->mMethodMatchInfo->mBestIdx;
  5693. auto typeInst = autoComplete->mMethodMatchInfo->mInstanceList[bestIdx].mTypeInstance;
  5694. auto methodDef = autoComplete->mMethodMatchInfo->mInstanceList[bestIdx].mMethodDef;
  5695. if (methodDef->mMethodDeclaration != NULL)
  5696. {
  5697. auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDef->mMethodDeclaration);
  5698. if (ctorDecl != NULL)
  5699. autoComplete->SetDefinitionLocation(ctorDecl->mThisToken);
  5700. else
  5701. autoComplete->SetDefinitionLocation(methodDef->GetMethodDeclaration()->mNameNode);
  5702. }
  5703. else // Just select type then
  5704. autoComplete->SetDefinitionLocation(typeInst->mTypeDef->mTypeDeclaration->mNameNode);
  5705. }
  5706. }
  5707. if (autoComplete->mGetDefinitionNode != NULL)
  5708. {
  5709. auto astNode = autoComplete->mGetDefinitionNode;
  5710. auto bfSource = autoComplete->mGetDefinitionNode->GetSourceData()->ToParserData();
  5711. if (bfSource != NULL)
  5712. {
  5713. int line = 0;
  5714. int lineChar = 0;
  5715. bfSource->GetLineCharAtIdx(astNode->GetSrcStart(), line, lineChar);
  5716. autoCompleteResultString += StrFormat("defLoc\t%s\t%d\t%d\n", bfSource->mFileName.c_str(), line, lineChar);
  5717. }
  5718. }
  5719. auto methodMatchInfo = autoComplete->mMethodMatchInfo;
  5720. if ((methodMatchInfo != NULL) && (wantsDocEntry == NULL))
  5721. {
  5722. if (methodMatchInfo->mInstanceList.size() > 0)
  5723. {
  5724. String invokeInfoText;
  5725. invokeInfoText += StrFormat("%d", methodMatchInfo->mBestIdx);
  5726. for (int srcPosIdx = 0; srcPosIdx < (int) methodMatchInfo->mSrcPositions.size(); srcPosIdx++)
  5727. invokeInfoText += StrFormat(" %d", methodMatchInfo->mSrcPositions[srcPosIdx]);
  5728. autoCompleteResultString += "invokeInfo\t";
  5729. autoCompleteResultString += invokeInfoText;
  5730. autoCompleteResultString += "\n";
  5731. }
  5732. int idx = 0;
  5733. for (auto& methodEntry : methodMatchInfo->mInstanceList)
  5734. {
  5735. String methodText;
  5736. if (methodEntry.mPayloadEnumField != NULL)
  5737. {
  5738. auto payloadFieldDef = methodEntry.mPayloadEnumField->GetFieldDef();
  5739. methodText += payloadFieldDef->mName;
  5740. methodText += "(\x1";
  5741. auto payloadType = methodEntry.mPayloadEnumField->mResolvedType;
  5742. BF_ASSERT(payloadType->IsTuple());
  5743. if (payloadType->IsTuple())
  5744. {
  5745. auto tupleType = (BfTupleType*)payloadType;
  5746. for (int fieldIdx = 0; fieldIdx < (int)tupleType->mFieldInstances.size(); fieldIdx++)
  5747. {
  5748. auto fieldInstance = &tupleType->mFieldInstances[fieldIdx];
  5749. auto fieldDef = fieldInstance->GetFieldDef();
  5750. if (fieldIdx > 0)
  5751. methodText += ",\x1 ";
  5752. methodText += bfModule->TypeToString(fieldInstance->mResolvedType, BfTypeNameFlag_ResolveGenericParamNames);
  5753. if (!fieldDef->IsUnnamedTupleField())
  5754. {
  5755. methodText += " ";
  5756. if (fieldDef->mName.StartsWith("_"))
  5757. methodText += fieldDef->mName.Substring(1);
  5758. else
  5759. methodText += fieldDef->mName;
  5760. }
  5761. }
  5762. }
  5763. methodText += "\x1)";
  5764. }
  5765. else
  5766. {
  5767. BfMethodInstance* methodInstance = NULL;
  5768. if (methodEntry.mMethodDef->mIdx < 0)
  5769. {
  5770. for (auto localMethod : mContext->mLocalMethodGraveyard)
  5771. {
  5772. if (localMethod->mMethodDef == methodEntry.mMethodDef)
  5773. {
  5774. methodInstance = localMethod->mMethodInstanceGroup->mDefault;
  5775. break;
  5776. }
  5777. }
  5778. }
  5779. else
  5780. methodInstance = bfModule->GetRawMethodInstanceAtIdx(methodEntry.mTypeInstance, methodEntry.mMethodDef->mIdx);
  5781. auto curMethodInstance = methodInstance;
  5782. curMethodInstance = methodMatchInfo->mCurMethodInstance;
  5783. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(bfModule->mCurTypeInstance, methodMatchInfo->mCurTypeInstance);
  5784. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(bfModule->mCurMethodInstance, curMethodInstance);
  5785. Array<String> genericMethodNameOverrides;
  5786. Array<String>* genericMethodNameOverridesPtr = NULL;
  5787. if (methodInstance->GetNumGenericArguments() != 0)
  5788. {
  5789. genericMethodNameOverridesPtr = &genericMethodNameOverrides;
  5790. for (int methodGenericArgIdx = 0; methodGenericArgIdx < (int)methodInstance->GetNumGenericArguments(); methodGenericArgIdx++)
  5791. {
  5792. BfType* methodGenericArg = NULL;
  5793. if (methodEntry.mGenericArguments.size() > 0)
  5794. methodGenericArg = methodEntry.mGenericArguments[methodGenericArgIdx];
  5795. String argName;
  5796. if (methodGenericArg == NULL)
  5797. argName = methodInstance->mMethodDef->mGenericParams[methodGenericArgIdx]->mName;
  5798. else
  5799. argName = bfModule->TypeToString(methodGenericArg, BfTypeNameFlag_ResolveGenericParamNames, NULL);
  5800. genericMethodNameOverrides.push_back(argName);
  5801. }
  5802. }
  5803. if (methodInstance->mMethodDef->mMethodType != BfMethodType_Ctor)
  5804. {
  5805. if (methodInstance->mReturnType != NULL)
  5806. methodText += bfModule->TypeToString(methodInstance->mReturnType, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr);
  5807. else
  5808. methodText += BfTypeUtils::TypeToString(methodInstance->mMethodDef->mReturnTypeRef);
  5809. methodText += " ";
  5810. }
  5811. if (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor)
  5812. methodText += "this";
  5813. else
  5814. {
  5815. auto methodName = methodInstance->mMethodDef->mName;
  5816. int splitIdx = (int)methodName.IndexOf('@');
  5817. if (splitIdx != -1)
  5818. methodText += methodName.Substring(0, splitIdx);
  5819. else
  5820. methodText += methodName;
  5821. }
  5822. if (methodInstance->GetNumGenericArguments() != 0)
  5823. {
  5824. methodText += "<";
  5825. for (int methodGenericArgIdx = 0; methodGenericArgIdx < (int)methodInstance->GetNumGenericArguments(); methodGenericArgIdx++)
  5826. {
  5827. if (methodGenericArgIdx > 0)
  5828. methodText += ", ";
  5829. methodText += genericMethodNameOverrides[methodGenericArgIdx];
  5830. }
  5831. methodText += ">";
  5832. }
  5833. //TODO: Show default param values also
  5834. methodText += "(\x1";
  5835. if (methodInstance->GetParamCount() == 0)
  5836. {
  5837. // Hm - is this ever useful? Messes up some cases actually
  5838. // If param resolution failed then we need to print the original param def
  5839. /*for (int paramIdx = 0; paramIdx < (int) methodInstance->mMethodDef->mParams.size(); paramIdx++)
  5840. {
  5841. if (paramIdx > 0)
  5842. methodText += ",\x1 ";
  5843. auto paramDef = methodInstance->mMethodDef->mParams[paramIdx];
  5844. methodText += BfTypeUtils::TypeToString(paramDef->mTypeRef);
  5845. methodText += " ";
  5846. methodText += paramDef->mName;
  5847. }*/
  5848. }
  5849. int dispParamIdx = 0;
  5850. for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
  5851. {
  5852. auto paramKind = methodInstance->GetParamKind(paramIdx);
  5853. if ((paramKind == BfParamKind_ImplicitCapture) || (paramKind == BfParamKind_AppendIdx))
  5854. continue;
  5855. if (dispParamIdx > 0)
  5856. methodText += ",\x1 ";
  5857. auto type = methodInstance->GetParamType(paramIdx);
  5858. BfExpression* paramInitializer = methodInstance->GetParamInitializer(paramIdx);
  5859. if (paramInitializer != NULL)
  5860. methodText += "[";
  5861. if (paramKind == BfParamKind_Params)
  5862. methodText += "params ";
  5863. if (type->IsGenericParam())
  5864. {
  5865. auto genericParamType = (BfGenericParamType*)type;
  5866. if (genericParamType->mGenericParamKind == BfGenericParamKind_Method)
  5867. {
  5868. if (methodInstance->GetNumGenericParams() > 0)
  5869. {
  5870. auto genericParamInstance = methodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
  5871. methodText += genericParamInstance->GetGenericParamDef()->mName;
  5872. }
  5873. else
  5874. {
  5875. BfMethodInstance* curMethodInstance = methodEntry.mCurMethodInstance;
  5876. auto genericParamInstance = curMethodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
  5877. methodText += genericParamInstance->GetGenericParamDef()->mName;
  5878. }
  5879. }
  5880. else
  5881. {
  5882. BfGenericTypeInstance* genericType = (BfGenericTypeInstance*)methodEntry.mTypeInstance;
  5883. auto genericParamInstance = genericType->mGenericParams[genericParamType->mGenericParamIdx];
  5884. methodText += genericParamInstance->GetGenericParamDef()->mName;
  5885. }
  5886. }
  5887. else
  5888. methodText += bfModule->TypeToString(type, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr);
  5889. methodText += " ";
  5890. methodText += methodInstance->GetParamName(paramIdx);
  5891. if (paramInitializer != NULL)
  5892. {
  5893. methodText += " = ";
  5894. methodText += paramInitializer->ToString();
  5895. methodText += "]";
  5896. }
  5897. dispParamIdx++;
  5898. }
  5899. methodText += "\x1)";
  5900. }
  5901. if (methodEntry.mMethodDef != NULL)
  5902. {
  5903. auto methodDeclaration = methodEntry.mMethodDef->GetMethodDeclaration();
  5904. if ((methodDeclaration != NULL) && (methodDeclaration->mDocumentation != NULL))
  5905. {
  5906. String docString;
  5907. _GetDocString(methodDeclaration->mDocumentation, docString);
  5908. methodText += "\x03";
  5909. methodText += docString;
  5910. }
  5911. }
  5912. autoCompleteResultString += "invoke\t" + methodText + "\n";
  5913. idx++;
  5914. }
  5915. }
  5916. Array<AutoCompleteEntry*> entries;
  5917. for (auto& entry : autoComplete->mEntriesSet)
  5918. {
  5919. entries.Add(&entry);
  5920. }
  5921. std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs)
  5922. {
  5923. return stricmp(lhs->mDisplay, rhs->mDisplay) < 0;
  5924. });
  5925. String docString;
  5926. for (auto entry : entries)
  5927. {
  5928. if ((wantsDocEntry != NULL) && (entry->mDocumentation == NULL))
  5929. continue;
  5930. autoCompleteResultString += String(entry->mEntryType);
  5931. autoCompleteResultString += "\t";
  5932. autoCompleteResultString += String(entry->mDisplay);
  5933. if ((entry->mDocumentation != NULL) && (wantsDocEntry != NULL) && (strcmp(wantsDocEntry, entry->mDisplay) == 0))
  5934. {
  5935. docString.Clear();
  5936. _GetDocString(entry->mDocumentation, docString);
  5937. autoCompleteResultString += '\x03';
  5938. autoCompleteResultString += docString;
  5939. }
  5940. autoCompleteResultString += "\n";
  5941. }
  5942. }
  5943. }
  5944. String BfCompiler::GetTypeDefList()
  5945. {
  5946. String result;
  5947. BfProject* curProject = NULL;
  5948. Dictionary<BfProject*, int> projectIds;
  5949. for (auto typeDef : mSystem->mTypeDefs)
  5950. {
  5951. if (typeDef->mProject != curProject)
  5952. {
  5953. curProject = typeDef->mProject;
  5954. int* projectIdPtr;
  5955. if (projectIds.TryAdd(curProject, NULL, &projectIdPtr))
  5956. {
  5957. *projectIdPtr = (int)projectIds.size() - 1;
  5958. result += "+";
  5959. result += curProject->mName;
  5960. result += "\n";
  5961. }
  5962. else
  5963. {
  5964. char str[32];
  5965. sprintf(str, "=%d\n", *projectIdPtr);
  5966. result += str;
  5967. }
  5968. }
  5969. if (((!typeDef->mIsPartial) || (typeDef->mIsCombinedPartial)))
  5970. {
  5971. if (typeDef->IsGlobalsContainer())
  5972. {
  5973. result += "g";
  5974. if (!typeDef->mNamespace.IsEmpty())
  5975. {
  5976. typeDef->mNamespace.ToString(result);
  5977. result += ".";
  5978. }
  5979. result += ":static\n";
  5980. continue;
  5981. }
  5982. else if (typeDef->mTypeCode == BfTypeCode_Interface)
  5983. result += "i";
  5984. else if (typeDef->mTypeCode == BfTypeCode_Object)
  5985. result += "c";
  5986. else
  5987. result += "v";
  5988. result += BfTypeUtils::TypeToString(typeDef) + "\n";
  5989. }
  5990. }
  5991. return result;
  5992. }
  5993. struct TypeDefMatchHelper
  5994. {
  5995. public:
  5996. StringImpl& mResult;
  5997. Array<String> mSearch;
  5998. uint32 mFoundFlags;
  5999. int32 mFoundCount;
  6000. bool mHasDotSearch;
  6001. String mCurTypeName;
  6002. String mTempStr;
  6003. public:
  6004. TypeDefMatchHelper(StringImpl& str) : mResult(str)
  6005. {
  6006. mFoundFlags = 0;
  6007. mFoundCount = 0;
  6008. mHasDotSearch = false;
  6009. }
  6010. void Sanitize(StringImpl& str)
  6011. {
  6012. for (int i = 0; i < (int)str.length(); i++)
  6013. {
  6014. char c = str[i];
  6015. if (c < (char)32)
  6016. {
  6017. str[i] = ' ';
  6018. }
  6019. }
  6020. }
  6021. void AddParams(BfMethodDef* methodDef)
  6022. {
  6023. int visParamIdx = 0;
  6024. for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
  6025. {
  6026. auto paramDef = methodDef->mParams[paramIdx];
  6027. if ((paramDef->mParamKind == BfParamKind_AppendIdx) || (paramDef->mParamKind == BfParamKind_ImplicitCapture))
  6028. continue;
  6029. if (visParamIdx > 0)
  6030. mResult += ", ";
  6031. StringT<64> refName;
  6032. paramDef->mTypeRef->ToString(refName);
  6033. Sanitize(refName);
  6034. mResult += refName;
  6035. mResult += " ";
  6036. mResult += paramDef->mName;
  6037. visParamIdx++;
  6038. }
  6039. }
  6040. void AddLocation(BfAstNode* node)
  6041. {
  6042. if (node == NULL)
  6043. return;
  6044. auto parserData = node->GetSourceData()->ToParserData();
  6045. if (parserData != NULL)
  6046. {
  6047. mResult += parserData->mFileName;
  6048. int lineNum = 0;
  6049. int column = 0;
  6050. parserData->GetLineCharAtIdx(node->GetSrcStart(), lineNum, column);
  6051. mResult += StrFormat("\t%d\t%d", lineNum, column);
  6052. }
  6053. };
  6054. void AddFieldDef(BfFieldDef* fieldDef)
  6055. {
  6056. mResult += "\t";
  6057. AddLocation(fieldDef->GetRefNode());
  6058. mResult += "\n";
  6059. }
  6060. void AddPropertyDef(BfTypeDef* typeDef, BfPropertyDef* propDef)
  6061. {
  6062. if (propDef->mName == "[]")
  6063. {
  6064. mResult += "[";
  6065. for (auto methodDef : propDef->mMethods)
  6066. {
  6067. if (methodDef->mMethodType == BfMethodType_PropertyGetter)
  6068. {
  6069. AddParams(methodDef);
  6070. break;
  6071. }
  6072. }
  6073. mResult += "]";
  6074. }
  6075. else
  6076. mResult += propDef->mName;
  6077. mResult += "\t";
  6078. auto refNode = propDef->GetRefNode();
  6079. if (refNode == NULL)
  6080. refNode = typeDef->GetRefNode();
  6081. AddLocation(refNode);
  6082. mResult += "\n";
  6083. }
  6084. void AddMethodDef(BfMethodDef* methodDef)
  6085. {
  6086. if (methodDef->mMethodType == BfMethodType_Ctor)
  6087. {
  6088. if (methodDef->mIsStatic)
  6089. mResult += "static ";
  6090. mResult += "this";
  6091. }
  6092. else if (methodDef->mMethodType == BfMethodType_Dtor)
  6093. {
  6094. if (methodDef->mIsStatic)
  6095. mResult += "static ";
  6096. mResult += "~this";
  6097. }
  6098. else
  6099. mResult += methodDef->mName;
  6100. if (methodDef->mMethodType == BfMethodType_Mixin)
  6101. mResult += "!";
  6102. mResult += "(";
  6103. AddParams(methodDef);
  6104. mResult += ")";
  6105. mResult += "\t";
  6106. AddLocation(methodDef->GetRefNode());
  6107. mResult += "\n";
  6108. }
  6109. void ClearResults()
  6110. {
  6111. mFoundFlags = 0;
  6112. mFoundCount = 0;
  6113. }
  6114. bool MergeFlags(uint32 flags)
  6115. {
  6116. int flagIdx = 0;
  6117. while (flags > 0)
  6118. {
  6119. if (((flags & 1) != 0) && ((mFoundFlags & (1 << flagIdx)) == 0))
  6120. {
  6121. mFoundFlags |= (1 << flagIdx);
  6122. mFoundCount++;
  6123. }
  6124. flags >>= 1;
  6125. flagIdx++;
  6126. }
  6127. return mFoundCount == mSearch.mSize;
  6128. }
  6129. uint32 CheckMatch(const StringView& str)
  6130. {
  6131. uint32 matchFlags = 0;
  6132. for (int i = 0; i < mSearch.mSize; i++)
  6133. {
  6134. if (((mFoundFlags & (1 << i)) == 0) && (str.IndexOf(mSearch[i], true) != -1))
  6135. {
  6136. mFoundCount++;
  6137. matchFlags |= (1 << i);
  6138. mFoundFlags |= (1 << i);
  6139. }
  6140. }
  6141. return matchFlags;
  6142. }
  6143. bool CheckCompletesMatch(BfAtomComposite& name)
  6144. {
  6145. for (int i = 0; i < name.mSize; i++)
  6146. {
  6147. CheckMatch(name.mParts[i]->mString);
  6148. if (mFoundCount == mSearch.mSize)
  6149. return true;
  6150. }
  6151. return false;
  6152. }
  6153. bool IsFullMatch()
  6154. {
  6155. return mFoundCount == mSearch.mSize;
  6156. }
  6157. bool CheckMemberMatch(BfTypeDef* typeDef, const StringView& str)
  6158. {
  6159. if (CheckMatch(str) == 0)
  6160. {
  6161. if (mHasDotSearch)
  6162. {
  6163. mTempStr.Clear();
  6164. mTempStr += mCurTypeName;
  6165. mTempStr += ".";
  6166. mTempStr += str;
  6167. if (CheckMatch(mTempStr) == 0)
  6168. return false;
  6169. }
  6170. else
  6171. return false;
  6172. }
  6173. if ((IsFullMatch()) || (CheckCompletesMatch(typeDef->mFullName)))
  6174. return true;
  6175. return false;
  6176. }
  6177. };
  6178. String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr)
  6179. {
  6180. String result;
  6181. TypeDefMatchHelper matchHelper(result);
  6182. //
  6183. {
  6184. int searchIdx = 0;
  6185. while (searchIdx < (int)searchStr.length())
  6186. {
  6187. int spacePos = (int)searchStr.IndexOf(' ', searchIdx);
  6188. String str;
  6189. if (spacePos == -1)
  6190. str = searchStr.Substring(searchIdx);
  6191. else
  6192. str = searchStr.Substring(searchIdx, spacePos - searchIdx);
  6193. str.Trim();
  6194. if (!str.IsEmpty())
  6195. matchHelper.mSearch.Add(str);
  6196. if (str.Contains('.'))
  6197. matchHelper.mHasDotSearch = true;
  6198. if (spacePos == -1)
  6199. break;
  6200. searchIdx = spacePos + 1;
  6201. }
  6202. //// We sort from longest to shortest to make sure longer strings match before shorter, which
  6203. //// matters when the shorter string is a subset of the longer string
  6204. //matchHelper.mSearch.Sort([](const String& lhs, const String& rhs)
  6205. // {
  6206. // int lenCmp = (int)(rhs.length() - lhs.length());
  6207. // if (lenCmp != 0)
  6208. // return lenCmp < 0;
  6209. // return lhs < rhs;
  6210. // });
  6211. }
  6212. BfProject* curProject = NULL;
  6213. Dictionary<BfProject*, int> projectIds;
  6214. Dictionary<BfAtom*, int> atomMatchMap;
  6215. struct ProjectInfo
  6216. {
  6217. Dictionary<String, int> matchedNames;
  6218. };
  6219. Array<ProjectInfo> projectInfos;
  6220. projectInfos.Resize(mSystem->mProjects.size());
  6221. String typeName;
  6222. String foundName;
  6223. int partialIdx = 0;
  6224. for (auto typeDef : mSystem->mTypeDefs)
  6225. {
  6226. if (typeDef->mIsPartial)
  6227. continue;
  6228. bool fullyMatchesName = false;
  6229. if (matchHelper.mHasDotSearch)
  6230. {
  6231. matchHelper.mCurTypeName.Clear();
  6232. typeDef->mFullName.ToString(matchHelper.mCurTypeName);
  6233. matchHelper.ClearResults();
  6234. matchHelper.CheckMatch(matchHelper.mCurTypeName);
  6235. fullyMatchesName = matchHelper.IsFullMatch();
  6236. }
  6237. int matchIdx = -1;
  6238. //BfAtomComposite foundComposite;
  6239. if (!fullyMatchesName)
  6240. {
  6241. for (auto fieldDef : typeDef->mFields)
  6242. {
  6243. matchHelper.ClearResults();
  6244. bool hasMatch = false;
  6245. if (matchHelper.CheckMemberMatch(typeDef, fieldDef->mName))
  6246. {
  6247. result += "F";
  6248. if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
  6249. result += ".";
  6250. result += fieldDef->mName;
  6251. matchHelper.AddFieldDef(fieldDef);
  6252. }
  6253. }
  6254. for (auto propDef : typeDef->mProperties)
  6255. {
  6256. if (propDef->GetRefNode() == NULL)
  6257. continue;
  6258. matchHelper.ClearResults();
  6259. if (matchHelper.CheckMemberMatch(typeDef, propDef->mName))
  6260. {
  6261. result += "P";
  6262. if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
  6263. result += ".";
  6264. matchHelper.AddPropertyDef(typeDef, propDef);
  6265. }
  6266. }
  6267. for (auto methodDef : typeDef->mMethods)
  6268. {
  6269. if ((methodDef->mMethodType != BfMethodType_Normal) &&
  6270. (methodDef->mMethodType != BfMethodType_Mixin) &&
  6271. (methodDef->mMethodType != BfMethodType_Ctor) &&
  6272. (methodDef->mMethodType != BfMethodType_Dtor))
  6273. continue;
  6274. if (methodDef->mMethodDeclaration == NULL)
  6275. continue;
  6276. matchHelper.ClearResults();
  6277. if (matchHelper.CheckMemberMatch(typeDef, methodDef->mName))
  6278. {
  6279. result += "M";
  6280. if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
  6281. result += ".";
  6282. matchHelper.AddMethodDef(methodDef);
  6283. }
  6284. }
  6285. uint32 matchFlags = 0;
  6286. for (int atomIdx = typeDef->mFullName.mSize - 1; atomIdx >= 0; atomIdx--)
  6287. {
  6288. auto atom = typeDef->mFullName.mParts[atomIdx];
  6289. int* matchesPtr = NULL;
  6290. if (atomMatchMap.TryAdd(atom, NULL, &matchesPtr))
  6291. {
  6292. matchHelper.ClearResults();
  6293. *matchesPtr = matchHelper.CheckMatch(atom->mString);
  6294. }
  6295. if (*matchesPtr != 0)
  6296. {
  6297. if (matchIdx == -1)
  6298. matchIdx = atomIdx;
  6299. matchFlags |= *matchesPtr;
  6300. }
  6301. }
  6302. matchHelper.ClearResults();
  6303. if (!matchHelper.MergeFlags(matchFlags))
  6304. {
  6305. continue;
  6306. }
  6307. //foundComposite.Set(typeDef->mFullName.mParts, matchIdx + 1, NULL, 0);
  6308. //foundComposite = typeDef->mFullName;
  6309. }
  6310. if (typeDef->mProject != curProject)
  6311. {
  6312. curProject = typeDef->mProject;
  6313. int* projectIdPtr;
  6314. if (projectIds.TryAdd(curProject, NULL, &projectIdPtr))
  6315. {
  6316. *projectIdPtr = (int)projectIds.size() - 1;
  6317. result += "+";
  6318. result += curProject->mName;
  6319. result += "\n";
  6320. }
  6321. else
  6322. {
  6323. char str[32];
  6324. sprintf(str, "=%d\n", *projectIdPtr);
  6325. result += str;
  6326. }
  6327. }
  6328. typeName = BfTypeUtils::TypeToString(typeDef);
  6329. if (matchIdx != -1)
  6330. {
  6331. int* matchIdxPtr = 0;
  6332. auto projectInfo = &projectInfos[typeDef->mProject->mIdx];
  6333. int dotCount = 0;
  6334. foundName = typeName;
  6335. for (int i = 0; i < (int)typeName.length(); i++)
  6336. {
  6337. if (typeName[i] == '.')
  6338. {
  6339. if (dotCount == matchIdx)
  6340. {
  6341. foundName.Clear();
  6342. foundName.Append(typeName.c_str(), i);
  6343. break;
  6344. }
  6345. dotCount++;
  6346. }
  6347. }
  6348. if (projectInfo->matchedNames.TryAdd(foundName, NULL, &matchIdxPtr))
  6349. {
  6350. *matchIdxPtr = partialIdx++;
  6351. result += StrFormat(">%d@", matchIdx);
  6352. }
  6353. else
  6354. {
  6355. result += StrFormat("<%d@", *matchIdxPtr);
  6356. }
  6357. }
  6358. else
  6359. {
  6360. result += ":";
  6361. }
  6362. if (typeDef->IsGlobalsContainer())
  6363. {
  6364. result += "g";
  6365. if (!typeDef->mNamespace.IsEmpty())
  6366. {
  6367. typeDef->mNamespace.ToString(result);
  6368. result += ".";
  6369. }
  6370. result += ":static\n";
  6371. continue;
  6372. }
  6373. else if (typeDef->mTypeCode == BfTypeCode_Interface)
  6374. result += "i";
  6375. else if (typeDef->mTypeCode == BfTypeCode_Object)
  6376. result += "c";
  6377. else
  6378. result += "v";
  6379. result += typeName + "\n";
  6380. }
  6381. return result;
  6382. }
  6383. String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
  6384. {
  6385. BfProject* project = NULL;
  6386. int idx = 0;
  6387. int sep = (int)inTypeName.IndexOf(':');
  6388. if (sep != -1)
  6389. {
  6390. idx = sep + 1;
  6391. project = mSystem->GetProject(inTypeName.Substring(0, sep));
  6392. }
  6393. String typeName;
  6394. int genericCount = 0;
  6395. int pendingGenericCount = 0;
  6396. for ( ; idx < (int)inTypeName.length(); idx++)
  6397. {
  6398. char c = inTypeName[idx];
  6399. if (c == '<')
  6400. genericCount = 1;
  6401. else if (genericCount > 0)
  6402. {
  6403. if (c == ',')
  6404. genericCount++;
  6405. else if (c == '>')
  6406. {
  6407. pendingGenericCount = genericCount;
  6408. genericCount = 0;
  6409. }
  6410. }
  6411. else
  6412. {
  6413. if (pendingGenericCount != 0)
  6414. {
  6415. typeName += StrFormat("`%d", pendingGenericCount);
  6416. pendingGenericCount = 0;
  6417. }
  6418. typeName += c;
  6419. }
  6420. }
  6421. bool isGlobals = false;
  6422. if (typeName == ":static")
  6423. {
  6424. typeName.clear();
  6425. isGlobals = true;
  6426. }
  6427. if (typeName.EndsWith(".:static"))
  6428. {
  6429. typeName.RemoveToEnd(typeName.length() - 8);
  6430. isGlobals = true;
  6431. }
  6432. String result;
  6433. TypeDefMatchHelper matchHelper(result);
  6434. BfAtomComposite nameComposite;
  6435. if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
  6436. {
  6437. auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
  6438. while (itr)
  6439. {
  6440. auto typeDef = *itr;
  6441. if ((!typeDef->mIsPartial) &&
  6442. (typeDef->mProject == project) &&
  6443. (typeDef->mFullName == nameComposite) &&
  6444. (typeDef->IsGlobalsContainer() == isGlobals) &&
  6445. (typeDef->GetSelfGenericParamCount() == pendingGenericCount))
  6446. {
  6447. auto refNode = typeDef->GetRefNode();
  6448. result += "S";
  6449. matchHelper.AddLocation(refNode);
  6450. result += "\n";
  6451. for (auto fieldDef : typeDef->mFields)
  6452. {
  6453. result += "F";
  6454. result += fieldDef->mName;
  6455. matchHelper.AddFieldDef(fieldDef);
  6456. }
  6457. for (auto propDef : typeDef->mProperties)
  6458. {
  6459. if (propDef->GetRefNode() == NULL)
  6460. continue;
  6461. result += "P";
  6462. matchHelper.AddPropertyDef(typeDef, propDef);
  6463. }
  6464. for (auto methodDef : typeDef->mMethods)
  6465. {
  6466. if ((methodDef->mMethodType != BfMethodType_Normal) &&
  6467. (methodDef->mMethodType != BfMethodType_Mixin) &&
  6468. (methodDef->mMethodType != BfMethodType_Ctor) &&
  6469. (methodDef->mMethodType != BfMethodType_Dtor))
  6470. continue;
  6471. if (methodDef->mMethodDeclaration == NULL)
  6472. continue;
  6473. result += "M";
  6474. matchHelper.AddMethodDef(methodDef);
  6475. }
  6476. }
  6477. itr.MoveToNextHashMatch();
  6478. }
  6479. }
  6480. return result;
  6481. }
  6482. //////////////////////////////////////////////////////////////////////////
  6483. PerfManager* BfGetPerfManager(BfParser* bfParser);
  6484. /*BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetDefaultTargetTriple(BfCompiler* bfCompiler)
  6485. {
  6486. String& autoCompleteResultString = *gTLStrReturn.Get();
  6487. return autoCompleteResultString.c_str();
  6488. }*/
  6489. BF_EXPORT bool BF_CALLTYPE BfCompiler_Compile(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, const char* outputPath)
  6490. {
  6491. BP_ZONE("BfCompiler_Compile");
  6492. SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
  6493. bfCompiler->mPassInstance = bfPassInstance;
  6494. bfCompiler->Compile(outputPath);
  6495. return !bfCompiler->mPassInstance->HasFailed();
  6496. }
  6497. BF_EXPORT void BF_CALLTYPE BfCompiler_ClearResults(BfCompiler* bfCompiler)
  6498. {
  6499. bfCompiler->ClearResults();
  6500. }
  6501. BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfParser* bfParser, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
  6502. {
  6503. BP_ZONE("BfCompiler_ClassifySource");
  6504. BfSourceClassifier bfSourceClassifier(bfParser, charData);
  6505. bfSourceClassifier.mClassifierPassId = bfPassInstance->mClassifierPassId;
  6506. String& autoCompleteResultString = *gTLStrReturn.Get();
  6507. autoCompleteResultString.clear();
  6508. bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
  6509. bfSourceClassifier.mEnabled = doClassifyPass;
  6510. // Full classifier pass?
  6511. bfSourceClassifier.mSkipMethodInternals = true;
  6512. bfSourceClassifier.mSkipTypeDeclarations = true;
  6513. if ((charData != NULL) && (doClassifyPass))
  6514. bfSourceClassifier.Visit(bfParser->mRootNode);
  6515. bfSourceClassifier.mSkipTypeDeclarations = false;
  6516. bfSourceClassifier.mSkipMethodInternals = false;
  6517. if (charData != NULL)
  6518. resolvePassData->mSourceClassifier = &bfSourceClassifier;
  6519. bfPassInstance->mFilterErrorsTo = bfParser;
  6520. bfPassInstance->mTrimMessagesToCursor = true;
  6521. SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
  6522. SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
  6523. bool canceled = false;
  6524. if (resolvePassData->mAutoComplete != NULL)
  6525. {
  6526. bfCompiler->ProcessAutocompleteTempType();
  6527. }
  6528. else
  6529. canceled = !bfCompiler->Compile("");
  6530. resolvePassData->mSourceClassifier = NULL;
  6531. if ((charData != NULL) && (doClassifyPass))
  6532. {
  6533. bfSourceClassifier.mIsSideChannel = false;
  6534. bfSourceClassifier.Visit(bfParser->mErrorRootNode);
  6535. bfSourceClassifier.mIsSideChannel = true;
  6536. bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);
  6537. }
  6538. return !canceled;
  6539. }
  6540. BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, char* name, int cursorPos)
  6541. {
  6542. String typeName = name;
  6543. auto system = bfCompiler->mSystem;
  6544. AutoCrit autoCrit(system->mSystemLock);
  6545. String& autoCompleteResultString = *gTLStrReturn.Get();
  6546. autoCompleteResultString.Clear();
  6547. BfPassInstance passInstance(bfCompiler->mSystem);
  6548. BfParser parser(bfCompiler->mSystem);
  6549. parser.SetSource(typeName.c_str(), (int)typeName.length());
  6550. parser.Parse(&passInstance);
  6551. parser.mCursorIdx = cursorPos;
  6552. parser.mCursorCheckIdx = cursorPos;
  6553. BfReducer reducer;
  6554. reducer.mAlloc = parser.mAlloc;
  6555. reducer.mPassInstance = &passInstance;
  6556. reducer.mAllowTypeWildcard = true;
  6557. if (parser.mRootNode->mChildArr.mSize == 0)
  6558. return false;
  6559. bool attribWasClosed = false;
  6560. bool isAttributeRef = false;
  6561. auto firstNode = parser.mRootNode->mChildArr[0];
  6562. auto endIdx = parser.mRootNode->mSrcEnd;
  6563. reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
  6564. if (auto tokenNode = BfNodeDynCast<BfTokenNode>(firstNode))
  6565. {
  6566. if (tokenNode->mToken == BfToken_LBracket)
  6567. {
  6568. if (auto lastToken = BfNodeDynCast<BfTokenNode>(parser.mRootNode->mChildArr.back()))
  6569. {
  6570. if (lastToken->mToken == BfToken_RBracket)
  6571. {
  6572. attribWasClosed = true;
  6573. endIdx = lastToken->mSrcStart;
  6574. }
  6575. }
  6576. isAttributeRef = true;
  6577. if (parser.mRootNode->mChildArr.mSize < 2)
  6578. return false;
  6579. firstNode = parser.mRootNode->mChildArr[1];
  6580. reducer.mVisitorPos.MoveNext();
  6581. }
  6582. }
  6583. reducer.mVisitorPos.MoveNext();
  6584. auto typeRef = reducer.CreateTypeRef(firstNode);
  6585. if (typeRef == NULL)
  6586. return false;
  6587. BfResolvePassData resolvePassData;
  6588. if (cursorPos != -1)
  6589. {
  6590. resolvePassData.mResolveType = BfResolveType_Autocomplete;
  6591. parser.mParserFlags = (BfParserFlag)(parser.mParserFlags | ParserFlag_Autocomplete);
  6592. resolvePassData.mAutoComplete = new BfAutoComplete();
  6593. resolvePassData.mAutoComplete->mSystem = bfCompiler->mSystem;
  6594. resolvePassData.mAutoComplete->mCompiler = bfCompiler;
  6595. resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule;
  6596. }
  6597. resolvePassData.mParser = &parser;
  6598. SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, &resolvePassData);
  6599. SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &passInstance);
  6600. if (resolvePassData.mAutoComplete != NULL)
  6601. {
  6602. if (isAttributeRef)
  6603. resolvePassData.mAutoComplete->CheckAttributeTypeRef(typeRef);
  6604. else
  6605. resolvePassData.mAutoComplete->CheckTypeRef(typeRef, false);
  6606. bfCompiler->GenerateAutocompleteInfo();
  6607. }
  6608. if (passInstance.HasFailed())
  6609. return false;
  6610. if (typeRef->mSrcEnd != endIdx)
  6611. return false;
  6612. if (!bfCompiler->mContext->mScratchModule->ValidateTypeWildcard(typeRef, isAttributeRef))
  6613. return false;
  6614. if ((isAttributeRef) && (!attribWasClosed))
  6615. return false;
  6616. return true;
  6617. }
  6618. BF_EXPORT void BF_CALLTYPE BfCompiler_ClearCompletionPercentage(BfCompiler* bfCompiler)
  6619. {
  6620. bfCompiler->mCompletionPct = 0;
  6621. }
  6622. BF_EXPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(BfCompiler* bfCompiler)
  6623. {
  6624. return bfCompiler->mCompletionPct;
  6625. }
  6626. BF_EXPORT int BF_CALLTYPE BfCompiler_GetCompileRevision(BfCompiler* bfCompiler)
  6627. {
  6628. return bfCompiler->mRevision;
  6629. }
  6630. BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler)
  6631. {
  6632. bfCompiler->Cancel();
  6633. }
  6634. BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler)
  6635. {
  6636. bfCompiler->ClearBuildCache();
  6637. }
  6638. BF_EXPORT void BF_CALLTYPE BfCompiler_Delete(BfCompiler* bfCompiler)
  6639. {
  6640. delete bfCompiler;
  6641. }
  6642. BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone()
  6643. {
  6644. #ifdef BF_PLATFORM_WINDOWS
  6645. BeLibManager::Get()->Clear();
  6646. #endif
  6647. }
  6648. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler)
  6649. {
  6650. String& outString = *gTLStrReturn.Get();
  6651. outString.clear();
  6652. outString = bfCompiler->GetTypeDefList();
  6653. return outString.c_str();
  6654. }
  6655. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefMatches(BfCompiler* bfCompiler, const char* searchStr)
  6656. {
  6657. String& outString = *gTLStrReturn.Get();
  6658. outString.clear();
  6659. outString = bfCompiler->GetTypeDefMatches(searchStr);
  6660. return outString.c_str();
  6661. }
  6662. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompiler, const char* typeDefName)
  6663. {
  6664. String& outString = *gTLStrReturn.Get();
  6665. outString.clear();
  6666. outString = bfCompiler->GetTypeDefInfo(typeDefName);
  6667. return outString.c_str();
  6668. }
  6669. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool* hadOutputChanges)
  6670. {
  6671. BF_FATAL("not used ?");
  6672. *hadOutputChanges = false;
  6673. String& outString = *gTLStrReturn.Get();
  6674. outString.clear();
  6675. for (auto mainModule : bfCompiler->mContext->mModules)
  6676. {
  6677. if (!mainModule->mIsReified)
  6678. continue;
  6679. if (mainModule->mProject != bfProject)
  6680. continue;
  6681. if (bfCompiler->mOptions.mHotProject != NULL)
  6682. continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
  6683. for (auto&& moduleFileName : mainModule->mOutFileNames)
  6684. {
  6685. if (!moduleFileName.mModuleWritten)
  6686. continue;
  6687. if (!outString.empty())
  6688. outString += "\n";
  6689. outString += moduleFileName.mFileName;
  6690. }
  6691. }
  6692. if (bfCompiler->mHotState != NULL)
  6693. {
  6694. Array<String> outPaths;
  6695. for (int i = 0; i < (int)bfCompiler->mHotState->mQueuedOutFiles.size(); i++)
  6696. {
  6697. auto& fileEntry = bfCompiler->mHotState->mQueuedOutFiles[i];
  6698. if (fileEntry.mProject != bfProject)
  6699. continue;
  6700. outPaths.Add(fileEntry.mFileName);
  6701. bfCompiler->mHotState->mQueuedOutFiles.RemoveAtFast(i);
  6702. i--;
  6703. }
  6704. //outPaths.Sort();
  6705. std::sort(outPaths.begin(), outPaths.end(), [](const String& lhs, const String& rhs) { return lhs < rhs; });
  6706. for (auto& path : outPaths)
  6707. {
  6708. if (!outString.empty())
  6709. outString += "\n";
  6710. outString += path;
  6711. outString += BF_OBJ_EXT;
  6712. }
  6713. }
  6714. return outString.c_str();
  6715. }
  6716. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges)
  6717. {
  6718. BP_ZONE("BfCompiler_GetUsedOutputFileNames");
  6719. *hadOutputChanges = false;
  6720. String& outString = *gTLStrReturn.Get();
  6721. outString.clear();
  6722. Array<BfModule*> moduleList;
  6723. moduleList.Reserve(bfProject->mUsedModules.size());
  6724. if (bfCompiler->mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
  6725. {
  6726. for (auto mainModule : bfCompiler->mContext->mModules)
  6727. {
  6728. if ((!mainModule->mIsReified) || (mainModule->mIsScratchModule))
  6729. continue;
  6730. if (bfCompiler->mOptions.mHotProject != NULL)
  6731. continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
  6732. if (!bfCompiler->IsModuleAccessible(mainModule, bfProject))
  6733. continue;
  6734. moduleList.push_back(mainModule);
  6735. }
  6736. }
  6737. else
  6738. {
  6739. for (auto mainModule : bfProject->mUsedModules)
  6740. {
  6741. if ((!mainModule->mIsReified) || (mainModule->mIsScratchModule))
  6742. continue;
  6743. if (bfCompiler->mOptions.mHotProject != NULL)
  6744. continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
  6745. moduleList.push_back(mainModule);
  6746. }
  6747. }
  6748. std::sort(moduleList.begin(), moduleList.end(), [&](BfModule* moduleA, BfModule* moduleB) { return moduleA->mModuleName < moduleB->mModuleName; } );
  6749. HashSet<String> usedFileNames;
  6750. usedFileNames.Reserve(moduleList.size());
  6751. for (auto mainModule : moduleList)
  6752. {
  6753. for (auto fileNameIdx : mainModule->mImportFileNames)
  6754. {
  6755. auto fileName = bfCompiler->mContext->mStringObjectIdMap[fileNameIdx].mString;
  6756. if (!usedFileNames.TryAdd(fileName, NULL))
  6757. continue;
  6758. if (!outString.empty())
  6759. outString += "\n";
  6760. outString += fileName;
  6761. }
  6762. for (auto&& moduleFileName : mainModule->mOutFileNames)
  6763. {
  6764. if (!moduleFileName.mModuleWritten)
  6765. continue;
  6766. bool canReference = true;
  6767. for (auto project : moduleFileName.mProjects)
  6768. {
  6769. if (!bfProject->ContainsReference(project))
  6770. canReference = false;
  6771. if (bfProject != project)
  6772. {
  6773. if (project->mTargetType == BfTargetType_BeefDynLib)
  6774. canReference = false;
  6775. }
  6776. }
  6777. if (!canReference)
  6778. continue;
  6779. String fileName = moduleFileName.mFileName;
  6780. #ifdef BF_PLATFORM_WINDOWS
  6781. if (moduleFileName.mWroteToLib)
  6782. fileName = BeLibManager::GetLibFilePath(fileName);
  6783. #endif
  6784. if (!usedFileNames.TryAdd(fileName, NULL))
  6785. continue;
  6786. if (!outString.empty())
  6787. outString += "\n";
  6788. outString += fileName;
  6789. if (mainModule->mWroteToLib)
  6790. break;
  6791. }
  6792. }
  6793. if (bfCompiler->mHotState != NULL)
  6794. {
  6795. Array<String> outPaths;
  6796. for (int i = 0; i < (int)bfCompiler->mHotState->mQueuedOutFiles.size(); i++)
  6797. {
  6798. auto& fileEntry = bfCompiler->mHotState->mQueuedOutFiles[i];
  6799. if (fileEntry.mProject != bfProject)
  6800. continue;
  6801. if (!bfCompiler->mHotState->mHotProject->mUsedModules.Contains(fileEntry.mModule))
  6802. continue;
  6803. outPaths.Add(fileEntry.mFileName);
  6804. if (flushQueuedHotFiles)
  6805. {
  6806. bfCompiler->mHotState->mQueuedOutFiles.RemoveAtFast(i);
  6807. i--;
  6808. }
  6809. }
  6810. std::sort(outPaths.begin(), outPaths.end(), [](const String& lhs, const String& rhs) { return lhs < rhs; });
  6811. for (auto& path : outPaths)
  6812. {
  6813. if (!outString.empty())
  6814. outString += "\n";
  6815. outString += path;
  6816. outString += BF_OBJ_EXT;
  6817. }
  6818. }
  6819. for (auto& fileEntry : bfCompiler->mCodeGen.mCodeGenFiles)
  6820. {
  6821. if (fileEntry.mWasCached)
  6822. continue;
  6823. if (!bfProject->ContainsReference(fileEntry.mProject))
  6824. continue;
  6825. *hadOutputChanges = true;
  6826. }
  6827. return outString.c_str();
  6828. }
  6829. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetAutocompleteInfo(BfCompiler* bfCompiler)
  6830. {
  6831. String& autoCompleteResultString = *gTLStrReturn.Get();
  6832. return autoCompleteResultString.c_str();
  6833. }
  6834. BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetSymbolReferences(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData)
  6835. {
  6836. BP_ZONE("BfCompiler_GetSymbolReferences");
  6837. String& outString = *gTLStrReturn.Get();
  6838. outString.clear();
  6839. SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
  6840. SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
  6841. bfCompiler->GetSymbolReferences();
  6842. std::map<String, String*> sortedParserMap;
  6843. for (auto& parserDataPair : resolvePassData->mFoundSymbolReferencesParserData)
  6844. {
  6845. sortedParserMap.insert(std::make_pair(parserDataPair.mKey->mFileName, &parserDataPair.mValue));
  6846. }
  6847. for (auto& parserData : sortedParserMap)
  6848. {
  6849. if (!outString.empty())
  6850. outString += "\n";
  6851. outString += parserData.first + "\t" + *(parserData.second);
  6852. }
  6853. return outString.c_str();
  6854. }
  6855. BF_EXPORT bool BF_CALLTYPE BfCompiler_GetHasHotPendingDataChanges(BfCompiler* bfCompiler)
  6856. {
  6857. return (bfCompiler->mHotState != NULL) &&
  6858. ((!bfCompiler->mHotState->mPendingDataChanges.IsEmpty()) || (!bfCompiler->mHotState->mPendingFailedSlottings.IsEmpty()));
  6859. }
  6860. BF_EXPORT void BF_CALLTYPE BfCompiler_HotCommit(BfCompiler* bfCompiler)
  6861. {
  6862. bfCompiler->HotCommit();
  6863. }
  6864. BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_Start(BfCompiler* bfCompiler, int flags)
  6865. {
  6866. bfCompiler->HotResolve_Start((BfCompiler::HotResolveFlags)flags);
  6867. }
  6868. BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_AddActiveMethod(BfCompiler* bfCompiler, const char* methodName)
  6869. {
  6870. bfCompiler->HotResolve_AddActiveMethod(methodName);
  6871. }
  6872. BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_AddDelegateMethod(BfCompiler* bfCompiler, const char* methodName)
  6873. {
  6874. bfCompiler->HotResolve_AddDelegateMethod(methodName);
  6875. }
  6876. // 0: heap, 1: user stated 'not used', 2: user stated 'used'
  6877. BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_ReportType(BfCompiler* bfCompiler, int typeId, int usageKind)
  6878. {
  6879. bfCompiler->HotResolve_ReportType(typeId, (BfCompiler::HotTypeFlags)usageKind);
  6880. }
  6881. // 0: heap, 1: user stated 'used', 2: user stated 'not used'
  6882. BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_ReportTypeRange(BfCompiler* bfCompiler, const char* typeName, int usageKind)
  6883. {
  6884. //TODO: Implement
  6885. }
  6886. BF_EXPORT const char* BF_CALLTYPE BfCompiler_HotResolve_Finish(BfCompiler* bfCompiler)
  6887. {
  6888. String& outString = *gTLStrReturn.Get();
  6889. outString = bfCompiler->HotResolve_Finish();
  6890. return outString.c_str();
  6891. }
  6892. enum BfCompilerOptionFlags
  6893. {
  6894. BfCompilerOptionFlag_EmitDebugInfo = 1,
  6895. BfCompilerOptionFlag_EmitLineInfo = 2,
  6896. BfCompilerOptionFlag_WriteIR = 4,
  6897. BfCompilerOptionFlag_GenerateOBJ = 8,
  6898. BfCompilerOptionFlag_NoFramePointerElim = 0x10,
  6899. BfCompilerOptionFlag_ClearLocalVars = 0x20,
  6900. BfCompilerOptionFlag_RuntimeChecks = 0x40,
  6901. BfCompilerOptionFlag_EmitDynamicCastCheck = 0x80,
  6902. BfCompilerOptionFlag_EnableObjectDebugFlags = 0x100,
  6903. BfCompilerOptionFlag_EmitObjectAccessCheck = 0x200,
  6904. BfCompilerOptionFlag_EnableCustodian = 0x400,
  6905. BfCompilerOptionFlag_EnableRealtimeLeakCheck = 0x800,
  6906. BfCompilerOptionFlag_EnableSideStack = 0x1000,
  6907. BfCompilerOptionFlag_EnableHotSwapping = 0x2000,
  6908. BfCompilerOptionFlag_IncrementalBuild = 0x4000,
  6909. BfCompilerOptionFlag_DebugAlloc = 0x8000
  6910. };
  6911. BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(BfCompiler* bfCompiler, BfProject* hotProject, int hotIdx,
  6912. int machineType, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads,
  6913. BfCompilerOptionFlags optionFlags, char* mallocLinkName, char* freeLinkName)
  6914. {
  6915. BfLogSys(bfCompiler->mSystem, "BfCompiler_SetOptions\n");
  6916. //printf("BfCompiler_SetOptions Threads:%d\n", maxWorkerThreads);
  6917. auto options = &bfCompiler->mOptions;
  6918. options->mErrorString.Clear();
  6919. options->mHotProject = hotProject;
  6920. options->mHotCompileIdx = hotIdx;
  6921. options->mMachineType = (BfMachineType)machineType;
  6922. bfCompiler->mCodeGen.SetMaxThreads(maxWorkerThreads);
  6923. if (!bfCompiler->mIsResolveOnly)
  6924. {
  6925. bool allowHotSwapping = (optionFlags & BfCompilerOptionFlag_EnableHotSwapping) != 0;
  6926. bool emitDebugInfo = (optionFlags & BfCompilerOptionFlag_EmitDebugInfo) != 0;
  6927. // These settings only matter for code generation, they are not applicable for resolveOnly
  6928. options->mCompileOnDemandKind = BfCompileOnDemandKind_ResolveUnused;
  6929. //options->mCompileOnDemandKind = BfCompileOnDemandKind_AlwaysInclude;
  6930. options->mToolsetType = (BfToolsetType)toolsetType;
  6931. options->mSIMDSetting = (BfSIMDSetting)simdSetting;
  6932. options->mIncrementalBuild = (optionFlags & BfCompilerOptionFlag_IncrementalBuild) != 0;
  6933. options->mWriteIR = (optionFlags & BfCompilerOptionFlag_WriteIR) != 0;
  6934. options->mGenerateObj = (optionFlags & BfCompilerOptionFlag_GenerateOBJ) != 0;
  6935. options->mNoFramePointerElim = (optionFlags & BfCompilerOptionFlag_NoFramePointerElim) != 0;
  6936. options->mInitLocalVariables = (optionFlags & BfCompilerOptionFlag_ClearLocalVars) != 0;
  6937. options->mRuntimeChecks = (optionFlags & BfCompilerOptionFlag_RuntimeChecks) != 0;
  6938. options->mEmitDynamicCastCheck = (optionFlags & BfCompilerOptionFlag_EmitDynamicCastCheck) != 0;
  6939. options->mObjectHasDebugFlags = (optionFlags & BfCompilerOptionFlag_EnableObjectDebugFlags) != 0;
  6940. options->mEnableRealtimeLeakCheck = ((optionFlags & BfCompilerOptionFlag_EnableRealtimeLeakCheck) != 0) && options->mObjectHasDebugFlags;
  6941. options->mDebugAlloc = ((optionFlags & BfCompilerOptionFlag_DebugAlloc) != 0) || options->mEnableRealtimeLeakCheck;
  6942. #ifdef _WINDOWS
  6943. if (options->mToolsetType == BfToolsetType_GNU)
  6944. {
  6945. options->mErrorString = "Toolset 'GNU' is not available on this platform. Consider changing 'Workspace/General/Toolset'.";
  6946. }
  6947. #else
  6948. if (options->mToolsetType == BfToolsetType_Microsoft)
  6949. {
  6950. options->mErrorString = "Toolset 'Microsoft' is not available on this platform. Consider changing 'Workspace/General/Toolset'.";
  6951. }
  6952. BF_ASSERT(!options->mEnableRealtimeLeakCheck);
  6953. #endif
  6954. options->mEmitObjectAccessCheck = (optionFlags & BfCompilerOptionFlag_EmitDebugInfo) != 0;
  6955. options->mAllocStackCount = allocStackCount;
  6956. if (hotProject != NULL)
  6957. {
  6958. String errorName;
  6959. if (options->mAllowHotSwapping != allowHotSwapping)
  6960. errorName = "Hot Compilation Enabled";
  6961. else if (options->mMallocLinkName != mallocLinkName)
  6962. errorName = "Malloc";
  6963. else if (options->mFreeLinkName != freeLinkName)
  6964. errorName = "Free";
  6965. if (!options->mEmitDebugInfo)
  6966. {
  6967. options->mErrorString = "Hot compilation cannot be used when the target is not built with debug information. Consider setting 'Workspace/Beef/Debug/Debug Information' to 'Yes'.";
  6968. }
  6969. else if (!errorName.IsEmpty())
  6970. {
  6971. options->mErrorString = StrFormat("Unable to change option '%s' during hot compilation", errorName.c_str());
  6972. }
  6973. }
  6974. else
  6975. {
  6976. options->mAllowHotSwapping = allowHotSwapping;
  6977. options->mHasVDataExtender = options->mAllowHotSwapping;
  6978. options->mMallocLinkName = mallocLinkName;
  6979. options->mFreeLinkName = freeLinkName;
  6980. options->mEmitDebugInfo = emitDebugInfo;
  6981. options->mEmitLineInfo = (optionFlags & BfCompilerOptionFlag_EmitLineInfo) != 0;;
  6982. options->mEnableCustodian = (optionFlags & BfCompilerOptionFlag_EnableCustodian) != 0;
  6983. options->mEnableSideStack = (optionFlags & BfCompilerOptionFlag_EnableSideStack) != 0;
  6984. }
  6985. }
  6986. else
  6987. {
  6988. options->mCompileOnDemandKind = BfCompileOnDemandKind_AlwaysInclude;
  6989. options->mAllowHotSwapping = false;
  6990. options->mObjectHasDebugFlags = false;
  6991. options->mEnableRealtimeLeakCheck = false;
  6992. options->mEmitObjectAccessCheck = false;
  6993. options->mEmitDynamicCastCheck = false;
  6994. options->mRuntimeChecks = (optionFlags & BfCompilerOptionFlag_RuntimeChecks) != 0;
  6995. }
  6996. }
  6997. BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler)
  6998. {
  6999. bfCompiler->mOptions.mForceRebuildIdx++;
  7000. }