BfCompiler.cpp 256 KB

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