1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233 |
- #pragma warning(disable:4996)
- #pragma warning(push)
- #pragma warning(disable:4800)
- #pragma warning(disable:4244)
- #pragma warning(disable:4141)
- #pragma warning(disable:4624)
- #pragma warning(disable:4146)
- #pragma warning(disable:4267)
- #pragma warning(disable:4291)
- #include "BeefySysLib/util/AllocDebug.h"
- #include "llvm/Support/Compiler.h"
- #include "BfCompiler.h"
- #include "BfSystem.h"
- #include "BfParser.h"
- #include "BfReducer.h"
- #include "BfExprEvaluator.h"
- #include "../Backend/BeLibManger.h"
- #include <fcntl.h>
- #include "BfConstResolver.h"
- #include "BfMangler.h"
- #include "BfDemangler.h"
- #include "BeefySysLib/util/PerfTimer.h"
- #include "BfSourceClassifier.h"
- #include "BfAutoComplete.h"
- #include "BfResolvePass.h"
- #include "BeefySysLib/util/BeefPerf.h"
- #include "../LLVMUtils.h"
- #pragma warning(pop)
- namespace llvm
- {
- extern bool DebugFlag;
- }
- #define SPLIT_CONTEXTS
- Beefy::BfCompiler* gBfCompiler = NULL;
- void pt(llvm::Type* t)
- {
- //Beefy::OutputDebugStrF("pv((llvm::Type*)%p)\n", t);
- Beefy::debug_ostream os;
- t->print(os);
- os << "\n";
- os << " isSized: " << t->isSized() << "\n";
- os.flush();
- if (auto pointerType = llvm::dyn_cast<llvm::PointerType>(t))
- {
- Beefy::OutputDebugStrF("Element: ");
- pt(pointerType->getElementType());
- }
- }
- void ppt(llvm::Type* t)
- {
- auto pointerType = llvm::dyn_cast<llvm::PointerType>(t);
- if (pointerType == NULL)
- {
- Beefy::OutputDebugStrF("Not a pointer type");
- return;
- }
- pt(pointerType->getElementType());
- }
- void pt(llvm::DINode* t)
- {
- Beefy::debug_ostream os;
- t->print(os);
- os << "\n";
- os.flush();
- }
- void pt(llvm::Value* v)
- {
- pt(v->getType());
- }
- void pv(const llvm::Value* v)
- {
- Beefy::debug_ostream os;
- v->print(os);
- os << "\n";
- os.flush();
- pt(v->getType());
- }
- void ppt(llvm::Value* v)
- {
- ppt(v->getType());
- }
- void pmd(llvm::Metadata* md)
- {
- Beefy::debug_ostream os;
- md->print(os);
- os << "\n";
- os.flush();
- }
- void pdl(llvm::DebugLoc& dl)
- {
- Beefy::debug_ostream os;
- dl.print(os);
- os << "\n";
- os.flush();
- }
- void pm(llvm::Module* module)
- {
- Beefy::debug_ostream os;
- module->print(os, NULL);
- os << "\n";
- os.flush();
- }
- void PrintUsers(llvm::MDNode* md)
- {
- /*Beefy::debug_ostream os;
- //auto val = llvm::ReplaceableMetadataImpl::get(*md);
- auto val = md->Context.getReplaceableUses();
- if (val == NULL)
- {
- os << "Not replaceable\n";
- }
- else
- {
- //md->print(os);
- typedef std::pair<void *, std::pair<llvm::MetadataTracking::OwnerTy, uint64_t>> UseTy;
- llvm::SmallVector<UseTy, 8> Uses(val->UseMap.begin(), val->UseMap.end());
- std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) {
- return L.second.second < R.second.second;
- });
- for (const auto &Pair : Uses)
- {
- auto Owner = Pair.second.first;
- os << Beefy::StrFormat(" %d %p %d\n", Pair.second.first.isNull(), Pair.first, Pair.second.second, Pair).c_str();
- }
- os << "\n";
- }
- os.flush();*/
- }
- void ptbf(Beefy::BfType* bfType)
- {
- Beefy::OutputDebugStrF("%s\n", bfType->GetModule()->TypeToString(bfType).c_str());
- }
- void pt(const Beefy::BfTypedValue& val)
- {
- Beefy::OutputDebugStrF("%s\n", val.mType->GetModule()->TypeToString(val.mType).c_str());
- }
- void pt(llvm::SmallVectorImpl<llvm::Value*>& llvmArgs)
- {
- Beefy::debug_ostream os;
- for (int i = 0; i < (int)llvmArgs.size(); i++)
- {
- if (i > 0)
- os << ", ";
- llvmArgs[i]->getType()->print(os);
- }
- os << "\n";
- os.flush();
- }
- void PrintUsers(llvm::Value* v)
- {
- for (auto user : v->users())
- {
- pt(user);
- }
- }
- /*void PrintFunc(Beefy::BfMethodInstance* methodInstance)
- {
- Beefy::debug_ostream os;
- methodInstance->mIRFunction.mLLVMValue->print(os);
- os << "\n";
- os.flush();
- }*/
- USING_NS_BF;
- using namespace llvm;
- int Beefy::BfWorkListEntry::sCurReqId = 0;
- GlobalVariable* AllocGlobalVariable(Module &M, Type *Ty, bool isConstant,
- GlobalValue::LinkageTypes Linkage, Constant *Initializer,
- const Twine &Name = "", GlobalVariable *InsertBefore = nullptr,
- GlobalValue::ThreadLocalMode tlm = GlobalValue::NotThreadLocal, unsigned AddressSpace = 0,
- bool isExternallyInitialized = false);
- #include "BeefySysLib/util/AllocDebug.h"
- //////////////////////////////////////////////////////////////////////////
- BfCompiler::HotData::~HotData()
- {
- for (auto& kv : mMethodMap)
- {
- auto hotMethod = kv.mValue;
- hotMethod->Clear();
- }
- for (auto& kv : mThisType)
- kv.mValue->Deref();
- for (auto& kv : mAllocation)
- kv.mValue->Deref();
- for (auto& kv : mDevirtualizedMethods)
- kv.mValue->Deref();
- for (auto& kv : mFuncPtrs)
- kv.mValue->Deref();
- for (auto& kv : mVirtualDecls)
- kv.mValue->Deref();
- for (auto& kv : mInnerMethods)
- kv.mValue->Deref();
- for (auto& kv : mMethodMap)
- kv.mValue->Deref();
- }
- template <typename TDict>
- static void DeleteUnused(TDict& dict)
- {
- auto itr = dict.begin();
- while (itr != dict.end())
- {
- auto val = itr->mValue;
- BF_ASSERT(val->mRefCount >= 1);
- if (val->mRefCount == 1)
- {
- val->Deref();
- itr = dict.Remove(itr);
- }
- else
- ++itr;
- }
- }
- template <typename TDict, typename TElement>
- static typename TDict::value_type AllocFromMap(TDict& dict, TElement* elem)
- {
- typename TDict::value_type* valuePtr;
- if (dict.TryAdd(elem, NULL, &valuePtr))
- {
- auto val = new typename std::remove_pointer<typename TDict::value_type>::type(elem);
- val->mRefCount++;
- *valuePtr = val;
- }
- return *valuePtr;
- }
- void BfCompiler::HotData::ClearUnused(bool isHotCompile)
- {
- BP_ZONE("BfCompiler::HotData::ClearUnused");
- DeleteUnused(mThisType);
- DeleteUnused(mAllocation);
- DeleteUnused(mDevirtualizedMethods);
- DeleteUnused(mVirtualDecls);
- DeleteUnused(mInnerMethods);
- if (isHotCompile)
- {
- // We need to keep all function pointer references ever, since we can't tell if we still reference them or not
- DeleteUnused(mFuncPtrs);
- }
- }
- BfHotThisType* BfCompiler::HotData::GetThisType(BfHotTypeVersion* hotVersion)
- {
- return AllocFromMap(mThisType, hotVersion);
- }
- BfHotAllocation* BfCompiler::HotData::GetAllocation(BfHotTypeVersion* hotVersion)
- {
- return AllocFromMap(mAllocation, hotVersion);
- }
- BfHotDevirtualizedMethod* BfCompiler::HotData::GetDevirtualizedMethod(BfHotMethod* hotMethod)
- {
- return AllocFromMap(mDevirtualizedMethods, hotMethod);
- }
- BfHotFunctionReference* BfCompiler::HotData::GetFunctionReference(BfHotMethod* hotMethod)
- {
- return AllocFromMap(mFuncPtrs, hotMethod);
- }
- BfHotInnerMethod* BfCompiler::HotData::GetInnerMethod(BfHotMethod* hotMethod)
- {
- return AllocFromMap(mInnerMethods, hotMethod);
- }
- BfHotVirtualDeclaration* BfCompiler::HotData::GetVirtualDeclaration(BfHotMethod* hotMethod)
- {
- return AllocFromMap(mVirtualDecls, hotMethod);
- }
- BfCompiler::HotState::~HotState()
- {
-
- }
- bool BfCompiler::HotState::HasPendingChanges(BfTypeInstance* type)
- {
- return (type->mHotTypeData != NULL) && (type->mHotTypeData->mPendingDataChange);
- }
- void BfCompiler::HotState::RemovePendingChanges(BfTypeInstance* type)
- {
- BF_ASSERT(type->mHotTypeData->mPendingDataChange);
- if (!type->mHotTypeData->mPendingDataChange)
- return;
- type->mHotTypeData->mPendingDataChange = false;
- bool didRemove = mPendingDataChanges.Remove(type->mTypeId);
- BF_ASSERT(didRemove);
- }
- BfCompiler::HotResolveData::~HotResolveData()
- {
- for (auto hotMethod : mActiveMethods)
- hotMethod->Deref();
- for (auto kv : mReachableMethods)
- kv.mKey->Deref();
- }
- //////////////////////////////////////////////////////////////////////////
- BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
- {
- //llvm::DebugFlag = true;
- memset(&mStats, 0, sizeof(mStats));
- mCompletionPct = 0;
- mCanceling = false;
- mIsResolveOnly = isResolveOnly;
- mResolvePassData = NULL;
- mPassInstance = NULL;
- mRevision = 0;
- mLastRevisionAborted = false;
- gBfCompiler = this;
- mSystem = bfSystem;
- mCurTypeId = 1;
- mTypeInitCount = 0;
- //mMaxInterfaceSlots = 16;
- mMaxInterfaceSlots = -1;
- mInterfaceSlotCountChanged = false;
- mHSPreserveIdx = 0;
- mCompileLogFP = NULL;
- mWantsDeferMethodDecls = false;
- mHadCancel = false;
- mCompileState = CompileState_None;
- //mMaxInterfaceSlots = 4;
- mContext = new BfContext(this);
- mHotData = NULL;
- mHotState = NULL;
- mHotResolveData = NULL;
-
- mArray1TypeDef = NULL;
- mArray2TypeDef = NULL;
- mArray3TypeDef = NULL;
- mArray4TypeDef = NULL;
- mSpanTypeDef = NULL;
- mAttributeTypeDef = NULL;
- mAttributeUsageAttributeTypeDef = NULL;
- mBfObjectTypeDef = NULL;
- mClassVDataTypeDef = NULL;
- mCLinkAttributeTypeDef = NULL;
- mCReprAttributeTypeDef = NULL;
- mNoDiscardAttributeTypeDef = NULL;
- mDisableObjectAccessChecksAttributeTypeDef = NULL;
- mDbgRawAllocDataTypeDef = NULL;
- mDeferredCallTypeDef = NULL;
- mDelegateTypeDef = NULL;
- mEnumTypeDef = NULL;
- mFriendAttributeTypeDef = NULL;
- mCheckedAttributeTypeDef = NULL;
- mUncheckedAttributeTypeDef = NULL;
- mFunctionTypeDef = NULL;
- mGCTypeDef = NULL;
- mGenericIEnumerableTypeDef = NULL;
- mGenericIEnumeratorTypeDef = NULL;
- mGenericIRefEnumeratorTypeDef = NULL;
- mInlineAttributeTypeDef = NULL;
- mInternalTypeDef = NULL;
- mIPrintableTypeDef = NULL;
- mIHashableTypeDef = NULL;
- mLinkNameAttributeTypeDef = NULL;
- mMethodRefTypeDef = NULL;
- mNullableTypeDef = NULL;
- mOrderedAttributeTypeDef = NULL;
- mPointerTTypeDef = NULL;
- mPointerTypeDef = NULL;
- mReflectArrayType = NULL;
- mReflectFieldDataDef = NULL;
- mReflectFieldSplatDataDef = NULL;
- mReflectMethodDataDef = NULL;
- mReflectParamDataDef = NULL;
- mReflectPointerType = NULL;
- mReflectSizedArrayType = NULL;
- mReflectSpecializedGenericType = NULL;
- mReflectTypeInstanceTypeDef = NULL;
- mReflectUnspecializedGenericType = NULL;
- mSizedArrayTypeDef = NULL;
- mSkipAccessCheckAttributeTypeDef = NULL;
- mStaticInitAfterAttributeTypeDef = NULL;
- mStaticInitPriorityAttributeTypeDef = NULL;
- mStringTypeDef = NULL;
- mThreadStaticAttributeTypeDef = NULL;
- mTypeTypeDef = NULL;
- mUnboundAttributeTypeDef = NULL;
- mValueTypeTypeDef = NULL;
- mObsoleteAttributeTypeDef = NULL;
- mErrorAttributeTypeDef = NULL;
- mWarnAttributeTypeDef = NULL;
- mLastAutocompleteModule = NULL;
- }
- BfCompiler::~BfCompiler()
- {
- delete mContext;
- delete mHotData;
- delete mHotState;
- delete mHotResolveData;
- }
- bool BfCompiler::IsTypeAccessible(BfType* checkType, BfProject* curProject)
- {
- if (checkType->IsBoxed())
- return IsTypeAccessible(((BfBoxedType*)checkType)->mElementType, curProject);
-
- BfTypeInstance* typeInst = checkType->ToTypeInstance();
- if (typeInst != NULL)
- {
- if (checkType->IsTuple())
- {
- for (auto&& fieldInst : typeInst->mFieldInstances)
- {
- if (!IsTypeAccessible(fieldInst.mResolvedType, curProject))
- return false;
- }
- }
- auto genericTypeInst = typeInst->ToGenericTypeInstance();
- if (genericTypeInst != NULL)
- {
- for (auto genericArg : genericTypeInst->mTypeGenericArguments)
- if (!IsTypeAccessible(genericArg, curProject))
- return false;
- }
- return curProject->ContainsReference(typeInst->mTypeDef->mProject);
- }
-
- if (checkType->IsPointer())
- return IsTypeAccessible(((BfPointerType*)checkType)->mElementType, curProject);
- if (checkType->IsRef())
- return IsTypeAccessible(((BfPointerType*)checkType)->mElementType, curProject);
-
- return true;
- }
- bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject)
- {
- if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
- return IsTypeAccessible(checkType, curProject);
- BfTypeInstance* typeInst = checkType->ToTypeInstance();
- if (typeInst != NULL)
- {
- if ((typeInst->mTypeDef->mProject != NULL) && (typeInst->mTypeDef->mProject != curProject))
- {
- if (typeInst->mTypeDef->mProject->mTargetType == BfTargetType_BeefDynLib)
- return false;
- }
- if (checkType->IsInterface())
- return typeInst->mIsReified;
-
- //TODO: We could check to see if this project has any reified specialized instances...
- if (checkType->IsUnspecializedType())
- return typeInst->mIsReified;
- if (checkType->IsTuple())
- {
- for (auto&& fieldInst : typeInst->mFieldInstances)
- {
- if (!IsTypeUsed(fieldInst.mResolvedType, curProject))
- return false;
- }
- }
- auto genericTypeInst = typeInst->ToGenericTypeInstance();
- if (genericTypeInst != NULL)
- {
- for (auto genericArg : genericTypeInst->mTypeGenericArguments)
- if (!IsTypeUsed(genericArg, curProject))
- return false;
- }
- auto module = typeInst->GetModule();
- if (module == NULL)
- return true;
- return curProject->mUsedModules.Contains(module);
- }
- if (checkType->IsPointer())
- return IsTypeUsed(((BfPointerType*)checkType)->mElementType, curProject);
- if (checkType->IsRef())
- return IsTypeUsed(((BfPointerType*)checkType)->mElementType, curProject);
- return true;
- }
- bool BfCompiler::IsModuleAccessible(BfModule* module, BfProject* curProject)
- {
- for (auto checkType : module->mOwnedTypeInstances)
- {
- if (!IsTypeAccessible(checkType, curProject))
- return false;
- }
- return curProject->ContainsReference(module->mProject);
- }
- void BfCompiler::FixVDataHash(BfModule* bfModule)
- {
- // We recreate the actual vdata hash now that we're done creating new string literals
- /*for (auto context : mContexts)
- HASH128_MIXIN(bfModule->mDataHash, bfModule->mHighestUsedStringId);*/
- }
- void BfCompiler::CheckModuleStringRefs(BfModule* module, BfVDataModule* vdataModule, int lastModuleRevision, HashSet<int>& foundStringIds, HashSet<int>& dllNameSet, Array<BfMethodInstance*>& dllMethods, Array<BfCompiler::StringValueEntry>& stringValueEntries)
- {
- for (int stringId : module->mStringPoolRefs)
- {
- if (foundStringIds.Add(stringId))
- {
- BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId];
-
- if (IsHotCompile())
- {
- if (vdataModule->mDefinedStrings.Contains(stringId))
- continue;
- }
- StringValueEntry stringEntry;
- stringEntry.mId = stringId;
- vdataModule->mDefinedStrings.Add(stringId);
- stringEntry.mStringVal = vdataModule->CreateStringObjectValue(stringPoolEntry.mString, stringId, true);
- stringValueEntries.Add(stringEntry);
- CompileLog("String %d %s\n", stringId, stringPoolEntry.mString.c_str());
- }
- }
- for (auto dllNameId : module->mImportFileNames)
- dllNameSet.Add(dllNameId);
- for (auto& dllImportEntry : module->mDllImportEntries)
- dllMethods.push_back(dllImportEntry.mMethodInstance);
- auto altModule = module->mNextAltModule;
- while (altModule != NULL)
- {
- CheckModuleStringRefs(altModule, vdataModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
- altModule = altModule->mNextAltModule;
- }
- for (auto& specModulePair : module->mSpecializedMethodModules)
- CheckModuleStringRefs(specModulePair.mValue, vdataModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
- }
- void BfCompiler::HashModuleVData(BfModule* module, HashContext& vdataHash)
- {
- BP_ZONE("BfCompiler::HashModuleVData");
- if (module->mStringPoolRefs.size() > 0)
- {
- module->mStringPoolRefs.Sort([](int lhs, int rhs) { return lhs < rhs; });
- vdataHash.Mixin(&module->mStringPoolRefs[0], (int)module->mStringPoolRefs.size() * (int)sizeof(int));
- }
-
- if (module->mImportFileNames.size() > 0)
- {
- module->mImportFileNames.Sort([](int lhs, int rhs) { return lhs < rhs; });
- vdataHash.Mixin(&module->mImportFileNames[0], (int)module->mImportFileNames.size() * (int)sizeof(int));
- }
-
- auto altModule = module->mNextAltModule;
- while (altModule != NULL)
- {
- HashModuleVData(altModule, vdataHash);
- altModule = altModule->mNextAltModule;
- }
- for (auto& specModulePair : module->mSpecializedMethodModules)
- {
- HashModuleVData(specModulePair.mValue, vdataHash);
- }
- }
- BfIRFunction BfCompiler::CreateLoadSharedLibraries(BfVDataModule* bfModule, Array<BfMethodInstance*>& dllMethods)
- {
- BfIRType nullPtrType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
- BfIRType nullPtrPtrType = bfModule->mBfIRBuilder->MapType(bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)));
- BfIRType voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None));
- SmallVector<BfIRType, 2> paramTypes;
- auto loadSharedLibrariesFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
- auto loadSharedLibFunc = bfModule->mBfIRBuilder->CreateFunction(loadSharedLibrariesFuncType, BfIRLinkageType_External, "BfLoadSharedLibraries");
- bfModule->SetupIRMethod(NULL, loadSharedLibFunc, false);
- bfModule->mBfIRBuilder->SetActiveFunction(loadSharedLibFunc);
- auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
- HashSet<int> dllNameSet;
- auto internalType = bfModule->ResolveTypeDef(mInternalTypeDef);
- bfModule->PopulateType(internalType);
- auto getSharedProcAddressInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "GetSharedProcAddressInto");
- auto loadSharedLibraryProc = bfModule->GetMethodByName(internalType->ToTypeInstance(), "LoadSharedLibraryInto");
- BF_ASSERT(getSharedProcAddressInstance);
- BF_ASSERT(loadSharedLibraryProc);
- if (!getSharedProcAddressInstance)
- {
- bfModule->Fail("Missing Internal.GetSharedProcAddressInto");
- return loadSharedLibFunc;
- }
- if (!loadSharedLibraryProc)
- {
- bfModule->Fail("Missing Internal.LoadSharedLibraryInto");
- return loadSharedLibFunc;
- }
- Dictionary<int, BfIRValue> dllHandleMap;
- for (auto methodInstance : dllMethods)
- {
- auto typeInstance = methodInstance->GetOwner();
- auto methodDef = methodInstance->mMethodDef;
- BF_ASSERT(methodInstance->GetCustomAttributes() != NULL);
- for (auto customAttr : methodInstance->GetCustomAttributes()->mAttributes)
- {
- if (customAttr.mType->mTypeDef->mFullName.ToString() == "System.ImportAttribute")
- {
- bool doCLink = false;
- bool undecorated = false;
- BfCallingConvention callingConvention = methodDef->mCallingConvention;
- for (auto fieldSet : customAttr.mSetField)
- {
- BfFieldDef* fieldDef = fieldSet.mFieldRef;
- if (fieldDef->mName == "CLink")
- {
- auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
- if (constant != NULL)
- doCLink = constant->mBool;
- }
- if (fieldDef->mName == "Undecorated")
- {
- auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
- if (constant != NULL)
- undecorated = constant->mBool;
- }
- if (fieldDef->mName == "CallingConvention")
- {
- auto constant = typeInstance->mConstHolder->GetConstant(fieldSet.mParam.mValue);
- if (constant != NULL)
- {
- int callingConventionVal = (int)constant->mInt32;
- if ((callingConventionVal == 3) || (callingConventionVal == 1))
- callingConvention = BfCallingConvention_Stdcall;
- else if (callingConventionVal == 2)
- callingConvention = BfCallingConvention_Cdecl;
- }
- }
- }
- if (customAttr.mCtorArgs.size() == 1)
- {
- auto fileNameArg = customAttr.mCtorArgs[0];
- int strNum = 0;
- auto constant = typeInstance->mConstHolder->GetConstant(fileNameArg);
- if (constant != NULL)
- {
- if (constant->IsNull())
- continue; // Invalid
- strNum = constant->mInt32;
- }
- else
- {
- strNum = bfModule->GetStringPoolIdx(fileNameArg, typeInstance->mConstHolder);
- }
- BfIRValue dllHandleVar;
- if (!dllHandleMap.TryGetValue(strNum, &dllHandleVar))
- {
- String dllHandleName = StrFormat("bf_hs_preserve@dllHandle%d", strNum);
- dllHandleVar = bfModule->mBfIRBuilder->CreateGlobalVariable(nullPtrType, false, BfIRLinkageType_External,
- bfModule->GetDefaultValue(bfModule->GetPrimitiveType(BfTypeCode_NullPtr)), dllHandleName);
- BfIRValue namePtr = bfModule->GetStringCharPtr(strNum);
- SmallVector<BfIRValue, 1> args;
- args.push_back(namePtr);
- args.push_back(dllHandleVar);
- BfIRValue dllHandleValue = bfModule->mBfIRBuilder->CreateCall(loadSharedLibraryProc.mFunc, args);
-
- dllHandleMap[strNum] = dllHandleVar;
- }
- String methodImportName;
- if (undecorated)
- {
- methodImportName = methodInstance->mMethodDef->mName;
- }
- else if (doCLink)
- {
- methodImportName = methodInstance->mMethodDef->mName;
- if ((mSystem->mPtrSize == 4) && (callingConvention == BfCallingConvention_Stdcall))
- {
- int argSize = (int)methodDef->mParams.size() * mSystem->mPtrSize;
- methodImportName = StrFormat("_%s$%d", methodImportName.c_str(), argSize);
- }
- }
- else
- BfMangler::Mangle(methodImportName, GetMangleKind(), methodInstance);
- BfIRValue methodNameValue = bfModule->mBfIRBuilder->CreateGlobalStringPtr(methodImportName);
- //auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
- //auto globalVarPtr = bfModule->mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, nullPtrPtrType);
- auto func = bfModule->CreateDllImportGlobalVar(methodInstance, false);
- auto globalVarPtr = bfModule->mBfIRBuilder->CreateBitCast(func, nullPtrPtrType);
- BfSizedVector<BfIRValue, 2> args;
- args.push_back(bfModule->mBfIRBuilder->CreateLoad(dllHandleVar));
- args.push_back(methodNameValue);
- args.push_back(globalVarPtr);
- BfIRValue dllFuncValVoidPtr = bfModule->mBfIRBuilder->CreateCall(getSharedProcAddressInstance.mFunc, args);
- }
- }
- }
- }
- bfModule->mBfIRBuilder->CreateRetVoid();
- return loadSharedLibFunc;
- }
- void BfCompiler::GetTestMethods(BfVDataModule* bfModule, Array<TestMethod>& testMethods, HashContext& vdataHashCtx)
- {
- vdataHashCtx.Mixin(0xBEEF0001); // Marker
- auto _CheckMethod = [&](BfTypeInstance* typeInstance, BfMethodInstance* methodInstance)
- {
- auto project = typeInstance->mTypeDef->mProject;
- if (project->mTargetType != BfTargetType_BeefTest)
- return;
- if (project != bfModule->mProject)
- return;
- bool isTest = false;
- if ((methodInstance->GetCustomAttributes() != NULL) &&
- (methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
- isTest = true;
- if (!isTest)
- return;
- if (!methodInstance->mMethodDef->mIsStatic)
- {
- bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it is not static", bfModule->MethodToString(methodInstance).c_str()),
- methodInstance->mMethodDef->GetRefNode());
- bfModule->mHadBuildError = true;
- return;
- }
- if (methodInstance->GetParamCount() > 0)
- {
- if ((methodInstance->GetParamInitializer(0) == NULL) &&
- (methodInstance->GetParamKind(0) != BfParamKind_Params))
- {
- bfModule->Fail(StrFormat("Method '%s' cannot be used for testing because it contains parameters without defaults", bfModule->MethodToString(methodInstance).c_str()),
- methodInstance->mMethodDef->GetRefNode());
- bfModule->mHadBuildError = true;
- return;
- }
- }
- BF_ASSERT(typeInstance->IsReified());
- TestMethod testMethod;
- testMethod.mMethodInstance = methodInstance;
- testMethods.Add(testMethod);
- if (!bfModule->mProject->mUsedModules.Contains(typeInstance->mModule))
- bfModule->mProject->mUsedModules.Add(typeInstance->mModule);
- vdataHashCtx.Mixin(methodInstance->GetOwner()->mTypeId);
- vdataHashCtx.Mixin(methodInstance->mMethodDef->mIdx);
- };
- for (auto type : mContext->mResolvedTypes)
- {
- auto typeInstance = type->ToTypeInstance();
- if (typeInstance == NULL)
- continue;
- for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
- {
- if (methodInstanceGroup.mDefault != NULL)
- {
- _CheckMethod(typeInstance, methodInstanceGroup.mDefault);
- }
- }
- }
- }
- void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& testMethods, BfIRValue& retValue)
- {
- for (auto& testMethod : testMethods)
- {
- auto methodInstance = testMethod.mMethodInstance;
- auto typeInstance = methodInstance->GetOwner();
- testMethod.mName += bfModule->TypeToString(typeInstance);
- testMethod.mName += ".";
- testMethod.mName += methodInstance->mMethodDef->mName;
- testMethod.mName += "\t";
- auto testAttribute = methodInstance->GetCustomAttributes()->Get(mTestAttributeTypeDef);
- for (auto& field : testAttribute->mSetField)
- {
- auto constant = typeInstance->mConstHolder->GetConstant(field.mParam.mValue);
- if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_Boolean) && (constant->mBool))
- {
- BfFieldDef* fieldDef = field.mFieldRef;
- if (fieldDef->mName == "ShouldFail")
- {
- testMethod.mName += "Sf";
- }
- else if (fieldDef->mName == "Profile")
- {
- testMethod.mName += "Pr";
- }
- else if (fieldDef->mName == "Ignore")
- {
- testMethod.mName += "Ig";
- }
- }
- }
- bfModule->UpdateSrcPos(methodInstance->mMethodDef->GetRefNode(), (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
- testMethod.mName += StrFormat("\t%s\t%d\t%d", bfModule->mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), bfModule->mCurFilePosition.mCurLine, bfModule->mCurFilePosition.mCurColumn);
- }
- std::stable_sort(testMethods.begin(), testMethods.end(),
- [](const TestMethod& lhs, const TestMethod& rhs)
- {
- return lhs.mName < rhs.mName;
- });
- String methodData;
- for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
- {
- String& methodName = testMethods[methodIdx].mName;
- if (!methodData.IsEmpty())
- methodData += "\n";
- methodData += methodName;
- }
- //////////////////////////////////////////////////////////////////////////
- auto testInitMethod = bfModule->GetInternalMethod("Test_Init");
- auto testQueryMethod = bfModule->GetInternalMethod("Test_Query");
- auto testFinishMethod = bfModule->GetInternalMethod("Test_Finish");
- auto char8PtrType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Char8));
- BfIRType strCharType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_Char8), (int)methodData.length() + 1);
- BfIRValue strConstant = bfModule->mBfIRBuilder->CreateConstString(methodData);
- BfIRValue gv = bfModule->mBfIRBuilder->CreateGlobalVariable(strCharType,
- true, BfIRLinkageType_External,
- strConstant, "__bfTestData");
- BfIRValue strPtrVal = bfModule->mBfIRBuilder->CreateBitCast(gv, bfModule->mBfIRBuilder->MapType(char8PtrType));
- SizedArray<BfIRValue, 4> irArgs;
- irArgs.Add(strPtrVal);
- bfModule->mBfIRBuilder->CreateCall(testInitMethod.mFunc, irArgs);
- BfIRBlock testHeadBlock = bfModule->mBfIRBuilder->CreateBlock("testHead");
- BfIRBlock testEndBlock = bfModule->mBfIRBuilder->CreateBlock("testEnd");
- bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
- bfModule->mBfIRBuilder->AddBlock(testHeadBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(testHeadBlock);
- irArgs.clear();
- auto testVal = bfModule->mBfIRBuilder->CreateCall(testQueryMethod.mFunc, irArgs);
- auto switchVal = bfModule->mBfIRBuilder->CreateSwitch(testVal, testEndBlock, (int)testMethods.size());
- for (int methodIdx = 0; methodIdx < (int)testMethods.size(); methodIdx++)
- {
- auto methodInstance = testMethods[methodIdx].mMethodInstance;
- String& methodName = testMethods[methodIdx].mName;
- auto testBlock = bfModule->mBfIRBuilder->CreateBlock(StrFormat("test%d", methodIdx));
- bfModule->mBfIRBuilder->AddSwitchCase(switchVal, bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, methodIdx), testBlock);
- bfModule->mBfIRBuilder->AddBlock(testBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(testBlock);
- auto moduleMethodInstance = bfModule->ReferenceExternalMethodInstance(methodInstance);
- irArgs.clear();
- if (methodInstance->GetParamCount() > 0)
- {
- if (methodInstance->GetParamKind(0) == BfParamKind_Params)
- {
- auto paramType = methodInstance->GetParamType(0);
- auto paramTypeInst = paramType->ToTypeInstance();
- BfTypedValue paramVal = BfTypedValue(bfModule->mBfIRBuilder->CreateAlloca(bfModule->mBfIRBuilder->MapTypeInst(paramTypeInst)), paramType);
- bfModule->InitTypeInst(paramVal, NULL, false, BfIRValue());
- //TODO: Assert 'length' var is at slot 1
- auto arrayBits = bfModule->mBfIRBuilder->CreateBitCast(paramVal.mValue, bfModule->mBfIRBuilder->MapType(paramTypeInst->mBaseType));
- auto addr = bfModule->mBfIRBuilder->CreateInBoundsGEP(arrayBits, 0, 1);
- auto storeInst = bfModule->mBfIRBuilder->CreateAlignedStore(bfModule->GetConstValue(0), addr, 4);
- irArgs.Add(paramVal.mValue);
- }
- else
- {
- for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++)
- {
- irArgs.Add(methodInstance->mDefaultValues[defaultIdx]);
- }
- }
- }
- BfExprEvaluator exprEvaluator(bfModule);
- exprEvaluator.CreateCall(moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
- bfModule->mBfIRBuilder->CreateBr(testHeadBlock);
- }
- bfModule->mBfIRBuilder->AddBlock(testEndBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(testEndBlock);
- irArgs.clear();
- bfModule->mBfIRBuilder->CreateCall(testFinishMethod.mFunc, irArgs);
- retValue = bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0);
- }
- void BfCompiler::CreateVData(BfVDataModule* bfModule)
- {
- bool isHotCompile = IsHotCompile();
- if ((isHotCompile) && (bfModule->mProject != mOptions.mHotProject))
- return;
-
- BP_ZONE("BfCompiler::CreateVData");
- BfLogSysM("CreateVData %s\n", bfModule->mProject->mName.c_str());
- CompileLog("CreateVData %s\n", bfModule->mProject->mName.c_str());
-
- bfModule->mProject->mUsedModules.Add(bfModule);
- auto project = bfModule->mProject;
- auto vdataContext = bfModule->mContext;
- BF_ASSERT(bfModule->mModuleName == "vdata");
- //////////////////////////////////////////////////////////////////////////
- // Create types we'll need for vdata, so we won't change the vdata hash afterward
- bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
- ///
-
- auto typeDefType = bfModule->ResolveTypeDef(mTypeTypeDef)->ToTypeInstance();
- if (!typeDefType)
- return;
- BF_ASSERT(typeDefType != NULL);
- vdataContext->mBfTypeType = typeDefType->ToTypeInstance();
- auto typeInstanceDefType = bfModule->ResolveTypeDef(mReflectTypeInstanceTypeDef);
- if (!typeInstanceDefType)
- return;
- auto typeInstanceDefTypeInstance = typeInstanceDefType->ToTypeInstance();
- auto typeDef = mSystem->FindTypeDef("System.ClassVData");
- BF_ASSERT(typeDef != NULL);
- auto bfClassVDataType = bfModule->ResolveTypeDef(typeDef)->ToTypeInstance();
- vdataContext->mBfClassVDataPtrType = bfModule->CreatePointerType(bfClassVDataType);
- //////////////////////////////////////////////////////////////////////////
- int numEntries = 0;
- int numConcreteTypes = 0;
- Array<BfType*> orderedTypes;
- for (auto type : mContext->mResolvedTypes)
- {
- numEntries++;
- BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
- if (!type->IsReified())
- continue;
- orderedTypes.Add(type);
- CompileLog("TypeId:%d %s\n", type->mTypeId, bfModule->TypeToString(type).c_str());
- if ((type != NULL) && (type->IsObjectOrInterface()))
- {
- numConcreteTypes++;
- auto typeInst = type->ToTypeInstance();
- if (typeInst->mModule == NULL)
- {
- BF_ASSERT(mPassInstance->HasFailed());
- continue;
- }
- }
- }
- {
- BP_ZONE("BfCompiler::CreateVData sort orderedTypes");
- orderedTypes.Sort([](BfType* lhs, BfType* rhs)
- {
- return lhs->mTypeId < rhs->mTypeId;
- });
- }
- BfLogSysM("TypeEntries: %d ConcreteTypes: %d\n", numEntries, numConcreteTypes);
-
- HashContext vdataHashCtx;
- //vdataHashCtx.mDbgViz = true;
- vdataHashCtx.Mixin(bfModule->mProject->mVDataConfigHash);
-
- Array<TestMethod> testMethods;
- if (project->mTargetType == BfTargetType_BeefTest)
- GetTestMethods(bfModule, testMethods, vdataHashCtx);
- Array<BfType*> vdataTypeList;
- std::multimap<String, BfTypeInstance*> sortedStaticInitMap;
- std::multimap<String, BfTypeInstance*> sortedStaticDtorMap;
- std::multimap<String, BfTypeInstance*> sortedStaticMarkMap;
- std::multimap<String, BfTypeInstance*> sortedStaticTLSMap;
- HashSet<BfModule*> usedModuleSet;
- vdataHashCtx.MixinStr(project->mStartupObject);
- vdataHashCtx.Mixin(project->mTargetType);
-
- for (auto type : orderedTypes)
- {
- if (type == NULL)
- continue;
- if (type->IsTemporary())
- continue;
- if ((type->IsGenericParam()) || (type->IsUnspecializedTypeVariation()))
- continue;
- auto typeInst = type->ToTypeInstance();
- if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
- continue;
- if (!IsTypeUsed(type, project))
- continue;
- vdataTypeList.push_back(type);
- vdataHashCtx.Mixin(type->mTypeId);
- BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
- if ((type != NULL) && (typeInst != NULL))
- {
- auto module = typeInst->mModule;
- if (module == NULL)
- continue;
-
- if (type->IsInterface())
- vdataHashCtx.Mixin(typeInst->mSlotNum);
- if (!module->mIsScratchModule)
- {
- BF_ASSERT(module->mIsReified);
- if (usedModuleSet.Add(module))
- {
- CompileLog("UsedModule %p %s\n", module, module->mModuleName.c_str());
-
- HashModuleVData(module, vdataHashCtx);
- }
- }
-
- vdataHashCtx.Mixin(typeInst->mTypeDef->mSignatureHash);
-
- for (auto iface : typeInst->mInterfaces)
- {
- vdataHashCtx.Mixin(iface.mInterfaceType->mTypeId);
- vdataHashCtx.Mixin(iface.mDeclaringType->mTypeCode);
- vdataHashCtx.Mixin(iface.mDeclaringType->mProject);
- }
-
- if (!typeInst->IsUnspecializedType())
- {
- for (auto& methodInstGroup : typeInst->mMethodInstanceGroups)
- {
- bool isImplementedAndReified = (methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) &&
- (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mIsUnspecialized);
- vdataHashCtx.Mixin(isImplementedAndReified);
- }
- }
- // Could be necessary if a base type in another project adds new virtual methods (for example)
- auto baseType = typeInst->mBaseType;
- while (baseType != NULL)
- {
- vdataHashCtx.Mixin(baseType->mTypeDef->mSignatureHash);
- baseType = baseType->mBaseType;
- }
- if (module->mProject != bfModule->mProject)
- {
- if ((module->mProject != NULL) && (module->mProject->mTargetType == BfTargetType_BeefDynLib))
- continue;
- }
- if (typeInst->mHasStaticInitMethod)
- sortedStaticInitMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
- else if (typeInst->mHasStaticDtorMethod) // Only store types not already in the static init map
- sortedStaticDtorMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
- if ((typeInst->mHasStaticMarkMethod) && (mOptions.mEnableRealtimeLeakCheck))
- sortedStaticMarkMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
- if ((typeInst->mHasTLSFindMethod) && (mOptions.mEnableRealtimeLeakCheck))
- sortedStaticTLSMap.insert(std::make_pair(bfModule->TypeToString(type), typeInst));
- }
- }
- int lastModuleRevision = bfModule->mRevision;
- Val128 vdataHash = vdataHashCtx.Finish128();
- bool wantsRebuild = vdataHash != bfModule->mDataHash;
- if (bfModule->mHadBuildError)
- wantsRebuild = true;
- // If we did one of those 'hot compile' partial vdata builds, now build the whole thing
- if ((!IsHotCompile()) && (bfModule->mHadHotObjectWrites))
- wantsRebuild = true;
- if (mOptions.mHotProject != NULL)
- {
- HashContext vdataHashCtxEx;
- vdataHashCtxEx.Mixin(mOptions.mHotProject->mName);
-
- vdataHashCtxEx.Mixin((int)mHotState->mNewlySlottedTypeIds.size());
- for (auto typeId : mHotState->mNewlySlottedTypeIds)
- vdataHashCtxEx.Mixin(typeId);
-
- vdataHashCtxEx.Mixin((int)mHotState->mSlotDefineTypeIds.size());
- for (auto typeId : mHotState->mSlotDefineTypeIds)
- vdataHashCtxEx.Mixin(typeId);
- Val128 vdataHashEx = vdataHashCtxEx.Finish128();
- if (mHotState->mVDataHashEx.IsZero())
- {
- if (!mHotState->mNewlySlottedTypeIds.IsEmpty())
- wantsRebuild = true;
- if (!mHotState->mSlotDefineTypeIds.IsEmpty())
- wantsRebuild = true;
- }
- else
- {
- if (vdataHashEx != mHotState->mVDataHashEx)
- wantsRebuild = true;
- }
- mHotState->mVDataHashEx = vdataHashEx;
- }
- if ((wantsRebuild) || (bfModule->mIsModuleMutable))
- {
- bfModule->StartNewRevision();
- if (bfModule->mAwaitingInitFinish)
- bfModule->FinishInit();
- }
- // We add the string hash into vdata hash later
- bfModule->mDataHash = vdataHash;//vdataPreStringHash;
- // This handles "no StartNewRevision" 'else' case, but also handles if vdata failed to complete from a previous compilation
- if (!bfModule->mIsModuleMutable)
- {
- CompileLog("VData unchanged, skipping\n");
- return;
- }
-
- BfTypeInstance* stringType = bfModule->ResolveTypeDef(mStringTypeDef, BfPopulateType_Data)->ToTypeInstance();
- BfTypeInstance* reflectSpecializedTypeInstance = bfModule->ResolveTypeDef(mReflectSpecializedGenericType)->ToTypeInstance();
- BfTypeInstance* reflectUnspecializedTypeInstance = bfModule->ResolveTypeDef(mReflectUnspecializedGenericType)->ToTypeInstance();
- BfTypeInstance* reflectArrayTypeInstance = bfModule->ResolveTypeDef(mReflectArrayType)->ToTypeInstance();
- bool madeBfTypeData = false;
-
- bool needsTypeList = bfModule->IsMethodImplementedAndReified(typeDefType, "GetType");
- bool needsObjectTypeData = needsTypeList || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "RawGetType") || bfModule->IsMethodImplementedAndReified(vdataContext->mBfObjectType, "GetType");
- bool needsTypeNames = bfModule->IsMethodImplementedAndReified(typeDefType, "GetName");
- bool needsStringLiteralList = (mOptions.mAllowHotSwapping) || (bfModule->IsMethodImplementedAndReified(stringType, "Intern"));
- Dictionary<int, int> usedStringIdMap;
- HashSet<BfType*> reflectTypeSet;
- reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef));
- reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectSpecializedGenericType));
- reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectUnspecializedGenericType));
- reflectTypeSet.Add(vdataContext->mUnreifiedModule->ResolveTypeDef(mReflectArrayType));
-
- SmallVector<BfIRValue, 256> typeDataVector;
- for (auto type : vdataTypeList)
- {
- if (type->IsTypeAlias())
- continue;
- if (type->IsTypeInstance())
- BF_ASSERT(!type->IsIncomplete());
- auto typeInst = type->ToTypeInstance();
-
- if ((typeInst != NULL) && (!typeInst->IsReified()) && (!typeInst->IsUnspecializedType()))
- continue;
- bool needsTypeData = (needsTypeList) || ((type->IsObject()) && (needsObjectTypeData));
- bool forceReflectFields = false;
- if (bfModule->mProject->mReferencedTypeData.Contains(type))
- {
- needsTypeData = true;
- if (type->IsEnum())
- forceReflectFields = true;
- }
- bool needsVData = (type->IsObject()) && (typeInst->mHasBeenInstantiated);
- BfIRValue typeVariable;
-
- if ((needsTypeData) || (needsVData))
- {
- if (reflectTypeSet.Contains(type))
- {
- needsTypeData = true;
- needsVData = true;
- }
- typeVariable = bfModule->CreateTypeData(type, usedStringIdMap, forceReflectFields, needsTypeData, needsTypeNames, needsVData);
- }
- type->mDirty = false;
-
- if (needsTypeList)
- {
- int typeId = type->mTypeId;
- if (typeId == -1)
- continue;
- if (typeId >= (int)typeDataVector.size())
- typeDataVector.resize(typeId + 1);
- typeDataVector[typeId] = typeVariable;
- }
- }
- for (int typeId = 0; typeId < (int)typeDataVector.size(); typeId++)
- {
- if (!typeDataVector[typeId])
- typeDataVector[typeId] = bfModule->GetDefaultValue(typeDefType);
- }
- // We only need 'sTypes' if we actually reference it
- //
- {
- auto typeDefPtrType = bfModule->CreatePointerType(typeDefType);
- StringT<128> typesVariableName;
- BfMangler::MangleStaticFieldName(typesVariableName, GetMangleKind(), typeDefType->ToTypeInstance(), "sTypes", typeDefPtrType);
- auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(typeDefType), (int)typeDataVector.size());
- auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, typeDataVector);
- BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_External,
- typeDataConst, typesVariableName);
- }
-
- HashSet<int> foundStringIds;
- for (int stringId : bfModule->mStringPoolRefs)
- foundStringIds.Add(stringId);
- Array<BfModule*> orderedUsedModules;
- for (auto module : usedModuleSet)
- orderedUsedModules.push_back(module);
- std::sort(orderedUsedModules.begin(), orderedUsedModules.end(), [] (BfModule* lhs, BfModule* rhs)
- {
- return lhs->mModuleName < rhs->mModuleName;
- });
- Array<BfMethodInstance*> dllMethods;
- Array<BfIRValue> forceLinkValues;
- HashSet<int> dllNameSet;
- Array<BfCompiler::StringValueEntry> stringValueEntries;
- for (auto module : orderedUsedModules)
- {
- CheckModuleStringRefs(module, bfModule, lastModuleRevision, foundStringIds, dllNameSet, dllMethods, stringValueEntries);
- if ((module->mHasForceLinkMarker) &&
- ((!isHotCompile) || (module->mHadHotObjectWrites)))
- forceLinkValues.Add(bfModule->CreateForceLinkMarker(module, NULL));
- }
- if (!forceLinkValues.IsEmpty())
- {
- auto elemType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Int8));
- auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(elemType), (int)forceLinkValues.size());
- auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, forceLinkValues);
- BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_Internal,
- typeDataConst, "FORCELINK_MODULES");
- }
-
- // Generate strings array
- {
- if (!needsStringLiteralList)
- {
- stringValueEntries.Clear();
- }
- std::sort(stringValueEntries.begin(), stringValueEntries.end(),
- [](const StringValueEntry& lhs, const StringValueEntry& rhs)
- {
- return lhs.mId < rhs.mId;
- });
-
- auto stringPtrType = bfModule->CreatePointerType(stringType);
- auto stringPtrIRType = bfModule->mBfIRBuilder->MapTypeInstPtr(stringType);
-
- StringT<128> stringsVariableName;
- BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sStringLiterals", stringPtrType);
- Array<BfIRValue> stringList;
- stringList.Add(bfModule->mBfIRBuilder->CreateConstNull(stringPtrIRType));
- for (auto& stringValueEntry : stringValueEntries)
- stringList.Add(stringValueEntry.mStringVal);
- stringList.Add(bfModule->mBfIRBuilder->CreateConstNull(stringPtrIRType));
- BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)stringList.size());
- auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
-
- auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
-
- if (bfModule->mBfIRBuilder->DbgHasInfo())
- {
- auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size());
- bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar);
- }
- }
- // Generate string ID array
- {
- auto stringType = bfModule->ResolveTypeDef(mStringTypeDef, BfPopulateType_Data)->ToTypeInstance();
- auto stringPtrType = bfModule->CreatePointerType(stringType);
- auto stringPtrIRType = bfModule->mBfIRBuilder->MapTypeInstPtr(stringType);
- StringT<128> stringsVariableName;
- BfMangler::MangleStaticFieldName(stringsVariableName, GetMangleKind(), stringType->ToTypeInstance(), "sIdStringLiterals", stringPtrType);
- Array<BfIRValue> stringList;
- stringList.Resize(usedStringIdMap.size());
- for (auto& kv : usedStringIdMap)
- {
- stringList[kv.mValue] = bfModule->mStringObjectPool[kv.mKey];
- }
- BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)usedStringIdMap.size());
- auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
- auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
- if (bfModule->mBfIRBuilder->DbgHasInfo())
- {
- auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size());
- bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar);
- }
- }
- BfIRFunction loadSharedLibFunc = CreateLoadSharedLibraries(bfModule, dllMethods);
-
- BfIRType nullPtrType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_NullPtr));
- BfIRType voidType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_None));
- BfIRType int32Type = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_Int32));
- struct _StaticInitEntry
- {
- int mPriority;
- BfTypeInstance* mTypeInstance;
- };
- Array<_StaticInitEntry> staticInitList;
- // Populate staticInitList
- {
- Dictionary<int, BfTypeInstance*> pendingIDToInstanceMap;
- HashSet<BfTypeInstance*> handledTypes;
- BfType* staticInitPriorityAttributeType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStaticInitPriorityAttributeTypeDef);
- BfType* staticInitAfterAttributeType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStaticInitAfterAttributeTypeDef);
- bool forceAdd = false;
- for (int pass = 0; true; pass++)
- {
- bool hadAdd = false;
- for (auto& mapEntry : sortedStaticInitMap)
- {
- auto typeInst = mapEntry.second;
- if ((typeInst != NULL) && (!typeInst->IsUnspecializedType()) && (typeInst->mHasStaticInitMethod))
- {
- if (pass == 0)
- {
- int priority = 0;
- bool hadInitAfterAttribute = false;
- if (typeInst->mCustomAttributes != NULL)
- {
- for (auto& customAttr : typeInst->mCustomAttributes->mAttributes)
- {
- if (customAttr.mType == staticInitAfterAttributeType)
- hadInitAfterAttribute = true;
- if (customAttr.mType == staticInitPriorityAttributeType)
- {
- if (customAttr.mCtorArgs.size() == 1)
- {
- auto constant = typeInst->mConstHolder->GetConstant(customAttr.mCtorArgs[0]);
- if (constant != NULL)
- priority = constant->mInt32;
- }
- }
- }
- }
- if (!hadInitAfterAttribute)
- {
- staticInitList.push_back({ priority, typeInst });
- mapEntry.second = NULL;
- }
- else
- {
- pendingIDToInstanceMap.TryAdd(typeInst->mTypeId, typeInst);
- }
- }
- else
- {
- if (pendingIDToInstanceMap.ContainsKey(typeInst->mTypeId))
- {
- bool doAdd = true;
- if (!forceAdd)
- {
- for (auto& customAttr : typeInst->mCustomAttributes->mAttributes)
- {
- if (customAttr.mType == staticInitAfterAttributeType)
- {
- if (customAttr.mCtorArgs.size() == 0)
- {
- doAdd = false;
- }
- else
- {
- auto ctorArg = customAttr.mCtorArgs[0];
- auto constant = typeInst->mConstHolder->GetConstant(ctorArg);
- if (constant != NULL)
- {
- int refTypeId = constant->mInt32;
- if (pendingIDToInstanceMap.ContainsKey(refTypeId))
- doAdd = false;
- }
- }
- }
- }
- }
- if (doAdd)
- {
- staticInitList.push_back({ 0, typeInst });
- pendingIDToInstanceMap.Remove(typeInst->mTypeId);
- hadAdd = true;
- }
- }
- }
- }
- }
- if (pass == 0)
- {
- std::sort(staticInitList.begin(), staticInitList.end(),
- [](const _StaticInitEntry& lhs, const _StaticInitEntry& rhs)
- {
- return lhs.mPriority > rhs.mPriority;
- });
- }
- if ((pass > 0) && (!hadAdd) && (pendingIDToInstanceMap.size() > 0)) // Circular ref?
- forceAdd = true;
- if (pendingIDToInstanceMap.size() == 0)
- break;
- }
- }
- // We want to call DTORS in reverse order from CTORS
- Array<BfTypeInstance*> dtorList;
- for (intptr idx = staticInitList.size() - 1; idx >= 0; idx--)
- {
- auto typeInst = staticInitList[idx].mTypeInstance;
- if (typeInst->mHasStaticDtorMethod)
- {
- dtorList.push_back(typeInst);
- }
- }
- for (auto itr = sortedStaticDtorMap.rbegin(); itr != sortedStaticDtorMap.rend(); itr++)
- {
- auto typeInst = itr->second;
- dtorList.push_back(typeInst);
- }
- /// Generate "BfCallAllStaticDtors"
- BfIRFunction dtorFunc;
- {
- SmallVector<BfIRType, 2> paramTypes;
- auto dtorFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
- dtorFunc = bfModule->mBfIRBuilder->CreateFunction(dtorFuncType, BfIRLinkageType_External, "BfCallAllStaticDtors");
- bfModule->SetupIRMethod(NULL, dtorFunc, false);
- bfModule->mBfIRBuilder->SetActiveFunction(dtorFunc);
- auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
- for (auto typeInst : dtorList)
- {
- for (auto& methodGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodGroup.mDefault;
- if ((methodInstance != NULL) &&
- (methodInstance->mMethodDef->mIsStatic) &&
- (methodInstance->mMethodDef->mMethodType == BfMethodType_Dtor) &&
- ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
- {
- if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
- continue;
- if (methodInstance->mHotMethod != NULL)
- methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
- auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
- bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
- }
- }
- }
- bfModule->mBfIRBuilder->CreateRetVoid();
- }
- // Generate "main"
- if (!IsHotCompile())
- {
- BfIRFunctionType mainFuncType;
- BfIRFunction mainFunc;
- if ((project->mTargetType == BfTargetType_BeefConsoleApplication) || (project->mTargetType == BfTargetType_BeefTest))
- {
- SmallVector<BfIRType, 2> paramTypes;
- paramTypes.push_back(int32Type);
- paramTypes.push_back(nullPtrType);
- mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
- mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "main");
- bfModule->SetupIRMethod(NULL, mainFunc, false);
- }
- else if (project->mTargetType == BfTargetType_BeefDynLib)
- {
- SmallVector<BfIRType, 4> paramTypes;
- paramTypes.push_back(nullPtrType); // hinstDLL
- paramTypes.push_back(int32Type); // fdwReason
- paramTypes.push_back(nullPtrType); // lpvReserved
- mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
- mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "DllMain");
- if (mSystem->mPtrSize == 4)
- bfModule->mBfIRBuilder->SetFuncCallingConv(mainFunc, BfIRCallingConv_StdCall);
- bfModule->SetupIRMethod(NULL, mainFunc, false);
- }
- else if (project->mTargetType == BfTargetType_BeefWindowsApplication)
- {
- SmallVector<BfIRType, 4> paramTypes;
- paramTypes.push_back(nullPtrType); // hInstance
- paramTypes.push_back(nullPtrType); // hPrevInstance
- paramTypes.push_back(nullPtrType); // lpCmdLine
- paramTypes.push_back(int32Type); // nCmdShow
- mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
- mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "WinMain");
- if (mSystem->mPtrSize == 4)
- bfModule->mBfIRBuilder->SetFuncCallingConv(mainFunc, BfIRCallingConv_StdCall);
- bfModule->SetupIRMethod(NULL, mainFunc, false);
- }
- else
- {
- SmallVector<BfIRType, 2> paramTypes;
- paramTypes.push_back(int32Type);
- paramTypes.push_back(nullPtrType);
- mainFuncType = bfModule->mBfIRBuilder->CreateFunctionType(voidType, paramTypes, false);
- mainFunc = bfModule->mBfIRBuilder->CreateFunction(mainFuncType, BfIRLinkageType_External, "BeefMain");
- bfModule->SetupIRMethod(NULL, mainFunc, false);
- }
- bfModule->mBfIRBuilder->SetActiveFunction(mainFunc);
- auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
-
- #ifndef BF_PLATFORM_WINDOWS
- {
- SmallVector<BfIRType, 2> paramTypes;
- paramTypes.push_back(int32Type);
- paramTypes.push_back(nullPtrType);
- auto setCmdLineFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
- auto setCmdLineFunc = bfModule->mBfIRBuilder->CreateFunction(setCmdLineFuncType, BfIRLinkageType_External, "BfpSystem_SetCommandLine");
- bfModule->SetupIRMethod(NULL, setCmdLineFunc, false);
- SmallVector<BfIRValue, 2> args;
- args.push_back(bfModule->mBfIRBuilder->GetArgument(0));
- args.push_back(bfModule->mBfIRBuilder->GetArgument(1));
- bfModule->mBfIRBuilder->CreateCall(setCmdLineFunc, args);
- }
- #endif
-
- BfIRBlock initSkipBlock;
- if (project->mTargetType == BfTargetType_BeefDynLib)
- {
- auto initBlock = bfModule->mBfIRBuilder->CreateBlock("doInit", false);
- initSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipInit", false);
- auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 1));
- bfModule->mBfIRBuilder->CreateCondBr(cmpResult, initBlock, initSkipBlock);
- bfModule->mBfIRBuilder->AddBlock(initBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(initBlock);
- auto moduleMethodInstance = bfModule->GetInternalMethod("SetModuleHandle", 1);
- if (moduleMethodInstance)
- {
- SmallVector<BfIRValue, 1> args;
- args.push_back(bfModule->mBfIRBuilder->GetArgument(0));
- bfModule->mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, args);
- }
- }
- // Do the LoadLibrary calls below priority 100
- bool didSharedLibLoad = false;
- auto _CheckSharedLibLoad = [&]()
- {
- if (!didSharedLibLoad)
- {
- bfModule->mBfIRBuilder->CreateCall(loadSharedLibFunc, SmallVector<BfIRValue, 0>());
- didSharedLibLoad = true;
- }
- };
- for (auto& staticInitEntry : staticInitList)
- {
- if (staticInitEntry.mPriority < 100)
- _CheckSharedLibLoad();
- auto typeInst = staticInitEntry.mTypeInstance;
- for (auto& methodGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodGroup.mDefault;
- if ((methodInstance != NULL) &&
- (methodInstance->mMethodDef->mIsStatic) &&
- (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor) &&
- ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
- {
- if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
- continue;
- auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
- if (methodInstance->mHotMethod != NULL)
- methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
- bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
- }
- }
- }
- _CheckSharedLibLoad();
- if (initSkipBlock)
- {
- bfModule->mBfIRBuilder->CreateBr(initSkipBlock);
- bfModule->mBfIRBuilder->AddBlock(initSkipBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(initSkipBlock);
- }
- BfIRValue retValue;
- if ((project->mTargetType == BfTargetType_BeefConsoleApplication) || (project->mTargetType == BfTargetType_BeefWindowsApplication))
- {
- bool hadRet = false;
- String entryClassName = project->mStartupObject;
- typeDef = mSystem->FindTypeDef(entryClassName, 0, bfModule->mProject);
- if (typeDef != NULL)
- {
- auto type = bfModule->ResolveTypeDef(typeDef);
- BF_ASSERT((type != NULL) || (mPassInstance->HasFailed()));
- if (type != NULL)
- {
- BfType* stringType = vdataContext->mUnreifiedModule->ResolveTypeDef(mStringTypeDef);
- BfType* int32Type = bfModule->GetPrimitiveType(BfTypeCode_Int32);
- BfType* intType = bfModule->GetPrimitiveType(BfTypeCode_IntPtr);
- BfType* voidType = bfModule->GetPrimitiveType(BfTypeCode_None);
- bool hadValidMainMethod = false;
- BfModuleMethodInstance moduleMethodInst;
- for (auto methodDef : typeDef->mMethods)
- {
- if (methodDef->mName == "Main")
- {
- hadValidMainMethod = true;
- moduleMethodInst = bfModule->GetMethodInstanceAtIdx(type->ToTypeInstance(), methodDef->mIdx);
- if (!methodDef->mIsStatic)
- {
- mPassInstance->Fail("Main method must be static", methodDef->GetRefNode());
- hadValidMainMethod = false;
- }
-
- if ((moduleMethodInst.mMethodInstance->mReturnType != int32Type) &&
- (moduleMethodInst.mMethodInstance->mReturnType != intType) &&
- (moduleMethodInst.mMethodInstance->mReturnType != voidType))
- {
- mPassInstance->Fail("Main method must return void, int, or int32", methodDef->GetRefNode());
- hadValidMainMethod = false;
- }
-
- if (moduleMethodInst.mMethodInstance->GetParamCount() == 0)
- {
- // No params
- }
- else
- {
- auto paramType = moduleMethodInst.mMethodInstance->GetParamType(0);
- if ((moduleMethodInst.mMethodInstance->GetParamCount() != 1) || (!paramType->IsArray()) || (paramType->GetUnderlyingType() != stringType))
- {
- mPassInstance->Fail("Main method must be declared with either no parameters or a single String[] parameter", methodDef->GetRefNode());
- hadValidMainMethod = false;
- }
- }
- }
- }
-
- if (moduleMethodInst)
- {
- if (hadValidMainMethod)
- {
- bool hasArgs = moduleMethodInst.mMethodInstance->GetParamCount() != 0;
-
- BfIRType intType = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_IntPtr));
- BfIRType int32Type = bfModule->mBfIRBuilder->MapType(bfModule->GetPrimitiveType(BfTypeCode_Int32));
- // Create BeefEntry thunk
- SmallVector<BfIRType, 1> paramTypes;
- if (hasArgs)
- {
- paramTypes.push_back(bfModule->mBfIRBuilder->MapType(moduleMethodInst.mMethodInstance->GetParamType(0)));
- }
- BfIRFunctionType thunkFuncType = bfModule->mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, false);
-
- BfIRFunction thunkMainFunc = bfModule->mBfIRBuilder->CreateFunction(thunkFuncType, BfIRLinkageType_External, "BeefMain");
- bfModule->SetupIRMethod(NULL, thunkMainFunc, false);
- bfModule->mBfIRBuilder->SetActiveFunction(thunkMainFunc);
- auto thunkEntryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(thunkEntryBlock);
- SmallVector<BfIRValue, 1> args;
- if (hasArgs)
- args.push_back(bfModule->mBfIRBuilder->GetArgument(0));
- auto methodInstance = moduleMethodInst.mMethodInstance;
- if (methodInstance->mHotMethod != NULL)
- methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
- auto retVal = bfModule->mBfIRBuilder->CreateCall(moduleMethodInst.mFunc, args);
- if (moduleMethodInst.mMethodInstance->mReturnType->IsVoid())
- {
- bfModule->mBfIRBuilder->CreateRet(bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0));
- }
- else
- {
- retVal = bfModule->mBfIRBuilder->CreateNumericCast(retVal, true, BfTypeCode_Int32);
- bfModule->mBfIRBuilder->CreateRet(retVal);
- }
- hadRet = true;
- auto internalType = bfModule->ResolveTypeDef(mInternalTypeDef);
-
- args.clear();
- // Call BeefEntry thunk
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
- if (hasArgs)
- {
- auto createParamsMethodInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "CreateParamsArray");
- auto callValue = bfModule->mBfIRBuilder->CreateCall(createParamsMethodInstance.mFunc, SmallVector<BfIRValue, 0>());
- args.push_back(callValue);
- }
- retValue = bfModule->mBfIRBuilder->CreateCall(thunkMainFunc, args);
- if (hasArgs)
- {
- auto deleteStringArrayMethodInstance = bfModule->GetMethodByName(internalType->ToTypeInstance(), "DeleteStringArray");
- bfModule->mBfIRBuilder->CreateCall(deleteStringArrayMethodInstance.mFunc, args);
- }
- }
- }
- else
- {
- mPassInstance->Fail(StrFormat("Unable to find Main method in class '%s'", entryClassName.c_str()));
- }
- }
- }
- else
- {
- if (entryClassName.empty())
- mPassInstance->Fail(StrFormat("No entry point class specified for executable in project '%s'", project->mName.c_str()));
- else
- mPassInstance->Fail(StrFormat("Unable to find entry point class '%s' in project '%s'", entryClassName.c_str(), project->mName.c_str()));
- bfModule->mHadBuildError = true;
- }
- if (!hadRet)
- retValue = bfModule->GetConstValue32(0);
- }
- else if (project->mTargetType == BfTargetType_BeefDynLib)
- {
- retValue = bfModule->GetConstValue32(1);
- }
- if (project->mTargetType == BfTargetType_BeefTest)
- EmitTestMethod(bfModule, testMethods, retValue);
- BfIRBlock deinitSkipBlock;
- if (project->mTargetType == BfTargetType_BeefDynLib)
- {
- auto deinitBlock = bfModule->mBfIRBuilder->CreateBlock("doDeinit", false);
- deinitSkipBlock = bfModule->mBfIRBuilder->CreateBlock("skipDeinit", false);
- auto cmpResult = bfModule->mBfIRBuilder->CreateCmpEQ(bfModule->mBfIRBuilder->GetArgument(1), bfModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, 0));
- bfModule->mBfIRBuilder->CreateCondBr(cmpResult, deinitBlock, deinitSkipBlock);
- bfModule->mBfIRBuilder->AddBlock(deinitBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(deinitBlock);
- }
- bfModule->mBfIRBuilder->CreateCall(dtorFunc, SizedArray<BfIRValue, 0>());
-
- BfModuleMethodInstance shutdownMethod = bfModule->GetInternalMethod("Shutdown");
- if (shutdownMethod)
- {
- bfModule->mBfIRBuilder->CreateCall(shutdownMethod.mFunc, SizedArray<BfIRValue, 0>());
- }
- if (deinitSkipBlock)
- {
- bfModule->mBfIRBuilder->CreateBr(deinitSkipBlock);
- bfModule->mBfIRBuilder->AddBlock(deinitSkipBlock);
- bfModule->mBfIRBuilder->SetInsertPoint(deinitSkipBlock);
- }
- if (retValue)
- bfModule->mBfIRBuilder->CreateRet(retValue);
- else
- bfModule->mBfIRBuilder->CreateRetVoid();
- if ((mOptions.mAllowHotSwapping) && (bfModule->mHasFullDebugInfo))
- {
- auto int8Type = bfModule->GetPrimitiveType(BfTypeCode_Int8);
- int dataSize = 16*1024;
- auto irArrType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(int8Type), dataSize);
- String name = "__BFTLS_EXTRA";
- auto irVal = bfModule->mBfIRBuilder->CreateGlobalVariable(irArrType, false, BfIRLinkageType_External, bfModule->mBfIRBuilder->CreateConstStructZero(irArrType), name, true);
- BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize);
- bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, NULL, 0, dbgArrayType, false, irVal);
- }
- }
-
- // Generate "System.GC.MarkAllStaticMembers"
- auto gcType = vdataContext->mUnreifiedModule->ResolveTypeDef(mGCTypeDef);
- if (bfModule->IsMethodImplementedAndReified(gcType->ToTypeInstance(), "MarkAllStaticMembers"))
- {
- bfModule->PopulateType(gcType);
- auto moduleMethodInstance = bfModule->GetMethodByName(gcType->ToTypeInstance(), "MarkAllStaticMembers");
- bfModule->mBfIRBuilder->SetActiveFunction(moduleMethodInstance.mFunc);
- if (!moduleMethodInstance)
- {
- bfModule->Fail("Internal error: System.GC doesn't contain MarkAllStaticMembers method");
- }
- else
- {
- auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
- for (auto& mapEntry : sortedStaticMarkMap)
- {
- auto typeInst = mapEntry.second;
- if (typeInst->IsUnspecializedType())
- continue;
-
- for (auto& methodGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodGroup.mDefault;
- if ((methodInstance != NULL) &&
- (methodInstance->mMethodDef->mIsStatic) &&
- (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) &&
- (methodInstance->mMethodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) &&
- ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
- {
- if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
- continue;
- auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
- if (methodInstance->mHotMethod != NULL)
- methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_AlwaysCalled);
- bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
- }
- }
- }
- bfModule->mBfIRBuilder->CreateRetVoid();
- }
- }
- // Generate "System.GC.FindAllTLSMembers"
- if (bfModule->IsMethodImplementedAndReified(gcType->ToTypeInstance(), "FindAllTLSMembers"))
- {
- bfModule->PopulateType(gcType);
- auto moduleMethodInstance = bfModule->GetMethodByName(gcType->ToTypeInstance(), "FindAllTLSMembers");
- bfModule->mBfIRBuilder->SetActiveFunction(moduleMethodInstance.mFunc);
- if (!moduleMethodInstance)
- {
- bfModule->Fail("Internal error: System.GC doesn't contain FindAllTLSMembers method");
- }
- else
- {
- auto entryBlock = bfModule->mBfIRBuilder->CreateBlock("entry", true);
- bfModule->mBfIRBuilder->SetInsertPoint(entryBlock);
- for (auto& mapEntry : sortedStaticTLSMap)
- {
- auto typeInst = mapEntry.second;
- if (typeInst->IsUnspecializedType())
- continue;
- for (auto& methodGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodGroup.mDefault;
- if ((methodInstance != NULL) &&
- (methodInstance->mMethodDef->mIsStatic) &&
- (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) &&
- (methodInstance->mMethodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS) &&
- ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
- {
- if (!typeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, bfModule->mProject))
- continue;
- auto methodModule = bfModule->GetMethodInstanceAtIdx(typeInst, methodInstance->mMethodDef->mIdx);
- bfModule->mBfIRBuilder->CreateCall(methodModule.mFunc, SmallVector<BfIRValue, 0>());
- }
- }
- }
- bfModule->mBfIRBuilder->CreateRetVoid();
- }
- }
- if (bfModule->mHadBuildError)
- {
- bfModule->mDataHash = 0;
- }
- }
- // This method clears out unused generic types AFTER compilation of reified types has occurred
- void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
- {
- BP_ZONE("BfCompiler::UpdateDependencyMap");
- BfLogSysM("Compiler::UpdateDependencyMap %d\n", deleteUnusued);
- bool madeFullPass = true;
- if (mCanceling)
- madeFullPass = false;
- if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
- madeFullPass = false;
-
- // Remove old data in dependency maps, and find types which don't have any references (direct or indirect)
- // to a non-generic type and remove them
- for (int pass = 0; true; pass++)
- {
- // This assert can fail if we have a dependency error, where deleting a type causes a dependent type
- // to be rebuilt
- BF_ASSERT(pass < 100);
- bool foundNew = false;
-
- for (auto type : mContext->mResolvedTypes)
- {
- if (type != NULL)
- {
- auto depType = type->ToDependedType();
- auto typeInst = type->ToTypeInstance();
-
- if (depType != NULL)
- {
- extern BfModule* gLastCreatedModule;
-
- for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr)
- {
- auto dependentType = itr->mKey;
-
- if (dependentType->IsIncomplete())
- {
- BF_ASSERT(dependentType->IsDeleting() || dependentType->IsOnDemand() || !dependentType->HasBeenReferenced() || !madeFullPass || dependentType->IsSpecializedByAutoCompleteMethod());
- }
- }
- // Not combined with previous loop because PopulateType could modify typeInst->mDependencyMap
- for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end();)
- {
- auto dependentType = itr->mKey;
- auto depTypeInst = dependentType->ToTypeInstance();
- auto& depData = itr->mValue;
-
- bool isInvalidVersion = (dependentType->mRevision > depData.mRevision) && (deleteUnusued) && (madeFullPass);
-
- //TODO: Just to cause crash if dependentType is deleted
- bool isIncomplete = dependentType->IsIncomplete();
- if ((isInvalidVersion) && (!dependentType->IsDeleting()))
- {
- if (!dependentType->HasBeenReferenced())
- {
- BfLogSysM("Skipping remove of old dependent %p from %p\n", dependentType, typeInst);
- //BF_ASSERT(dependentType->IsGenericTypeInstance());
- // We have a pending type rebuild but we're not sure whether we're being deleted or not yet...
- ++itr;
- continue;
- }
- }
- if ((dependentType->IsDeleting()) || (isInvalidVersion))
- {
- // If we're deleting the type, OR the dependency of the type has been removed.
- // We detect a removed dependency by the dependent type changing but the dependency revision
- // is older than the dependent type.
- BfLogSysM("Removing old dependent %p from %p\n", dependentType, typeInst);
- itr = depType->mDependencyMap.erase(itr);
- }
- else
- {
- // There needs to be more usage than just being used as part of the method specialization's MethodGenericArg.
- // Keep in mind that actually invoking a generic method creates a DependencyFlag_LocalUsage dependency. The
- // DependencyFlag_MethodGenericArg is just used by the owner during creation of the method specialization
- bool isDependentUsage =
- (depData.mFlags != BfDependencyMap::DependencyFlag_UnspecializedType) &&
- (depData.mFlags != BfDependencyMap::DependencyFlag_MethodGenericArg);
-
- // We need to consider specialized generic types separately, to remove unused specializations
- if (typeInst != NULL)
- {
- if ((depTypeInst != NULL) && (typeInst->mLastNonGenericUsedRevision != mRevision) && (isDependentUsage) &&
- ((!dependentType->IsGenericTypeInstance()) || (dependentType->IsUnspecializedType()) || (depTypeInst->mLastNonGenericUsedRevision == mRevision)))
- {
- typeInst->mLastNonGenericUsedRevision = mRevision;
- foundNew = true;
-
- if (!typeInst->HasBeenReferenced())
- mContext->AddTypeToWorkList(typeInst);
- }
- }
-
- ++itr;
- }
- }
- if ((!depType->IsGenericTypeInstance() && (!depType->IsBoxed())) ||
- (depType->IsUnspecializedType()) ||
- ((typeInst != NULL) && (typeInst->mLastNonGenericUsedRevision == mRevision)))
- {
- if ((depType->mRebuildFlags & BfTypeRebuildFlag_AwaitingReference) != 0)
- {
- mContext->MarkAsReferenced(depType);
- }
- }
- }
- }
- }
- if (mCanceling)
- madeFullPass = false;
- if (!madeFullPass)
- {
- // We can't delete types based on the dependency map when we're canceling, because we may still
- // have items in the work queues (particularly the mMethodWorkList) that will create
- // new dependencies -- things may unduly be thought to be deleted.
- return;
- }
- if (foundNew)
- {
- // This will work through generic method specializations for the types referenced above, clearing out AwaitingReference flags for
- // newly-referenced generics, and queuing up their method specializations as well
- didWork |= DoWorkLoop(false, false);
- }
- else if (deleteUnusued)
- {
- // Work queues should be empty if we're not canceling
- BF_ASSERT(mContext->mPopulateTypeWorkList.size() == 0);
- BF_ASSERT(mContext->mMethodWorkList.size() == 0);
- // We need to use a delete queue because we trigger a RebuildType for dependent types,
- // but we need to make sure we don't rebuild any types that may be next in line for
- // deletion, so we must set BfTypeRebuildFlag_DeleteQueued first to avoid that
- Array<BfDependedType*> deleteQueue;
- // We bubble out
- for (auto type : mContext->mResolvedTypes)
- {
- auto depType = type->ToDependedType();
- // Delete if we're a generic
- if ((depType != NULL) && (!depType->IsDeleting()))
- {
- auto typeInst = depType->ToTypeInstance();
-
- bool wantDelete = false;
- if (typeInst != NULL)
- {
- wantDelete = (typeInst->mLastNonGenericUsedRevision != mRevision) &&
- (typeInst->IsGenericTypeInstance() || typeInst->IsBoxed()) && (!typeInst->IsUnspecializedType());
- }
- wantDelete |= (depType->IsOnDemand()) && (depType->mDependencyMap.IsEmpty());
- if (wantDelete)
- {
- deleteQueue.push_back(depType);
- depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_DeleteQueued);
- foundNew = true;
- }
- }
- }
- for (auto depType : deleteQueue)
- {
- BfLogSysM("Deleting type from deleteQueue in UpdateDependencyMap %p\n", depType);
- mContext->DeleteType(depType, true);
- }
- if (deleteQueue.size() != 0)
- {
- mContext->UpdateAfterDeletingTypes();
- }
- }
- if (!foundNew)
- break;
- }
- #ifdef _DEBUG
- if (deleteUnusued)
- {
- for (auto type : mContext->mResolvedTypes)
- {
- // This flag should be handled by now
- BF_ASSERT((type->mRebuildFlags & BfTypeRebuildFlag_AwaitingReference) == 0);
- }
- }
- #endif
-
- BP_ZONE("UpdateDependencyMap QueuedSpecializedMethodRebuildTypes");
- HashSet<BfTypeInstance*> specializerSet;
- for (auto rebuildType : mContext->mQueuedSpecializedMethodRebuildTypes)
- {
- if (rebuildType->mRevision != mRevision)
- {
- mContext->RebuildType(rebuildType);
- rebuildType->mRebuildFlags = (BfTypeRebuildFlags)(rebuildType->mRebuildFlags | BfTypeRebuildFlag_SpecializedMethodRebuild);
- for (auto& dep : rebuildType->mDependencyMap)
- {
- auto depType = dep.mKey;
- auto& depData = dep.mValue;
- auto depTypeInst = depType->ToTypeInstance();
- if (depTypeInst == NULL)
- continue;
- if ((depData.mFlags & BfDependencyMap::DependencyFlag_Calls) != 0)
- {
- specializerSet.Add(depTypeInst);
- }
- }
- }
- }
- for (auto depType : specializerSet)
- {
- mContext->QueueMethodSpecializations(depType, true);
- }
- for (auto rebuildType : mContext->mQueuedSpecializedMethodRebuildTypes)
- {
- rebuildType->mRebuildFlags = (BfTypeRebuildFlags)(rebuildType->mRebuildFlags & ~BfTypeRebuildFlag_SpecializedMethodRebuild);
- }
- mContext->mQueuedSpecializedMethodRebuildTypes.Clear();
- }
- // When we are unsure of whether an old generic instance will survive, we RebuildType but don't put it in any worklist.
- // One of three things happens:
- // 1) It gets built on demand
- // 2) It gets deleted in UpdateDependencyMap
- // 3) It stays undefined and we need to build it here
- void BfCompiler::ProcessPurgatory(bool reifiedOnly)
- {
- BP_ZONE("BfCompiler::ProcessPuragory");
- while (true)
- {
- mContext->RemoveInvalidWorkItems();
-
- //for (auto type : mGenericInstancePurgatory)
- for (int i = 0; i < (int)mGenericInstancePurgatory.size(); i++)
- {
- auto type = mGenericInstancePurgatory[i];
- if ((reifiedOnly) && (!type->IsReified()))
- continue;
- if (!type->IsDeleting())
- {
- auto module = type->GetModule();
- if (module != NULL)
- module->PopulateType(type, BfPopulateType_Full);
- }
- if (reifiedOnly)
- {
- mGenericInstancePurgatory.RemoveAtFast(i);
- i--;
- }
- }
- if (!reifiedOnly)
- mGenericInstancePurgatory.Clear();
- int prevPurgatorySize = (int)mGenericInstancePurgatory.size();
- mContext->ProcessWorkList(reifiedOnly, reifiedOnly);
- if (prevPurgatorySize == (int)mGenericInstancePurgatory.size())
- break;
- }
- }
- bool BfCompiler::VerifySlotNums()
- {
- BP_ZONE("BfCompiler::VerifySlotNums");
- SmallVector<BfTypeInstance*, 16> isSlotUsed;
- for (auto type : mContext->mResolvedTypes)
- {
- if (!type->IsReified())
- continue;
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
- if (typeInst->IsUnspecializedType())
- continue;
- if (typeInst->IsInterface())
- {
- if (typeInst->mSlotNum == -2)
- continue; // Not used
- if ((typeInst->mVirtualMethodTableSize > 0) && (typeInst->mSlotNum == -1))
- {
- // Slot not assigned yet
- return false;
- }
- continue;
- }
- isSlotUsed.clear();
- isSlotUsed.resize(mMaxInterfaceSlots);
- auto checkType = typeInst;
- while (checkType != NULL)
- {
- for (auto iface : checkType->mInterfaces)
- {
- int slotNum = iface.mInterfaceType->mSlotNum;
- if (slotNum >= 0)
- {
- if ((isSlotUsed[slotNum] != NULL) && (isSlotUsed[slotNum] != iface.mInterfaceType))
- return false; // Collision
- isSlotUsed[slotNum] = iface.mInterfaceType;
- }
- }
-
- checkType = checkType->mBaseType;
- }
- }
- return true;
- }
- bool BfCompiler::QuickGenerateSlotNums()
- {
- /*SmallVector<bool, 16> isSlotUsed;
- for (auto globalTypeEntry : mResolvedTypes)
- {
- BfType* type = globalTypeEntry->mType;
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
- if (typeInst->IsInterface())
- {
- if ((typeInst->mVirtualMethodTableSize > 0) && (typeInst->mSlotNum == -1))
- {
- // Slot not assigned yet
- return false;
- }
- continue;
- }
- }
- return VerifySlotNums();*/
- // Implement later
- return false;
- }
- class BfSlotEntry
- {
- public:
- BfTypeInstance* mTypeInstance;
- int mRefCount;
- Array<BfTypeInstance*> mConcurrentRefs;
- };
- typedef std::pair<BfTypeInstance*, BfTypeInstance*> InterfacePair;
- typedef Dictionary<BfTypeInstance*, BfSlotEntry*> SlotEntryMap;
- static BfSlotEntry* GetSlotEntry(SlotEntryMap& slotEntryMap, BfTypeInstance* typeInst)
- {
- BF_ASSERT(typeInst->IsReified());
- BfSlotEntry** slotEntryPtr = NULL;
- if (!slotEntryMap.TryAdd(typeInst, NULL, &slotEntryPtr))
- return *slotEntryPtr;
-
- BfSlotEntry* slotEntry = new BfSlotEntry();
- slotEntry->mTypeInstance = typeInst;
- slotEntry->mRefCount = 0;
- //insertPair.first->second = slotEntry;
- *slotEntryPtr = slotEntry;
- return slotEntry;
- }
- static InterfacePair MakeInterfacePair(BfTypeInstance* iface1, BfTypeInstance* iface2)
- {
- if (iface1->mTypeId < iface2->mTypeId)
- return InterfacePair(iface1, iface2);
- return InterfacePair(iface2, iface1);
- }
- struct InterfacePairHash
- {
- size_t operator()(const InterfacePair& val) const
- {
- return (((size_t)val.first) >> 2) ^ ((size_t)val.second);
- }
- };
- bool BfCompiler::SlowGenerateSlotNums()
- {
- BP_ZONE("BfCompiler::SlowGenerateSlotNums");
-
- SlotEntryMap ifaceUseMap;
-
- std::unordered_set<InterfacePair, InterfacePairHash> concurrentInterfaceSet;
- HashSet<BfTypeInstance*> foundIFaces;
-
- if (mMaxInterfaceSlots < 0)
- {
- mMaxInterfaceSlots = 0;
- }
- bool isHotCompile = IsHotCompile();
- for (auto type : mContext->mResolvedTypes)
- {
- if (!type->IsReified())
- continue;
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
- if (typeInst->IsUnspecializedType())
- continue;
- if (typeInst->IsInterface())
- {
- if (typeInst->mSlotNum == -2) // Not needed
- continue;
- if (!isHotCompile) // Hot compiles cannot remap slot numbers
- typeInst->mSlotNum = -1;
- if (typeInst->mVirtualMethodTableSize > 0)
- {
- GetSlotEntry(ifaceUseMap, typeInst);
- }
- continue;
- }
- foundIFaces.Clear();
- auto checkTypeInst = typeInst;
- while (checkTypeInst != NULL)
- {
- for (auto iface : checkTypeInst->mInterfaces)
- {
- auto interfaceType = iface.mInterfaceType;
- if (interfaceType->mSlotNum == -2)
- continue; // Not needed
- if ((isHotCompile) && (interfaceType->mSlotNum == -1))
- checkTypeInst->mDirty = true; // We're about to slot an interface here
- if (interfaceType->mVirtualMethodTableSize > 0)
- {
- BfSlotEntry* slotEntry = GetSlotEntry(ifaceUseMap, interfaceType);
- slotEntry->mRefCount++;
- foundIFaces.Add(iface.mInterfaceType);
- }
- }
- checkTypeInst = checkTypeInst->mBaseType;
- }
- for (auto itr1 = foundIFaces.begin(); itr1 != foundIFaces.end(); ++itr1)
- {
- auto itr2 = itr1;
- ++itr2;
- for ( ; itr2 != foundIFaces.end(); ++itr2)
- {
- auto iface1 = *itr1;
- auto iface2 = *itr2;
-
- InterfacePair ifacePair = MakeInterfacePair(iface1, iface2);
- if (concurrentInterfaceSet.insert(ifacePair).second)
- {
- BfSlotEntry* entry1 = GetSlotEntry(ifaceUseMap, iface1);
- BfSlotEntry* entry2 = GetSlotEntry(ifaceUseMap, iface2);
- entry1->mConcurrentRefs.push_back(iface2);
- entry2->mConcurrentRefs.push_back(iface1);
- }
- }
- }
- }
-
- Array<BfSlotEntry*> sortedIfaceUseMap;
- for (auto& entry : ifaceUseMap)
- {
- if (!isHotCompile)
- BF_ASSERT(entry.mValue->mTypeInstance->mSlotNum == -1);
- sortedIfaceUseMap.push_back(entry.mValue);
- }
-
- std::sort(sortedIfaceUseMap.begin(), sortedIfaceUseMap.end(), [] (BfSlotEntry* lhs, BfSlotEntry* rhs)
- {
- if (lhs->mRefCount != rhs->mRefCount)
- return lhs->mRefCount > rhs->mRefCount;
- return lhs->mTypeInstance->mTypeId < rhs->mTypeInstance->mTypeId;
- });
- bool failed = false;
- SmallVector<bool, 16> isSlotUsed;
- for (auto slotEntry : sortedIfaceUseMap)
- {
- BfTypeInstance* iface = slotEntry->mTypeInstance;
- if (iface->mSlotNum >= 0)
- {
- BF_ASSERT(isHotCompile);
- continue;
- }
- isSlotUsed.clear();
- if (mMaxInterfaceSlots > 0)
- isSlotUsed.resize(mMaxInterfaceSlots);
- BF_ASSERT(iface->mSlotNum == -1);
- BF_ASSERT(iface->IsInterface());
- for (auto iface2 : slotEntry->mConcurrentRefs)
- {
- int slotNum2 = iface2->mSlotNum;
- if (slotNum2 != -1)
- isSlotUsed[slotNum2] = true;
- }
- for (int checkSlot = 0; checkSlot < mMaxInterfaceSlots; checkSlot++)
- {
- if (!isSlotUsed[checkSlot])
- {
- iface->mSlotNum = checkSlot;
- break;
- }
- }
- if (iface->mSlotNum == -1)
- {
- if (isHotCompile)
- {
- failed = true;
- mPassInstance->Fail("Interface slot numbering overflow. Restart the program or revert changes.");
- break;
- }
- iface->mSlotNum = mMaxInterfaceSlots;
- if (mOptions.mIncrementalBuild)
- {
- // Allocate more than enough interface slots
- mMaxInterfaceSlots += 3;
- }
- else
- mMaxInterfaceSlots++;
- // failed = true;
- // mPassInstance->Fail(StrFormat("Interface slot numbering overflow, increase the maximum slot number from '%d'", mMaxInterfaceSlots));
- // break;
- }
- // if (iface->mSlotNum == -1)
- // {
- // failed = true;
- // mPassInstance->Fail(StrFormat("Interface slot numbering overflow, increase the maximum slot number from '%d'", mMaxInterfaceSlots));
- // break;
- // }
- if (isHotCompile)
- {
- mHotState->mNewlySlottedTypeIds.Add(iface->mTypeId);
- mHotState->mSlotDefineTypeIds.Add(iface->mTypeId);
- }
- }
- if (!failed)
- {
- bool success = VerifySlotNums();
- if (!success)
- {
- BF_DBG_FATAL("Failed!");
- }
- }
- for (auto& entry : ifaceUseMap)
- delete entry.mValue;
- return true;
- }
- void BfCompiler::GenerateSlotNums()
- {
- BP_ZONE("BfCompiler::GenerateSlotNums");
-
- if (mMaxInterfaceSlots < 0)
- {
- if (mOptions.mIncrementalBuild)
- mMaxInterfaceSlots = 3;
- else
- mMaxInterfaceSlots = 0;
- }
- bool isHotCompile = IsHotCompile();
-
- for (auto type : mContext->mResolvedTypes)
- {
- if (!type->IsInterface())
- continue;
- auto typeInstance = type->ToTypeInstance();
- if ((typeInstance->mSlotNum <= 0) || (!isHotCompile))
- {
- if (mContext->mReferencedIFaceSlots.Contains(typeInstance))
- {
- if (typeInstance->mSlotNum == -2)
- typeInstance->mSlotNum = -1;
- }
- else
- typeInstance->mSlotNum = -2; // Not needed
- }
- }
- if (VerifySlotNums())
- return;
-
- if (!QuickGenerateSlotNums())
- SlowGenerateSlotNums();
- BfLogSysM("GenerateSlotNums mMaxInterfaceSlots: %d\n", mMaxInterfaceSlots);
- }
- void BfCompiler::GenerateDynCastData()
- {
- BP_ZONE("BfCompiler::GenerateDynCastData");
- Array<int> firstDerivedIds;
- Array<int> nextSiblingIds;
- firstDerivedIds.Resize(mCurTypeId);
- nextSiblingIds.Resize(mCurTypeId);
- for (auto type : mContext->mResolvedTypes)
- {
- if (type->IsBoxed())
- continue;
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
-
- if (typeInst->mBaseType == NULL)
- continue;
-
- int baseId = typeInst->mBaseType->mTypeId;
- int firstDerivedId = firstDerivedIds[baseId];
- nextSiblingIds[typeInst->mTypeId] = firstDerivedIds[baseId];
- firstDerivedIds[baseId] = typeInst->mTypeId;
- }
- int curInheritanceId = 1;
- std::function<void(BfTypeInstance*)> _AddTypeInfo = [&](BfTypeInstance* typeInst)
- {
- if (typeInst->mInheritanceId != curInheritanceId)
- {
- typeInst->mInheritanceId = curInheritanceId;
- typeInst->mDirty = true;
- }
- curInheritanceId++;
- int childId = firstDerivedIds[typeInst->mTypeId];
- while (childId != 0)
- {
- auto childType = mContext->mTypes[childId]->ToTypeInstance();
- _AddTypeInfo(childType);
- childId = nextSiblingIds[childId];
- }
- int inheritanceCount = curInheritanceId - typeInst->mInheritanceId - 1;
- if (typeInst->mInheritanceCount != inheritanceCount)
- {
- typeInst->mInheritanceCount = inheritanceCount;
- typeInst->mDirty = true;
- }
- };
- _AddTypeInfo(mContext->mBfObjectType);
- auto valueTypeInst = mContext->mScratchModule->ResolveTypeDef(mValueTypeTypeDef)->ToTypeInstance();
- _AddTypeInfo(valueTypeInst);
- }
- void BfCompiler::UpdateRevisedTypes()
- {
- BP_ZONE("BfCompiler::UpdateRevisedTypes");
-
- // See if we have any name conflicts and remove those
- auto typeDefItr = mSystem->mTypeDefs.begin();
- while (typeDefItr != mSystem->mTypeDefs.end())
- {
- auto typeDef = *typeDefItr;
- auto origTypeDef = typeDef;
- if (typeDef->mNextRevision != NULL)
- typeDef = typeDef->mNextRevision;
- if (typeDef->mDupDetectedRevision == mRevision)
- {
- ++typeDefItr;
- continue;
- }
- typeDef->mDupDetectedRevision = -1;
- if ((typeDef->mIsCombinedPartial) || (typeDef->mDefState == BfTypeDef::DefState_Deleted) || (typeDef->mTypeCode == BfTypeCode_Extension))
- {
- ++typeDefItr;
- continue;
- }
-
- bool removedElement = false;
- auto nextTypeDefItr = typeDefItr;
- nextTypeDefItr.MoveToNextHashMatch();
- while (nextTypeDefItr)
- {
- auto nextTypeDef = *nextTypeDefItr;
- if (nextTypeDef->mNextRevision != NULL)
- nextTypeDef = nextTypeDef->mNextRevision;
- if ((nextTypeDef->mIsCombinedPartial) || (nextTypeDef->mDefState == BfTypeDef::DefState_Deleted) || (nextTypeDef->mTypeCode == BfTypeCode_Extension) ||
- (typeDef->mFullName != nextTypeDef->mFullName) || (typeDef->mGenericParamDefs.size() != nextTypeDef->mGenericParamDefs.size()))
- {
- nextTypeDefItr.MoveToNextHashMatch();
- continue;
- }
- if ((typeDef->mIsPartial) && (nextTypeDef->mIsPartial) &&
- (!typeDef->IsGlobalsContainer()) &&
- (typeDef->mProject != nextTypeDef->mProject))
- {
- BfTypeDef* typeA = NULL;
- BfTypeDef* typeB = NULL;
- BfError* error = NULL;
- if (typeDef->mProject->ReferencesOrReferencedBy(nextTypeDef->mProject))
- {
- typeA = typeDef;
- typeB = nextTypeDef;
- }
- else if (nextTypeDef->mProject->ReferencesOrReferencedBy(typeDef->mProject))
- {
- typeA = nextTypeDef;
- typeB = typeDef;
- }
- if (typeA != NULL)
- {
- error = mPassInstance->Fail(StrFormat("Partial type in project '%s' cannot extend a type from a referenced project", typeA->mProject->mName.c_str()).c_str(),
- typeA->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo(StrFormat("Previous definition in project '%s'", typeB->mProject->mName.c_str()),
- typeB->mTypeDeclaration->mNameNode);
- }
- if (error != NULL)
- error->mIsPersistent = true;
- }
-
- if (((!typeDef->mIsPartial) || (!nextTypeDef->mIsPartial)) &&
- (!typeDef->IsGlobalsContainer()) && (!nextTypeDef->IsGlobalsContainer()) &&
- (typeDef->mProject->ReferencesOrReferencedBy(nextTypeDef->mProject)))
- {
- nextTypeDef->mDupDetectedRevision = mRevision;
- BfError* error = NULL;
- /*if ((typeDef->mIsPartial) && (typeDef->mTypeCode != BfTypeCode_Extension))
- {
- error = mPassInstance->Fail("Missing 'partial' modifier; another partial definition of this type exists", nextTypeDef->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
- }
- else if ((nextTypeDef->mIsPartial) && (nextTypeDef->mTypeCode != BfTypeCode_Extension))
- {
- error = mPassInstance->Fail("Missing 'partial' modifier; another partial definition of this type exists", typeDef->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo("Previous definition", nextTypeDef->mTypeDeclaration->mNameNode);
- }
- else */if (nextTypeDef->mOuterType != NULL)
- {
- 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,
- nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
- }
- else if (!nextTypeDef->mNamespace.IsEmpty())
- {
- error = mPassInstance->Fail(StrFormat("The namespace '%s' already has a definition for '%s'", nextTypeDef->mNamespace.ToString().c_str(),
- nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
- }
- else
- {
- error = mPassInstance->Fail(StrFormat("The global namespace already has a definition for '%s'",
- nextTypeDef->mName->mString.mPtr), nextTypeDef->mTypeDeclaration->mNameNode);
- mPassInstance->MoreInfo("Previous definition", typeDef->mTypeDeclaration->mNameNode);
- }
- if (error != NULL)
- error->mIsPersistent = true;
- }
-
- nextTypeDefItr.MoveToNextHashMatch();
- }
- ++typeDefItr;
- }
-
- mContext->PreUpdateRevisedTypes();
- // If we missed out on required types previously, now we should be 'okay'
- mInInvalidState = false;
- // We can't do any yields in here - the compiler state is invalid from the time we inject a new
- // typedef revision up until we finish the associated RebuildType
- int compositeBucket = 0;
-
- // These are "extension" defs that were unmatched last run through
- Array<BfTypeDef*> prevSoloExtensions;
- mSystem->mTypeDefs.CheckRehash();
- // Process the typedefs one bucket at a time. When we are combining extensions or partials (globals) into a single definition then
- // we will be making multiple passes over the bucket that contains that name
- for (int bucketIdx = 0; bucketIdx < mSystem->mTypeDefs.mHashSize; bucketIdx++)
- {
- bool hadPartials = false;
- bool hadChanges = false;
-
- if (mSystem->mTypeDefs.mHashHeads == NULL)
- break;
- // Partials combiner
- auto outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (outerTypeDefEntry != NULL)
- {
- auto outerTypeDef = outerTypeDefEntry->mValue;
- if (outerTypeDef->mDefState == BfTypeDef::DefState_Deleted)
- {
- hadChanges = true;
- outerTypeDefEntry = outerTypeDefEntry->mNext;
- continue;
- }
- if (outerTypeDef->mNextRevision != NULL)
- hadChanges = true;
- BfTypeDefMap::Entry* rootTypeDefEntry = NULL;
- BfTypeDef* rootTypeDef = NULL;
- BfTypeDef* compositeTypeDef = NULL;
-
- auto latestOuterTypeDef = outerTypeDef->GetLatest();
- if ((outerTypeDef->mTypeCode == BfTypeCode_Extension) && (!outerTypeDef->mIsPartial))
- {
- prevSoloExtensions.Add(outerTypeDef);
- outerTypeDef->mIsPartial = true;
- }
-
- if ((outerTypeDef->mIsPartial) || (outerTypeDef->mIsCombinedPartial))
- {
- // Initialize mPartialUsed flags
- if (!hadPartials)
- {
- auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (checkTypeDefEntry != NULL)
- {
- auto checkTypeDef = checkTypeDefEntry->mValue;
- if ((checkTypeDefEntry->mHash == outerTypeDefEntry->mHash) &&
- (checkTypeDef->NameEquals(outerTypeDef)))
- {
- checkTypeDef->mPartialUsed = false;
- }
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- }
- hadPartials = true;
- }
- }
- if ((outerTypeDef->mTypeCode == BfTypeCode_Extension) && (!outerTypeDef->mPartialUsed))
- {
- // Find root type, and we assume the composite type follows this
- auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (checkTypeDefEntry != NULL)
- {
- auto checkTypeDef = checkTypeDefEntry->mValue;
- if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||
- (checkTypeDef->mIsCombinedPartial) ||
- (checkTypeDef->mTypeCode == BfTypeCode_Extension) ||
- (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
- (checkTypeDef->mPartialUsed) ||
- (!checkTypeDef->NameEquals(outerTypeDef)) ||
- (checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()) ||
- (!outerTypeDef->mProject->ContainsReference(checkTypeDef->mProject)))
- {
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- continue;
- }
- rootTypeDef = checkTypeDef;
- rootTypeDefEntry = checkTypeDefEntry;
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- }
- }
- else if ((outerTypeDef->mIsExplicitPartial) && (!outerTypeDef->mPartialUsed))
- {
- // For explicit partials there is no 'root type' so we just use the first explicit partial
- rootTypeDef = outerTypeDef;
- rootTypeDefEntry = outerTypeDefEntry;
- // Find composite type, there is no explicit position for this
- auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (checkTypeDefEntry != NULL)
- {
- auto checkTypeDef = checkTypeDefEntry->mValue;
- if ((checkTypeDefEntry->mHash != outerTypeDefEntry->mHash) ||
- (!checkTypeDef->mIsCombinedPartial) ||
- (checkTypeDef->mPartialUsed) ||
- (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted) ||
- (!checkTypeDef->NameEquals(outerTypeDef)) ||
- (checkTypeDef->mGenericParamDefs.size() != outerTypeDef->mGenericParamDefs.size()) ||
- (outerTypeDef->mProject != checkTypeDef->mProject))
- {
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- continue;
- }
- compositeTypeDef = checkTypeDef;
- if (compositeTypeDef->mNextRevision != NULL)
- {
- // This is an old 'next revision'
- delete compositeTypeDef->mNextRevision;
- compositeTypeDef->mNextRevision = NULL;
- }
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- }
- }
- // Now find extensions to apply to the rootTypeDef
- if (rootTypeDef != NULL)
- {
- bool partialsHadChanges = false;
- bool hadSignatureChange = false;
- bool compositeIsNew = false;
- if (compositeTypeDef == NULL)
- {
- if ((rootTypeDef->mIsExplicitPartial) || (rootTypeDefEntry->mNext == NULL) || (!rootTypeDefEntry->mNext->mValue->mIsCombinedPartial))
- {
- compositeTypeDef = new BfTypeDef();
- compositeTypeDef->mSystem = rootTypeDef->mSystem;
- compositeTypeDef->mProject = rootTypeDef->mProject;
- compositeTypeDef->mName = rootTypeDef->mName;
- compositeTypeDef->mName->mRefCount++;
- mSystem->TrackName(compositeTypeDef);
- compositeTypeDef->mNameEx = rootTypeDef->mNameEx;
- compositeTypeDef->mNameEx->Ref();
- compositeTypeDef->mProtection = rootTypeDef->mProtection;
- compositeTypeDef->mNamespace = rootTypeDef->mNamespace;
- compositeTypeDef->mTypeCode = BfTypeCode_Extension;
- compositeTypeDef->mFullName = rootTypeDef->mFullName;
- compositeTypeDef->mFullNameEx = rootTypeDef->mFullNameEx;
- compositeTypeDef->mIsCombinedPartial = true;
- // if (rootTypeDef->IsGlobalsContainer())
- // {
- // //NOP;
- // auto didAdd = mSystem->mGlobalsMap.TryAdd(rootTypeDef->mNamespace, compositeTypeDef);
- // BF_ASSERT(didAdd);
- // }
- for (auto prevGenericParam : rootTypeDef->mGenericParamDefs)
- {
- BfGenericParamDef* copiedGenericParam = new BfGenericParamDef();
- *copiedGenericParam = *prevGenericParam;
- compositeTypeDef->mGenericParamDefs.Add(copiedGenericParam);
- }
- mSystem->mTypeDefs.AddAfter(compositeTypeDef, rootTypeDefEntry);
- // compositeTypeDef->mNext = rootTypeDef->mNext;
- // rootTypeDef->mNext = compositeTypeDef;
- partialsHadChanges = true;
- hadSignatureChange = true;
- compositeIsNew = true;
- BfLogSysM("Creating compositeTypeDef %p\n", compositeTypeDef);
- }
- else
- {
- BF_ASSERT(rootTypeDefEntry->mNext->mValue->NameEquals(rootTypeDef));
- compositeTypeDef = rootTypeDefEntry->mNext->mValue;
- if (compositeTypeDef->mNextRevision != NULL)
- {
- // This is an old 'next revision'
- delete compositeTypeDef->mNextRevision;
- compositeTypeDef->mNextRevision = NULL;
- }
- }
- }
-
- // Collect the partials
- BfSizedVector<BfTypeDef*, 8> typeParts;
- typeParts.push_back(rootTypeDef);
- auto checkTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (checkTypeDefEntry != NULL)
- {
- auto checkTypeDef = checkTypeDefEntry->mValue;
- bool isValidProject;
- if (rootTypeDef->mIsExplicitPartial)
- isValidProject = rootTypeDef->mProject == checkTypeDef->mProject;
- else
- isValidProject = checkTypeDef->mProject->ContainsReference(rootTypeDef->mProject);
- if (checkTypeDef != rootTypeDef)
- {
- if ((checkTypeDef->mIsCombinedPartial) ||
- (!checkTypeDef->mIsPartial) ||
- (checkTypeDef->mPartialUsed) ||
- (!checkTypeDef->NameEquals(rootTypeDef)) ||
- (checkTypeDef->mGenericParamDefs.size() != rootTypeDef->mGenericParamDefs.size()) ||
- (!isValidProject))
- {
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- continue;
- }
- }
- compositeTypeDef->mPartialUsed = true;
- checkTypeDef->mPartialUsed = true;
-
- if (checkTypeDef->mDefState == BfTypeDef::DefState_Deleted)
- {
- partialsHadChanges = true;
- hadSignatureChange = true;
- }
- else
- {
- if (checkTypeDef != rootTypeDef)
- typeParts.push_back(checkTypeDef);
- if (checkTypeDef->mNextRevision != NULL)
- {
- partialsHadChanges = true;
- BF_ASSERT(checkTypeDef->mNextRevision->mGenericParamDefs.size() == rootTypeDef->mGenericParamDefs.size());
- //mSystem->InjectNewRevision(checkTypeDef);
- //BF_ASSERT(checkTypeDef->mGenericParamDefs.size() == rootTypeDef->mGenericParamDefs.size());
- }
- else if (checkTypeDef->mDefState == BfTypeDef::DefState_New)
- partialsHadChanges = true;
- }
- checkTypeDefEntry = checkTypeDefEntry->mNext;
- }
- // Set this down here, because the InjectNewRevision will clear this flag
- rootTypeDef->mIsPartial = true;
-
- if (partialsHadChanges)
- {
- BF_ASSERT(compositeTypeDef->mNextRevision == NULL);
- mSystem->VerifyTypeDef(compositeTypeDef);
- for (auto checkTypeDef : typeParts)
- {
- mSystem->VerifyTypeDef(checkTypeDef);
- // Apply any def state that is more conservative
- if (checkTypeDef->mDefState == BfTypeDef::DefState_Signature_Changed)
- compositeTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
- else if (checkTypeDef->mDefState == BfTypeDef::DefState_InlinedInternals_Changed)
- {
- if (compositeTypeDef->mDefState != BfTypeDef::DefState_Signature_Changed)
- compositeTypeDef->mDefState = BfTypeDef::DefState_InlinedInternals_Changed;
- }
- else if (checkTypeDef->mDefState == BfTypeDef::DefState_Internals_Changed)
- {
- if ((compositeTypeDef->mDefState != BfTypeDef::DefState_Signature_Changed) &&
- (compositeTypeDef->mDefState != BfTypeDef::DefState_InlinedInternals_Changed))
- compositeTypeDef->mDefState = BfTypeDef::DefState_Internals_Changed;
- }
- BF_ASSERT(checkTypeDef->mIsPartial);
- if (checkTypeDef->mNextRevision != NULL)
- {
- mSystem->VerifyTypeDef(checkTypeDef->mNextRevision);
- mSystem->InjectNewRevision(checkTypeDef);
- }
- checkTypeDef->mIsPartial = true;
- checkTypeDef->mDefState = BfTypeDef::DefState_Defined;
- mSystem->AddToCompositePartial(mPassInstance, compositeTypeDef, checkTypeDef);
- }
- mSystem->FinishCompositePartial(compositeTypeDef);
- if (!compositeIsNew)
- {
- if (compositeTypeDef->mNextRevision != NULL)
- {
- BF_ASSERT(compositeTypeDef->mPartials.size() != 0);
- }
- }
- // We use the root typedef's namespace search for the composite, but this should only be
- // used for cases where we CANNOT specify a typeref on an extension. IE: custom attributes
- // for a type can only be added on the root typedef. If this changes then we need to make
- // sure that we attach a definingType to attributes
- for (auto name : compositeTypeDef->mNamespaceSearch)
- mSystem->ReleaseAtomComposite(name);
- compositeTypeDef->mNamespaceSearch = rootTypeDef->mNamespaceSearch;
- for (auto name : compositeTypeDef->mNamespaceSearch)
- mSystem->RefAtomComposite(name);
- if (rootTypeDef != NULL)
- compositeTypeDef->mNamespaceSearch = rootTypeDef->mNamespaceSearch;
- else
- compositeTypeDef->mNamespaceSearch.Clear();
- //BfLogSysM("Composite type %p updating. isNew: %d\n", compositeTypeDef, compositeIsNew);
- if (compositeIsNew)
- {
- compositeTypeDef->mDefState = BfTypeDef::DefState_New;
- mSystem->InjectNewRevision(compositeTypeDef);
- // Reset 'New' state
- compositeTypeDef->mDefState = BfTypeDef::DefState_New;
- }
- else if (hadSignatureChange)
- compositeTypeDef->mDefState = BfTypeDef::DefState_Signature_Changed;
- if (compositeTypeDef->mDefState == BfTypeDef::DefState_Defined)
- {
- // No changes, just inject
- mSystem->InjectNewRevision(compositeTypeDef);
- }
- /*if (compositeTypeDef->mTypeCode == BfTypeCode_Extension)
- {
- BF_ASSERT(rootTypeDef == NULL);
- compositeTypeDef->mTypeCode = BfTypeCode_Object;
- }*/
- auto latestCompositeTypeDef = compositeTypeDef->GetLatest();
- if (latestCompositeTypeDef->mTypeCode == BfTypeCode_Extension)
- {
- BF_ASSERT(rootTypeDef == NULL);
- latestCompositeTypeDef->mTypeCode = BfTypeCode_Object;
- }
- BfLogSysM("Partial combined type typedef %p updated from parser %p\n", compositeTypeDef, latestCompositeTypeDef->mTypeDeclaration->GetSourceData());
- }
- }
- outerTypeDefEntry = outerTypeDefEntry->mNext;
- }
- // Handle unused partials, apply any new revisions, process pending deletes
-
- if ((hadPartials) || (hadChanges))
- {
- BfTypeDef* checkMasterTypeDef = NULL;
- BfTypeDef* deletedCombinedPartial = NULL;
- outerTypeDefEntry = mSystem->mTypeDefs.mHashHeads[bucketIdx];
- while (outerTypeDefEntry != NULL)
- {
- auto outerTypeDef = outerTypeDefEntry->mValue;
- auto nextTypeDefEntry = outerTypeDefEntry->mNext;
- if ((outerTypeDef->mIsPartial) && (!outerTypeDef->mIsExplicitPartial) && (outerTypeDef->mTypeCode != BfTypeCode_Extension) &&
- (nextTypeDefEntry != NULL) && (!nextTypeDefEntry->mValue->mPartialUsed))
- {
- // This is a root type that we've removed all extensions from, so now we go back to treating it as the actual definition
- // instead of using the composite that immediately follows it
- BF_ASSERT(outerTypeDef->mTypeCode != BfTypeCode_Extension);
- outerTypeDef->mIsPartial = false;
- outerTypeDef->mPartialIdx = -1;
- }
- if (outerTypeDef->mDefState == BfTypeDef::DefState_Deleted)
- {
- BfLogSysM("UpdateRevisedTypes deleting type %p\n", outerTypeDef);
- outerTypeDef->mDefState = BfTypeDef::DefState_Deleted;
- mSystem->RemoveTypeDef(outerTypeDef);
- }
- else if (!outerTypeDef->mPartialUsed)
- {
- if (outerTypeDef->mIsCombinedPartial)
- {
- BfLogSysM("UpdateRevisedTypes deleting combinedPartial type %p\n", outerTypeDef);
- deletedCombinedPartial = outerTypeDef;
- outerTypeDef->mDefState = BfTypeDef::DefState_Deleted;
- mSystem->RemoveTypeDef(outerTypeDef);
- }
- else if (outerTypeDef->mTypeCode == BfTypeCode_Extension)
- {
- auto error = mPassInstance->Fail(StrFormat("Unable to find root type definition for extension '%s'", outerTypeDef->GetLatest()->mFullName.ToString().c_str()),
- outerTypeDef->GetLatest()->mTypeDeclaration->mNameNode);
- if (error != NULL)
- error->mIsPersistent = true;
- if (outerTypeDef->mIsPartial)
- {
- // Allow this typeDef be a full solo type by itself
- outerTypeDef->mIsPartial = false;
- if (outerTypeDef->mNextRevision != NULL)
- outerTypeDef->mNextRevision->mIsPartial = false;
- if (outerTypeDef->mPartialIdx != -1)
- {
- outerTypeDef->mPartialIdx = -1;
- outerTypeDef->mDefState = BfTypeDef::DefState_New;
- }
- }
- }
- }
- if (outerTypeDef->mDefState != BfTypeDef::DefState_Deleted)
- checkMasterTypeDef = outerTypeDef;
- if ((deletedCombinedPartial != NULL) && (checkMasterTypeDef != NULL) &&
- (deletedCombinedPartial->NameEquals(checkMasterTypeDef)))
- {
- // Remap nested types to their master typeDef
- for (auto nestedType : deletedCombinedPartial->mNestedTypes)
- {
- nestedType->mOuterType = checkMasterTypeDef;
- }
- deletedCombinedPartial = NULL;
- checkMasterTypeDef = NULL;
- }
- outerTypeDefEntry = nextTypeDefEntry;
- }
- }
- }
- for (auto typeDef : prevSoloExtensions)
- {
- // If this got added to a composite partial then delete the previous solo type
- if (typeDef->mIsPartial)
- {
- BfLogSysM("Solo partial going back to normal partial %p\n", typeDef);
- typeDef->mIsPartial = false;
- auto type = mContext->mScratchModule->ResolveTypeDef(typeDef, BfPopulateType_Identity);
- mContext->DeleteType(type);
- typeDef->mIsPartial = true;
- }
- }
-
- mContext->UpdateRevisedTypes();
- mContext->VerifyTypeLookups();
-
- if (mStats.mTypesDeleted != 0)
- mContext->UpdateAfterDeletingTypes();
- mContext->RemoveInvalidWorkItems();
- for (auto typeDef : mSystem->mTypeDefs)
- {
- auto latestTypeDef = typeDef->GetLatest();
- if ((latestTypeDef->mOuterType != NULL) && (latestTypeDef->mOuterType->mIsPartial))
- latestTypeDef->mOuterType = mSystem->GetOuterTypeNonPartial(latestTypeDef);
- }
- mSystem->mNeedsTypesHandledByCompiler = false;
- //TODO:
- //Sleep(300);
- //mSystem->CheckLockYield();
- }
- BfTypeDef* BfCompiler::GetArrayTypeDef(int dimensions)
- {
- BF_ASSERT(dimensions <= 4);
- if (dimensions == 1)
- return mArray1TypeDef;
- if (dimensions == 2)
- return mArray2TypeDef;
- if (dimensions == 3)
- return mArray3TypeDef;
- return mArray4TypeDef;
- }
- void BfCompiler::VisitAutocompleteExteriorIdentifiers()
- {
- for (auto checkNode : mResolvePassData->mExteriorAutocompleteCheckNodes)
- {
- bool isUsingDirective = false;
- BfIdentifierNode* checkIdentifier = NULL;
- if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(checkNode))
- {
- checkIdentifier = usingDirective->mNamespace;
- }
- else if (auto usingDirective = BfNodeDynCast<BfUsingStaticDirective>(checkNode))
- {
- if (usingDirective->mTypeRef != NULL)
- {
- BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL);
- SetAndRestoreValue<BfTypeInstance*> prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL);
- mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, NULL);
- if (mResolvePassData->mAutoComplete != NULL)
- mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, isUsingDirective);
- continue;
- }
- }
- else
- checkIdentifier = BfNodeDynCast<BfIdentifierNode>(checkNode);
- if (checkIdentifier == NULL)
- continue;
- if (mResolvePassData->mAutoComplete != NULL)
- mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
- if ((checkIdentifier->IsFromParser(mResolvePassData->mParser)) && (mResolvePassData->mSourceClassifier != NULL))
- {
- if (isUsingDirective)
- {
- while (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier))
- {
- mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
- checkIdentifier = qualifiedNameNode->mLeft;
- }
- if (checkIdentifier != NULL)
- mResolvePassData->mSourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
- }
- }
- }
- mResolvePassData->mExteriorAutocompleteCheckNodes.Clear();
- }
- void BfCompiler::VisitSourceExteriorNodes()
- {
- BP_ZONE("BfCompiler::VisitSourceExteriorNodes");
- String str;
- Array<BfAtom*> namespaceParts;
- Array<BfAstNode*> srcNodes;
- std::function<bool(BfAstNode*)> _AddName = [&](BfAstNode* node)
- {
- if (auto qualifiedName = BfNodeDynCast<BfQualifiedNameNode>(node))
- {
- if (!_AddName(qualifiedName->mLeft))
- return false;
- if (!_AddName(qualifiedName->mRight))
- return false;
- }
- else if (auto identifier = BfNodeDynCast<BfIdentifierNode>(node))
- {
- srcNodes.Add(identifier);
- str.Clear();
- identifier->ToString(str);
- auto atom = mSystem->FindAtom(str);
- if (atom == NULL)
- {
- String prevNamespace;
- for (auto part : namespaceParts)
- {
- if (!prevNamespace.IsEmpty())
- prevNamespace += ".";
- prevNamespace += part->mString;
- }
- if (prevNamespace.IsEmpty())
- mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", str.c_str()), identifier);
- else
- mPassInstance->Fail(StrFormat("The namespace '%s' does not exist in the namespace '%s'", str.c_str(), prevNamespace.c_str()), identifier);
- return false;
- }
- namespaceParts.Add(atom);
- }
- return true;
- };
- auto _CheckParser = [&](BfParser* parser)
- {
- if (parser->mNextRevision != NULL)
- parser = parser->mNextRevision;
- if (parser->mAwaitingDelete)
- return;
- if (parser->mParserData->mExteriorNodesCheckIdx == mSystem->mTypeMapVersion)
- return;
- bool failed = false;
- for (auto node : parser->mParserData->mExteriorNodes)
- {
- if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(node))
- {
- srcNodes.Clear();
- namespaceParts.Clear();
- bool success = _AddName(usingDirective->mNamespace);
-
- for (int i = 0; i < (int)namespaceParts.size(); i++)
- {
- BfAtomComposite checkNamespace;
- checkNamespace.mParts = &namespaceParts[0];
- checkNamespace.mSize = i + 1;
- if (!mSystem->ContainsNamespace(checkNamespace, parser->mProject))
- {
- failed = true;
- BfAtomComposite prevNamespace;
- prevNamespace.mParts = &namespaceParts[0];
- prevNamespace.mSize = i;
- if (i == 0)
- mPassInstance->Fail(StrFormat("The namespace '%s' does not exist", namespaceParts[i]->mString.ToString().c_str()), srcNodes[i]);
- else
- 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]);
- break;
- }
- }
- }
- else if (auto usingDirective = BfNodeDynCast<BfUsingStaticDirective>(node))
- {
- if (usingDirective->mTypeRef != NULL)
- {
- BF_ASSERT(mContext->mScratchModule->mCurTypeInstance == NULL);
- SetAndRestoreValue<BfTypeInstance*> prevCurTypeInstance(mContext->mScratchModule->mCurTypeInstance, NULL);
- mContext->mScratchModule->ResolveTypeRef(usingDirective->mTypeRef, NULL);
- if ((mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL))
- mResolvePassData->mAutoComplete->CheckTypeRef(usingDirective->mTypeRef, false, false);
- return;
- }
- }
- }
- if (!failed)
- parser->mParserData->mExteriorNodesCheckIdx = mSystem->mTypeMapVersion;
- };
- if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
- {
- _CheckParser(mResolvePassData->mParser);
- }
- else
- {
- for (auto parser : mSystem->mParsers)
- {
- _CheckParser(parser);
- }
- }
- }
- void BfCompiler::ProcessAutocompleteTempType()
- {
- BP_ZONE_F("BfCompiler::ProcessAutocompleteTempType %d", mResolvePassData->mResolveType);
- String& autoCompleteResultString = *gTLStrReturn.Get();
- autoCompleteResultString.clear();
-
- if (mContext->mBfObjectType == NULL)
- return; // Not initialized yet
- auto module = mContext->mScratchModule;
- auto autoComplete = mResolvePassData->mAutoComplete;
- BfLogSysM("ProcessAutocompleteTempType %d\n", autoComplete->mResolveType);
- SetAndRestoreValue<bool> prevCanceling(mCanceling, false);
- BF_ASSERT(mResolvePassData->mAutoComplete->mDefMethod == NULL);
- if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
- {
- for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
- {
- String typeName = tempTypeDef->ToString();
- BfLogSysM("BfResolveType_GetNavigationData TypeDef:%p %s\n", tempTypeDef, typeName.c_str());
- auto refNode = tempTypeDef->GetRefNode();
- if ((refNode != NULL) && (!tempTypeDef->IsGlobalsContainer()))
- {
- if (!autoCompleteResultString.empty())
- autoCompleteResultString += "\n";
- String typeName = BfTypeUtils::TypeToString(tempTypeDef, BfTypeNameFlag_OmitNamespace);
- module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
- autoCompleteResultString += typeName;
- if (tempTypeDef->mTypeCode == BfTypeCode_Object)
- autoCompleteResultString += "\tclass";
- else if (tempTypeDef->mTypeCode == BfTypeCode_Enum)
- autoCompleteResultString += "\tenum";
- else if (tempTypeDef->mTypeCode == BfTypeCode_Struct)
- autoCompleteResultString += "\tstruct";
- else if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
- autoCompleteResultString += "\ttypealias";
- else
- autoCompleteResultString += "\t";
- autoCompleteResultString += StrFormat("\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
- }
- String methodText;
- for (auto methodDef : tempTypeDef->mMethods)
- {
- if (((methodDef->mMethodType == BfMethodType_Normal) || (methodDef->mMethodType == BfMethodType_Operator) ||
- (methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_Dtor) ||
- (methodDef->mMethodType == BfMethodType_Mixin)) &&
- (methodDef->mMethodDeclaration != NULL))
- {
- methodText = methodDef->ToString();
- if (typeName != "@")
- methodText = typeName + "." + methodText;
- if (!autoCompleteResultString.empty())
- autoCompleteResultString += "\n";
- auto methodDeclaration = methodDef->GetMethodDeclaration();
- BfAstNode* refNode = methodDeclaration;
- if (methodDeclaration->mBody != NULL)
- refNode = methodDeclaration->mBody;
- else if (methodDeclaration->mNameNode != NULL)
- refNode = methodDeclaration->mNameNode;
- module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
- methodText += StrFormat("\tmethod\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
- autoCompleteResultString += methodText;
- }
- }
- for (auto propDef : tempTypeDef->mProperties)
- {
- auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(propDef->mFieldDeclaration);
- if ((propDeclaration == NULL) || (propDeclaration->mNameNode == NULL))
- continue;
- String propText = propDef->mName;
- if (typeName != "@")
- propText = typeName + "." + propText;
- if (!autoCompleteResultString.empty())
- autoCompleteResultString += "\n";
- BfAstNode* refNode = propDeclaration->mNameNode;
- module->UpdateSrcPos(refNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
- propText += StrFormat("\tproperty\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
- autoCompleteResultString += propText;
- }
- }
- module->CleanupFileInstances();
- return;
- }
- if (autoComplete->mResolveType == BfResolveType_GetCurrentLocation)
- {
- for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
- {
- String typeName = tempTypeDef->mNamespace.ToString();
- if (!typeName.empty())
- typeName += ".";
- typeName += tempTypeDef->ToString();
- autoCompleteResultString = typeName;
- int cursorPos = mResolvePassData->mParser->mCursorIdx;
- for (auto methodDef : tempTypeDef->mMethods)
- {
- BfAstNode* defNode = methodDef->mMethodDeclaration;
- if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
- defNode = propertyDeclaration;
- if ((defNode != NULL) &&
- (defNode->Contains(cursorPos)))
- {
- String methodText = methodDef->ToString();
- if (typeName != "@")
- methodText = typeName + "." + methodText;
- autoCompleteResultString = methodText;
- break;
- }
- }
- }
- module->CleanupFileInstances();
- return;
- }
- // >>> VisitExteriorIdentifiers
- mResolvePassData->mAutoComplete->SetModule(module);
- {
- SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, NULL);
- BP_ZONE("VisitExteriorIdentifiers");
- VisitAutocompleteExteriorIdentifiers();
- }
- VisitSourceExteriorNodes();
- BfTypeDef* tempTypeDef = NULL;
- for (auto checkTempType : mResolvePassData->mAutoCompleteTempTypes)
- {
- if (mResolvePassData->mAutoComplete->IsAutocompleteNode(checkTempType->mTypeDeclaration))
- {
- tempTypeDef = checkTempType;
- mContext->HandleChangedTypeDef(tempTypeDef, true);
- }
- }
-
- if (tempTypeDef == NULL)
- {
- GenerateAutocompleteInfo();
- BfLogSysM("ProcessAutocompleteTempType - no tempTypeDef\n");
- return;
- }
- if (tempTypeDef->mProject->mDisabled)
- {
- BfLogSysM("ProcessAutocompleteTempType - project disabled\n");
- return;
- }
- SetAndRestoreValue<BfMethodState*> prevMethodState(module->mCurMethodState, NULL);
- BfTypeState typeState;
- typeState.mCurTypeDef = tempTypeDef;
- SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
- BfTypeDef* actualTypeDef = NULL;
- auto typeName = tempTypeDef->mFullName;
- int wantNumGenericParams = (int)tempTypeDef->mGenericParamDefs.size();
- auto actualTypeDefItr = mSystem->mTypeDefs.TryGet(typeName);
- while (actualTypeDefItr)
- {
- auto checkTypeDef = *actualTypeDefItr;
- if ((!checkTypeDef->mIsPartial) /*&& (checkTypeDef->mTypeCode != BfTypeCode_Extension)*/ &&
- ((checkTypeDef->mTypeCode == tempTypeDef->mTypeCode) || (tempTypeDef->mTypeCode == BfTypeCode_Extension)))
- {
- if ((checkTypeDef->NameEquals(tempTypeDef)) && (checkTypeDef->mIsCombinedPartial) &&
- (checkTypeDef->mGenericParamDefs.size() == tempTypeDef->mGenericParamDefs.size()) &&
- (tempTypeDef->mProject->ContainsReference(checkTypeDef->mProject)))
- {
- actualTypeDef = mSystem->FilterDeletedTypeDef(checkTypeDef);
- break;
- }
- if ((checkTypeDef->mGenericParamDefs.size() == wantNumGenericParams) &&
- (FileNameEquals(tempTypeDef->mSource->mSourceData->ToParserData()->mFileName, checkTypeDef->mSource->mSourceData->ToParserData()->mFileName)) &&
- (tempTypeDef->mProject == checkTypeDef->mProject))
- {
- actualTypeDef = mSystem->FilterDeletedTypeDef(checkTypeDef);
- break;
- }
- }
-
- actualTypeDefItr.MoveToNextHashMatch();
- }
- if ((actualTypeDef == NULL) || (actualTypeDef->mTypeDeclaration == NULL))
- {
- auto autoComplete = mResolvePassData->mAutoComplete;
- if (autoComplete->IsAutocompleteNode(tempTypeDef->mTypeDeclaration->mNameNode))
- {
- BfIdentifierNode* nameNode = tempTypeDef->mTypeDeclaration->mNameNode;
- if (tempTypeDef->mTypeCode == BfTypeCode_Extension)
- {
- autoComplete->AddTopLevelNamespaces(nameNode);
- autoComplete->AddTopLevelTypes(nameNode);
- autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
- autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
- }
- }
- //mResolvePassData->mSourceClassifier->MarkSkipped(tempTypeDef->mTypeDeclaration);
- GenerateAutocompleteInfo();
- return;
- }
-
- if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
- {
- mResolvePassData->mSourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
- }
- BfTypeInstance* typeInst;
- {
- BP_ZONE("ProcessAutocompleteTempType.ResolveTypeDef");
- typeInst = (BfTypeInstance*)module->ResolveTypeDef(actualTypeDef, BfPopulateType_IdentityNoRemapAlias);
- if ((typeInst != NULL) && (typeInst->IsIncomplete()))
- module->PopulateType(typeInst, BfPopulateType_Full);
- }
- if (typeInst == NULL)
- {
- return;
- }
- BF_ASSERT((typeInst->mSize != -1) || (typeInst->IsTypeAlias()));
- #ifdef _DEBUG
- if ((typeInst->mModule != NULL) && (!typeInst->mModule->mIsScratchModule))
- mLastAutocompleteModule = typeInst->mModule;
- #endif
- SetAndRestoreValue<BfTypeInstance*> prevType(module->mCurTypeInstance, typeInst);
- typeState.mTypeInstance = typeInst;
-
- BfGenericExtensionEntry* genericExEntry = NULL;
- bool hadTempExtensionInfo = false;
- if ((tempTypeDef->IsExtension()) && (actualTypeDef->mIsCombinedPartial) && (typeInst->IsGenericTypeInstance()))
- {
- // Add to our extension info map and then take it out at the end...
- auto genericTypeInst = (BfGenericTypeInstance*)typeInst;
- module->BuildGenericExtensionInfo(genericTypeInst, tempTypeDef);
- genericTypeInst->mGenericExtensionInfo->mExtensionMap.TryGetValue(tempTypeDef, &genericExEntry);
- BF_ASSERT(genericExEntry != NULL);
- hadTempExtensionInfo = true;
- }
- if ((typeInst->IsUnspecializedType()) || (!typeInst->IsGenericTypeInstance()))
- {
- auto autoComplete = mResolvePassData->mAutoComplete;
- if (autoComplete->IsAutocompleteNode(tempTypeDef->mTypeDeclaration->mNameNode))
- {
- BfIdentifierNode* nameNode;
- nameNode = tempTypeDef->mTypeDeclaration->mNameNode;
- if ((actualTypeDef->mIsCombinedPartial) && (tempTypeDef->mTypeCode == BfTypeCode_Extension))
- {
- autoComplete->AddTopLevelNamespaces(tempTypeDef->mTypeDeclaration->mNameNode);
- autoComplete->AddTopLevelTypes(tempTypeDef->mTypeDeclaration->mNameNode);
- autoComplete->SetDefinitionLocation(actualTypeDef->mTypeDeclaration->mNameNode);
- }
- else
- autoComplete->SetDefinitionLocation(nameNode);
- autoComplete->mDefType = actualTypeDef;
- autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
- autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
- }
- }
- if (tempTypeDef->mTypeCode == BfTypeCode_TypeAlias)
- {
- auto typeAliasDecl = (BfTypeAliasDeclaration*)tempTypeDef->mTypeDeclaration;
- if (typeAliasDecl->mAliasToType != NULL)
- {
- autoComplete->CheckTypeRef(typeAliasDecl->mAliasToType, false);
- module->ResolveTypeRef(typeAliasDecl->mAliasToType);
- }
- }
- // Save and restore mFieldResolveReentrys, we could fire off autocomplete while resolving a field
- SetAndRestoreValue<decltype (module->mContext->mFieldResolveReentrys)> prevTypeResolveReentry(module->mContext->mFieldResolveReentrys);
- module->mContext->mFieldResolveReentrys.Clear();
- if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
- {
- BfAttributeTargets attrTarget;
- if (tempTypeDef->mIsDelegate)
- attrTarget = BfAttributeTargets_Delegate;
- else if (typeInst->IsEnum())
- attrTarget = BfAttributeTargets_Enum;
- else if (typeInst->IsInterface())
- attrTarget = BfAttributeTargets_Interface;
- else if (typeInst->IsStruct())
- attrTarget = BfAttributeTargets_Struct;
- else
- attrTarget = BfAttributeTargets_Class;
- auto customAttrs = module->GetCustomAttributes(tempTypeDef->mTypeDeclaration->mAttributes, attrTarget);
- delete customAttrs;
- }
-
- for (int genericParamIdx = 0; genericParamIdx < (int)tempTypeDef->mGenericParamDefs.size(); genericParamIdx++)
- {
- auto genericParamDef = tempTypeDef->mGenericParamDefs[genericParamIdx];
- auto genericParamInstance = new BfGenericTypeParamInstance(tempTypeDef, genericParamIdx);
- module->ResolveGenericParamConstraints(genericParamInstance, tempTypeDef->mGenericParamDefs, genericParamIdx);
- delete genericParamInstance;
- for (auto nameNode : genericParamDef->mNameNodes)
- module->HandleTypeGenericParamRef(nameNode, tempTypeDef, genericParamIdx);
- }
- for (auto fieldDef : tempTypeDef->mFields)
- {
- BP_ZONE("ProcessAutocompleteTempType.CheckField");
- auto fieldDecl = fieldDef->mFieldDeclaration;
- if (BfNodeIsA<BfPropertyDeclaration>(fieldDecl))
- continue; // Don't process auto-generated property fields
- if (fieldDef->mTypeRef != NULL)
- module->ResolveTypeRef(fieldDef->mTypeRef);
- mResolvePassData->mAutoComplete->CheckTypeRef(fieldDef->mTypeRef, true);
-
- BfFieldDef* actualFieldDef = NULL;
- for (auto checkFieldDef : actualTypeDef->mFields)
- {
- if ((checkFieldDef->mName == fieldDef->mName) &&
- (checkFieldDef->mIsConst == fieldDef->mIsConst) &&
- (checkFieldDef->mIsStatic == fieldDef->mIsStatic))
- {
- actualFieldDef = checkFieldDef;
- }
- }
- if ((autoComplete->mIsGetDefinition) && (fieldDef->mFieldDeclaration != NULL) && (autoComplete->IsAutocompleteNode(fieldDef->mFieldDeclaration->mNameNode)))
- {
- for (int i = 0; i < (int)actualTypeDef->mFields.size(); i++)
- {
- auto actualFieldDef = actualTypeDef->mFields[i];
- if (actualFieldDef->mName == fieldDef->mName)
- {
- autoComplete->mDefType = actualTypeDef;
- autoComplete->mDefField = actualFieldDef;
- autoComplete->SetDefinitionLocation(fieldDef->mFieldDeclaration->mNameNode);
- autoComplete->mInsertStartIdx = fieldDef->mFieldDeclaration->mNameNode->GetSrcStart();
- autoComplete->mInsertEndIdx = fieldDef->mFieldDeclaration->mNameNode->GetSrcEnd();
- break;
- }
- }
- }
- if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
- {
- auto customAttrs = module->GetCustomAttributes(fieldDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Field);
- delete customAttrs;
- }
- if (fieldDef->mIsConst)
- {
- module->ResolveConstField(typeInst, NULL, fieldDef);
- }
- if (fieldDef->mInitializer == NULL)
- {
- if (BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef))
- {
- if (fieldDef->mInitializer == NULL)
- {
- if ((fieldDef->mTypeRef->IsA<BfVarTypeReference>()) || (fieldDef->mTypeRef->IsA<BfLetTypeReference>()))
- mPassInstance->Fail("Implicitly-typed fields must be initialized", fieldDef->GetRefNode());
- }
- }
- }
- }
-
- auto checkTypeDef = tempTypeDef;
- while (checkTypeDef != NULL)
- {
- for (auto baseType : checkTypeDef->mBaseTypes)
- {
- autoComplete->CheckTypeRef(baseType, false);
- module->ResolveTypeRef(baseType);
- }
- checkTypeDef = checkTypeDef->mOuterType;
- }
-
- for (auto propDef : tempTypeDef->mProperties)
- {
- if ((propDef->mFieldDeclaration != NULL) && (propDef->mFieldDeclaration->mAttributes != NULL))
- {
- auto customAttrs = module->GetCustomAttributes(propDef->mFieldDeclaration->mAttributes, BfAttributeTargets_Property);
- delete customAttrs;
- }
-
- auto propDeclaration = BfNodeDynCast<BfPropertyDeclaration>(propDef->mFieldDeclaration);
- if (propDeclaration != NULL)
- autoComplete->CheckProperty(propDeclaration);
- module->ResolveTypeRef(propDef->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AllowRef);
- if ((autoComplete->mIsGetDefinition) && (propDef->mFieldDeclaration != NULL) && (autoComplete->IsAutocompleteNode(propDef->mFieldDeclaration->mNameNode)))
- {
- auto checkType = typeInst;
- while (checkType != NULL)
- {
- for (auto checkProp : checkType->mTypeDef->mProperties)
- {
- if (checkProp->mName == propDef->mName)
- {
- auto checkPropDeclaration = BfNodeDynCast<BfPropertyDeclaration>(checkProp->mFieldDeclaration);
- if ((checkPropDeclaration->mVirtualSpecifier == NULL) || (checkPropDeclaration->mVirtualSpecifier->GetToken() == BfToken_Virtual))
- {
- autoComplete->SetDefinitionLocation(checkPropDeclaration->mNameNode);
- autoComplete->mDefType = checkType->mTypeDef;
- autoComplete->mDefProp = checkProp;
- checkType = NULL;
- break;
- }
- }
- }
- if (checkType != NULL)
- checkType = checkType->mBaseType;
- }
- }
- }
-
- Array<BfMethodInstance*> methodInstances;
- for (auto methodDef : tempTypeDef->mMethods)
- {
- auto methodDeclaration = methodDef->GetMethodDeclaration();
- if (methodDeclaration != NULL)
- autoComplete->CheckMethod(methodDeclaration, false);
- if (!methodDef->mWantsBody)
- {
- if (methodDeclaration != NULL)
- {
- if (methodDeclaration->mAttributes != NULL)
- {
- auto customAttrs = module->GetCustomAttributes(methodDeclaration->mAttributes, (methodDef->mMethodType == BfMethodType_Ctor) ? BfAttributeTargets_Constructor : BfAttributeTargets_Method);
- delete customAttrs;
- }
- }
- else if (auto methodPropertyDeclaration = methodDef->GetPropertyMethodDeclaration())
- {
- if (methodPropertyDeclaration->mAttributes != NULL)
- {
- auto customAttrs = module->GetCustomAttributes(methodPropertyDeclaration->mAttributes, BfAttributeTargets_Method);
- delete customAttrs;
- }
- }
-
- continue;
- }
- BP_ZONE("ProcessAutocompleteTempType.CheckMethod");
- BfMethodInstanceGroup methodInstanceGroup;
- methodInstanceGroup.mOwner = typeInst;
- methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
- BfMethodInstance* methodInstance = new BfMethodInstance();
- methodInstances.push_back(methodInstance);
- methodInstance->mMethodDef = methodDef;
- methodInstance->mMethodInstanceGroup = &methodInstanceGroup;
- methodInstance->mIsAutocompleteMethod = true;
-
- for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
- {
- auto genericParamType = module->GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
- methodInstance->GetMethodInfoEx()->mMethodGenericArguments.push_back(genericParamType);
- auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
- methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
- //module->ResolveGenericParamConstraints(genericParamInstance, methodDef->mGenericParams[genericParamIdx]);
- }
- SetAndRestoreValue<BfFilePosition> prevFilePos(module->mCurFilePosition);
- SetAndRestoreValue<BfMethodInstance*> prevMethodInst(module->mCurMethodInstance, methodInstance);
- module->DoMethodDeclaration(methodDeclaration, true);
- module->mIncompleteMethodCount++;
- module->ProcessMethod(methodInstance);
-
- if (methodInstance->mIRFunction)
- {
- BfLogSysM("Autocomplete removing IRFunction %d\n", methodInstance->mIRFunction.mId);
- module->mBfIRBuilder->Func_DeleteBody(methodInstance->mIRFunction);
- module->mBfIRBuilder->Func_EraseFromParent(methodInstance->mIRFunction);
- }
- }
-
- if ((mResolvePassData->mAutoComplete->mDefType == actualTypeDef) && (mResolvePassData->mAutoComplete->mDefMethod != NULL))
- {
- BfMethodDef* tempDefMethod = NULL;
- for (auto checkMethod : tempTypeDef->mMethods)
- {
- if (checkMethod == mResolvePassData->mAutoComplete->mDefMethod)
- tempDefMethod = checkMethod;
- }
- if (tempDefMethod != NULL)
- {
- BfMethodDef* actualReplaceMethodDef = NULL;
- for (auto checkMethodDef : actualTypeDef->mMethods)
- {
- if ((checkMethodDef->mMethodType == tempDefMethod->mMethodType) &&
- (checkMethodDef->mMethodDeclaration != NULL) && (tempDefMethod->mMethodDeclaration != NULL) &&
- (checkMethodDef->mMethodDeclaration->GetSrcStart() == tempDefMethod->mMethodDeclaration->GetSrcStart()))
- actualReplaceMethodDef = checkMethodDef;
- }
- if (actualReplaceMethodDef == NULL)
- {
- autoComplete->mDefType = NULL;
- autoComplete->mDefField = NULL;
- autoComplete->mDefProp = NULL;
- autoComplete->mReplaceLocalId = -1;
- autoComplete->mDefMethod = NULL;
- }
- else
- autoComplete->mDefMethod = actualReplaceMethodDef;
- }
- }
- if (hadTempExtensionInfo)
- {
- auto genericTypeInst = (BfGenericTypeInstance*)typeInst;
- genericTypeInst->mGenericExtensionInfo->mExtensionMap.Remove(tempTypeDef);
- }
- for (auto checkNode : mResolvePassData->mExteriorAutocompleteCheckNodes)
- {
- BP_ZONE("ProcessAutocompleteTempType.CheckIdentifier");
- bool isUsingDirective = false;
- BfIdentifierNode* checkIdentifier = NULL;
- if (auto usingDirective = BfNodeDynCast<BfUsingDirective>(checkNode))
- {
- isUsingDirective = true;
- checkIdentifier = usingDirective->mNamespace;
- }
- else
- checkIdentifier = BfNodeDynCast<BfIdentifierNode>(checkNode);
- mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
- }
- GenerateAutocompleteInfo();
- for (auto methodInstance : methodInstances)
- delete methodInstance;
- methodInstances.Clear();
-
- module->CleanupFileInstances();
- module->ClearConstData();
- BfLogSysM("ProcessAutocompleteTempType end\n");
- }
- BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReference* typeRef)
- {
- //auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration,
- //(BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue | BfResolveTypeRefFlag_AllowGenericTypeParamConstValue));
- auto resolvedType = module->ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowRef);
- if ((resolvedType != NULL) && (resolvedType->IsTypeInstance()))
- {
- auto typeInst = resolvedType->ToTypeInstance();
- //TODO: Did we need this?
- // The ResolveTypeRef call already does mResolvePassData->HandleTypeReference, so we were adding double entries
- //mResolvePassData->HandleTypeReference(typeRef, typeInst->mTypeDef);
- }
- return resolvedType;
- }
- void BfCompiler::AddDepsToRebuildTypeList(BfTypeInstance* replaceTypeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList)
- {
- for (auto& dep : replaceTypeInst->mDependencyMap)
- {
- auto depType = dep.mKey;
- auto depTypeInst = depType->ToTypeInstance();
- if (depTypeInst == NULL)
- continue;
- if (mResolvePassData->mParser != NULL)
- {
- // Only find references within the current file
- if (!depTypeInst->mTypeDef->HasSource(mResolvePassData->mParser))
- continue;
- }
- bool allowRebuild = ((!depTypeInst->IsGenericTypeInstance()) ||
- ((depTypeInst->IsUnspecializedType()) && (!depTypeInst->IsUnspecializedTypeVariation())));
- if ((depTypeInst->IsClosure()) || (depTypeInst->IsConcreteInterfaceType()) || (depTypeInst->IsRetTypeType()))
- allowRebuild = false;
- if (allowRebuild)
- rebuildTypeInstList.Add(depTypeInst);
- }
- }
- void BfCompiler::GetSymbolReferences()
- {
- BfLogSysM("GetSymbolReferences\n");
- if (mInInvalidState)
- return; // Don't even try
- auto context = mContext;
- if (context->mBfObjectType == NULL)
- return; // Not initialized yet
- auto module = context->mScratchModule;
- if (mResolvePassData->mAutoComplete != NULL)
- mResolvePassData->mAutoComplete->SetModule(module);
-
- const char* strPtr = mResolvePassData->mQueuedReplaceTypeDef.c_str();
- BfTypeDef* typeDef = mSystem->FindTypeDefEx(strPtr);
- if ((typeDef == NULL) || (typeDef->mTypeDeclaration == NULL))
- return;
- mResolvePassData->mSymbolReferenceTypeDef = typeDef;
- auto replaceType = module->ResolveTypeDef(typeDef, BfPopulateType_IdentityNoRemapAlias);
- module->PopulateType(replaceType);
- auto replaceTypeInst = replaceType->ToTypeInstance();
- HashSet<BfTypeInstance*> rebuildTypeInstList;
- if (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Local)
- {
- AddDepsToRebuildTypeList(replaceTypeInst, rebuildTypeInstList);
- // For generic types, add all references from all specialized versions
- if (replaceTypeInst->IsGenericTypeInstance())
- {
- for (auto type : mContext->mResolvedTypes)
- {
- auto typeInst = type->ToTypeInstance();
- if ((typeInst != replaceTypeInst) && (typeInst != NULL) && (typeInst->mTypeDef == typeDef))
- AddDepsToRebuildTypeList(typeInst, rebuildTypeInstList);
- }
- }
- }
- rebuildTypeInstList.Add(replaceTypeInst);
- //TODO: Did we need this to be rebuildTypeInst->mModule??? Why?
- //auto rebuildModule = rebuildTypeInst->mModule;
- auto rebuildModule = context->mScratchModule;
- auto _CheckAttributes = [&](BfAttributeDirective* attrib, BfTypeDef* declaringType)
- {
- if ((mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Type) &&
- (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Field) &&
- (mResolvePassData->mGetSymbolReferenceKind != BfGetSymbolReferenceKind_Property))
- return;
- while (attrib != NULL)
- {
- String attrName = attrib->mAttributeTypeRef->ToString();
- BfType* attrType = NULL;
- BfAtomComposite nameComposite;
- if (mSystem->ParseAtomComposite(attrName + "Attribute", nameComposite))
- {
- BfTypeDef* attrTypeDef = module->FindTypeDefRaw(nameComposite, 0, replaceTypeInst, declaringType, NULL);
- if (attrTypeDef != NULL)
- {
- mResolvePassData->HandleTypeReference(attrib->mAttributeTypeRef, attrTypeDef);
- attrTypeDef->PopulateMemberSets();
- for (auto argExpr : attrib->mArguments)
- {
- if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(argExpr))
- {
- auto propName = assignExpr->mLeft->ToString();
- BfMemberSetEntry* propDefEntry;
- if (attrTypeDef->mPropertySet.TryGetWith(propName, &propDefEntry))
- {
- mResolvePassData->HandlePropertyReference(assignExpr->mLeft, attrTypeDef, (BfPropertyDef*)propDefEntry->mMemberDef);
- }
- else if (attrTypeDef->mFieldSet.TryGetWith(propName, &propDefEntry))
- {
- mResolvePassData->HandleFieldReference(assignExpr->mLeft, attrTypeDef, (BfFieldDef*)propDefEntry->mMemberDef);
- }
- }
- }
- }
- }
- attrib = attrib->mNextAttribute;
- }
- };
- for (auto rebuildTypeInst : rebuildTypeInstList)
- {
- auto context = mContext;
- auto module = context->mScratchModule;
- SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(module->mCurTypeInstance, rebuildTypeInst);
- SetAndRestoreValue<bool> prevIgnoreErrors(module->mIgnoreErrors, true);
- // Run through base types for type renames
- auto typeDef = rebuildTypeInst->mTypeDef;
- if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mNameNode != NULL))
- {
- if (typeDef->mIsCombinedPartial)
- {
- for (auto checkTypeDef : typeDef->mPartials)
- {
- auto nameNode = checkTypeDef->mTypeDeclaration->mNameNode;
- if ((mResolvePassData->mParser == NULL) || (nameNode->IsFromParser(mResolvePassData->mParser)))
- mResolvePassData->HandleTypeReference(nameNode, typeDef);
- if (checkTypeDef->IsExtension())
- {
- if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type)
- {
- BfTypeState typeState;
- typeState.mCurTypeDef = checkTypeDef;
- SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
- for (auto baseTypeRef : checkTypeDef->mBaseTypes)
- CheckSymbolReferenceTypeRef(module, baseTypeRef);
- for (auto genericParam : checkTypeDef->mGenericParamDefs)
- {
- for (auto constraint : genericParam->mInterfaceConstraints)
- module->ResolveTypeRef(constraint, BfPopulateType_Identity);
- }
- }
- }
- }
- }
- else
- {
- mResolvePassData->HandleTypeReference(typeDef->mTypeDeclaration->mNameNode, typeDef);
- }
- }
- if (!typeDef->mPartials.IsEmpty())
- {
- for (auto partialDef : typeDef->mPartials)
- {
- if ((partialDef->mTypeDeclaration != NULL) && (partialDef->mTypeDeclaration->mAttributes != NULL))
- _CheckAttributes(partialDef->mTypeDeclaration->mAttributes, typeDef);
- }
- }
- else
- {
- if ((typeDef->mTypeDeclaration != NULL) && (typeDef->mTypeDeclaration->mAttributes != NULL))
- _CheckAttributes(typeDef->mTypeDeclaration->mAttributes, typeDef);
- }
- if (auto typeAliasDeclaration = BfNodeDynCast<BfTypeAliasDeclaration>(typeDef->mTypeDeclaration))
- {
- CheckSymbolReferenceTypeRef(module, typeAliasDeclaration->mAliasToType);
- }
-
- if (mResolvePassData != NULL)
- {
- if (rebuildTypeInst->IsGenericTypeInstance())
- {
- auto genericTypeInstance = (BfGenericTypeInstance*)rebuildTypeInst;
- for (int genericParamIdx = 0; genericParamIdx < (int)genericTypeInstance->mTypeGenericArguments.size(); genericParamIdx++)
- {
- BfGenericTypeParamInstance genericParamInstance(genericTypeInstance->mTypeDef, genericParamIdx);
- auto genericParamDef = typeDef->mGenericParamDefs[genericParamIdx];
- //BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, genericParamIdx);
- if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam)
- {
- for (auto nameNode : genericParamDef->mNameNodes)
- if (nameNode != NULL)
- mResolvePassData->HandleTypeGenericParam(nameNode, typeDef, genericParamIdx);
- }
- rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, typeDef->mGenericParamDefs, genericParamIdx);
- }
- }
- }
-
- if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type)
- {
- for (auto baseTypeRef : typeDef->mBaseTypes)
- CheckSymbolReferenceTypeRef(module, baseTypeRef);
- }
- BfTypeState typeState;
- SetAndRestoreValue<BfTypeState*> prevTypeState(module->mContext->mCurTypeState, &typeState);
- if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Property)
- {
- for (auto propDef : typeDef->mProperties)
- {
- BfPropertyDef* checkPropDef = propDef;
- BfTypeInstance* checkTypeInst = rebuildTypeInst;
- typeState.mCurTypeDef = propDef->mDeclaringType;
- module->GetBasePropertyDef(checkPropDef, checkTypeInst);
- if (propDef->mFieldDeclaration != NULL)
- mResolvePassData->HandlePropertyReference(propDef->mFieldDeclaration->mNameNode, checkTypeInst->mTypeDef, checkPropDef);
- }
- }
- if (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Field)
- {
- for (auto fieldDef : typeDef->mFields)
- {
- if (fieldDef->mFieldDeclaration != NULL)
- {
- typeState.mCurTypeDef = fieldDef->mDeclaringType;
- mResolvePassData->HandleFieldReference(fieldDef->mFieldDeclaration->mNameNode, typeDef, fieldDef);
- }
- }
- }
-
- for (auto& fieldInst : rebuildTypeInst->mFieldInstances)
- {
- auto fieldDef = fieldInst.GetFieldDef();
- if (fieldDef != NULL)
- {
- typeState.mCurTypeDef = fieldDef->mDeclaringType;
- if (fieldDef->mTypeRef != NULL)
- CheckSymbolReferenceTypeRef(module, fieldDef->mTypeRef);
- if ((fieldDef->mIsConst) && (fieldDef->mInitializer != NULL))
- {
- BfConstResolver constResolver(module);
- constResolver.Resolve(fieldDef->mInitializer);
- }
- if ((fieldDef->mFieldDeclaration != NULL) && (fieldDef->mFieldDeclaration->mAttributes != NULL))
- _CheckAttributes(fieldDef->mFieldDeclaration->mAttributes, fieldDef->mDeclaringType);
- }
- }
- for (auto& propDef : rebuildTypeInst->mTypeDef->mProperties)
- {
- typeState.mCurTypeDef = propDef->mDeclaringType;
- if (propDef->mTypeRef != NULL)
- CheckSymbolReferenceTypeRef(module, propDef->mTypeRef);
- }
-
- if (rebuildModule == NULL)
- continue;
- rebuildModule->EnsureIRBuilder();
- SetAndRestoreValue<BfTypeInstance*> prevTypeInstance2(rebuildModule->mCurTypeInstance, rebuildTypeInst);
- for (auto& methodInstGroup : rebuildTypeInst->mMethodInstanceGroups)
- {
- // Run through all methods
- bool isDefault = true;
-
- BfMethodInstanceGroup::MapType::iterator methodItr;
- if (methodInstGroup.mMethodSpecializationMap != NULL)
- methodItr = methodInstGroup.mMethodSpecializationMap->begin();
- while (true)
- {
- BfMethodInstance* rebuildMethodInstance;
- if (isDefault)
- {
- rebuildMethodInstance = methodInstGroup.mDefault;
- if (rebuildMethodInstance == NULL)
- break;
- isDefault = false;
- }
- else
- {
- //TODO: Why did we process specialized methods?
- // This caused renaming of types picking up 'T' usage from generic methods
- break;
- // if (methodInstGroup.mMethodSpecializationMap == NULL)
- // break;
- // if (methodItr == methodInstGroup.mMethodSpecializationMap->end())
- // break;
- // rebuildMethodInstance = methodItr->mValue;
- // ++methodItr;
- }
-
- if ((rebuildMethodInstance->mIsUnspecializedVariation) || (rebuildMethodInstance->IsSpecializedGenericMethod()))
- continue;
-
- SetAndRestoreValue<BfMethodInstance*> prevTypeInstance(rebuildModule->mCurMethodInstance, rebuildMethodInstance);
- auto methodDef = rebuildMethodInstance->mMethodDef;
- auto methodDeclaration = methodDef->GetMethodDeclaration();
- typeState.mCurTypeDef = methodDef->mDeclaringType;
-
- if ((methodDeclaration != NULL) && (methodDeclaration->mAttributes != NULL))
- _CheckAttributes(methodDeclaration->mAttributes, methodDef->mDeclaringType);
- if ((mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Type) ||
- (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_MethodGenericParam) ||
- (mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_TypeGenericParam))
- {
- if (methodDef->mExplicitInterface != NULL)
- CheckSymbolReferenceTypeRef(rebuildModule, methodDef->mExplicitInterface);
- for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
- {
- auto param = methodDef->mParams[paramIdx];
- CheckSymbolReferenceTypeRef(rebuildModule, param->mTypeRef);
- }
- if (methodDef->mReturnTypeRef != NULL)
- CheckSymbolReferenceTypeRef(rebuildModule, methodDef->mReturnTypeRef);
- }
- if (rebuildMethodInstance->mIgnoreBody)
- {
- auto methodDeclaration = methodDef->GetMethodDeclaration();
- if (methodDeclaration != NULL)
- mResolvePassData->HandleMethodReference(methodDeclaration->mNameNode, typeDef, methodDef);
- for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
- {
- auto param = methodDef->mParams[paramIdx];
- if (param->mParamDeclaration != NULL)
- {
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(param->mParamDeclaration->mNameNode))
- mResolvePassData->HandleLocalReference(identifierNode, rebuildTypeInst->mTypeDef, rebuildMethodInstance->mMethodDef, paramIdx + 1);
- else if (auto tupleExprNode = BfNodeDynCast<BfTupleExpression>(param->mParamDeclaration->mNameNode))
- {
- for (int fieldIdx = 0; fieldIdx < (int)tupleExprNode->mValues.size(); fieldIdx++)
- {
- if (auto identifierNode = BfNodeDynCast<BfIdentifierNode>(tupleExprNode->mValues[fieldIdx]))
- mResolvePassData->HandleLocalReference(identifierNode, rebuildTypeInst->mTypeDef, rebuildMethodInstance->mMethodDef, paramIdx + 1);
- }
- }
- }
- }
- }
- else
- {
- for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
- {
- auto param = methodDef->mParams[paramIdx];
- if ((param->mParamDeclaration != NULL) && (param->mParamDeclaration->mInitializer != NULL))
- {
- auto paramType = rebuildMethodInstance->GetParamType(paramIdx);
- BfConstResolver constResolver(rebuildModule);
- constResolver.Resolve(param->mParamDeclaration->mInitializer, paramType);
- }
- }
- if (rebuildMethodInstance->mHasBeenProcessed)
- {
- if (rebuildMethodInstance->mIRFunction)
- rebuildModule->mBfIRBuilder->Func_DeleteBody(rebuildMethodInstance->mIRFunction);
- rebuildMethodInstance->mHasBeenProcessed = false;
- rebuildModule->mIncompleteMethodCount++;
- }
- else
- {
- if ((rebuildModule->mIncompleteMethodCount == 0) && (!rebuildModule->mIsScratchModule))
- {
- BF_FATAL("Shouldn't be processing this method");
- }
- }
-
- for (int genericParamIdx = 0; genericParamIdx < (int)rebuildMethodInstance->GetNumGenericArguments(); genericParamIdx++)
- {
- BfGenericMethodParamInstance genericParamInstance(rebuildMethodInstance->mMethodDef, genericParamIdx);
- auto genericParamDef = methodDef->mGenericParams[genericParamIdx];
- if (mResolvePassData != NULL)
- {
- for (auto nameNode : genericParamDef->mNameNodes)
- if (nameNode != NULL)
- mResolvePassData->HandleMethodGenericParam(nameNode, typeDef, methodDef, genericParamIdx);
- }
- rebuildModule->ResolveGenericParamConstraints(&genericParamInstance, methodDef->mGenericParams, genericParamIdx);
- }
- rebuildModule->ProcessMethod(rebuildMethodInstance);
- }
- }
- }
- }
- }
- void BfCompiler::UpdateCompletion()
- {
- if (mIsResolveOnly)
- return;
- float typeScale = 10.0f;
- float methodScale = 1.0f;
- float queueModuleScale = 50.0f;
- float genModuleScale = 50.0f;
- mCodeGen.UpdateStats();
- BF_ASSERT(mCodeGen.mQueuedCount >= mCodeGen.mCompletionCount);
- BF_ASSERT(mStats.mModulesFinished <= mStats.mModulesStarted);
- BF_ASSERT(mCodeGen.mCompletionCount <= mStats.mModulesStarted);
- float numerator = ((mStats.mQueuedTypesProcessed * typeScale) + //(mStats.mMethodsProcessed * methodScale) +
- (mStats.mModulesFinished * queueModuleScale) + (mCodeGen.mCompletionCount * genModuleScale));
- float divisor = ((mStats.mTypesQueued * typeScale) + //(mStats.mMethodsQueued * methodScale) +
- (mStats.mModulesStarted * queueModuleScale) + (mStats.mReifiedModuleCount * genModuleScale));
- float checkPct = 0;
- if (divisor > 0)
- {
- checkPct = numerator / divisor;
- BF_ASSERT(checkPct >= 0);
- if (checkPct > mCompletionPct)
- mCompletionPct = checkPct;
- }
- else
- mCompletionPct = 0;
- if (!mHadCancel)
- BF_ASSERT(mCompletionPct <= 1.0f);
- if (mCompletionPct > 1.0f)
- mCompletionPct = 1.0f;
- }
- void BfCompiler::MarkStringPool(BfModule* module)
- {
- for (int stringId : module->mStringPoolRefs)
- {
- BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId];
- stringPoolEntry.mLastUsedRevision = mRevision;
- }
- /*if (module->mOptModule != NULL)
- MarkStringPool(module->mOptModule);*/
- auto altModule = module->mNextAltModule;
- while (altModule != NULL)
- {
- MarkStringPool(altModule);
- altModule = altModule->mNextAltModule;
- }
- for (auto& specModulePair : module->mSpecializedMethodModules)
- MarkStringPool(specModulePair.mValue);
- }
- void BfCompiler::ClearUnusedStringPoolEntries()
- {
- BF_ASSERT(!IsHotCompile());
-
- for (auto module : mContext->mModules)
- {
- MarkStringPool(module);
- }
- for (auto itr = mContext->mStringObjectIdMap.begin(); itr != mContext->mStringObjectIdMap.end(); )
- {
- int strId = itr->mKey;
- BfStringPoolEntry& stringPoolEntry = itr->mValue;
- if (stringPoolEntry.mLastUsedRevision != mRevision)
- {
- CompileLog("Clearing unused string: %d %s\n", itr->mKey, stringPoolEntry.mString.c_str());
- mContext->mStringObjectPool.Remove(stringPoolEntry.mString);
- itr = mContext->mStringObjectIdMap.Remove(itr);
- }
- else
- ++itr;
- }
- }
- void BfCompiler::ClearBuildCache()
- {
- mCodeGen.ClearBuildCache();
- for (auto project : mSystem->mProjects)
- {
- String libPath = mOutputDirectory + "/" + project->mName + "/" + project->mName + "__.lib";
- BfpFile_Delete(libPath.c_str(), NULL);
- }
- }
- int BfCompiler::GetDynCastVDataCount()
- {
- int dynElements = 1 + mMaxInterfaceSlots;
- return ((dynElements * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
- }
- bool BfCompiler::IsAutocomplete()
- {
- return (mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL);
- }
- BfAutoComplete* BfCompiler::GetAutoComplete()
- {
- if (mResolvePassData != NULL)
- return mResolvePassData->mAutoComplete;
- return NULL;
- }
- bool BfCompiler::IsHotCompile()
- {
- return mOptions.mHotProject != NULL;
- }
- bool BfCompiler::IsSkippingExtraResolveChecks()
- {
- return mIsResolveOnly && !mOptions.mExtraResolveChecks;
- }
- int BfCompiler::GetVTableMethodOffset()
- {
- if (mOptions.mHasVDataExtender)
- return 1;
- return 0;
- }
- bool BfCompiler::DoWorkLoop(bool onlyReifiedTypes, bool onlyReifiedMethods)
- {
- bool hadAnyWork = false;
- while (true)
- {
- bool didWork = false;
- didWork |= mContext->ProcessWorkList(onlyReifiedTypes, onlyReifiedMethods);
- if (!didWork)
- break;
- hadAnyWork = true;
- }
- return hadAnyWork;
- }
- BfMangler::MangleKind BfCompiler::GetMangleKind()
- {
- if (mOptions.mToolsetType == BfToolsetType_GNU)
- return BfMangler::MangleKind_GNU;
- return (mSystem->mPtrSize == 8) ? BfMangler::MangleKind_Microsoft_64 : BfMangler::MangleKind_Microsoft_32;
- }
- //////////////////////////////////////////////////////////////////////////
- int ArrTest()
- {
- //SizedArray<int, 8> intArr;
- //Array<int> intArr;
- //std::vector<int> intArr;
- BfSizedVector<int, 8> intArr;
- //int val = intArr.GetLastSafe();
- intArr.push_back(123);
- intArr.pop_back();
- intArr.push_back(234);
-
- intArr.push_back(345);
- //intArr.push_back(567);
- //auto itr = std::find(intArr.begin(), intArr.end(), 234);
- //intArr.erase(itr);
- for (auto itr = intArr.begin(); itr != intArr.end(); )
- {
- if (*itr == 234)
- itr = intArr.erase(itr);
- else
- itr++;
- }
- return (int)intArr.size();
- //intArr.RemoveAt(2);
- }
- //////////////////////////////////////////////////////////////////////////
- void BfCompiler::PopulateReified()
- {
- BP_ZONE("PopulateReified");
- BfContext* context = mContext;
- bool hasTests = mSystem->HasTestProjects();
- Array<BfMethodInstance*> impChainHeadMethods;
- // Types can pull in new dependencies, so fully populate types until they stop
- bool reifiedOnly = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
- while (true)
- {
- BP_ZONE("Compile_PopulateTypes");
-
- int startTypeInitCount = mTypeInitCount;
- bool didWork = false;
- BfLogSysM("PopulateReified iteration start\n");
- int typeCount = 0;
- for (auto type : context->mResolvedTypes)
- {
- auto module = type->GetModule();
- typeCount++;
- if (module == NULL)
- continue;
- if (!type->IsReified())
- {
- // On compiles, only handle reified types in this loop. This fixes cases where our first instance of a dependent type
- // is found to be unreified and then we have to reify it later. It's not an error, just a compile perf issue
- continue;
- }
- // We have to not populate generic type instances because that may force us to populate a type that SHOULD be deleted
- if ((type->IsIncomplete()) && (type->IsTypeInstance()) && (!type->IsGenericTypeInstance()))
- {
- mSystem->CheckLockYield();
- module->PopulateType(type, BfPopulateType_Full);
- }
- auto typeInst = type->ToTypeInstance();
-
- if ((typeInst != NULL) && (typeInst->IsGenericTypeInstance()) && (!typeInst->IsUnspecializedType()))
- {
- auto unspecializedType = module->GetUnspecializedTypeInstance(typeInst);
- if (!unspecializedType->mIsReified)
- unspecializedType->mIsReified = true;
- }
-
- // Check reifications forced by virtuals or interfaces
- if ((!mIsResolveOnly) && (typeInst != NULL) && (typeInst->mIsReified) && (typeInst->IsObject()) && (!typeInst->IsUnspecializedType())
- && (typeInst->mHasBeenInstantiated) && (!typeInst->IsIncomplete()))
- {
- // If we have chained methods, make sure we implement the chain members if the chain head is implemented and reified
- if (typeInst->mTypeDef->mIsCombinedPartial)
- {
- bool hasUnimpChainMembers = false;
- impChainHeadMethods.Clear();
- for (auto& methodInstanceGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodInstanceGroup.mDefault;
- if (methodInstance == NULL)
- continue;
- if (methodInstance->mChainType == BfMethodChainType_ChainHead)
- {
- if (methodInstance->IsReifiedAndImplemented())
- impChainHeadMethods.Add(methodInstance);
- }
- else if (methodInstance->mChainType == BfMethodChainType_ChainMember)
- {
- if (!methodInstance->IsReifiedAndImplemented())
- hasUnimpChainMembers = true;
- }
- else if ((methodInstance->mChainType == BfMethodChainType_None) && (methodInstance->mMethodDef->IsDefaultCtor()))
- {
- if (!methodInstance->IsReifiedAndImplemented())
- hasUnimpChainMembers = true;
- }
- }
- if ((hasUnimpChainMembers) && (!impChainHeadMethods.IsEmpty()))
- {
- for (auto& methodInstanceGroup : typeInst->mMethodInstanceGroups)
- {
- auto methodInstance = methodInstanceGroup.mDefault;
- if (methodInstance == NULL)
- continue;
- bool forceMethod = false;
- if (methodInstance->mChainType == BfMethodChainType_ChainMember)
- {
- if (!methodInstance->IsReifiedAndImplemented())
- {
- for (auto impMethodInstance : impChainHeadMethods)
- {
- if (typeInst->mModule->CompareMethodSignatures(methodInstance, impMethodInstance))
- {
- forceMethod = true;
- }
- }
- }
- }
- else if (methodInstance->mMethodDef->IsDefaultCtor())
- {
- if (!methodInstance->IsReifiedAndImplemented())
- forceMethod = true;
- }
- if (forceMethod)
- {
- typeInst->mModule->GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, BfTypeVector(),
- (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass));
- }
- }
- }
- }
- // If we have any virtual methods overrides that are unreified but the declaring virtual method is reified then we also need to reify
- for (auto&& vEntry : typeInst->mVirtualMethodTable)
- {
- if ((vEntry.mDeclaringMethod.mTypeInstance == NULL) ||
- (vEntry.mDeclaringMethod.mTypeInstance->IsIncomplete()) ||
- (vEntry.mImplementingMethod.mTypeInstance == NULL) ||
- (vEntry.mImplementingMethod.mTypeInstance->IsIncomplete()))
- continue;
- BfMethodInstance* declaringMethod = vEntry.mDeclaringMethod;
- if (declaringMethod == NULL)
- continue;
- if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented()))
- {
- BfMethodInstance* implMethod = vEntry.mImplementingMethod;
- if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
- {
- didWork = true;
- typeInst->mModule->GetMethodInstance(implMethod);
- }
- }
- }
- for (auto& ifaceTypeInst : typeInst->mInterfaces)
- {
- auto ifaceInst = ifaceTypeInst.mInterfaceType;
- int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
- int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
- auto declTypeDef = ifaceTypeInst.mDeclaringType;
- for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++)
- {
- auto ifaceMethodInst = ifaceInst->mMethodInstanceGroups[iMethodIdx].mDefault;
- if ((ifaceMethodInst == NULL) || (!ifaceMethodInst->IsReifiedAndImplemented()))
- continue;
- auto implMethodRef = &typeInst->mInterfaceMethodTable[iMethodIdx + startIdx].mMethodRef;
- BfMethodInstance* implMethod = *implMethodRef;
- if (implMethod == NULL)
- continue;
- if (!implMethod->IsReifiedAndImplemented())
- {
- didWork = true;
- typeInst->mModule->GetMethodInstance(implMethod);
- }
- }
- }
- }
- }
- BfLogSysM("PopulateReified iteration done\n");
- didWork |= DoWorkLoop(reifiedOnly, reifiedOnly);
- if (reifiedOnly)
- didWork |= DoWorkLoop(false, reifiedOnly);
- if (startTypeInitCount != mTypeInitCount)
- didWork = true;
- if (didWork)
- continue;
- // We get everything on the first pass through
- if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
- break;
- if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_SkipUnused)
- break;
- if (startTypeInitCount == mTypeInitCount)
- break;
- }
- }
- void BfCompiler::HotCommit()
- {
- if (mHotState == NULL)
- return;
- mHotState->mCommittedHotCompileIdx = mOptions.mHotCompileIdx;
- for (auto type : mContext->mResolvedTypes)
- {
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
- if (typeInst->mHotTypeData == NULL)
- continue;
- for (int typeIdx = (int)typeInst->mHotTypeData->mTypeVersions.size() - 1; typeIdx >= 0; typeIdx--)
- {
- auto hotVersion = typeInst->mHotTypeData->mTypeVersions[typeIdx];
- if (hotVersion->mCommittedHotCompileIdx != -1)
- break;
- hotVersion->mCommittedHotCompileIdx = mHotState->mCommittedHotCompileIdx;
- if ((!hotVersion->mInterfaceMapping.IsEmpty()) && (typeIdx > 0))
- {
- auto hotVersionHead = typeInst->mHotTypeData->GetLatestVersionHead();
- if ((hotVersionHead != hotVersion) && (hotVersionHead->mDataHash == hotVersion->mDataHash))
- {
- // When we have a slot failure, the data hash will match but we actually do need to use the new mInterfaceMapping entries
- // So we copy them over to the
- hotVersionHead->mInterfaceMapping = hotVersion->mInterfaceMapping;
- }
- }
- }
- }
- }
- void BfCompiler::HotResolve_Start(HotResolveFlags flags)
- {
- BfLogSysM("BfCompiler::HotResolve_Start\n");
- delete mHotResolveData;
- mHotResolveData = new HotResolveData();
- mHotResolveData->mFlags = flags;
-
- mHotResolveData->mHotTypeIdFlags.Resize(mCurTypeId);
- mHotResolveData->mReasons.Resize(mCurTypeId);
- if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
- {
- HotResolve_AddReachableMethod("BfCallAllStaticDtors");
- for (auto& kv : mHotData->mFuncPtrs)
- {
- auto funcRef = kv.mValue;
- HotResolve_AddReachableMethod(funcRef->mMethod, HotTypeFlag_FuncPtr, true);
- }
- }
- }
- bool BfCompiler::HotResolve_AddReachableMethod(BfHotMethod* hotMethod, HotTypeFlags flags, bool devirtualized, bool forceProcess)
- {
- HotReachableData* hotReachableData;
- if (mHotResolveData->mReachableMethods.TryAdd(hotMethod, NULL, &hotReachableData))
- {
- hotMethod->mRefCount++;
- }
- else
- {
- hotReachableData->mTypeFlags = (HotTypeFlags)(hotReachableData->mTypeFlags | flags);
- if ((!devirtualized) && (!hotReachableData->mHadNonDevirtualizedCall))
- {
- hotReachableData->mHadNonDevirtualizedCall = true;
- if (!forceProcess)
- return true;
- }
- if (!forceProcess)
- return false;
- }
- hotReachableData->mTypeFlags = (HotTypeFlags)(hotReachableData->mTypeFlags | flags);
- if (!devirtualized)
- hotReachableData->mHadNonDevirtualizedCall = true;
-
- for (auto hotDepData : hotMethod->mReferences)
- {
- if (hotDepData->mDataKind == BfHotDepDataKind_ThisType)
- {
- auto hotThisType = (BfHotThisType*)hotDepData;
- auto hotTypeVersion = hotThisType->mTypeVersion;
-
- HotTypeFlags hotTypeFlags = mHotResolveData->mHotTypeIdFlags[hotTypeVersion->mTypeId];
- bool isAllocated = (hotTypeFlags & (HotTypeFlag_Heap | HotTypeFlag_CanAllocate)) != 0;
- if (!isAllocated)
- {
- if (mHotResolveData->mDeferredThisCheckMethods.Add(hotMethod))
- {
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- mHotResolveData->mDeferredThisCheckMethods.Remove(hotMethod);
- }
- }
- else if (hotDepData->mDataKind == BfHotDepDataKind_Allocation)
- {
- auto hotAllocation = (BfHotAllocation*)hotDepData;
- auto hotTypeVersion = hotAllocation->mTypeVersion;
- HotResolve_ReportType(hotTypeVersion, flags, hotMethod);
- HotResolve_ReportType(hotTypeVersion, HotTypeFlag_CanAllocate, hotMethod);
- }
- else if (hotDepData->mDataKind == BfHotDepDataKind_TypeVersion)
- {
- auto hotTypeVersion = (BfHotTypeVersion*)hotDepData;
- HotResolve_ReportType(hotTypeVersion, flags, hotMethod);
- }
- else if (hotDepData->mDataKind == BfHotDepDataKind_Method)
- {
- auto checkMethod = (BfHotMethod*)hotDepData;
- HotResolve_AddReachableMethod(checkMethod, flags, false);
- }
- else if (hotDepData->mDataKind == BfHotDepDataKind_DevirtualizedMethod)
- {
- auto checkMethod = (BfHotDevirtualizedMethod*)hotDepData;
- HotResolve_AddReachableMethod(checkMethod->mMethod, flags, true);
- }
- else if (hotDepData->mDataKind == BfHotDepDataKind_DupMethod)
- {
- auto checkMethod = (BfHotDupMethod*)hotDepData;
- HotResolve_AddReachableMethod(checkMethod->mMethod, flags, true);
- }
- }
- return true;
- }
- void BfCompiler::HotResolve_AddReachableMethod(const StringImpl& methodName)
- {
- BfLogSysM("HotResolve_AddReachableMethod %s\n", methodName.c_str());
- String mangledName = methodName;
- BfHotMethod** hotMethodPtr;
- if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
- {
- BfLogSysM("Hot method not found\n");
- return;
- }
- BfHotMethod* hotMethod = *hotMethodPtr;
- while (hotMethod->mPrevVersion != NULL)
- {
- if (hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx != -1)
- break;
- hotMethod = hotMethod->mPrevVersion;
- }
- HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_ActiveFunction, true);
- }
- void BfCompiler::HotResolve_AddActiveMethod(BfHotMethod* hotMethod)
- {
- if (mHotResolveData->mActiveMethods.Add(hotMethod))
- {
- hotMethod->mRefCount++;
- }
- // We don't need to mark reachable methods unless we had data changes
- if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
- {
- HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_ActiveFunction, true);
- }
- if ((hotMethod->mFlags & BfHotDepDataFlag_HasDup) != 0)
- {
- for (auto depData : hotMethod->mReferences)
- {
- if (depData->mDataKind != BfHotDepDataKind_DupMethod)
- continue;
- auto hotDupMethod = (BfHotDupMethod*)depData;
- HotResolve_AddActiveMethod(hotDupMethod->mMethod);
- }
- }
- }
- void BfCompiler::HotResolve_AddActiveMethod(const StringImpl& methodName)
- {
- BfLogSysM("HotResolve_AddActiveMethod %s\n", methodName.c_str());
- String mangledName;
- int hotCompileIdx = 0;
-
- int tabIdx = (int)methodName.IndexOf('\t');
- if (tabIdx != -1)
- {
- mangledName = methodName.Substring(0, tabIdx);
- hotCompileIdx = atoi(methodName.c_str() + tabIdx + 1);
- }
- else
- mangledName = methodName;
-
- bool isDelegateRef = false;
- BfHotMethod** hotMethodPtr;
- if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
- {
- BfLogSysM("Hot method not found\n");
- return;
- }
- BfHotMethod* hotMethod = *hotMethodPtr;
- while (hotMethod->mPrevVersion != NULL)
- {
- if ((hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx != -1) && (hotCompileIdx < hotMethod->mSrcTypeVersion->mCommittedHotCompileIdx))
- break;
- hotMethod = hotMethod->mPrevVersion;
- }
- HotResolve_AddActiveMethod(hotMethod);
- }
- void BfCompiler::HotResolve_AddDelegateMethod(const StringImpl& methodName)
- {
- BfLogSysM("HotResolve_HotResolve_AddDelegateMethod %s\n", methodName.c_str());
- String mangledName = methodName;
- BfHotMethod** hotMethodPtr;
- if (!mHotData->mMethodMap.TryGetValue(mangledName, &hotMethodPtr))
- {
- BfLogSysM("Hot method not found\n");
- return;
- }
-
- BfHotMethod* hotMethod = *hotMethodPtr;
- HotResolve_AddReachableMethod(hotMethod, HotTypeFlag_Delegate, true);
- }
- void BfCompiler::HotResolve_ReportType(BfHotTypeVersion* hotTypeVersion, HotTypeFlags flags, BfHotDepData* reason)
- {
- auto& flagsRef = mHotResolveData->mHotTypeFlags[hotTypeVersion];
- if (flagsRef == (flagsRef | flags))
- return;
- flagsRef = (HotTypeFlags)(flags | flagsRef);
- bool applyFlags = true;
- if ((flags & (BfCompiler::HotTypeFlag_ActiveFunction | BfCompiler::HotTypeFlag_Delegate | BfCompiler::HotTypeFlag_FuncPtr)) != 0)
- {
- applyFlags = (hotTypeVersion->mCommittedHotCompileIdx != -1) && (mHotState->mPendingDataChanges.Contains(hotTypeVersion->mTypeId));
- if ((!applyFlags) && (hotTypeVersion->mCommittedHotCompileIdx != -1))
- applyFlags = mHotState->mPendingFailedSlottings.Contains(hotTypeVersion->mTypeId);
- if (applyFlags)
- {
- if (reason != NULL)
- mHotResolveData->mReasons[hotTypeVersion->mTypeId] = reason;
- }
- }
- if (applyFlags)
- {
- auto& flagsIdRef = mHotResolveData->mHotTypeIdFlags[hotTypeVersion->mTypeId];
- flagsIdRef = (HotTypeFlags)(flags | flagsIdRef);
- }
-
- BfLogSysM("HotResolve_ReportType %p %s Flags:%X DeclHotIdx:%d\n", hotTypeVersion, mContext->TypeIdToString(hotTypeVersion->mTypeId).c_str(), flags, hotTypeVersion->mDeclHotCompileIdx);
-
- for (auto member : hotTypeVersion->mMembers)
- {
- HotResolve_ReportType(member, flags, reason);
- }
- }
- void BfCompiler::HotResolve_ReportType(int typeId, HotTypeFlags flags)
- {
- if ((uint)typeId >= mHotResolveData->mHotTypeIdFlags.size())
- {
- BF_DBG_FATAL("Invalid typeId");
- return;
- }
- if (mHotResolveData->mHotTypeIdFlags[typeId] == (mHotResolveData->mHotTypeIdFlags[typeId] | flags))
- return;
- auto hotTypeData = mContext->GetHotTypeData(typeId);
- if (hotTypeData != NULL)
- {
- auto hotTypeVersion = hotTypeData->GetTypeVersion(mHotState->mCommittedHotCompileIdx);
- BF_ASSERT(hotTypeVersion != NULL);
- if (hotTypeVersion != NULL)
- HotResolve_ReportType(hotTypeVersion, flags, NULL);
- }
- mHotResolveData->mHotTypeIdFlags[typeId] = (HotTypeFlags)(flags | mHotResolveData->mHotTypeIdFlags[typeId]);
- }
- String BfCompiler::HotResolve_Finish()
- {
- BfLogSysM("HotResolve_Finish\n");
- if (mHotState == NULL)
- {
- // It's possible we did a HotCompile with no file changes and therefore didn't actually do a compile
- return "";
- }
- String result;
- if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
- {
- BF_ASSERT(!mHotState->mPendingDataChanges.IsEmpty() || !mHotState->mPendingFailedSlottings.IsEmpty());
- }
- else
- {
- BF_ASSERT(mHotState->mPendingDataChanges.IsEmpty() && mHotState->mPendingFailedSlottings.IsEmpty());
- }
-
- if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
- {
- auto _AddUsedType = [&](BfTypeDef* typeDef)
- {
- auto type = mContext->mUnreifiedModule->ResolveTypeDef(mReflectTypeInstanceTypeDef);
- if (type != NULL)
- HotResolve_ReportType(type->mTypeId, BfCompiler::HotTypeFlag_Heap);
- };
- // We have some types that can be allocated in a read-only section- pretend they are on the heap
- _AddUsedType(mReflectTypeInstanceTypeDef);
- _AddUsedType(mStringTypeDef);
- // Find any virtual method overrides that may have been called.
- // These can cause new reachable virtual methods to be called, which may take more than one iteration to fully resolve
- for (int methodPass = 0; true; methodPass++)
- {
- bool didWork = false;
-
- for (auto hotMethod : mHotResolveData->mDeferredThisCheckMethods)
- {
- if (HotResolve_AddReachableMethod(hotMethod, BfCompiler::HotTypeFlag_ActiveFunction, true, true))
- didWork = true;
- }
- HotTypeFlags typeFlags = HotTypeFlag_None;
- for (auto& kv : mHotData->mMethodMap)
- {
- String& methodName = kv.mKey;
- auto hotMethod = kv.mValue;
-
- bool doCall = false;
- bool forceAdd = false;
-
- if (mHotResolveData->mReachableMethods.ContainsKey(hotMethod))
- continue;
- for (auto ref : hotMethod->mReferences)
- {
- if (ref->mDataKind == BfHotDepDataKind_ThisType)
- continue;
- if (ref->mDataKind != BfHotDepDataKind_VirtualDecl)
- break;
- auto hotVirtualDecl = (BfHotVirtualDeclaration*)ref;
- HotReachableData* hotReachableData;
- if (mHotResolveData->mReachableMethods.TryGetValue(hotVirtualDecl->mMethod, &hotReachableData))
- {
- if (hotReachableData->mHadNonDevirtualizedCall)
- {
- typeFlags = hotReachableData->mTypeFlags;
- doCall = true;
- }
- }
- }
-
- if (!doCall)
- {
- if ((hotMethod->mFlags & BfHotDepDataFlag_AlwaysCalled) != 0)
- {
- typeFlags = BfCompiler::HotTypeFlag_ActiveFunction;
- doCall = true;
- }
- }
- if (doCall)
- {
- if (HotResolve_AddReachableMethod(hotMethod, typeFlags, true, forceAdd))
- didWork = true;
- }
- }
- if (!didWork)
- break;
- }
- int errorCount = 0;
- for (int typeId = 0; typeId < (int)mHotResolveData->mHotTypeIdFlags.size(); typeId++)
- {
- auto flags = mHotResolveData->mHotTypeIdFlags[typeId];
- if (flags == 0)
- continue;
- auto type = mContext->mTypes[typeId];
- Dictionary<BfHotMethod*, String*> methodNameMap;
- if ((flags > BfCompiler::HotTypeFlag_UserNotUsed) &&
- ((mHotState->mPendingDataChanges.Contains(typeId)) || (mHotState->mPendingFailedSlottings.Contains(typeId))))
- {
- bool isBadTypeUsed = false;
- if ((flags & HotTypeFlag_Heap) != 0)
- isBadTypeUsed = true;
- else if ((flags & (HotTypeFlag_ActiveFunction | HotTypeFlag_Delegate | HotTypeFlag_FuncPtr)) != 0)
- {
- // If we detect an old version being used, it's only an issue if this type can actually be allocated
- if ((flags & HotTypeFlag_CanAllocate) != 0)
- {
- isBadTypeUsed = true;
- }
- }
- if (isBadTypeUsed)
- {
- bool reasonIsActiveMethod = false;
- String methodReason;
- auto reason = mHotResolveData->mReasons[typeId];
- if ((reason != NULL) && (reason->mDataKind == BfHotDepDataKind_Method))
- {
- auto hotMethod = (BfHotMethod*)reason;
- reasonIsActiveMethod = mHotResolveData->mActiveMethods.Contains(hotMethod);
- if (methodNameMap.IsEmpty())
- {
- for (auto& kv : mHotData->mMethodMap)
- {
- auto hotMethod = kv.mValue;
- while (hotMethod != NULL)
- {
- methodNameMap[hotMethod] = &kv.mKey;
- hotMethod = hotMethod->mPrevVersion;
- }
- }
- }
- String** strPtr;
- if (methodNameMap.TryGetValue(hotMethod, &strPtr))
- {
- methodReason += BfDemangler::Demangle((**strPtr), DbgLanguage_Beef, BfDemangler::Flag_BeefFixed);
- }
- }
- errorCount++;
- if (errorCount >= 1000)
- {
- result += "\n (more errors)...";
- break;
- }
- if (!result.IsEmpty())
- result += "\n";
- result += "'";
- result += mContext->TypeIdToString(typeId);
- result += "'";
- if ((flags & BfCompiler::HotTypeFlag_Heap) != 0)
- result += " allocated on the heap";
- else if ((flags & BfCompiler::HotTypeFlag_ActiveFunction) != 0)
- {
- if (reasonIsActiveMethod)
- result += StrFormat(" used by active method '%s'", methodReason.c_str());
- else if (!methodReason.IsEmpty())
- result += StrFormat(" previous data version used by deleted method '%s', reachable by an active method", methodReason.c_str());
- else
- result += " previous data version used by a deleted method reachable by an active method";
- }
- else if ((flags & BfCompiler::HotTypeFlag_Delegate) != 0)
- {
- if (!methodReason.IsEmpty())
- result += StrFormat(" previous data version used by deleted method '%s', reachable by a delegate", methodReason.c_str());
- else
- result += " previous data version used by a deleted method reachable by a delegate";
- }
- else if ((flags & BfCompiler::HotTypeFlag_FuncPtr) != 0)
- {
- if (!methodReason.IsEmpty())
- result += StrFormat(" previous data version used by deleted method '%s', reachable by a function pointer", methodReason.c_str());
- else
- result += " previous data version used by a deleted method reachable by a function pointer";
- }
- else if ((flags & BfCompiler::HotTypeFlag_UserUsed) != 0)
- result += " stated as used by the program";
- }
- }
- String typeName = mContext->TypeIdToString(typeId);
- BfLogSysM(" %d %s %02X\n", typeId, typeName.c_str(), flags);
- }
- if (result.IsEmpty())
- {
- for (auto typeId : mHotState->mPendingDataChanges)
- {
- auto type = mContext->mTypes[typeId];
- auto typeInstance = type->ToTypeInstance();
- BF_ASSERT(typeInstance->mHotTypeData->mPendingDataChange);
- typeInstance->mHotTypeData->mPendingDataChange = false;
- typeInstance->mHotTypeData->mHadDataChange = true;
- typeInstance->mHotTypeData->mVTableOrigLength = -1;
- typeInstance->mHotTypeData->mOrigInterfaceMethodsLength = -1;
- BfLogSysM("Pending data change applied to type %p\n", typeInstance);
- }
- mHotState->mPendingDataChanges.Clear();
- mHotState->mPendingFailedSlottings.Clear();
- }
- }
- ClearOldHotData();
- if ((mHotResolveData->mFlags & HotResolveFlag_HadDataChanges) != 0)
- {
- for (int pass = 0; pass < 2; pass++)
- {
- bool wantsReachable = pass == 0;
- Array<String> methodList;
- for (auto& kv : mHotData->mMethodMap)
- {
- auto hotMethod = kv.mValue;
- bool reachable = mHotResolveData->mReachableMethods.ContainsKey(hotMethod);
- if (reachable != wantsReachable)
- continue;
- String methodName;
- methodName += BfDemangler::Demangle(kv.mKey, DbgLanguage_Beef, BfDemangler::Flag_BeefFixed);
- methodName += " - ";
- methodName += kv.mKey;
- methodList.Add(methodName);
- }
- methodList.Sort([](const String& lhs, const String& rhs) { return lhs < rhs; });
- for (auto& methodName : methodList)
- BfLogSysM("%s: %s\n", wantsReachable ? "Reachable" : "Unreachable", methodName.c_str());
- }
- }
- delete mHotResolveData;
- mHotResolveData = NULL;
-
- return result;
- }
- void BfCompiler::ClearOldHotData()
- {
- if (mHotData == NULL)
- return;
- // TODO: Get rid of old hot data during hot compiles, too
- // if (IsHotCompile())
- // return;
- BP_ZONE("BfCompiler::ClearOldHotData");
-
- bool isHotCompile = IsHotCompile();
- auto itr = mHotData->mMethodMap.begin();
- while (itr != mHotData->mMethodMap.end())
- {
- String& methodName = itr->mKey;
- auto hotMethod = itr->mValue;
- bool doDelete = false;
- // If a previous version of a method is not currently active then it should be impossible to ever reach it
- while (hotMethod->mPrevVersion != NULL)
- {
- auto prevMethod = hotMethod->mPrevVersion;
- if (prevMethod->mRefCount > 1)
- {
- BF_ASSERT((mHotResolveData != NULL) && (mHotResolveData->mActiveMethods.Contains(prevMethod)));
- break;
- }
-
- hotMethod->mPrevVersion = prevMethod->mPrevVersion;
- prevMethod->mPrevVersion = NULL;
- prevMethod->Deref();
- }
- BF_ASSERT(hotMethod->mRefCount >= 1);
- if (hotMethod->mPrevVersion == NULL)
- {
- if (hotMethod->mRefCount <= 1)
- {
- doDelete = true;
- }
- else if ((!isHotCompile) && ((hotMethod->mFlags & (BfHotDepDataFlag_IsBound | BfHotDepDataFlag_RetainMethodWithoutBinding)) == 0))
- {
- doDelete = true;
- }
- }
- bool doRemove = doDelete;
- if ((hotMethod->mFlags & BfHotDepDataFlag_HasDup) != 0)
- {
- bool hasDupMethod = false;
- for (int idx = 0; idx < (int)hotMethod->mReferences.size(); idx++)
- {
- auto depData = hotMethod->mReferences[idx];
- if (depData->mDataKind == BfHotDepDataKind_DupMethod)
- {
- auto dupMethod = (BfHotDupMethod*)depData;
- if (doDelete)
- {
- doRemove = false;
- dupMethod->mMethod->mRefCount++;
- itr->mValue = dupMethod->mMethod;
- }
- else
- {
- if ((dupMethod->mMethod->mRefCount == 1) ||
- ((!IsHotCompile()) && (dupMethod->mMethod->mFlags & BfHotDepDataFlag_IsBound) == 0))
- {
- dupMethod->Deref();
- hotMethod->mReferences.RemoveAt(idx);
- idx--;
- }
- }
- }
- }
- }
- if (doDelete)
- {
- BfLogSysM("Deleting hot method %p %s\n", hotMethod, methodName.c_str());
- //BF_ASSERT(hotMethod->mRefCount == 1);
- hotMethod->Clear();
- hotMethod->Deref();
- if (doRemove)
- itr = mHotData->mMethodMap.Remove(itr);
- }
- else
- ++itr;
- }
- mHotData->ClearUnused(IsHotCompile());
- for (auto type : mContext->mResolvedTypes)
- {
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
- if (typeInst->mHotTypeData == NULL)
- continue;
- bool foundCommittedVersion = false;
- auto latestVersionHead = typeInst->mHotTypeData->GetLatestVersionHead();
- for (int typeIdx = (int)typeInst->mHotTypeData->mTypeVersions.size() - 1; typeIdx >= 0; typeIdx--)
- {
- auto hotVersion = typeInst->mHotTypeData->mTypeVersions[typeIdx];
- if (hotVersion == latestVersionHead)
- {
- // We have to keep the latest version head -- otherwise we would lose vdata and interface mapping data
- continue;
- }
- if ((!foundCommittedVersion) && (mHotState != NULL) && (hotVersion->mDeclHotCompileIdx <= mHotState->mCommittedHotCompileIdx))
- {
- // Don't remove the latest committed version
- foundCommittedVersion = true;
- }
- else if (hotVersion->mRefCount == 1)
- {
- typeInst->mHotTypeData->mTypeVersions.RemoveAt(typeIdx);
- hotVersion->Deref();
- BF_ASSERT(typeInst->mHotTypeData->mTypeVersions.size() > 0);
- }
- }
- }
- }
- void BfCompiler::CompileReified()
- {
- BP_ZONE("Compile_ResolveTypeDefs");
- for (auto typeDef : mSystem->mTypeDefs)
- {
- mSystem->CheckLockYield();
- if (mCanceling)
- {
- BfLogSysM("Canceling from Compile typeDef loop\n");
- break;
- }
- if (typeDef->mProject->mDisabled)
- continue;
- if (typeDef->mIsPartial)
- continue;
- bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll);
- if (typeDef->mProject->IsTestProject())
- {
- for (auto methodDef : typeDef->mMethods)
- {
- auto methodDeclaration = methodDef->GetMethodDeclaration();
- if ((methodDeclaration != NULL) && (methodDeclaration->mAttributes != NULL) &&
- (methodDeclaration->mAttributes->Contains("Test")))
- isAlwaysInclude = true;
- }
- }
- //TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check?
- if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude))
- continue;
- auto scratchModule = mContext->mScratchModule;
- scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
- }
-
- if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
- {
- for (auto project : mSystem->mProjects)
- {
- String entryClassName = project->mStartupObject;
- auto typeDef = mSystem->FindTypeDef(entryClassName, 0, project);
- if (typeDef != NULL)
- {
- typeDef->mIsAlwaysInclude = true;
- auto resolvedType = mContext->mScratchModule->ResolveTypeDef(typeDef);
- if (resolvedType != NULL)
- {
- auto resolvedTypeInst = resolvedType->ToTypeInstance();
- if (resolvedTypeInst != NULL)
- {
- auto module = resolvedTypeInst->GetModule();
- if (!module->mIsReified)
- module->ReifyModule();
- mContext->mScratchModule->PopulateType(resolvedType, BfPopulateType_Full);
- BfMemberSetEntry* memberSetEntry;
- if (resolvedTypeInst->mTypeDef->mMethodSet.TryGetWith(String("Main"), &memberSetEntry))
- {
- BfMethodDef* methodDef = (BfMethodDef*)memberSetEntry->mMemberDef;
- while (methodDef != NULL)
- {
- auto moduleMethodInstance = mContext->mScratchModule->GetMethodInstanceAtIdx(resolvedTypeInst, methodDef->mIdx);
- auto methodInstance = moduleMethodInstance.mMethodInstance;
- if (methodInstance->GetParamCount() != 0)
- {
- mContext->mScratchModule->GetInternalMethod("CreateParamsArray");
- mContext->mScratchModule->GetInternalMethod("DeleteStringArray");
- }
-
- methodDef = methodDef->mNextWithSameName;
- }
- }
- }
- }
- }
- }
- }
- PopulateReified();
- }
- bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
- {
- BP_ZONE("BfCompiler::Compile");
-
- if (!mOptions.mErrorString.IsEmpty())
- {
- mPassInstance->Fail(mOptions.mErrorString);
- return false;
- }
-
- {
- String hotSwapErrors;
- String toolsetErrors;
- for (auto project : mSystem->mProjects)
- {
- if (project->mDisabled)
- continue;
- if (project->mCodeGenOptions.mLTOType != BfLTOType_None)
- {
- if (mOptions.mAllowHotSwapping)
- {
- if (!hotSwapErrors.IsEmpty())
- hotSwapErrors += ", ";
- hotSwapErrors += project->mName;
- }
- if (mOptions.mToolsetType != BfToolsetType_LLVM)
- {
- if (!toolsetErrors.IsEmpty())
- toolsetErrors += ", ";
- toolsetErrors += project->mName;
- }
- }
- }
- if (!hotSwapErrors.IsEmpty())
- 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()));
- if (!toolsetErrors.IsEmpty())
- 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()));
- }
- //
- {
- String attribName;
- mAttributeTypeOptionMap.Clear();
- for (int typeOptionsIdx = 0; typeOptionsIdx < (int)mSystem->mTypeOptions.size(); typeOptionsIdx++)
- {
- auto& typeOptions = mSystem->mTypeOptions[typeOptionsIdx];
- for (auto& attributeFilter : typeOptions.mAttributeFilters)
- {
- attribName = attributeFilter;
- attribName += "Attribute";
- Array<int>* arrPtr = NULL;
- mAttributeTypeOptionMap.TryAdd(attribName, NULL, &arrPtr);
- arrPtr->Add(typeOptionsIdx);
- }
- }
- }
- // Inc revision for next run through Compile
- mRevision++;
- BfLogSysM("Compile Start. Revision: %d\n", mRevision);
- if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
- mContext->mUnreifiedModule->mIsReified = true;
- else
- mContext->mUnreifiedModule->mIsReified = false;
- if (mOptions.mAllowHotSwapping)
- {
- if (mHotData == NULL)
- {
- mHotData = new HotData();
- mHotData->mCompiler = this;
- }
- }
- else
- {
- delete mHotData;
- mHotData = NULL;
- }
- if (IsHotCompile())
- {
- if (!mOptions.mAllowHotSwapping)
- {
- mPassInstance->Fail("Hot Compilation is not enabled");
- return true;
- }
- if (mHotState == NULL)
- {
- mHotState = new HotState();
- mHotState->mHotProject = mOptions.mHotProject;
- }
- else
- {
- // It should be impossible to switch hot projects without a non-hot compile between them
- BF_ASSERT(mHotState->mHotProject == mOptions.mHotProject);
- }
- }
- else
- {
- for (auto& kv : mContext->mSavedTypeDataMap)
- {
- auto savedTypeData = kv.mValue;
- delete savedTypeData->mHotTypeData;
- savedTypeData->mHotTypeData = NULL;
- }
- delete mHotState;
- mHotState = NULL;
- // This will get rid of any old method data so we don't have any more mPrevVersions
- ClearOldHotData();
- }
-
- int prevUnfinishedModules = mStats.mModulesStarted - mStats.mModulesFinished;
- mCompletionPct = 0;
- memset(&mStats, 0, sizeof(mStats));
- mCodeGen.ClearResults();
- mCodeGen.ResetStats();
- mStats.mModulesStarted = prevUnfinishedModules;
- if ((mLastRevisionAborted) && (!mIsResolveOnly))
- {
- auto _AddCount = [&](BfModule* module)
- {
- if (module->mAddedToCount)
- {
- if (module->mIsReified)
- mStats.mReifiedModuleCount++;
- }
- };
- for (auto mainModule : mContext->mModules)
- {
- _AddCount(mainModule);
- for (auto specKV : mainModule->mSpecializedMethodModules)
- {
- _AddCount(specKV.mValue);
- }
- }
- }
-
- if (IsHotCompile())
- {
- mContext->EnsureHotMangledVirtualMethodNames();
- }
- mOutputDirectory = outputDirectory;
- mSystem->StartYieldSection();
- mCanceling = false;
- mSystem->CheckLockYield();
- #ifdef WANT_COMPILE_LOG
- if (!mIsResolveOnly)
- {
- mCompileLogFP = fopen(StrFormat("compile%d.txt", mRevision).c_str(), "wb");
- }
- #endif
- BfTypeDef* typeDef;
- BfLogSysM("UpdateRevisedTypes Revision %d. ResolvePass:%d CursorIdx:%d\n", mRevision, mIsResolveOnly,
- ((mResolvePassData == NULL) || (mResolvePassData->mParser == NULL)) ? - 1 : mResolvePassData->mParser->mCursorIdx);
-
- mCompileState = CompileState_Normal;
- UpdateRevisedTypes();
- // We need to defer processing the graveyard until here, because mLookupResults contain atom references so we need to make sure
- // those aren't deleted until we can properly handle it.
- mSystem->ProcessAtomGraveyard();
-
- BpEnter("Compile_Start");
- bool hasRequiredTypes = true;
- //HashSet<BfTypeDef*> internalTypeDefs;
- auto _GetRequiredType = [&](const StringImpl& typeName, int genericArgCount = 0)
- {
- auto typeDef = mSystem->FindTypeDef(typeName, genericArgCount);
- if (typeDef == NULL)
- {
- mPassInstance->Fail(StrFormat("Unable to find system type: %s", typeName.c_str()));
- hasRequiredTypes = false;
- }
- return typeDef;
- };
- mArray1TypeDef = _GetRequiredType("System.Array1");
- mArray2TypeDef = _GetRequiredType("System.Array2");
- mArray3TypeDef = _GetRequiredType("System.Array3");
- mArray4TypeDef = _GetRequiredType("System.Array4");
- mSpanTypeDef = _GetRequiredType("System.Span", 1);
- mAttributeTypeDef = _GetRequiredType("System.Attribute");
- mAttributeUsageAttributeTypeDef = _GetRequiredType("System.AttributeUsageAttribute");
- mBfObjectTypeDef = _GetRequiredType("System.Object");
- mClassVDataTypeDef = _GetRequiredType("System.ClassVData");
- mCLinkAttributeTypeDef = _GetRequiredType("System.CLinkAttribute");
- mCReprAttributeTypeDef = _GetRequiredType("System.CReprAttribute");
- mNoDiscardAttributeTypeDef = _GetRequiredType("System.NoDiscardAttribute");
- mDisableObjectAccessChecksAttributeTypeDef = _GetRequiredType("System.DisableObjectAccessChecksAttribute");
- mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData");
- mDeferredCallTypeDef = _GetRequiredType("System.DeferredCall");
- mDelegateTypeDef = _GetRequiredType("System.Delegate");
- mEnumTypeDef = _GetRequiredType("System.Enum");
- mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
- mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
- mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute");
- mFunctionTypeDef = _GetRequiredType("System.Function");
- mGCTypeDef = _GetRequiredType("System.GC");
- mGenericIEnumerableTypeDef = _GetRequiredType("System.Collections.Generic.IEnumerable");
- mGenericIEnumeratorTypeDef = _GetRequiredType("System.Collections.Generic.IEnumerator");
- mGenericIRefEnumeratorTypeDef = _GetRequiredType("System.Collections.Generic.IRefEnumerator");
- mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
- mInternalTypeDef = _GetRequiredType("System.Internal");
- mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
- mIHashableTypeDef = _GetRequiredType("System.IHashable");
- mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
- mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);
- mNullableTypeDef = _GetRequiredType("System.Nullable");
- mOrderedAttributeTypeDef = _GetRequiredType("System.OrderedAttribute");
- mPointerTTypeDef = _GetRequiredType("System.Pointer", 1);
- mPointerTypeDef = _GetRequiredType("System.Pointer", 0);
- mReflectArrayType = _GetRequiredType("System.Reflection.ArrayType");
- mReflectFieldDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldData");
- mReflectFieldSplatDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldSplatData");
- mReflectMethodDataDef = _GetRequiredType("System.Reflection.TypeInstance.MethodData");
- mReflectParamDataDef = _GetRequiredType("System.Reflection.TypeInstance.ParamData");
- mReflectPointerType = _GetRequiredType("System.Reflection.PointerType");
- mReflectSizedArrayType = _GetRequiredType("System.Reflection.SizedArrayType");
- mReflectSpecializedGenericType = _GetRequiredType("System.Reflection.SpecializedGenericType");
- mReflectTypeInstanceTypeDef = _GetRequiredType("System.Reflection.TypeInstance");
- mReflectUnspecializedGenericType = _GetRequiredType("System.Reflection.UnspecializedGenericType");
- mSizedArrayTypeDef = _GetRequiredType("System.SizedArray", 2);
- mSkipAccessCheckAttributeTypeDef = _GetRequiredType("System.SkipAccessCheckAttribute");
- mStaticInitAfterAttributeTypeDef = _GetRequiredType("System.StaticInitAfterAttribute");
- mStaticInitPriorityAttributeTypeDef = _GetRequiredType("System.StaticInitPriorityAttribute");
- mStringTypeDef = _GetRequiredType("System.String");
- mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
- mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
- mTypeTypeDef = _GetRequiredType("System.Type");
- mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
- mValueTypeTypeDef = _GetRequiredType("System.ValueType");
- mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
- mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
- mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
- for (int i = 0; i < BfTypeCode_Length; i++)
- mContext->mPrimitiveStructTypes[i] = NULL;
- if (!hasRequiredTypes)
- {
- // Force rebuilding
- mInInvalidState = true;
- mOptions.mForceRebuildIdx++;
- return true;
- }
-
- mSystem->CheckLockYield();
- VisitSourceExteriorNodes();
- //BF_ASSERT(hasRequiredTypes);
- if (!mIsResolveOnly)
- {
- HashSet<BfModule*> foundVDataModuleSet;
- for (auto bfProject : mSystem->mProjects)
- {
- if (bfProject->mDisabled)
- continue;
- if ((mBfObjectTypeDef != NULL) && (!bfProject->ContainsReference(mBfObjectTypeDef->mProject)))
- {
- mPassInstance->Fail(StrFormat("Project '%s' must reference core library '%s'", bfProject->mName.c_str(), mBfObjectTypeDef->mProject->mName.c_str()));
- }
- if ((bfProject->mTargetType != BfTargetType_BeefConsoleApplication) && (bfProject->mTargetType != BfTargetType_BeefWindowsApplication) &&
- (bfProject->mTargetType != BfTargetType_BeefDynLib) &&
- (bfProject->mTargetType != BfTargetType_C_ConsoleApplication) && (bfProject->mTargetType != BfTargetType_C_WindowsApplication) &&
- (bfProject->mTargetType != BfTargetType_BeefTest))
- continue;
- if (bfProject->mTargetType == BfTargetType_BeefTest)
- {
- // Force internal test methods
- auto bfModule = mContext->mScratchModule;
- bfModule->GetInternalMethod("Test_Init");
- bfModule->GetInternalMethod("Test_Query");
- bfModule->GetInternalMethod("Test_Finish");
- }
- bool found = false;
- for (auto module : mVDataModules)
- {
- if (module->mProject == bfProject)
- {
- found = true;
- foundVDataModuleSet.Add(module);
- //module->StartNewRevision();
- }
- }
- if (!found)
- {
- auto module = new BfVDataModule(mContext);
- module->mProject = bfProject;
- module->Init();
- module->FinishInit();
- module->mIsSpecialModule = true;
- BF_ASSERT(!mContext->mLockModules);
- mContext->mModules.push_back(module);
- mVDataModules.push_back(module);
- foundVDataModuleSet.Add(module);
- }
- }
- // Remove old vdata
- for (int moduleIdx = 0; moduleIdx < (int) mVDataModules.size(); moduleIdx++)
- {
- auto module = mVDataModules[moduleIdx];
- if (!foundVDataModuleSet.Contains(module))
- {
- delete module;
- mVDataModules.erase(mVDataModules.begin() + moduleIdx);
- moduleIdx--;
-
- mContext->mModules.Remove(module);
- }
- }
- }
- if (mIsResolveOnly)
- VisitAutocompleteExteriorIdentifiers();
- if (!hasRequiredTypes)
- {
- BfLogSysM("Missing required types\n");
- }
- mStats.mTypesQueued = 0;
- mStats.mMethodsQueued = 0;
-
- mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size();
- mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size();
- if (hasRequiredTypes)
- {
- mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef, BfPopulateType_Full);
-
- mContext->RemapObject();
-
- mSystem->CheckLockYield();
-
- mWantsDeferMethodDecls = mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude;
-
- CompileReified();
- mWantsDeferMethodDecls = false;
- }
-
- BpLeave();
- BpEnter("Compile_End");
-
- {
- BP_ZONE("ProcessingLiveness");
- for (auto type : mContext->mResolvedTypes)
- {
- auto depType = type->ToDependedType();
- if (depType != NULL)
- depType->mRebuildFlags = (BfTypeRebuildFlags)(depType->mRebuildFlags | BfTypeRebuildFlag_AwaitingReference);
- }
-
- bool didWork = false;
- UpdateDependencyMap(mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_ResolveUnused, didWork);
- if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)
- {
- // If UpdateDependencyMap caused methods to be reified, then we need to run PopulateReified again-
- // because those methods may be virtual and we need to reify overrides (for example).
- // We use the DoWorkLoop result to determine if there were actually any changes from UpdateDependencyMap
- if (didWork)
- {
- PopulateReified();
- }
- }
- }
-
- if (hasRequiredTypes)
- ProcessPurgatory(true);
- // Mark used modules
- if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!mCanceling))
- {
- bool hadActualTarget = false;
- if (!mIsResolveOnly)
- {
- SizedArray<BfModule*, 32> requiredModules;
- for (auto typeDef : mSystem->mTypeDefs)
- {
- if ((typeDef->mIsAlwaysInclude) && (!typeDef->mIsPartial))
- {
- auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef);
- if (requiredType != NULL)
- {
- auto requiredModule = requiredType->GetModule();
- if (requiredModule != NULL)
- requiredModules.push_back(requiredModule);
- }
- }
- }
- mContext->mReferencedIFaceSlots.Clear();
- bool hasTests = false;
- for (auto project : mSystem->mProjects)
- {
- if (project->mTargetType == BfTargetType_BeefTest)
- hasTests = true;
- project->mUsedModules.Clear();
- project->mReferencedTypeData.Clear();
- if (project->mDisabled)
- continue;
- if (project->mTargetType == BfTargetType_BeefLib)
- continue;
- hadActualTarget = true;
- for (auto requiredModule : requiredModules)
- {
- mContext->MarkUsedModules(project, requiredModule);
- }
- String entryClassName = project->mStartupObject;
- typeDef = mSystem->FindTypeDef(entryClassName, 0, project);
- if (typeDef != NULL)
- {
- auto startupType = mContext->mScratchModule->ResolveTypeDef(typeDef);
- if (startupType != NULL)
- {
- auto startupTypeInst = startupType->ToTypeInstance();
- if (startupTypeInst != NULL)
- {
- mContext->MarkUsedModules(project, startupTypeInst->GetModule());
- }
- }
- }
- if (hasTests)
- {
- for (auto type : mContext->mResolvedTypes)
- {
- auto typeInstance = type->ToTypeInstance();
- if ((typeInstance != NULL) &&
- (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest))
- {
- bool typeHasTest = false;
- for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
- {
- if (methodInstanceGroup.mDefault != NULL)
- {
- auto methodInstance = methodInstanceGroup.mDefault;
- if ((methodInstance->GetCustomAttributes() != NULL) &&
- (methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
- {
- typeHasTest = true;
- }
- }
- }
- if (typeHasTest)
- mContext->MarkUsedModules(typeInstance->mTypeDef->mProject, typeInstance->mModule);
- }
- }
- }
- }
- // Leave types reified when hot compiling
- if ((!IsHotCompile()) && (hadActualTarget))
- mContext->TryUnreifyModules();
- }
- }
- // Generate slot nums
- if ((!mIsResolveOnly) && (hasRequiredTypes) && (!mCanceling))
- {
- if ((!IsHotCompile()) || (mHotState->mHasNewInterfaceTypes))
- {
- int prevSlotCount = mMaxInterfaceSlots;
- GenerateSlotNums();
- if ((prevSlotCount != -1) && (prevSlotCount != mMaxInterfaceSlots))
- {
- mInterfaceSlotCountChanged = true;
- }
- if (mHotState != NULL)
- mHotState->mHasNewInterfaceTypes = false;
- }
- }
- // Resolve unused types
- if ((mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_ResolveUnused) && (!mCanceling))
- {
- // Finish off any outstanding modules so we can code generate in parallel with handling the unreified stuff
- for (auto module : mContext->mModules)
- {
- if (!module->mIsSpecialModule)
- {
- if ((module->mIsReified) && (module->mIsModuleMutable))
- {
- module->Finish();
- }
- }
- }
- DoWorkLoop();
- BfLogSysM("Compile QueueUnused\n");
- mCompileState = BfCompiler::CompileState_Unreified;
- BpLeave();
- BpEnter("Compile_QueueUnused");
- while (true)
- {
- BP_ZONE("Compile_QueueUnused");
- bool queuedMoreMethods = false;
- int startTypeInitCount = mTypeInitCount;
-
- for (auto typeDef : mSystem->mTypeDefs)
- {
- mSystem->CheckLockYield();
- if (mCanceling)
- {
- BfLogSysM("Canceling from Compile typeDef loop\n");
- break;
- }
- if (typeDef->mProject->mDisabled)
- continue;
-
- if (typeDef->mIsPartial)
- continue;
- if (typeDef->mTypeCode == BfTypeCode_Extension)
- continue;
-
- mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_Full);
- }
- for (auto type : mContext->mResolvedTypes)
- {
- auto module = type->GetModule();
- if (module == NULL)
- continue;
- if ((type->IsIncomplete()) && (type->IsTypeInstance()) && (!type->IsSpecializedType()))
- {
- mSystem->CheckLockYield();
- module->PopulateType(type, BfPopulateType_Full);
- }
- auto typeInst = type->ToTypeInstance();
- if (typeInst == NULL)
- continue;
-
- if (typeInst->IsUnspecializedTypeVariation())
- continue;
- if (!typeInst->IsSpecializedType())
- {
- // Find any remaining methods for unreified processing
- for (auto&& methodInstGroup : typeInst->mMethodInstanceGroups)
- {
- if ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
- (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference))
- {
- queuedMoreMethods = true;
- if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mIsForeignMethodDef))
- {
- mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodInstGroup.mDefault->mMethodDef, BfTypeVector(),
- (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
- }
- else
- mContext->mUnreifiedModule->GetMethodInstance(typeInst, typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx], BfTypeVector(),
- (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
- }
- }
- }
- }
- if ((!queuedMoreMethods) && (startTypeInitCount == mTypeInitCount))
- break;
-
- DoWorkLoop();
- }
- bool didWork = false;
- UpdateDependencyMap(true, didWork);
- DoWorkLoop();
- mCompileState = BfCompiler::CompileState_Normal;
- }
- else
- {
- DoWorkLoop();
- }
-
- if (hasRequiredTypes)
- ProcessPurgatory(false);
-
- // Old Mark used modules
- if ((!mIsResolveOnly) && (hasRequiredTypes))
- {
- // if ((!mPassInstance->HasFailed()) && (!mCanceling))
- // {
- // if ((!IsHotCompile()) || (mHotState->mHasNewInterfaceTypes))
- // {
- // GenerateSlotNums();
- // if (mHotState != NULL)
- // mHotState->mHasNewInterfaceTypes = false;
- // }
- // }
- if ((!mPassInstance->HasFailed()) && (!mCanceling))
- {
- if (!mOptions.mAllowHotSwapping)
- {
- GenerateDynCastData();
- mContext->ProcessWorkList(false, false);
- }
- mCompileState = BfCompiler::CompileState_VData;
- for (auto vdataModule : mVDataModules)
- CreateVData(vdataModule);
- for (auto vdataModule : mVDataModules)
- FixVDataHash(vdataModule);
- mCompileState = BfCompiler::CompileState_Normal;
- }
- // Don't clear out unused string pool entries while we are hot swapping, because we want string literals
- // to still be the same pointer if it's erased and then put back
- if ((!IsHotCompile()) && (!mCanceling))
- ClearUnusedStringPoolEntries();
-
- mContext->UpdateAfterDeletingTypes();
- }
-
- // We need to check the specialized errors before writing out modules --
- // this call is responsible for deleting dead method specializations that contained errors, or for setting
- // the mHadBuildErrors on the module if there was a method specialization error that didn't die
- mContext->CheckSpecializedErrorData();
- mContext->Finish();
- if ((!mIsResolveOnly) && (!IsHotCompile()))
- ClearOldHotData();
-
- mPassInstance->TryFlushDeferredError();
- BpLeave();
- BpEnter("Compile_Finish");
-
- //TODO:!!
- //mCanceling = true;
- String moduleListStr;
- int numModulesWritten = 0;
- if ((hasRequiredTypes) && (!mCanceling))
- {
- if (!mIsResolveOnly)
- {
- int idx = 0;
-
- BF_ASSERT(mContext->mMethodWorkList.IsEmpty());
- //bfContext->mLockModules = true;
- for (int moduleIdx = 0; moduleIdx < (int)mContext->mModules.size(); moduleIdx++)
- {
- //bool clearModule = false;
- auto mainModule = mContext->mModules[moduleIdx];
- BfModule* bfModule = mainModule;
- if (bfModule->mIsReified)
- {
- auto itr = mainModule->mSpecializedMethodModules.begin();
- while (true)
- {
- if (bfModule->mIsModuleMutable)
- {
- //clearModule = true;
- // Note that Finish will just return immediately if we have errors, we don't write out modules with errors
- // The 'mLastModuleWrittenRevision' will not be updated in the case.
- bfModule->Finish();
- mainModule->mRevision = std::max(mainModule->mRevision, bfModule->mRevision);
- }
- if (bfModule->mLastModuleWrittenRevision == mRevision)
- {
- if (!moduleListStr.empty())
- moduleListStr += ", ";
- moduleListStr += bfModule->mModuleName;
- numModulesWritten++;
- }
- if (bfModule->mParentModule != NULL)
- {
- for (auto&& fileName : bfModule->mOutFileNames)
- {
- if (!mainModule->mOutFileNames.Contains(fileName))
- mainModule->mOutFileNames.push_back(fileName);
- }
- }
- if (bfModule->mNextAltModule != NULL)
- {
- bfModule = bfModule->mNextAltModule;
- }
- else
- {
- if (itr == mainModule->mSpecializedMethodModules.end())
- break;
- bfModule = itr->mValue;
- ++itr;
- }
- }
- }
-
- mainModule->ClearModule();
- }
- //bfContext->mLockModules = false;
- }
- else
- {
- bool isTargeted = (mResolvePassData != NULL) && (mResolvePassData->mParser != NULL);
- if (!isTargeted)
- {
- for (auto bfModule : mContext->mModules)
- {
- if (bfModule->mIsModuleMutable)
- {
- bfModule->Finish();
- bfModule->mRevision = std::max(bfModule->mRevision, bfModule->mRevision);
- bfModule->ClearModuleData();
- }
- }
- }
- }
- }
- /*if (!moduleListStr.empty())
- mPassInstance->OutputLine(StrFormat("%d modules generated: %s", numModulesWritten, moduleListStr.c_str()));*/
-
- //CompileLog("%d object files written: %s\n", numModulesWritten, moduleListStr.c_str());
-
- //printf("Compile done, waiting for finish\n");
- while (true)
- {
- if (!hasRequiredTypes)
- break;
- if (mCanceling)
- mCodeGen.Cancel();
- bool isDone = mCodeGen.Finish();
- UpdateCompletion();
- if (isDone)
- break;
- }
- mCodeGen.ProcessErrors(mPassInstance, mCanceling);
- // This has to happen after codegen because we may delete modules that are referenced in codegen
- mContext->Cleanup();
- if ((!IsHotCompile()) && (!mIsResolveOnly) && (!mCanceling))
- {
- // Only save 'saved type data' for temporarily-deleted types like on-demand types.
- // If we don't reuse it within a compilation pass then we put those IDs up to be
- // reused later. We don't do this for hot reloading because there are cases like
- // a user renaming a type that we want to allow him to be able to undo and then
- // hot-recompile successfully.
- for (auto& kv : mContext->mSavedTypeDataMap)
- {
- auto savedTypeData = kv.mValue;
- mTypeIdFreeList.Add(savedTypeData->mTypeId);
- delete savedTypeData;
- }
- mContext->mSavedTypeDataMap.Clear();
- mContext->mSavedTypeData.Clear();
- }
- #ifdef BF_PLATFORM_WINDOWS
- if (!mIsResolveOnly)
- {
- for (auto mainModule : mContext->mModules)
- {
- BfModule* bfModule = mainModule;
- if (bfModule->mIsReified)
- {
- for (auto outFileName : bfModule->mOutFileNames)
- {
- if (outFileName.mModuleWritten)
- BeLibManager::Get()->AddUsedFileName(outFileName.mFileName);
- }
- }
- }
- BeLibManager::Get()->Finish();
- }
- #endif
- int numObjFilesWritten = 0;
- for (auto& fileEntry : mCodeGen.mCodeGenFiles)
- {
- if (!fileEntry.mWasCached)
- numObjFilesWritten++;
- }
- mPassInstance->OutputLine(StrFormat(":low %d module%s built, %d object file%s generated",
- numModulesWritten, (numModulesWritten != 1) ? "s" : "",
- numObjFilesWritten, (numObjFilesWritten != 1) ? "s" : ""));
-
- BpLeave();
- mPassInstance->WriteErrorSummary();
- if ((mCanceling) && (!mIsResolveOnly))
- {
- mPassInstance->Fail("Build canceled");
- mContext->CancelWorkItems();
- CompileLog("Compile canceled\n");
- }
- BfLogSysM("TypesPopulated:%d MethodsDeclared:%d MethodsProcessed:%d Canceled? %d\n", mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
-
- UpdateCompletion();
- if ((!mIsResolveOnly) && (!mPassInstance->HasFailed()) && (!mCanceling))
- {
- //BF_ASSERT(mCompletionPct >= 0.99999f);
- }
-
- if (mCompileLogFP != NULL)
- {
- fclose(mCompileLogFP);
- mCompileLogFP = NULL;
- }
- UpdateCompletion();
- mStats.mTotalTypes = mContext->mResolvedTypes.mCount;
- String compileInfo;
- if (mIsResolveOnly)
- compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, mResolvePassData->mParser != NULL);
- compileInfo += StrFormat("TotalTypes:%d\nTypesPopulated:%d\nMethodsDeclared:%d\nMethodsProcessed:%d\nCanceled? %d\n", mStats.mTotalTypes, mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
- compileInfo += StrFormat("TypesPopulated:%d\n", mStats.mTypesPopulated);
- compileInfo += StrFormat("MethodDecls:%d\nMethodsProcessed:%d\nModulesStarted:%d\nModulesFinished:%d\n", mStats.mMethodDeclarations, mStats.mMethodsProcessed, mStats.mModulesFinished);
- BpEvent("CompileDone", compileInfo.c_str());
- if (mHotState != NULL)
- {
- for (auto& fileEntry : mCodeGen.mCodeGenFiles)
- {
- if (fileEntry.mWasCached)
- continue;
- mHotState->mQueuedOutFiles.Add(fileEntry);
- }
- if (!mPassInstance->HasFailed())
- {
- // Clear these out when we know we've compiled without error
- mHotState->mNewlySlottedTypeIds.Clear();
- mHotState->mSlotDefineTypeIds.Clear();
- }
- }
- mCompileState = BfCompiler::CompileState_None;
- // extern MemReporter gBEMemReporter;
- // extern int gBEMemReporterSize;
- // gBEMemReporter.Report();
- // int memReporterSize = gBEMemReporterSize;
- mLastRevisionAborted = mCanceling || !hasRequiredTypes;
- bool didCancel = mCanceling && hasRequiredTypes;
- mCanceling = false;
- return !didCancel;
- }
- bool BfCompiler::Compile(const StringImpl& outputDirectory)
- {
- bool success = DoCompile(outputDirectory);
- if (!success)
- return false;
- if (mPassInstance->HasFailed())
- return true;
- if (!mInterfaceSlotCountChanged)
- return true;
- BfLogSysM("Interface slot count increased. Rebuilding relevant modules.\n");
- mPassInstance->OutputLine("Interface slot count increased. Rebuilding relevant modules.");
- // Recompile with the increased slot count
- success = DoCompile(outputDirectory);
- BF_ASSERT(!mInterfaceSlotCountChanged);
- return success;
- }
- void BfCompiler::ClearResults()
- {
- BP_ZONE("BfCompiler::ClearResults");
- mCodeGen.ClearResults();
- }
- // Can should still leave the system in a state such that we when we save as much progress as possible while
- // still leaving the system in a state that the next attempt at compile will resume with a valid state
- // Canceling will still process the pending PopulateType calls but may leave items in the method worklist.
- // Note that Cancel is an async request to cancel
- void BfCompiler::Cancel()
- {
- mCanceling = true;
- mHadCancel = true;
- BfLogSysM("BfCompiler::Cancel\n");
- BpEvent("BfCompiler::Cancel", "");
- }
- //#define WANT_COMPILE_LOG
- void BfCompiler::CompileLog(const char* fmt ...)
- {
- #ifdef WANT_COMPILE_LOG
- if (mCompileLogFP == NULL)
- return;
- //static int lineNum = 0;
- //lineNum++;
-
- va_list argList;
- va_start(argList, fmt);
- String aResult = vformat(fmt, argList);
- va_end(argList);
- //aResult = StrFormat("%d ", lineNum) + aResult;
- fwrite(aResult.c_str(), 1, aResult.length(), mCompileLogFP);
- #endif
- }
- void BfCompiler::ReportMemory(MemReporter* memReporter)
- {
- AutoCrit crit(mSystem->mDataLock);
- {
- AutoMemReporter autoMemReporter(memReporter, "Context");
- mContext->ReportMemory(memReporter);
- }
- for (auto type : mContext->mResolvedTypes)
- {
- AutoMemReporter autoMemReporter(memReporter, "Types");
- type->ReportMemory(memReporter);
- }
- for (auto module : mContext->mModules)
- {
- AutoMemReporter autoMemReporter(memReporter, "Modules");
- module->ReportMemory(memReporter);
- }
- {
- AutoMemReporter autoMemReporter(memReporter, "ScratchModule");
- mContext->mScratchModule->ReportMemory(memReporter);
- }
-
- for (auto vdataModule : mVDataModules)
- {
- AutoMemReporter autoMemReporter(memReporter, "VDataModules");
- vdataModule->ReportMemory(memReporter);
- }
- if (mHotData != NULL)
- {
- AutoMemReporter autoMemReporter(memReporter, "HotData");
- memReporter->Add(sizeof(HotData));
- memReporter->AddMap(mHotData->mMethodMap);
- for (auto& kv : mHotData->mMethodMap)
- {
- memReporter->AddStr(kv.mKey);
- memReporter->Add(sizeof(BfHotMethod));
- memReporter->AddVec(kv.mValue->mReferences);
- }
- }
- if (mHotState != NULL)
- {
- AutoMemReporter autoMemReporter(memReporter, "HotState");
- memReporter->Add(sizeof(HotState));
- memReporter->AddVec(mHotState->mQueuedOutFiles, false);
- memReporter->AddHashSet(mHotState->mSlotDefineTypeIds, false);
- memReporter->AddHashSet(mHotState->mPendingDataChanges, false);
- memReporter->AddMap(mHotState->mDeletedTypeNameMap, false);
- for (auto& kv : mHotState->mDeletedTypeNameMap)
- {
- memReporter->AddStr(kv.mKey, false);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void BfCompiler::GenerateAutocompleteInfo()
- {
- BP_ZONE("BfCompiler::GetAutocompleteInfo");
-
- String& autoCompleteResultString = *gTLStrReturn.Get();
- autoCompleteResultString.Clear();
- auto _GetDocString = [&](BfCommentNode* commentNode, StringImpl& docString)
- {
- commentNode->ToString(docString);
- for (int i = 0; i < (int)docString.length(); i++)
- {
- char c = docString[i];
- if (c == '\n')
- docString[i] = '\x3';
- }
- };
- auto bfModule = mResolvePassData->mAutoComplete->mModule;
- if (bfModule != NULL)
- {
- auto autoComplete = mResolvePassData->mAutoComplete;
- if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
- return; // Already handled
- if (autoComplete->mResolveType == BfResolveType_GetVarType)
- {
- autoCompleteResultString = autoComplete->mVarTypeName;
- return;
- }
- if (autoComplete->mUncertain)
- autoCompleteResultString += "uncertain\n";
- if (autoComplete->mDefaultSelection.length() != 0)
- autoCompleteResultString += StrFormat("select\t%s\n", autoComplete->mDefaultSelection.c_str());
- auto _EncodeTypeDef = [] (BfTypeDef* typeDef)
- {
- String typeName = typeDef->mProject->mName + ":" + typeDef->mFullName.ToString();
- if (!typeDef->mGenericParamDefs.IsEmpty())
- typeName += StrFormat("`%d", (int)typeDef->mGenericParamDefs.size());
- return typeName;
- };
- if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
- {
- if (autoComplete->mDefTypeGenericParamIdx != -1)
- {
- autoCompleteResultString += StrFormat("typeGenericParam\t%d\n", autoComplete->mDefTypeGenericParamIdx);
- autoCompleteResultString += StrFormat("typeRef\t%s\n", _EncodeTypeDef(autoComplete->mDefType).c_str());
- }
- else if (autoComplete->mDefMethodGenericParamIdx != -1)
- {
- autoCompleteResultString += StrFormat("methodGenericParam\t%d\n", autoComplete->mDefMethodGenericParamIdx);
- autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
- }
- else if ((autoComplete->mReplaceLocalId != -1) && (autoComplete->mDefMethod != NULL))
- {
- autoCompleteResultString += StrFormat("localId\t%d\n", autoComplete->mReplaceLocalId);
- autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
- }
- else if (autoComplete->mDefField != NULL)
- {
- autoCompleteResultString += StrFormat("fieldRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefField->mIdx);
- }
- else if (autoComplete->mDefProp != NULL)
- {
- autoCompleteResultString += StrFormat("propertyRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefProp->mIdx);
- }
- else if (autoComplete->mDefMethod != NULL)
- {
- if (autoComplete->mDefMethod->mMethodType == BfMethodType_Ctor)
- autoCompleteResultString += StrFormat("ctorRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
- else
- autoCompleteResultString += StrFormat("methodRef\t%s\t%d\n", _EncodeTypeDef(autoComplete->mDefType).c_str(), autoComplete->mDefMethod->mIdx);
- }
- else if (autoComplete->mDefType != NULL)
- {
- autoCompleteResultString += StrFormat("typeRef\t%s\n", _EncodeTypeDef(autoComplete->mDefType).c_str());
- }
-
- if (autoComplete->mInsertEndIdx > 0)
- {
- if (mResolvePassData->mParser->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
- autoComplete->mInsertEndIdx--;
- }
- }
- const char* wantsDocEntry = NULL;
- if (!autoComplete->mDocumentationEntryName.IsEmpty())
- wantsDocEntry = autoComplete->mDocumentationEntryName.c_str();
- if (autoComplete->mInsertStartIdx != -1)
- {
- autoCompleteResultString += StrFormat("insertRange\t%d %d\n", autoComplete->mInsertStartIdx, autoComplete->mInsertEndIdx);
- }
- if ((autoComplete->mDefMethod == NULL) && (autoComplete->mGetDefinitionNode == NULL) && (autoComplete->mIsGetDefinition) && (autoComplete->mMethodMatchInfo != NULL))
- {
- // Take loc from methodMatchInfo
- if (autoComplete->mMethodMatchInfo->mInstanceList.size() > 0)
- {
- int bestIdx = autoComplete->mMethodMatchInfo->mBestIdx;
- auto typeInst = autoComplete->mMethodMatchInfo->mInstanceList[bestIdx].mTypeInstance;
- auto methodDef = autoComplete->mMethodMatchInfo->mInstanceList[bestIdx].mMethodDef;
- if (methodDef->mMethodDeclaration != NULL)
- {
- auto ctorDecl = BfNodeDynCast<BfConstructorDeclaration>(methodDef->mMethodDeclaration);
- if (ctorDecl != NULL)
- autoComplete->SetDefinitionLocation(ctorDecl->mThisToken);
- else
- autoComplete->SetDefinitionLocation(methodDef->GetMethodDeclaration()->mNameNode);
- }
- else // Just select type then
- autoComplete->SetDefinitionLocation(typeInst->mTypeDef->mTypeDeclaration->mNameNode);
- }
- }
- if (autoComplete->mGetDefinitionNode != NULL)
- {
- auto astNode = autoComplete->mGetDefinitionNode;
- auto bfSource = autoComplete->mGetDefinitionNode->GetSourceData()->ToParserData();
- if (bfSource != NULL)
- {
- int line = 0;
- int lineChar = 0;
- bfSource->GetLineCharAtIdx(astNode->GetSrcStart(), line, lineChar);
- autoCompleteResultString += StrFormat("defLoc\t%s\t%d\t%d\n", bfSource->mFileName.c_str(), line, lineChar);
- }
- }
- auto methodMatchInfo = autoComplete->mMethodMatchInfo;
- if ((methodMatchInfo != NULL) && (wantsDocEntry == NULL))
- {
- if (methodMatchInfo->mInstanceList.size() > 0)
- {
- String invokeInfoText;
- invokeInfoText += StrFormat("%d", methodMatchInfo->mBestIdx);
- for (int srcPosIdx = 0; srcPosIdx < (int) methodMatchInfo->mSrcPositions.size(); srcPosIdx++)
- invokeInfoText += StrFormat(" %d", methodMatchInfo->mSrcPositions[srcPosIdx]);
- autoCompleteResultString += "invokeInfo\t";
- autoCompleteResultString += invokeInfoText;
- autoCompleteResultString += "\n";
- }
- int idx = 0;
- for (auto& methodEntry : methodMatchInfo->mInstanceList)
- {
- String methodText;
- if (methodEntry.mPayloadEnumField != NULL)
- {
- auto payloadFieldDef = methodEntry.mPayloadEnumField->GetFieldDef();
- methodText += payloadFieldDef->mName;
- methodText += "(\x1";
- auto payloadType = methodEntry.mPayloadEnumField->mResolvedType;
- BF_ASSERT(payloadType->IsTuple());
- if (payloadType->IsTuple())
- {
- auto tupleType = (BfTupleType*)payloadType;
- for (int fieldIdx = 0; fieldIdx < (int)tupleType->mFieldInstances.size(); fieldIdx++)
- {
- auto fieldInstance = &tupleType->mFieldInstances[fieldIdx];
- auto fieldDef = fieldInstance->GetFieldDef();
- if (fieldIdx > 0)
- methodText += ",\x1 ";
- methodText += bfModule->TypeToString(fieldInstance->mResolvedType, BfTypeNameFlag_ResolveGenericParamNames);
- if (!fieldDef->IsUnnamedTupleField())
- {
- methodText += " ";
- if (fieldDef->mName.StartsWith("_"))
- methodText += fieldDef->mName.Substring(1);
- else
- methodText += fieldDef->mName;
- }
- }
- }
- methodText += "\x1)";
- }
- else
- {
- BfMethodInstance* methodInstance = NULL;
- if (methodEntry.mMethodDef->mIdx < 0)
- {
- for (auto localMethod : mContext->mLocalMethodGraveyard)
- {
- if (localMethod->mMethodDef == methodEntry.mMethodDef)
- {
- methodInstance = localMethod->mMethodInstanceGroup->mDefault;
- break;
- }
- }
- }
- else
- methodInstance = bfModule->GetRawMethodInstanceAtIdx(methodEntry.mTypeInstance, methodEntry.mMethodDef->mIdx);
- auto curMethodInstance = methodInstance;
- curMethodInstance = methodMatchInfo->mCurMethodInstance;
- SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(bfModule->mCurTypeInstance, methodMatchInfo->mCurTypeInstance);
- SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(bfModule->mCurMethodInstance, curMethodInstance);
- Array<String> genericMethodNameOverrides;
- Array<String>* genericMethodNameOverridesPtr = NULL;
- if (methodInstance->GetNumGenericArguments() != 0)
- {
- genericMethodNameOverridesPtr = &genericMethodNameOverrides;
- for (int methodGenericArgIdx = 0; methodGenericArgIdx < (int)methodInstance->GetNumGenericArguments(); methodGenericArgIdx++)
- {
- BfType* methodGenericArg = NULL;
- if (methodEntry.mGenericArguments.size() > 0)
- methodGenericArg = methodEntry.mGenericArguments[methodGenericArgIdx];
- String argName;
- if (methodGenericArg == NULL)
- argName = methodInstance->mMethodDef->mGenericParams[methodGenericArgIdx]->mName;
- else
- argName = bfModule->TypeToString(methodGenericArg, BfTypeNameFlag_ResolveGenericParamNames, NULL);
- genericMethodNameOverrides.push_back(argName);
- }
- }
- if (methodInstance->mMethodDef->mMethodType != BfMethodType_Ctor)
- {
- if (methodInstance->mReturnType != NULL)
- methodText += bfModule->TypeToString(methodInstance->mReturnType, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr);
- else
- methodText += BfTypeUtils::TypeToString(methodInstance->mMethodDef->mReturnTypeRef);
- methodText += " ";
- }
- if (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor)
- methodText += "this";
- else
- {
- auto methodName = methodInstance->mMethodDef->mName;
- int splitIdx = (int)methodName.IndexOf('@');
- if (splitIdx != -1)
- methodText += methodName.Substring(0, splitIdx);
- else
- methodText += methodName;
- }
- if (methodInstance->GetNumGenericArguments() != 0)
- {
- methodText += "<";
- for (int methodGenericArgIdx = 0; methodGenericArgIdx < (int)methodInstance->GetNumGenericArguments(); methodGenericArgIdx++)
- {
- if (methodGenericArgIdx > 0)
- methodText += ", ";
- methodText += genericMethodNameOverrides[methodGenericArgIdx];
- }
- methodText += ">";
- }
-
- //TODO: Show default param values also
- methodText += "(\x1";
- if (methodInstance->GetParamCount() == 0)
- {
- // Hm - is this ever useful? Messes up some cases actually
- // If param resolution failed then we need to print the original param def
- /*for (int paramIdx = 0; paramIdx < (int) methodInstance->mMethodDef->mParams.size(); paramIdx++)
- {
- if (paramIdx > 0)
- methodText += ",\x1 ";
- auto paramDef = methodInstance->mMethodDef->mParams[paramIdx];
- methodText += BfTypeUtils::TypeToString(paramDef->mTypeRef);
- methodText += " ";
- methodText += paramDef->mName;
- }*/
- }
- int dispParamIdx = 0;
- for (int paramIdx = 0; paramIdx < (int)methodInstance->GetParamCount(); paramIdx++)
- {
- auto paramKind = methodInstance->GetParamKind(paramIdx);
- if ((paramKind == BfParamKind_ImplicitCapture) || (paramKind == BfParamKind_AppendIdx))
- continue;
- if (dispParamIdx > 0)
- methodText += ",\x1 ";
- auto type = methodInstance->GetParamType(paramIdx);
- BfExpression* paramInitializer = methodInstance->GetParamInitializer(paramIdx);
- if (paramInitializer != NULL)
- methodText += "[";
- if (paramKind == BfParamKind_Params)
- methodText += "params ";
- if (type->IsGenericParam())
- {
- auto genericParamType = (BfGenericParamType*)type;
- if (genericParamType->mGenericParamKind == BfGenericParamKind_Method)
- {
- if (methodInstance->GetNumGenericParams() > 0)
- {
- auto genericParamInstance = methodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
- methodText += genericParamInstance->GetGenericParamDef()->mName;
- }
- else
- {
- BfMethodInstance* curMethodInstance = methodEntry.mCurMethodInstance;
- auto genericParamInstance = curMethodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
- methodText += genericParamInstance->GetGenericParamDef()->mName;
- }
- }
- else
- {
- BfGenericTypeInstance* genericType = (BfGenericTypeInstance*)methodEntry.mTypeInstance;
- auto genericParamInstance = genericType->mGenericParams[genericParamType->mGenericParamIdx];
- methodText += genericParamInstance->GetGenericParamDef()->mName;
- }
- }
- else
- methodText += bfModule->TypeToString(type, BfTypeNameFlag_ResolveGenericParamNames, genericMethodNameOverridesPtr);
- methodText += " ";
- methodText += methodInstance->GetParamName(paramIdx);
- if (paramInitializer != NULL)
- {
- methodText += " = ";
- methodText += paramInitializer->ToString();
- methodText += "]";
- }
- dispParamIdx++;
- }
- methodText += "\x1)";
- }
- if (methodEntry.mMethodDef != NULL)
- {
- auto methodDeclaration = methodEntry.mMethodDef->GetMethodDeclaration();
- if ((methodDeclaration != NULL) && (methodDeclaration->mDocumentation != NULL))
- {
- String docString;
- _GetDocString(methodDeclaration->mDocumentation, docString);
- methodText += "\x03";
- methodText += docString;
- }
- }
- autoCompleteResultString += "invoke\t" + methodText + "\n";
- idx++;
- }
- }
- Array<AutoCompleteEntry*> entries;
- for (auto& entry : autoComplete->mEntriesSet)
- {
- entries.Add(&entry);
- }
- std::sort(entries.begin(), entries.end(), [](AutoCompleteEntry* lhs, AutoCompleteEntry* rhs)
- {
- return stricmp(lhs->mDisplay, rhs->mDisplay) < 0;
- });
-
- String docString;
- for (auto entry : entries)
- {
- if ((wantsDocEntry != NULL) && (entry->mDocumentation == NULL))
- continue;
- autoCompleteResultString += String(entry->mEntryType);
- autoCompleteResultString += "\t";
- autoCompleteResultString += String(entry->mDisplay);
- if ((entry->mDocumentation != NULL) && (wantsDocEntry != NULL) && (strcmp(wantsDocEntry, entry->mDisplay) == 0))
- {
- docString.Clear();
- _GetDocString(entry->mDocumentation, docString);
- autoCompleteResultString += '\x03';
- autoCompleteResultString += docString;
- }
- autoCompleteResultString += "\n";
- }
- }
- }
- String BfCompiler::GetTypeDefList()
- {
- String result;
- BfProject* curProject = NULL;
- Dictionary<BfProject*, int> projectIds;
- for (auto typeDef : mSystem->mTypeDefs)
- {
- if (typeDef->mProject != curProject)
- {
- curProject = typeDef->mProject;
- int* projectIdPtr;
- if (projectIds.TryAdd(curProject, NULL, &projectIdPtr))
- {
- *projectIdPtr = (int)projectIds.size() - 1;
- result += "+";
- result += curProject->mName;
- result += "\n";
- }
- else
- {
- char str[32];
- sprintf(str, "=%d\n", *projectIdPtr);
- result += str;
- }
- }
-
- if (((!typeDef->mIsPartial) || (typeDef->mIsCombinedPartial)))
- {
- if (typeDef->IsGlobalsContainer())
- {
- result += "g";
- if (!typeDef->mNamespace.IsEmpty())
- {
- typeDef->mNamespace.ToString(result);
- result += ".";
- }
- result += ":static\n";
- continue;
- }
- else if (typeDef->mTypeCode == BfTypeCode_Interface)
- result += "i";
- else if (typeDef->mTypeCode == BfTypeCode_Object)
- result += "c";
- else
- result += "v";
- result += BfTypeUtils::TypeToString(typeDef) + "\n";
- }
- }
- return result;
- }
- struct TypeDefMatchHelper
- {
- public:
- StringImpl& mResult;
- Array<String> mSearch;
- uint32 mFoundFlags;
- int32 mFoundCount;
- bool mHasDotSearch;
- String mCurTypeName;
- String mTempStr;
- public:
- TypeDefMatchHelper(StringImpl& str) : mResult(str)
- {
- mFoundFlags = 0;
- mFoundCount = 0;
- mHasDotSearch = false;
- }
- void Sanitize(StringImpl& str)
- {
- for (int i = 0; i < (int)str.length(); i++)
- {
- char c = str[i];
- if (c < (char)32)
- {
- str[i] = ' ';
- }
- }
- }
- void AddParams(BfMethodDef* methodDef)
- {
- int visParamIdx = 0;
- for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size(); paramIdx++)
- {
- auto paramDef = methodDef->mParams[paramIdx];
- if ((paramDef->mParamKind == BfParamKind_AppendIdx) || (paramDef->mParamKind == BfParamKind_ImplicitCapture))
- continue;
- if (visParamIdx > 0)
- mResult += ", ";
- StringT<64> refName;
- paramDef->mTypeRef->ToString(refName);
- Sanitize(refName);
- mResult += refName;
- mResult += " ";
- mResult += paramDef->mName;
- visParamIdx++;
- }
- }
- void AddLocation(BfAstNode* node)
- {
- if (node == NULL)
- return;
- auto parserData = node->GetSourceData()->ToParserData();
- if (parserData != NULL)
- {
- mResult += parserData->mFileName;
- int lineNum = 0;
- int column = 0;
- parserData->GetLineCharAtIdx(node->GetSrcStart(), lineNum, column);
- mResult += StrFormat("\t%d\t%d", lineNum, column);
- }
- };
- void AddFieldDef(BfFieldDef* fieldDef)
- {
- mResult += "\t";
- AddLocation(fieldDef->GetRefNode());
- mResult += "\n";
- }
- void AddPropertyDef(BfTypeDef* typeDef, BfPropertyDef* propDef)
- {
- if (propDef->mName == "[]")
- {
- mResult += "[";
- for (auto methodDef : propDef->mMethods)
- {
- if (methodDef->mMethodType == BfMethodType_PropertyGetter)
- {
- AddParams(methodDef);
- break;
- }
- }
- mResult += "]";
- }
- else
- mResult += propDef->mName;
- mResult += "\t";
- auto refNode = propDef->GetRefNode();
- if (refNode == NULL)
- refNode = typeDef->GetRefNode();
- AddLocation(refNode);
- mResult += "\n";
- }
- void AddMethodDef(BfMethodDef* methodDef)
- {
- if (methodDef->mMethodType == BfMethodType_Ctor)
- {
- if (methodDef->mIsStatic)
- mResult += "static ";
- mResult += "this";
- }
- else if (methodDef->mMethodType == BfMethodType_Dtor)
- {
- if (methodDef->mIsStatic)
- mResult += "static ";
- mResult += "~this";
- }
- else
- mResult += methodDef->mName;
- if (methodDef->mMethodType == BfMethodType_Mixin)
- mResult += "!";
- mResult += "(";
- AddParams(methodDef);
- mResult += ")";
- mResult += "\t";
- AddLocation(methodDef->GetRefNode());
- mResult += "\n";
- }
- void ClearResults()
- {
- mFoundFlags = 0;
- mFoundCount = 0;
- }
- bool MergeFlags(uint32 flags)
- {
- int flagIdx = 0;
- while (flags > 0)
- {
- if (((flags & 1) != 0) && ((mFoundFlags & (1 << flagIdx)) == 0))
- {
- mFoundFlags |= (1 << flagIdx);
- mFoundCount++;
- }
- flags >>= 1;
- flagIdx++;
- }
- return mFoundCount == mSearch.mSize;
- }
- uint32 CheckMatch(const StringView& str)
- {
- uint32 matchFlags = 0;
- for (int i = 0; i < mSearch.mSize; i++)
- {
- if (((mFoundFlags & (1 << i)) == 0) && (str.IndexOf(mSearch[i], true) != -1))
- {
- mFoundCount++;
- matchFlags |= (1 << i);
- mFoundFlags |= (1 << i);
- }
- }
- return matchFlags;
- }
- bool CheckCompletesMatch(BfAtomComposite& name)
- {
- for (int i = 0; i < name.mSize; i++)
- {
- CheckMatch(name.mParts[i]->mString);
- if (mFoundCount == mSearch.mSize)
- return true;
- }
- return false;
- }
- bool IsFullMatch()
- {
- return mFoundCount == mSearch.mSize;
- }
-
- bool CheckMemberMatch(BfTypeDef* typeDef, const StringView& str)
- {
- if (CheckMatch(str) == 0)
- {
- if (mHasDotSearch)
- {
- mTempStr.Clear();
- mTempStr += mCurTypeName;
- mTempStr += ".";
- mTempStr += str;
- if (CheckMatch(mTempStr) == 0)
- return false;
- }
- else
- return false;
- }
- if ((IsFullMatch()) || (CheckCompletesMatch(typeDef->mFullName)))
- return true;
- return false;
- }
- };
- String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr)
- {
- String result;
- TypeDefMatchHelper matchHelper(result);
- //
- {
- int searchIdx = 0;
- while (searchIdx < (int)searchStr.length())
- {
- int spacePos = (int)searchStr.IndexOf(' ', searchIdx);
- String str;
- if (spacePos == -1)
- str = searchStr.Substring(searchIdx);
- else
- str = searchStr.Substring(searchIdx, spacePos - searchIdx);
- str.Trim();
- if (!str.IsEmpty())
- matchHelper.mSearch.Add(str);
- if (str.Contains('.'))
- matchHelper.mHasDotSearch = true;
- if (spacePos == -1)
- break;
- searchIdx = spacePos + 1;
- }
- //// We sort from longest to shortest to make sure longer strings match before shorter, which
- //// matters when the shorter string is a subset of the longer string
- //matchHelper.mSearch.Sort([](const String& lhs, const String& rhs)
- // {
- // int lenCmp = (int)(rhs.length() - lhs.length());
- // if (lenCmp != 0)
- // return lenCmp < 0;
- // return lhs < rhs;
- // });
- }
- BfProject* curProject = NULL;
- Dictionary<BfProject*, int> projectIds;
- Dictionary<BfAtom*, int> atomMatchMap;
- struct ProjectInfo
- {
- Dictionary<String, int> matchedNames;
- };
- Array<ProjectInfo> projectInfos;
- projectInfos.Resize(mSystem->mProjects.size());
-
- String typeName;
- String foundName;
- int partialIdx = 0;
- for (auto typeDef : mSystem->mTypeDefs)
- {
- if (typeDef->mIsPartial)
- continue;
- bool fullyMatchesName = false;
- if (matchHelper.mHasDotSearch)
- {
- matchHelper.mCurTypeName.Clear();
- typeDef->mFullName.ToString(matchHelper.mCurTypeName);
-
- matchHelper.ClearResults();
- matchHelper.CheckMatch(matchHelper.mCurTypeName);
- fullyMatchesName = matchHelper.IsFullMatch();
- }
- int matchIdx = -1;
- //BfAtomComposite foundComposite;
- if (!fullyMatchesName)
- {
- for (auto fieldDef : typeDef->mFields)
- {
- matchHelper.ClearResults();
- bool hasMatch = false;
- if (matchHelper.CheckMemberMatch(typeDef, fieldDef->mName))
- {
- result += "F";
- if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
- result += ".";
- result += fieldDef->mName;
- matchHelper.AddFieldDef(fieldDef);
- }
- }
- for (auto propDef : typeDef->mProperties)
- {
- if (propDef->GetRefNode() == NULL)
- continue;
- matchHelper.ClearResults();
- if (matchHelper.CheckMemberMatch(typeDef, propDef->mName))
- {
- result += "P";
- if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
- result += ".";
- matchHelper.AddPropertyDef(typeDef, propDef);
- }
- }
- for (auto methodDef : typeDef->mMethods)
- {
- if ((methodDef->mMethodType != BfMethodType_Normal) &&
- (methodDef->mMethodType != BfMethodType_Mixin) &&
- (methodDef->mMethodType != BfMethodType_Ctor) &&
- (methodDef->mMethodType != BfMethodType_Dtor))
- continue;
- if (methodDef->mMethodDeclaration == NULL)
- continue;
- matchHelper.ClearResults();
- if (matchHelper.CheckMemberMatch(typeDef, methodDef->mName))
- {
- result += "M";
- if (BfTypeUtils::TypeToString(result, typeDef, BfTypeNameFlag_HideGlobalName))
- result += ".";
- matchHelper.AddMethodDef(methodDef);
- }
- }
-
- uint32 matchFlags = 0;
- for (int atomIdx = typeDef->mFullName.mSize - 1; atomIdx >= 0; atomIdx--)
- {
- auto atom = typeDef->mFullName.mParts[atomIdx];
- int* matchesPtr = NULL;
- if (atomMatchMap.TryAdd(atom, NULL, &matchesPtr))
- {
- matchHelper.ClearResults();
- *matchesPtr = matchHelper.CheckMatch(atom->mString);
- }
- if (*matchesPtr != 0)
- {
- if (matchIdx == -1)
- matchIdx = atomIdx;
- matchFlags |= *matchesPtr;
- }
- }
- matchHelper.ClearResults();
- if (!matchHelper.MergeFlags(matchFlags))
- {
- continue;
- }
-
- //foundComposite.Set(typeDef->mFullName.mParts, matchIdx + 1, NULL, 0);
- //foundComposite = typeDef->mFullName;
- }
-
- if (typeDef->mProject != curProject)
- {
- curProject = typeDef->mProject;
- int* projectIdPtr;
- if (projectIds.TryAdd(curProject, NULL, &projectIdPtr))
- {
- *projectIdPtr = (int)projectIds.size() - 1;
- result += "+";
- result += curProject->mName;
- result += "\n";
- }
- else
- {
- char str[32];
- sprintf(str, "=%d\n", *projectIdPtr);
- result += str;
- }
- }
- typeName = BfTypeUtils::TypeToString(typeDef);
- if (matchIdx != -1)
- {
- int* matchIdxPtr = 0;
- auto projectInfo = &projectInfos[typeDef->mProject->mIdx];
- int dotCount = 0;
- foundName = typeName;
- for (int i = 0; i < (int)typeName.length(); i++)
- {
- if (typeName[i] == '.')
- {
- if (dotCount == matchIdx)
- {
- foundName.Clear();
- foundName.Append(typeName.c_str(), i);
- break;
- }
- dotCount++;
- }
- }
- if (projectInfo->matchedNames.TryAdd(foundName, NULL, &matchIdxPtr))
- {
- *matchIdxPtr = partialIdx++;
- result += StrFormat(">%d@", matchIdx);
- }
- else
- {
- result += StrFormat("<%d@", *matchIdxPtr);
- }
- }
- else
- {
- result += ":";
- }
-
- if (typeDef->IsGlobalsContainer())
- {
- result += "g";
- if (!typeDef->mNamespace.IsEmpty())
- {
- typeDef->mNamespace.ToString(result);
- result += ".";
- }
- result += ":static\n";
- continue;
- }
- else if (typeDef->mTypeCode == BfTypeCode_Interface)
- result += "i";
- else if (typeDef->mTypeCode == BfTypeCode_Object)
- result += "c";
- else
- result += "v";
- result += typeName + "\n";
- }
- return result;
- }
- String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
- {
- BfProject* project = NULL;
- int idx = 0;
- int sep = (int)inTypeName.IndexOf(':');
- if (sep != -1)
- {
- idx = sep + 1;
- project = mSystem->GetProject(inTypeName.Substring(0, sep));
- }
- String typeName;
- int genericCount = 0;
- int pendingGenericCount = 0;
- for ( ; idx < (int)inTypeName.length(); idx++)
- {
- char c = inTypeName[idx];
- if (c == '<')
- genericCount = 1;
- else if (genericCount > 0)
- {
- if (c == ',')
- genericCount++;
- else if (c == '>')
- {
- pendingGenericCount = genericCount;
- genericCount = 0;
- }
- }
- else
- {
- if (pendingGenericCount != 0)
- {
- typeName += StrFormat("`%d", pendingGenericCount);
- pendingGenericCount = 0;
- }
- typeName += c;
- }
- }
-
- bool isGlobals = false;
- if (typeName == ":static")
- {
- typeName.clear();
- isGlobals = true;
- }
- if (typeName.EndsWith(".:static"))
- {
- typeName.RemoveToEnd(typeName.length() - 8);
- isGlobals = true;
- }
-
- String result;
- TypeDefMatchHelper matchHelper(result);
-
- BfAtomComposite nameComposite;
- if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
- {
- auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
- while (itr)
- {
- auto typeDef = *itr;
- if ((!typeDef->mIsPartial) &&
- (typeDef->mProject == project) &&
- (typeDef->mFullName == nameComposite) &&
- (typeDef->IsGlobalsContainer() == isGlobals) &&
- (typeDef->GetSelfGenericParamCount() == pendingGenericCount))
- {
- auto refNode = typeDef->GetRefNode();
- result += "S";
- matchHelper.AddLocation(refNode);
- result += "\n";
- for (auto fieldDef : typeDef->mFields)
- {
- result += "F";
- result += fieldDef->mName;
- matchHelper.AddFieldDef(fieldDef);
- }
- for (auto propDef : typeDef->mProperties)
- {
- if (propDef->GetRefNode() == NULL)
- continue;
- result += "P";
- matchHelper.AddPropertyDef(typeDef, propDef);
- }
- for (auto methodDef : typeDef->mMethods)
- {
- if ((methodDef->mMethodType != BfMethodType_Normal) &&
- (methodDef->mMethodType != BfMethodType_Mixin) &&
- (methodDef->mMethodType != BfMethodType_Ctor) &&
- (methodDef->mMethodType != BfMethodType_Dtor))
- continue;
- if (methodDef->mMethodDeclaration == NULL)
- continue;
- result += "M";
- matchHelper.AddMethodDef(methodDef);
- }
- }
- itr.MoveToNextHashMatch();
- }
- }
- return result;
- }
- //////////////////////////////////////////////////////////////////////////
- PerfManager* BfGetPerfManager(BfParser* bfParser);
- /*BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetDefaultTargetTriple(BfCompiler* bfCompiler)
- {
- String& autoCompleteResultString = *gTLStrReturn.Get();
- return autoCompleteResultString.c_str();
- }*/
- BF_EXPORT bool BF_CALLTYPE BfCompiler_Compile(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, const char* outputPath)
- {
- BP_ZONE("BfCompiler_Compile");
-
- SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
- bfCompiler->mPassInstance = bfPassInstance;
- bfCompiler->Compile(outputPath);
- return !bfCompiler->mPassInstance->HasFailed();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_ClearResults(BfCompiler* bfCompiler)
- {
- bfCompiler->ClearResults();
- }
- BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfParser* bfParser, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
- {
- BP_ZONE("BfCompiler_ClassifySource");
- BfSourceClassifier bfSourceClassifier(bfParser, charData);
- bfSourceClassifier.mClassifierPassId = bfPassInstance->mClassifierPassId;
-
- String& autoCompleteResultString = *gTLStrReturn.Get();
- autoCompleteResultString.clear();
- bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
- bfSourceClassifier.mEnabled = doClassifyPass;
- // Full classifier pass?
-
- bfSourceClassifier.mSkipMethodInternals = true;
- bfSourceClassifier.mSkipTypeDeclarations = true;
- if ((charData != NULL) && (doClassifyPass))
- bfSourceClassifier.Visit(bfParser->mRootNode);
- bfSourceClassifier.mSkipTypeDeclarations = false;
- bfSourceClassifier.mSkipMethodInternals = false;
-
-
- if (charData != NULL)
- resolvePassData->mSourceClassifier = &bfSourceClassifier;
- bfPassInstance->mFilterErrorsTo = bfParser;
- bfPassInstance->mTrimMessagesToCursor = true;
- SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
- SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
- bool canceled = false;
- if (resolvePassData->mAutoComplete != NULL)
- {
- bfCompiler->ProcessAutocompleteTempType();
- }
- else
- canceled = !bfCompiler->Compile("");
- resolvePassData->mSourceClassifier = NULL;
-
- if ((charData != NULL) && (doClassifyPass))
- {
- bfSourceClassifier.mIsSideChannel = false;
- bfSourceClassifier.Visit(bfParser->mErrorRootNode);
- bfSourceClassifier.mIsSideChannel = true;
- bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);
- }
- return !canceled;
- }
- BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, char* name, int cursorPos)
- {
- String typeName = name;
- auto system = bfCompiler->mSystem;
- AutoCrit autoCrit(system->mSystemLock);
- String& autoCompleteResultString = *gTLStrReturn.Get();
- autoCompleteResultString.Clear();
- BfPassInstance passInstance(bfCompiler->mSystem);
- BfParser parser(bfCompiler->mSystem);
- parser.SetSource(typeName.c_str(), (int)typeName.length());
- parser.Parse(&passInstance);
- parser.mCursorIdx = cursorPos;
- parser.mCursorCheckIdx = cursorPos;
- BfReducer reducer;
- reducer.mAlloc = parser.mAlloc;
- reducer.mPassInstance = &passInstance;
- reducer.mAllowTypeWildcard = true;
-
- if (parser.mRootNode->mChildArr.mSize == 0)
- return false;
- bool attribWasClosed = false;
- bool isAttributeRef = false;
- auto firstNode = parser.mRootNode->mChildArr[0];
- auto endIdx = parser.mRootNode->mSrcEnd;
- reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
- if (auto tokenNode = BfNodeDynCast<BfTokenNode>(firstNode))
- {
- if (tokenNode->mToken == BfToken_LBracket)
- {
- if (auto lastToken = BfNodeDynCast<BfTokenNode>(parser.mRootNode->mChildArr.back()))
- {
- if (lastToken->mToken == BfToken_RBracket)
- {
- attribWasClosed = true;
- endIdx = lastToken->mSrcStart;
- }
- }
- isAttributeRef = true;
- if (parser.mRootNode->mChildArr.mSize < 2)
- return false;
- firstNode = parser.mRootNode->mChildArr[1];
- reducer.mVisitorPos.MoveNext();
- }
- }
-
- reducer.mVisitorPos.MoveNext();
- auto typeRef = reducer.CreateTypeRef(firstNode);
- if (typeRef == NULL)
- return false;
- BfResolvePassData resolvePassData;
- if (cursorPos != -1)
- {
- resolvePassData.mResolveType = BfResolveType_Autocomplete;
- parser.mParserFlags = (BfParserFlag)(parser.mParserFlags | ParserFlag_Autocomplete);
- resolvePassData.mAutoComplete = new BfAutoComplete();
- resolvePassData.mAutoComplete->mSystem = bfCompiler->mSystem;
- resolvePassData.mAutoComplete->mCompiler = bfCompiler;
- resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule;
- }
- resolvePassData.mParser = &parser;
-
- SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, &resolvePassData);
- SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &passInstance);
- if (resolvePassData.mAutoComplete != NULL)
- {
- if (isAttributeRef)
- resolvePassData.mAutoComplete->CheckAttributeTypeRef(typeRef);
- else
- resolvePassData.mAutoComplete->CheckTypeRef(typeRef, false);
- bfCompiler->GenerateAutocompleteInfo();
- }
- if (passInstance.HasFailed())
- return false;
- if (typeRef->mSrcEnd != endIdx)
- return false;
- if (!bfCompiler->mContext->mScratchModule->ValidateTypeWildcard(typeRef, isAttributeRef))
- return false;
- if ((isAttributeRef) && (!attribWasClosed))
- return false;
- return true;
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_ClearCompletionPercentage(BfCompiler* bfCompiler)
- {
- bfCompiler->mCompletionPct = 0;
- }
- BF_EXPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(BfCompiler* bfCompiler)
- {
- return bfCompiler->mCompletionPct;
- }
- BF_EXPORT int BF_CALLTYPE BfCompiler_GetCompileRevision(BfCompiler* bfCompiler)
- {
- return bfCompiler->mRevision;
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler)
- {
- bfCompiler->Cancel();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(BfCompiler* bfCompiler)
- {
- bfCompiler->ClearBuildCache();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_SetBuildValue(BfCompiler* bfCompiler, char* cacheDir, char* key, char* value)
- {
- bfCompiler->mCodeGen.SetBuildValue(cacheDir, key, value);
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetBuildValue(BfCompiler* bfCompiler, char* cacheDir, char* key)
- {
- String& outString = *gTLStrReturn.Get();
- outString = bfCompiler->mCodeGen.GetBuildValue(cacheDir, key);
- return outString.c_str();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_WriteBuildCache(BfCompiler* bfCompiler, char* cacheDir)
- {
- bfCompiler->mCodeGen.WriteBuildCache(cacheDir);
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_Delete(BfCompiler* bfCompiler)
- {
- delete bfCompiler;
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone()
- {
- #ifdef BF_PLATFORM_WINDOWS
- BeLibManager::Get()->Clear();
- #endif
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler)
- {
- String& outString = *gTLStrReturn.Get();
- outString.clear();
- outString = bfCompiler->GetTypeDefList();
- return outString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefMatches(BfCompiler* bfCompiler, const char* searchStr)
- {
- String& outString = *gTLStrReturn.Get();
- outString.clear();
- outString = bfCompiler->GetTypeDefMatches(searchStr);
- return outString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompiler, const char* typeDefName)
- {
- String& outString = *gTLStrReturn.Get();
- outString.clear();
- outString = bfCompiler->GetTypeDefInfo(typeDefName);
- return outString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool* hadOutputChanges)
- {
- BF_FATAL("not used ?");
- *hadOutputChanges = false;
- String& outString = *gTLStrReturn.Get();
- outString.clear();
- for (auto mainModule : bfCompiler->mContext->mModules)
- {
- if (!mainModule->mIsReified)
- continue;
- if (mainModule->mProject != bfProject)
- continue;
- if (bfCompiler->mOptions.mHotProject != NULL)
- continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
-
- for (auto&& moduleFileName : mainModule->mOutFileNames)
- {
- if (!moduleFileName.mModuleWritten)
- continue;
- if (!outString.empty())
- outString += "\n";
- outString += moduleFileName.mFileName;
- }
- }
-
- if (bfCompiler->mHotState != NULL)
- {
- Array<String> outPaths;
- for (int i = 0; i < (int)bfCompiler->mHotState->mQueuedOutFiles.size(); i++)
- {
- auto& fileEntry = bfCompiler->mHotState->mQueuedOutFiles[i];
- if (fileEntry.mProject != bfProject)
- continue;
- outPaths.Add(fileEntry.mFileName);
- bfCompiler->mHotState->mQueuedOutFiles.RemoveAtFast(i);
- i--;
- }
- //outPaths.Sort();
- std::sort(outPaths.begin(), outPaths.end(), [](const String& lhs, const String& rhs) { return lhs < rhs; });
- for (auto& path : outPaths)
- {
- if (!outString.empty())
- outString += "\n";
- outString += path;
- outString += BF_OBJ_EXT;
- }
- }
- return outString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges)
- {
- BP_ZONE("BfCompiler_GetUsedOutputFileNames");
- *hadOutputChanges = false;
- String& outString = *gTLStrReturn.Get();
- outString.clear();
-
- Array<BfModule*> moduleList;
- moduleList.Reserve(bfProject->mUsedModules.size());
- if (bfCompiler->mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
- {
- for (auto mainModule : bfCompiler->mContext->mModules)
- {
- if ((!mainModule->mIsReified) || (mainModule->mIsScratchModule))
- continue;
- if (bfCompiler->mOptions.mHotProject != NULL)
- continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
- if (!bfCompiler->IsModuleAccessible(mainModule, bfProject))
- continue;
-
- moduleList.push_back(mainModule);
- }
- }
- else
- {
- for (auto mainModule : bfProject->mUsedModules)
- {
- if ((!mainModule->mIsReified) || (mainModule->mIsScratchModule))
- continue;
- if (bfCompiler->mOptions.mHotProject != NULL)
- continue; // Only add new objs from mCodeGen.mCodeGenFiles during hot reload
- moduleList.push_back(mainModule);
- }
- }
- std::sort(moduleList.begin(), moduleList.end(), [&](BfModule* moduleA, BfModule* moduleB) { return moduleA->mModuleName < moduleB->mModuleName; } );
- HashSet<String> usedFileNames;
- usedFileNames.Reserve(moduleList.size());
- for (auto mainModule : moduleList)
- {
- for (auto fileNameIdx : mainModule->mImportFileNames)
- {
- auto fileName = bfCompiler->mContext->mStringObjectIdMap[fileNameIdx].mString;
- if (!usedFileNames.TryAdd(fileName, NULL))
- continue;
- if (!outString.empty())
- outString += "\n";
- outString += fileName;
- }
- for (auto&& moduleFileName : mainModule->mOutFileNames)
- {
- if (!moduleFileName.mModuleWritten)
- continue;
- bool canReference = true;
- for (auto project : moduleFileName.mProjects)
- {
- if (!bfProject->ContainsReference(project))
- canReference = false;
- if (bfProject != project)
- {
- if (project->mTargetType == BfTargetType_BeefDynLib)
- canReference = false;
- }
- }
- if (!canReference)
- continue;
-
- String fileName = moduleFileName.mFileName;
- #ifdef BF_PLATFORM_WINDOWS
- if (moduleFileName.mWroteToLib)
- fileName = BeLibManager::GetLibFilePath(fileName);
- #endif
- if (!usedFileNames.TryAdd(fileName, NULL))
- continue;
- if (!outString.empty())
- outString += "\n";
- outString += fileName;
- if (mainModule->mWroteToLib)
- break;
- }
- }
- if (bfCompiler->mHotState != NULL)
- {
- Array<String> outPaths;
- for (int i = 0; i < (int)bfCompiler->mHotState->mQueuedOutFiles.size(); i++)
- {
- auto& fileEntry = bfCompiler->mHotState->mQueuedOutFiles[i];
- if (fileEntry.mProject != bfProject)
- continue;
- if (!bfCompiler->mHotState->mHotProject->mUsedModules.Contains(fileEntry.mModule))
- continue;
- outPaths.Add(fileEntry.mFileName);
- if (flushQueuedHotFiles)
- {
- bfCompiler->mHotState->mQueuedOutFiles.RemoveAtFast(i);
- i--;
- }
- }
- std::sort(outPaths.begin(), outPaths.end(), [](const String& lhs, const String& rhs) { return lhs < rhs; });
- for (auto& path : outPaths)
- {
- if (!outString.empty())
- outString += "\n";
- outString += path;
- outString += BF_OBJ_EXT;
- }
- }
- for (auto& fileEntry : bfCompiler->mCodeGen.mCodeGenFiles)
- {
- if (fileEntry.mWasCached)
- continue;
- if (!bfProject->ContainsReference(fileEntry.mProject))
- continue;
- *hadOutputChanges = true;
- }
- return outString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetAutocompleteInfo(BfCompiler* bfCompiler)
- {
- String& autoCompleteResultString = *gTLStrReturn.Get();
- return autoCompleteResultString.c_str();
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetSymbolReferences(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData)
- {
- BP_ZONE("BfCompiler_GetSymbolReferences");
- String& outString = *gTLStrReturn.Get();
- outString.clear();
- SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
- SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
- bfCompiler->GetSymbolReferences();
- std::map<String, String*> sortedParserMap;
- for (auto& parserDataPair : resolvePassData->mFoundSymbolReferencesParserData)
- {
- sortedParserMap.insert(std::make_pair(parserDataPair.mKey->mFileName, &parserDataPair.mValue));
- }
- for (auto& parserData : sortedParserMap)
- {
- if (!outString.empty())
- outString += "\n";
- outString += parserData.first + "\t" + *(parserData.second);
- }
- return outString.c_str();
- }
- BF_EXPORT bool BF_CALLTYPE BfCompiler_GetHasHotPendingDataChanges(BfCompiler* bfCompiler)
- {
- return (bfCompiler->mHotState != NULL) &&
- ((!bfCompiler->mHotState->mPendingDataChanges.IsEmpty()) || (!bfCompiler->mHotState->mPendingFailedSlottings.IsEmpty()));
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotCommit(BfCompiler* bfCompiler)
- {
- bfCompiler->HotCommit();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_Start(BfCompiler* bfCompiler, int flags)
- {
- bfCompiler->HotResolve_Start((BfCompiler::HotResolveFlags)flags);
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_AddActiveMethod(BfCompiler* bfCompiler, const char* methodName)
- {
- bfCompiler->HotResolve_AddActiveMethod(methodName);
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_AddDelegateMethod(BfCompiler* bfCompiler, const char* methodName)
- {
- bfCompiler->HotResolve_AddDelegateMethod(methodName);
- }
- // 0: heap, 1: user stated 'not used', 2: user stated 'used'
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_ReportType(BfCompiler* bfCompiler, int typeId, int usageKind)
- {
- bfCompiler->HotResolve_ReportType(typeId, (BfCompiler::HotTypeFlags)usageKind);
- }
- // 0: heap, 1: user stated 'used', 2: user stated 'not used'
- BF_EXPORT void BF_CALLTYPE BfCompiler_HotResolve_ReportTypeRange(BfCompiler* bfCompiler, const char* typeName, int usageKind)
- {
- //TODO: Implement
- }
- BF_EXPORT const char* BF_CALLTYPE BfCompiler_HotResolve_Finish(BfCompiler* bfCompiler)
- {
- String& outString = *gTLStrReturn.Get();
- outString = bfCompiler->HotResolve_Finish();
- return outString.c_str();
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(BfCompiler* bfCompiler, BfProject* hotProject, int hotIdx,
- const char* targetTriple, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads,
- BfCompilerOptionFlags optionFlags, char* mallocLinkName, char* freeLinkName)
- {
- BfLogSys(bfCompiler->mSystem, "BfCompiler_SetOptions\n");
- //printf("BfCompiler_SetOptions Threads:%d\n", maxWorkerThreads);
-
- auto options = &bfCompiler->mOptions;
-
- options->mErrorString.Clear();
- options->mHotProject = hotProject;
- options->mHotCompileIdx = hotIdx;
- options->mTargetTriple = targetTriple;
- if (options->mTargetTriple.StartsWith("x86_64-"))
- options->mMachineType = BfMachineType_x64;
- else if (options->mTargetTriple.StartsWith("i686-"))
- options->mMachineType = BfMachineType_x86;
- else
- options->mMachineType = BfMachineType_x64; // Default
- bfCompiler->mCodeGen.SetMaxThreads(maxWorkerThreads);
- if (!bfCompiler->mIsResolveOnly)
- {
- bool allowHotSwapping = (optionFlags & BfCompilerOptionFlag_EnableHotSwapping) != 0;
- bool emitDebugInfo = (optionFlags & BfCompilerOptionFlag_EmitDebugInfo) != 0;
- // These settings only matter for code generation, they are not applicable for resolveOnly
- options->mCompileOnDemandKind = BfCompileOnDemandKind_ResolveUnused;
- //options->mCompileOnDemandKind = BfCompileOnDemandKind_AlwaysInclude;
- options->mToolsetType = (BfToolsetType)toolsetType;
- options->mSIMDSetting = (BfSIMDSetting)simdSetting;
- options->mIncrementalBuild = (optionFlags & BfCompilerOptionFlag_IncrementalBuild) != 0;
- options->mWriteIR = (optionFlags & BfCompilerOptionFlag_WriteIR) != 0;
- options->mGenerateObj = (optionFlags & BfCompilerOptionFlag_GenerateOBJ) != 0;
- options->mNoFramePointerElim = (optionFlags & BfCompilerOptionFlag_NoFramePointerElim) != 0;
- options->mInitLocalVariables = (optionFlags & BfCompilerOptionFlag_ClearLocalVars) != 0;
- options->mRuntimeChecks = (optionFlags & BfCompilerOptionFlag_RuntimeChecks) != 0;
- options->mEmitDynamicCastCheck = (optionFlags & BfCompilerOptionFlag_EmitDynamicCastCheck) != 0;
- options->mObjectHasDebugFlags = (optionFlags & BfCompilerOptionFlag_EnableObjectDebugFlags) != 0;
- options->mEnableRealtimeLeakCheck = ((optionFlags & BfCompilerOptionFlag_EnableRealtimeLeakCheck) != 0) && options->mObjectHasDebugFlags;
- options->mDebugAlloc = ((optionFlags & BfCompilerOptionFlag_DebugAlloc) != 0) || options->mEnableRealtimeLeakCheck;
- options->mOmitDebugHelpers = (optionFlags & BfCompilerOptionFlag_OmitDebugHelpers) != 0;
- #ifdef _WINDOWS
- if (options->mToolsetType == BfToolsetType_GNU)
- {
- options->mErrorString = "Toolset 'GNU' is not available on this platform. Consider changing 'Workspace/General/Toolset'.";
- }
- #else
- if (options->mToolsetType == BfToolsetType_Microsoft)
- {
- options->mErrorString = "Toolset 'Microsoft' is not available on this platform. Consider changing 'Workspace/General/Toolset'.";
- }
- BF_ASSERT(!options->mEnableRealtimeLeakCheck);
- #endif
- options->mEmitObjectAccessCheck = (optionFlags & BfCompilerOptionFlag_EmitDebugInfo) != 0;
- options->mAllocStackCount = allocStackCount;
-
- if (hotProject != NULL)
- {
- String errorName;
- if (options->mAllowHotSwapping != allowHotSwapping)
- errorName = "Hot Compilation Enabled";
- else if (options->mMallocLinkName != mallocLinkName)
- errorName = "Malloc";
- else if (options->mFreeLinkName != freeLinkName)
- errorName = "Free";
- if (!options->mEmitDebugInfo)
- {
- 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'.";
- }
- else if (!errorName.IsEmpty())
- {
- options->mErrorString = StrFormat("Unable to change option '%s' during hot compilation", errorName.c_str());
- }
- }
- else
- {
- options->mAllowHotSwapping = allowHotSwapping;
- options->mHasVDataExtender = options->mAllowHotSwapping;
- options->mMallocLinkName = mallocLinkName;
- options->mFreeLinkName = freeLinkName;
- options->mEmitDebugInfo = emitDebugInfo;
- options->mEmitLineInfo = (optionFlags & BfCompilerOptionFlag_EmitLineInfo) != 0;;
- options->mEnableCustodian = (optionFlags & BfCompilerOptionFlag_EnableCustodian) != 0;
- options->mEnableSideStack = (optionFlags & BfCompilerOptionFlag_EnableSideStack) != 0;
- }
- }
- else
- {
- options->mCompileOnDemandKind = BfCompileOnDemandKind_AlwaysInclude;
- options->mAllowHotSwapping = false;
- options->mObjectHasDebugFlags = false;
- options->mEnableRealtimeLeakCheck = false;
- options->mEmitObjectAccessCheck = false;
- options->mEmitDynamicCastCheck = false;
- options->mRuntimeChecks = (optionFlags & BfCompilerOptionFlag_RuntimeChecks) != 0;
- }
- }
- BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler)
- {
- bfCompiler->mOptions.mForceRebuildIdx++;
- }
|