BfCompiler.cpp 311 KB

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