BfCompiler.cpp 255 KB

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