BfModule.cpp 872 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151251522515325154251552515625157251582515925160251612516225163251642516525166251672516825169251702517125172251732517425175251762517725178251792518025181251822518325184251852518625187251882518925190251912519225193251942519525196251972519825199252002520125202252032520425205252062520725208252092521025211252122521325214252152521625217252182521925220252212522225223252242522525226252272522825229252302523125232252332523425235252362523725238252392524025241252422524325244252452524625247252482524925250252512525225253252542525525256252572525825259252602526125262252632526425265252662526725268252692527025271252722527325274252752527625277252782527925280252812528225283252842528525286252872528825289252902529125292252932529425295252962529725298252992530025301253022530325304253052530625307253082530925310253112531225313253142531525316253172531825319253202532125322253232532425325253262532725328253292533025331253322533325334253352533625337253382533925340253412534225343253442534525346253472534825349253502535125352253532535425355253562535725358253592536025361253622536325364253652536625367253682536925370253712537225373253742537525376253772537825379253802538125382253832538425385253862538725388253892539025391253922539325394253952539625397253982539925400254012540225403254042540525406254072540825409254102541125412254132541425415254162541725418254192542025421254222542325424254252542625427254282542925430254312543225433254342543525436254372543825439254402544125442254432544425445254462544725448254492545025451254522545325454254552545625457254582545925460254612546225463254642546525466254672546825469254702547125472254732547425475254762547725478254792548025481254822548325484254852548625487254882548925490254912549225493254942549525496254972549825499255002550125502255032550425505255062550725508255092551025511255122551325514255152551625517255182551925520255212552225523255242552525526255272552825529255302553125532255332553425535255362553725538255392554025541255422554325544255452554625547255482554925550255512555225553255542555525556255572555825559255602556125562255632556425565255662556725568
  1. //#define USE_THUNKED_MddLLOC..
  2. #include "BeefySysLib/util/AllocDebug.h"
  3. #pragma warning(disable:4996)
  4. #pragma warning(push) // 6
  5. #include "BfCompiler.h"
  6. #include "BfSystem.h"
  7. #include "BfParser.h"
  8. #include "BfCodeGen.h"
  9. #include "BfExprEvaluator.h"
  10. #include "../Backend/BeLibManger.h"
  11. #include "BfConstResolver.h"
  12. #include "BfMangler.h"
  13. #include "BeefySysLib/util/PerfTimer.h"
  14. #include "BeefySysLib/util/BeefPerf.h"
  15. #include "BeefySysLib/util/StackHelper.h"
  16. #include "BfSourceClassifier.h"
  17. #include "BfAutoComplete.h"
  18. #include "BfDemangler.h"
  19. #include "BfResolvePass.h"
  20. #include "BfFixits.h"
  21. #include "BfIRCodeGen.h"
  22. #include "BfDefBuilder.h"
  23. #include "BfDeferEvalChecker.h"
  24. #include "CeMachine.h"
  25. #include "CeDebugger.h"
  26. #include <fcntl.h>
  27. #include <time.h>
  28. #pragma warning(pop)
  29. //////////////////////////////////////////////////////////////////////////
  30. static bool gDebugStuff = false;
  31. USING_NS_BF;
  32. //////////////////////////////////////////////////////////////////////////
  33. void BfLocalVariable::Init()
  34. {
  35. if (mResolvedType->IsValuelessType())
  36. {
  37. mAssignedKind = BfLocalVarAssignKind_Unconditional;
  38. return;
  39. }
  40. if (mAssignedKind != BfLocalVarAssignKind_None)
  41. return;
  42. bool isStruct = mResolvedType->IsStruct();
  43. if (mResolvedType->IsRef())
  44. isStruct = mResolvedType->GetUnderlyingType()->IsStruct();
  45. if ((isStruct) || ((mIsThis) && (mResolvedType->IsStructOrStructPtr())))
  46. {
  47. auto resolvedTypeRef = mResolvedType;
  48. if ((resolvedTypeRef->IsPointer()) || (resolvedTypeRef->IsRef()))
  49. resolvedTypeRef = resolvedTypeRef->GetUnderlyingType();
  50. auto typeInstance = resolvedTypeRef->ToTypeInstance();
  51. mUnassignedFieldFlags = (1 << typeInstance->mMergedFieldDataCount) - 1;
  52. if ((mIsThis) && (typeInstance->mBaseType != NULL))
  53. {
  54. // Base ctor is responsible for initializing its own fields
  55. mUnassignedFieldFlags &= ~(((int64)1 << typeInstance->mBaseType->mMergedFieldDataCount) - 1);
  56. }
  57. if (mUnassignedFieldFlags == 0)
  58. mAssignedKind = BfLocalVarAssignKind_Unconditional;
  59. }
  60. else
  61. {
  62. mUnassignedFieldFlags = 1;
  63. }
  64. }
  65. BfLocalMethod::~BfLocalMethod()
  66. {
  67. BfLogSys(mSystem, "~BfLocalMethod %p\n", this);
  68. if (mMethodDeclaration != NULL)
  69. {
  70. mSource->mRefCount--;
  71. BF_ASSERT(mSource->mRefCount >= 0);
  72. }
  73. delete mMethodInstanceGroup;
  74. delete mMethodDef;
  75. }
  76. void BfLocalMethod::Dispose()
  77. {
  78. if (mMethodInstanceGroup == NULL)
  79. return;
  80. if (mMethodInstanceGroup->mDefault != NULL)
  81. mMethodInstanceGroup->mDefault->Dispose();
  82. if (mMethodInstanceGroup->mMethodSpecializationMap != NULL)
  83. {
  84. for (auto& kv : *mMethodInstanceGroup->mMethodSpecializationMap)
  85. kv.mValue->Dispose();
  86. }
  87. }
  88. void BfDeferredLocalAssignData::ExtendFrom(BfDeferredLocalAssignData* outerLocalAssignData, bool doChain)
  89. {
  90. mIsChained = doChain;
  91. if (outerLocalAssignData == NULL)
  92. return;
  93. mChainedAssignData = outerLocalAssignData;
  94. if (!doChain)
  95. {
  96. outerLocalAssignData->BreakExtendChain();
  97. mAssignedLocals = outerLocalAssignData->mAssignedLocals;
  98. }
  99. mVarIdBarrier = outerLocalAssignData->mVarIdBarrier;
  100. }
  101. // The "extend chain" is broken when we have a conditional where the variable may not be defined after the block.
  102. // IE: "a" will be defined after the following, but "b" will not necessarily be defined.
  103. // if ((GetValue(out a)) && (GetValue(out b)) {}
  104. void BfDeferredLocalAssignData::BreakExtendChain()
  105. {
  106. if (!mIsChained)
  107. return;
  108. mIsChained = false;
  109. if (mChainedAssignData == NULL)
  110. return;
  111. mChainedAssignData->BreakExtendChain();
  112. mAssignedLocals = mChainedAssignData->mAssignedLocals;
  113. }
  114. void BfDeferredLocalAssignData::SetIntersection(const BfDeferredLocalAssignData& otherLocalAssignData)
  115. {
  116. BreakExtendChain();
  117. for (int i = 0; i < (int)mAssignedLocals.size(); )
  118. {
  119. auto& local = mAssignedLocals[i];
  120. bool wantRemove = true;
  121. bool foundOtherFields = false;
  122. for (auto& otherLocalAssignData : otherLocalAssignData.mAssignedLocals)
  123. {
  124. if (otherLocalAssignData.mLocalVar == local.mLocalVar)
  125. {
  126. if ((otherLocalAssignData.mLocalVarField == local.mLocalVarField) || (otherLocalAssignData.mLocalVarField == -1))
  127. {
  128. if (otherLocalAssignData.mAssignKind == BfLocalVarAssignKind_Conditional)
  129. local.mAssignKind = BfLocalVarAssignKind_Conditional;
  130. wantRemove = false;
  131. }
  132. else
  133. foundOtherFields = true;
  134. }
  135. }
  136. if ((wantRemove) && (foundOtherFields))
  137. {
  138. for (auto& otherLocalAssignData : otherLocalAssignData.mAssignedLocals)
  139. {
  140. if (otherLocalAssignData.mLocalVar == local.mLocalVar)
  141. {
  142. mAssignedLocals.Add(otherLocalAssignData);
  143. }
  144. }
  145. }
  146. if (wantRemove)
  147. {
  148. mAssignedLocals.RemoveAt(i);
  149. }
  150. else
  151. i++;
  152. }
  153. mHadFallthrough = mHadFallthrough && otherLocalAssignData.mHadFallthrough;
  154. }
  155. void BfDeferredLocalAssignData::Validate() const
  156. {
  157. for (auto var : mAssignedLocals)
  158. {
  159. BF_ASSERT((uintptr)var.mLocalVar->mName.length() < 100000);
  160. }
  161. }
  162. void BfDeferredLocalAssignData::SetUnion(const BfDeferredLocalAssignData& otherLocalAssignData)
  163. {
  164. BreakExtendChain();
  165. Validate();
  166. otherLocalAssignData.Validate();
  167. auto otherItr = otherLocalAssignData.mAssignedLocals.begin();
  168. while (otherItr != otherLocalAssignData.mAssignedLocals.end())
  169. {
  170. if (!mAssignedLocals.Contains(*otherItr))
  171. mAssignedLocals.push_back(*otherItr);
  172. ++otherItr;
  173. }
  174. mHadFallthrough = mHadFallthrough || otherLocalAssignData.mHadFallthrough;
  175. }
  176. BfMethodState::~BfMethodState()
  177. {
  178. BF_ASSERT(mPendingNullConditional == NULL);
  179. if (mPrevMethodState != NULL)
  180. {
  181. BF_ASSERT(mCurAccessId == 1);
  182. BF_ASSERT(mCurLocalVarId <= 0);
  183. }
  184. for (auto local : mLocals)
  185. {
  186. if (local->mIsBumpAlloc)
  187. local->~BfLocalVariable();
  188. else
  189. delete local;
  190. }
  191. for (auto& kv : mLambdaCache)
  192. delete kv.mValue;
  193. }
  194. BfMethodState* BfMethodState::GetMethodStateForLocal(BfLocalVariable* localVar)
  195. {
  196. auto checkMethodState = this;
  197. while (checkMethodState != NULL)
  198. {
  199. if ((localVar->mLocalVarIdx < checkMethodState->mLocals.size()) &&
  200. (checkMethodState->mLocals[localVar->mLocalVarIdx] == localVar))
  201. return checkMethodState;
  202. checkMethodState = checkMethodState->mPrevMethodState;
  203. }
  204. BF_FATAL("Failed to find method state for localvar");
  205. return NULL;
  206. }
  207. void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx, BfLocalVarAssignKind assignKind, bool isFromDeferredAssignData)
  208. {
  209. auto localVarMethodState = GetMethodStateForLocal(localVar);
  210. if (localVarMethodState != this)
  211. {
  212. return;
  213. }
  214. if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
  215. {
  216. BfDeferredLocalAssignData* ifDeferredLocalAssignData = NULL;
  217. // 'a' is always defined, but 'b' isn't:
  218. // if (Check(out a) || Check(out b)) { } int z = a;
  219. auto deferredLocalAssignData = mDeferredLocalAssignData;
  220. if ((deferredLocalAssignData != NULL) &&
  221. (deferredLocalAssignData->mIsIfCondition) &&
  222. (!deferredLocalAssignData->mIfMayBeSkipped))
  223. {
  224. ifDeferredLocalAssignData = deferredLocalAssignData;
  225. deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
  226. }
  227. while ((deferredLocalAssignData != NULL) &&
  228. ((deferredLocalAssignData->mIsChained) || (deferredLocalAssignData->mIsUnconditional)))
  229. deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
  230. if (assignKind == BfLocalVarAssignKind_None)
  231. assignKind = ((deferredLocalAssignData != NULL) && (deferredLocalAssignData->mLeftBlock)) ? BfLocalVarAssignKind_Conditional : BfLocalVarAssignKind_Unconditional;
  232. if (localVar->mAssignedKind >= assignKind)
  233. {
  234. // Leave it alone
  235. }
  236. else if ((deferredLocalAssignData == NULL) || (localVar->mLocalVarId >= deferredLocalAssignData->mVarIdBarrier))
  237. {
  238. if (fieldIdx >= 0)
  239. {
  240. localVar->mUnassignedFieldFlags &= ~((int64)1 << fieldIdx);
  241. if (localVar->mUnassignedFieldFlags == 0)
  242. {
  243. if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
  244. localVar->mAssignedKind = assignKind;
  245. }
  246. }
  247. else
  248. {
  249. localVar->mAssignedKind = assignKind;
  250. }
  251. }
  252. else
  253. {
  254. BF_ASSERT(deferredLocalAssignData->mVarIdBarrier != -1);
  255. BfAssignedLocal defineVal = {localVar, fieldIdx, assignKind};
  256. if (!deferredLocalAssignData->Contains(defineVal))
  257. deferredLocalAssignData->mAssignedLocals.push_back(defineVal);
  258. if (ifDeferredLocalAssignData != NULL)
  259. {
  260. if (!ifDeferredLocalAssignData->Contains(defineVal))
  261. ifDeferredLocalAssignData->mAssignedLocals.push_back(defineVal);
  262. }
  263. }
  264. }
  265. localVar->mWrittenToId = GetRootMethodState()->mCurAccessId++;
  266. }
  267. void BfMethodState::ApplyDeferredLocalAssignData(const BfDeferredLocalAssignData& deferredLocalAssignData)
  268. {
  269. BF_ASSERT(&deferredLocalAssignData != mDeferredLocalAssignData);
  270. for (auto& assignedLocal : deferredLocalAssignData.mAssignedLocals)
  271. {
  272. LocalDefined(assignedLocal.mLocalVar, assignedLocal.mLocalVarField, assignedLocal.mAssignKind, true);
  273. }
  274. }
  275. void BfMethodState::Reset()
  276. {
  277. mHeadScope.mDeferredCallEntries.DeleteAll();
  278. }
  279. //////////////////////////////////////////////////////////////////////////
  280. void BfAmbiguityContext::Add(int id, BfTypeInterfaceEntry* interfaceEntry, int methodIdx, BfMethodInstance* candidateA, BfMethodInstance* candidateB)
  281. {
  282. Entry* entry = NULL;
  283. if (mEntries.TryAdd(id, NULL, &entry))
  284. {
  285. entry->mInterfaceEntry = interfaceEntry;
  286. entry->mMethodIdx = methodIdx;
  287. }
  288. if (!entry->mCandidates.Contains(candidateA))
  289. entry->mCandidates.push_back(candidateA);
  290. if (!entry->mCandidates.Contains(candidateB))
  291. entry->mCandidates.push_back(candidateB);
  292. }
  293. void BfAmbiguityContext::Remove(int id)
  294. {
  295. mEntries.Remove(id);
  296. }
  297. void BfAmbiguityContext::Finish()
  298. {
  299. for (auto& entryPair : mEntries)
  300. {
  301. int id = entryPair.mKey;
  302. auto entry = &entryPair.mValue;
  303. if (id >= 0)
  304. {
  305. auto declMethodInstance = mTypeInstance->mVirtualMethodTable[id].mDeclaringMethod;
  306. auto error = mModule->Fail(StrFormat("Method '%s' has ambiguous overrides", mModule->MethodToString(declMethodInstance).c_str()), declMethodInstance->mMethodDef->GetRefNode());
  307. for (auto candidate : entry->mCandidates)
  308. {
  309. mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(candidate).c_str()), candidate->mMethodDef->GetRefNode());
  310. }
  311. }
  312. else
  313. {
  314. auto iMethodInst = entry->mInterfaceEntry->mInterfaceType->mMethodInstanceGroups[entry->mMethodIdx].mDefault;
  315. auto error = mModule->Fail(StrFormat("Interface method '%s' has ambiguous implementations", mModule->MethodToString(iMethodInst).c_str()), entry->mInterfaceEntry->mDeclaringType->GetRefNode());
  316. for (auto candidate : entry->mCandidates)
  317. {
  318. mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", mModule->MethodToString(candidate).c_str()), candidate->mMethodDef->GetRefNode());
  319. }
  320. }
  321. }
  322. }
  323. //////////////////////////////////////////////////////////////////////////
  324. class HasAppendAllocVisitor : BfElementVisitor
  325. {
  326. public:
  327. bool mHas;
  328. public:
  329. HasAppendAllocVisitor()
  330. {
  331. mHas = false;
  332. }
  333. void Visit(BfObjectCreateExpression* objCreateExpr)
  334. {
  335. if (auto newToken = BfNodeDynCast<BfTokenNode>(objCreateExpr->mNewNode))
  336. {
  337. if (newToken->GetToken() == BfToken_Append)
  338. {
  339. mHas = true;
  340. }
  341. }
  342. }
  343. bool HasAppendAlloc(BfAstNode* node)
  344. {
  345. mHas = false;
  346. VisitChild(node);
  347. return mHas;
  348. }
  349. };
  350. class AppendAllocVisitor : public BfStructuralVisitor
  351. {
  352. public:
  353. BfModule* mModule;
  354. HasAppendAllocVisitor mHasAppendAllocVisitor;
  355. BfTypedValue mConstAccum;
  356. bool mFailed;
  357. bool mIsFirstConstPass;
  358. int mCurAppendAlign;
  359. public:
  360. AppendAllocVisitor()
  361. {
  362. mFailed = false;
  363. mIsFirstConstPass = false;
  364. mCurAppendAlign = 1;
  365. }
  366. void EmitAppendAlign(int align, int sizeMultiple = 0)
  367. {
  368. BF_ASSERT(align > 0);
  369. if (mIsFirstConstPass)
  370. mModule->mCurMethodInstance->mAppendAllocAlign = BF_MAX((int)mModule->mCurMethodInstance->mAppendAllocAlign, align);
  371. if (sizeMultiple == 0)
  372. sizeMultiple = align;
  373. if (mCurAppendAlign == 0)
  374. mCurAppendAlign = sizeMultiple;
  375. else
  376. {
  377. if (sizeMultiple % align == 0)
  378. mCurAppendAlign = align;
  379. else
  380. mCurAppendAlign = sizeMultiple % align;
  381. }
  382. BF_ASSERT(mCurAppendAlign > 0);
  383. if (mConstAccum)
  384. {
  385. auto constant = mModule->mBfIRBuilder->GetConstant(mConstAccum.mValue);
  386. if (constant != NULL)
  387. mConstAccum.mValue = mModule->GetConstValue(BF_ALIGN(constant->mInt64, align));
  388. else
  389. BF_ASSERT(mIsFirstConstPass);
  390. return;
  391. }
  392. mModule->EmitAppendAlign(align, sizeMultiple);
  393. }
  394. void Visit(BfAstNode* astNode) override
  395. {
  396. mModule->VisitChild(astNode);
  397. }
  398. void DoObjectCreate(BfObjectCreateExpression* objCreateExpr, BfVariableDeclaration* variableDecl)
  399. {
  400. if (auto newToken = BfNodeDynCast<BfTokenNode>(objCreateExpr->mNewNode))
  401. {
  402. if (newToken->GetToken() == BfToken_Append)
  403. {
  404. //auto variableDecl = BfNodeDynCast<BfVariableDeclaration>(objCreateExpr->mParent);
  405. auto accumValuePtr = mModule->mCurMethodState->mRetVal.mValue;
  406. auto intPtrType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
  407. BfArrayType* arrayType = NULL;
  408. bool isArrayAlloc = false;
  409. bool isRawArrayAlloc = objCreateExpr->mStarToken != NULL;
  410. SizedArray<BfIRValue, 2> dimLengthVals;
  411. BfType* origResolvedTypeRef = NULL;
  412. if (auto dotTypeRef = BfNodeDynCast<BfDotTypeReference>(objCreateExpr->mTypeRef))
  413. {
  414. if (variableDecl != NULL)
  415. {
  416. origResolvedTypeRef = mModule->ResolveTypeRef(variableDecl->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_NoResolveGenericParam);
  417. if (origResolvedTypeRef->IsObject())
  418. {
  419. if (origResolvedTypeRef->IsArray())
  420. {
  421. arrayType = (BfArrayType*)origResolvedTypeRef;
  422. origResolvedTypeRef = origResolvedTypeRef->GetUnderlyingType();
  423. isArrayAlloc = true;
  424. }
  425. }
  426. else if (origResolvedTypeRef->IsPointer())
  427. {
  428. origResolvedTypeRef = origResolvedTypeRef->GetUnderlyingType();
  429. }
  430. }
  431. }
  432. else if (auto arrayTypeRef = BfNodeDynCast<BfArrayTypeRef>(objCreateExpr->mTypeRef))
  433. {
  434. isArrayAlloc = true;
  435. bool handled = false;
  436. if (auto dotTypeRef = BfNodeDynCast<BfDotTypeReference>(arrayTypeRef->mElementType))
  437. {
  438. if (variableDecl->mTypeRef != NULL)
  439. {
  440. auto variableType = mModule->ResolveTypeRef(variableDecl->mTypeRef);
  441. if (variableType != NULL)
  442. {
  443. if (variableType->IsArray())
  444. origResolvedTypeRef = variableType->GetUnderlyingType();
  445. }
  446. handled = true;
  447. }
  448. }
  449. if (!handled)
  450. {
  451. origResolvedTypeRef = mModule->ResolveTypeRef(arrayTypeRef->mElementType);
  452. }
  453. if (origResolvedTypeRef == NULL)
  454. {
  455. mModule->AssertErrorState();
  456. return;
  457. }
  458. int dimensions = 1;
  459. if (arrayTypeRef->mParams.size() != 0)
  460. {
  461. auto intType = mModule->ResolveTypeDef(mModule->mSystem->mTypeIntPtr);
  462. for (auto arg : arrayTypeRef->mParams)
  463. {
  464. if (auto tokenNode = BfNodeDynCastExact<BfTokenNode>(arg))
  465. {
  466. if (tokenNode->GetToken() == BfToken_Comma)
  467. {
  468. if (isRawArrayAlloc)
  469. {
  470. mModule->Fail("Sized arrays cannot be multidimensional", tokenNode);
  471. continue;
  472. }
  473. dimensions++;
  474. continue;
  475. }
  476. }
  477. auto expr = BfNodeDynCast<BfExpression>(arg);
  478. if ((isRawArrayAlloc) && (!dimLengthVals.IsEmpty()))
  479. {
  480. mModule->CreateValueFromExpression(expr, intType);
  481. continue;
  482. }
  483. BfTypedValue dimLength;
  484. if (expr == NULL)
  485. {
  486. // Not specified
  487. dimLengthVals.push_back(BfIRValue());
  488. continue;
  489. }
  490. if (arg != NULL)
  491. dimLength = mModule->CreateValueFromExpression(expr, intType);
  492. if (!dimLength)
  493. {
  494. dimLength = mModule->GetDefaultTypedValue(intType);
  495. }
  496. dimLengthVals.push_back(dimLength.mValue);
  497. }
  498. }
  499. if (!isRawArrayAlloc)
  500. arrayType = mModule->CreateArrayType(origResolvedTypeRef, dimensions);
  501. }
  502. if (origResolvedTypeRef == NULL)
  503. origResolvedTypeRef = mModule->ResolveTypeRef(objCreateExpr->mTypeRef, BfPopulateType_Data, BfResolveTypeRefFlag_NoResolveGenericParam);
  504. if (origResolvedTypeRef == NULL)
  505. {
  506. mModule->AssertErrorState();
  507. return;
  508. }
  509. bool isGenericParam = origResolvedTypeRef->IsGenericParam();
  510. auto resolvedTypeRef = origResolvedTypeRef;
  511. auto resultType = resolvedTypeRef;
  512. BfIRValue sizeValue;
  513. int curAlign = 0;
  514. if (isArrayAlloc)
  515. {
  516. int dimensions = 1;
  517. if (arrayType != NULL)
  518. dimensions = arrayType->mDimensions;
  519. bool sizeFailed = false;
  520. //
  521. {
  522. BfAstNode* initNode = objCreateExpr;
  523. for (int dim = 0; dim < dimensions; dim++)
  524. {
  525. BfAstNode* nextInitNode = NULL;
  526. int dimSize = -1;
  527. if (initNode == objCreateExpr)
  528. {
  529. dimSize = objCreateExpr->mArguments.size();
  530. if (!objCreateExpr->mArguments.IsEmpty())
  531. nextInitNode = objCreateExpr->mArguments[0];
  532. }
  533. else if (auto tupleNode = BfNodeDynCast<BfTupleExpression>(initNode))
  534. {
  535. dimSize = (int)tupleNode->mCommas.size() + 1;
  536. }
  537. if (dimSize >= 0)
  538. {
  539. if (dim >= dimLengthVals.size())
  540. dimLengthVals.Add(mModule->GetConstValue(dimSize));
  541. }
  542. else
  543. {
  544. sizeFailed = true;
  545. }
  546. }
  547. }
  548. BfIRValue allocCount;
  549. if (!sizeFailed)
  550. {
  551. if (!dimLengthVals.IsEmpty())
  552. {
  553. allocCount = dimLengthVals[0];
  554. for (int dim = 1; dim < (int)dimLengthVals.size(); dim++)
  555. allocCount = mModule->mBfIRBuilder->CreateMul(allocCount, dimLengthVals[dim]);
  556. }
  557. }
  558. if (!allocCount)
  559. {
  560. mFailed = true;
  561. if (!mIsFirstConstPass)
  562. {
  563. if (!mConstAccum)
  564. mModule->Fail("Unable to determine append alloc size", objCreateExpr->mNewNode);
  565. return;
  566. }
  567. }
  568. mModule->PopulateType(resultType);
  569. if (isRawArrayAlloc)
  570. {
  571. curAlign = resultType->mAlign;
  572. EmitAppendAlign(resultType->mAlign);
  573. sizeValue = mModule->mBfIRBuilder->CreateMul(mModule->GetConstValue(resultType->GetStride()), allocCount);
  574. }
  575. else
  576. {
  577. if (arrayType == NULL)
  578. arrayType = mModule->CreateArrayType(resultType, 1);
  579. // Array is a special case where the total size isn't aligned with mAlign
  580. // since we add arbitrary elements to the end without padding the end to align
  581. EmitAppendAlign(arrayType->mAlign, resultType->mAlign);
  582. curAlign = arrayType->mAlign;
  583. auto firstElementField = &arrayType->mFieldInstances.back();
  584. int arrayClassSize = arrayType->mInstSize - firstElementField->mDataSize;
  585. sizeValue = mModule->GetConstValue(arrayClassSize);
  586. BfIRValue elementDataSize = mModule->mBfIRBuilder->CreateMul(mModule->GetConstValue(resultType->GetStride()), allocCount);
  587. sizeValue = mModule->mBfIRBuilder->CreateAdd(sizeValue, elementDataSize);
  588. }
  589. }
  590. else
  591. {
  592. auto typeInst = resultType->ToTypeInstance();
  593. if (typeInst != NULL)
  594. {
  595. curAlign = typeInst->mInstAlign;
  596. EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize);
  597. sizeValue = mModule->GetConstValue(typeInst->mInstSize);
  598. }
  599. else
  600. {
  601. curAlign = resultType->mAlign;
  602. EmitAppendAlign(resultType->mAlign, resultType->mSize);
  603. sizeValue = mModule->GetConstValue(resultType->mSize);
  604. }
  605. BfTypedValue emtpyThis(mModule->mBfIRBuilder->GetFakeVal(), resultType, (typeInst == NULL) || (typeInst->IsComposite()));
  606. BfExprEvaluator exprEvaluator(mModule);
  607. SetAndRestoreValue<bool> prevNoBind(exprEvaluator.mNoBind, exprEvaluator.mNoBind || isGenericParam);
  608. BfFunctionBindResult bindResult;
  609. bindResult.mWantsArgs = true;
  610. exprEvaluator.mFunctionBindResult = &bindResult;
  611. SizedArray<BfExpression*, 8> copiedArgs;
  612. for (BfExpression* arg : objCreateExpr->mArguments)
  613. copiedArgs.push_back(arg);
  614. BfSizedArray<BfExpression*> sizedArgExprs(copiedArgs);
  615. BfResolvedArgs argValues(&sizedArgExprs);
  616. if (typeInst != NULL)
  617. {
  618. exprEvaluator.ResolveArgValues(argValues);
  619. exprEvaluator.MatchConstructor(objCreateExpr->mTypeRef, objCreateExpr, emtpyThis, typeInst, argValues, false, true);
  620. }
  621. exprEvaluator.mFunctionBindResult = NULL;
  622. if (bindResult.mMethodInstance != NULL)
  623. {
  624. if (bindResult.mMethodInstance->mMethodDef->mHasAppend)
  625. {
  626. auto calcAppendArgs = bindResult.mIRArgs;
  627. BF_ASSERT(calcAppendArgs[0].IsFake());
  628. calcAppendArgs.RemoveRange(0, 2); // Remove 'this' and 'appendIdx'
  629. auto calcAppendMethodModule = mModule->GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
  630. auto subDependSize = mModule->TryConstCalcAppend(calcAppendMethodModule.mMethodInstance, calcAppendArgs);
  631. if (calcAppendMethodModule.mMethodInstance->mAppendAllocAlign > 0)
  632. {
  633. EmitAppendAlign(calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
  634. BF_ASSERT(calcAppendMethodModule.mMethodInstance->mEndingAppendAllocAlign > -1);
  635. mModule->mCurMethodState->mCurAppendAlign = BF_MAX(calcAppendMethodModule.mMethodInstance->mEndingAppendAllocAlign, 0);
  636. }
  637. curAlign = std::max(curAlign, (int)calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
  638. if ((!subDependSize) && (!mConstAccum))
  639. {
  640. BF_ASSERT(calcAppendMethodModule.mFunc);
  641. subDependSize = exprEvaluator.CreateCall(objCreateExpr, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
  642. BF_ASSERT(subDependSize.mType == mModule->GetPrimitiveType(BfTypeCode_IntPtr));
  643. }
  644. if (subDependSize)
  645. sizeValue = mModule->mBfIRBuilder->CreateAdd(sizeValue, subDependSize.mValue);
  646. else
  647. mFailed = true;
  648. }
  649. }
  650. }
  651. if (sizeValue)
  652. {
  653. if (mConstAccum)
  654. {
  655. if (!sizeValue.IsConst())
  656. {
  657. mFailed = true;
  658. if (!mIsFirstConstPass)
  659. return;
  660. }
  661. mConstAccum.mValue = mModule->mBfIRBuilder->CreateAdd(sizeValue, mConstAccum.mValue);
  662. }
  663. else
  664. {
  665. auto prevVal = mModule->mBfIRBuilder->CreateAlignedLoad(accumValuePtr, intPtrType->mAlign);
  666. auto addedVal = mModule->mBfIRBuilder->CreateAdd(sizeValue, prevVal);
  667. mModule->mBfIRBuilder->CreateAlignedStore(addedVal, accumValuePtr, intPtrType->mAlign);
  668. }
  669. }
  670. }
  671. }
  672. }
  673. void Visit(BfObjectCreateExpression* objCreateExpr) override
  674. {
  675. DoObjectCreate(objCreateExpr, NULL);
  676. }
  677. void Visit(BfVariableDeclaration* varDecl) override
  678. {
  679. if (mHasAppendAllocVisitor.HasAppendAlloc(varDecl))
  680. {
  681. if (auto objectCreateExpr = BfNodeDynCast<BfObjectCreateExpression>(varDecl->mInitializer))
  682. DoObjectCreate(objectCreateExpr, varDecl);
  683. else
  684. VisitChild(varDecl->mInitializer);
  685. if (varDecl->mNameNode != NULL)
  686. {
  687. BfLocalVariable* localDef = new BfLocalVariable();
  688. localDef->mName = varDecl->mNameNode->ToString();
  689. localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
  690. localDef->mResolvedType = mModule->GetPrimitiveType(BfTypeCode_None);
  691. localDef->mIsReadOnly = true;
  692. localDef->mParamFailed = true;
  693. localDef->mReadFromId = 0;
  694. mModule->AddLocalVariableDef(localDef);
  695. }
  696. }
  697. else
  698. {
  699. mModule->Visit(varDecl);
  700. }
  701. }
  702. void Visit(BfExpressionStatement* exprStatement) override
  703. {
  704. VisitChild(exprStatement->mExpression);
  705. }
  706. // void Visit(BfIfStatement* ifStmt) override
  707. // {
  708. // mModule->DoIfStatement(ifStmt,
  709. // mHasAppendAllocVisitor.HasAppendAlloc(ifStmt->mTrueStatement),
  710. // mHasAppendAllocVisitor.HasAppendAlloc(ifStmt->mFalseStatement));
  711. // }
  712. void Visit(BfBlock* block) override
  713. {
  714. if (!mHasAppendAllocVisitor.HasAppendAlloc(block))
  715. return;
  716. int appendAllocIdx = -1;
  717. for (int childIdx = block->mChildArr.mSize - 1; childIdx >= 0; childIdx--)
  718. {
  719. auto child = block->mChildArr.mVals[childIdx];
  720. if (mHasAppendAllocVisitor.HasAppendAlloc(child))
  721. {
  722. for (int emitIdx = 0; emitIdx <= childIdx; emitIdx++)
  723. {
  724. auto emitChild = block->mChildArr.mVals[emitIdx];
  725. mModule->UpdateSrcPos(emitChild);
  726. VisitChild(emitChild);
  727. if ((mFailed) && (!mIsFirstConstPass))
  728. break;
  729. }
  730. break;
  731. }
  732. }
  733. }
  734. };
  735. //////////////////////////////////////////////////////////////////////////
  736. BfModule* gLastCreatedModule = NULL;
  737. BfModule::BfModule(BfContext* context, const StringImpl& moduleName)
  738. {
  739. BfLogSys(context->mSystem, "BfModule::BFModule %p %s\n", this, moduleName.c_str());
  740. gLastCreatedModule = this;
  741. mContext = context;
  742. mModuleName = moduleName;
  743. if (!moduleName.empty())
  744. {
  745. StringT<256> upperModuleName = moduleName;
  746. MakeUpper(upperModuleName);
  747. mContext->mUsedModuleNames.Add(upperModuleName);
  748. }
  749. mAddedToCount = false;
  750. mParentModule = NULL;
  751. mNextAltModule = NULL;
  752. mBfIRBuilder = NULL;
  753. mWantsIRIgnoreWrites = false;
  754. mModuleOptions = NULL;
  755. mLastUsedRevision = -1;
  756. mUsedSlotCount = -1;
  757. mIsReified = true;
  758. mGeneratesCode = true;
  759. mReifyQueued = false;
  760. mIsSpecialModule = false;
  761. mIsComptimeModule = false;
  762. mIsScratchModule = false;
  763. mIsSpecializedMethodModuleRoot = false; // There may be mNextAltModules extending from this
  764. mHadBuildError = false;
  765. mHadBuildWarning = false;
  766. mIgnoreErrors = false;
  767. mHadIgnoredError = false;
  768. mIgnoreWarnings = false;
  769. mReportErrors = true;
  770. mIsInsideAutoComplete = false;
  771. mIsDeleting = false;
  772. mSkipInnerLookup = false;
  773. mIsHotModule = false;
  774. mSetIllegalSrcPosition = false;
  775. mNoResolveGenericParams = false;
  776. mWroteToLib = false;
  777. mContext = context;
  778. mCompiler = context->mCompiler;
  779. mSystem = mCompiler->mSystem;
  780. mProject = NULL;
  781. mCurMethodState = NULL;
  782. mAttributeState = NULL;
  783. mCurLocalMethodId = 0;
  784. mParentNodeEntry = NULL;
  785. mRevision = -1;
  786. mRebuildIdx = 0;
  787. mLastModuleWrittenRevision = 0;
  788. mIsModuleMutable = false;
  789. mExtensionCount = 0;
  790. mIncompleteMethodCount = 0;
  791. mOnDemandMethodCount = 0;
  792. mHasGenericMethods = false;
  793. mCurMethodInstance = NULL;
  794. mCurTypeInstance = NULL;
  795. mAwaitingInitFinish = false;
  796. mAwaitingFinish = false;
  797. mHasFullDebugInfo = false;
  798. mHadHotObjectWrites = false;
  799. for (int i = 0; i < BfBuiltInFuncType_Count; i++)
  800. mBuiltInFuncs[i] = BfIRFunction();
  801. BfLogSysM("Creating module %p: %s Reified: %d ResolveOnly: %d\n", this, mModuleName.c_str(), mIsReified, mCompiler->mIsResolveOnly);
  802. }
  803. void BfReportMemory();
  804. BfModule::~BfModule()
  805. {
  806. mRevision = -2;
  807. BfLogSysM("Deleting module %p: %s \n", this, mModuleName.c_str());
  808. if (!mIsDeleting)
  809. RemoveModuleData();
  810. }
  811. void BfModule::RemoveModuleData()
  812. {
  813. BF_ASSERT(!mIsDeleting);
  814. if (!mModuleName.empty())
  815. {
  816. // Note: module names not necessarily unique
  817. mContext->mUsedModuleNames.Remove(ToUpper(mModuleName));
  818. }
  819. CleanupFileInstances();
  820. delete mBfIRBuilder;
  821. mBfIRBuilder = NULL;
  822. //delete mCpu;
  823. for (auto prevModule : mPrevIRBuilders)
  824. delete prevModule;
  825. mPrevIRBuilders.Clear();
  826. for (auto& pairVal : mDeferredMethodCallData)
  827. delete pairVal.mValue;
  828. mDeferredMethodCallData.Clear();
  829. mDeferredMethodIds.Clear();
  830. for (auto& specModulePair : mSpecializedMethodModules)
  831. delete specModulePair.mValue;
  832. mSpecializedMethodModules.Clear();
  833. if (mNextAltModule != NULL)
  834. delete mNextAltModule;
  835. mNextAltModule = NULL;
  836. if (mModuleOptions != NULL)
  837. delete mModuleOptions;
  838. mModuleOptions = NULL;
  839. BfReportMemory();
  840. }
  841. void BfModule::Init(bool isFullRebuild)
  842. {
  843. mContext->mFinishedModuleWorkList.Remove(this);
  844. if ((mCompiler->mIsResolveOnly) && (this != mContext->mUnreifiedModule))
  845. BF_ASSERT(mIsReified);
  846. if (!mIsScratchModule)
  847. {
  848. mCompiler->mStats.mModulesStarted++;
  849. if (mIsReified)
  850. mCompiler->mStats.mReifiedModuleCount++;
  851. mAddedToCount = true;
  852. }
  853. mIsHotModule = (mProject != NULL) && (mCompiler->mOptions.mHotProject != NULL) && (mCompiler->mOptions.mHotProject->ContainsReference(mProject));
  854. mFuncReferences.Clear();
  855. mClassVDataRefs.Clear();
  856. mClassVDataExtRefs.Clear();
  857. //mTypeDataRefs.Clear();
  858. mDbgRawAllocDataRefs.Clear();
  859. CleanupFileInstances();
  860. mStaticFieldRefs.Clear();
  861. //mInterfaceSlotRefs.Clear();
  862. // If we are just doing an extension then the ownede types aren't rebuilt.
  863. // If we set mRevision then QueueMethodSpecializations wouldn't actually queue up required specializations
  864. // and we'd end up with link errors if the original module uniquely referred to any generic methods
  865. if (isFullRebuild)
  866. mRevision = mCompiler->mRevision;
  867. BF_ASSERT(mCurTypeInstance == NULL);
  868. mIsModuleMutable = true;
  869. BF_ASSERT((mBfIRBuilder == NULL) || (mCompiler->mIsResolveOnly));
  870. if (!mIsComptimeModule)
  871. {
  872. #ifdef _DEBUG
  873. EnsureIRBuilder(mCompiler->mLastAutocompleteModule == this);
  874. #else
  875. EnsureIRBuilder(false);
  876. #endif
  877. }
  878. mCurMethodState = NULL;
  879. mAwaitingInitFinish = true;
  880. mOnDemandMethodCount = 0;
  881. mAwaitingFinish = false;
  882. mHasForceLinkMarker = false;
  883. mUsedSlotCount = -1;
  884. }
  885. bool BfModule::WantsFinishModule()
  886. {
  887. return (mIncompleteMethodCount == 0) && (mOnDemandMethodCount == 0) && (!mHasGenericMethods) && (!mIsScratchModule) && (mExtensionCount == 0) && (mParentModule == NULL);
  888. }
  889. bool BfModule::IsHotCompile()
  890. {
  891. return mCompiler->IsHotCompile() && !mIsComptimeModule;
  892. }
  893. void BfModule::FinishInit()
  894. {
  895. BF_ASSERT(mAwaitingInitFinish);
  896. auto moduleOptions = GetModuleOptions();
  897. mBfIRBuilder->Start(mModuleName, mCompiler->mSystem->mPtrSize, IsOptimized());
  898. mBfIRBuilder->Module_SetTargetTriple(mCompiler->mOptions.mTargetTriple, mCompiler->mOptions.mTargetCPU);
  899. mBfIRBuilder->SetBackend(IsTargetingBeefBackend());
  900. if (moduleOptions.mOptLevel == BfOptLevel_OgPlus)
  901. {
  902. // Og+ requires debug info
  903. moduleOptions.mEmitDebugInfo = 1;
  904. }
  905. mHasFullDebugInfo = moduleOptions.mEmitDebugInfo == 1;
  906. if (mIsComptimeModule)
  907. mHasFullDebugInfo = true;
  908. if (((!mCompiler->mIsResolveOnly) && (!mIsScratchModule) && (moduleOptions.mEmitDebugInfo != 0) && (mIsReified)) ||
  909. (mIsComptimeModule))
  910. {
  911. mBfIRBuilder->DbgInit();
  912. }
  913. else
  914. mHasFullDebugInfo = false;
  915. if ((mBfIRBuilder->DbgHasInfo()) && (mModuleName != "") &&
  916. ((moduleOptions.mEmitDebugInfo != 0)))
  917. {
  918. if (mCompiler->mOptions.IsCodeView())
  919. {
  920. mBfIRBuilder->Module_AddModuleFlag("CodeView", 1);
  921. }
  922. else
  923. {
  924. mBfIRBuilder->Module_AddModuleFlag("Dwarf Version", 4);
  925. }
  926. mBfIRBuilder->Module_AddModuleFlag("Debug Info Version", 3);
  927. mDICompileUnit = mBfIRBuilder->DbgCreateCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, mModuleName, ".", "Beef Compiler 0.42.3", /*moduleOptions.mOptLevel > 0*/false, "", 0, !mHasFullDebugInfo);
  928. }
  929. mAwaitingInitFinish = false;
  930. }
  931. void BfModule::CalcGeneratesCode()
  932. {
  933. if ((!mIsReified) || (mIsScratchModule))
  934. {
  935. mGeneratesCode = false;
  936. return;
  937. }
  938. mGeneratesCode = false;
  939. for (auto typeInst : mOwnedTypeInstances)
  940. if (!typeInst->IsInterface())
  941. mGeneratesCode = true;
  942. }
  943. void BfModule::ReifyModule()
  944. {
  945. BF_ASSERT((mCompiler->mCompileState != BfCompiler::CompileState_Unreified) && (mCompiler->mCompileState != BfCompiler::CompileState_VData));
  946. BfLogSysM("ReifyModule %@ %s\n", this, mModuleName.c_str());
  947. BF_ASSERT((this != mContext->mScratchModule) && (this != mContext->mUnreifiedModule));
  948. mIsReified = true;
  949. CalcGeneratesCode();
  950. mReifyQueued = false;
  951. StartNewRevision(RebuildKind_SkipOnDemandTypes, true);
  952. mCompiler->mStats.mModulesReified++;
  953. }
  954. void BfModule::UnreifyModule()
  955. {
  956. BfLogSysM("UnreifyModule %p %s\n", this, mModuleName.c_str());
  957. BF_ASSERT((this != mContext->mScratchModule) && (this != mContext->mUnreifiedModule));
  958. mIsReified = false;
  959. CalcGeneratesCode();
  960. mReifyQueued = false;
  961. StartNewRevision(RebuildKind_None, true);
  962. mCompiler->mStats.mModulesUnreified++;
  963. }
  964. void BfModule::CleanupFileInstances()
  965. {
  966. for (auto& itr : mNamedFileInstanceMap)
  967. {
  968. BfLogSysM("FileInstance deleted: %p\n", itr.mValue);
  969. delete itr.mValue;
  970. }
  971. mCurFilePosition.mFileInstance = NULL;//
  972. mFileInstanceMap.Clear();
  973. mNamedFileInstanceMap.Clear();
  974. }
  975. void BfModule::Cleanup()
  976. {
  977. CleanupFileInstances();
  978. }
  979. void BfModule::PrepareForIRWriting(BfTypeInstance* typeInst)
  980. {
  981. if (HasCompiledOutput())
  982. {
  983. // It's possible that the target's code hasn't changed but we're requesting a new generic method specialization
  984. if ((!mIsModuleMutable) && (!typeInst->IsUnspecializedType()) && (!typeInst->mResolvingVarField))
  985. {
  986. StartExtension();
  987. }
  988. }
  989. else
  990. {
  991. EnsureIRBuilder();
  992. }
  993. }
  994. void BfModule::SetupIRBuilder(bool dbgVerifyCodeGen)
  995. {
  996. if (mIsScratchModule)
  997. {
  998. mBfIRBuilder->mIgnoreWrites = true;
  999. BF_ASSERT(!dbgVerifyCodeGen);
  1000. }
  1001. #ifdef _DEBUG
  1002. if (mCompiler->mIsResolveOnly)
  1003. {
  1004. // For "deep" verification testing
  1005. /*if (!mIsSpecialModule)
  1006. dbgVerifyCodeGen = true;*/
  1007. // We only want to turn this off on smaller builds for testing
  1008. mBfIRBuilder->mIgnoreWrites = true;
  1009. if (dbgVerifyCodeGen)
  1010. mBfIRBuilder->mIgnoreWrites = false;
  1011. if (!mBfIRBuilder->mIgnoreWrites)
  1012. {
  1013. // The only purpose of not ignoring writes is so we can verify the codegen one instruction at a time
  1014. mBfIRBuilder->mDbgVerifyCodeGen = true;
  1015. }
  1016. }
  1017. else if (!mGeneratesCode)
  1018. {
  1019. mBfIRBuilder->mIgnoreWrites = true;
  1020. }
  1021. else
  1022. {
  1023. // We almost always want this to be 'false' unless we need need to be able to inspect the generated LLVM
  1024. // code as we walk the AST
  1025. //mBfIRBuilder->mDbgVerifyCodeGen = true;
  1026. if (
  1027. (mModuleName == "-")
  1028. //|| (mModuleName == "BeefTest2_ClearColorValue")
  1029. //|| (mModuleName == "Tests_FuncRefs")
  1030. )
  1031. mBfIRBuilder->mDbgVerifyCodeGen = true;
  1032. // Just for testing!
  1033. //mBfIRBuilder->mIgnoreWrites = true;
  1034. }
  1035. #else
  1036. if (mCompiler->mIsResolveOnly)
  1037. {
  1038. // Always ignore writes in resolveOnly for release builds
  1039. mBfIRBuilder->mIgnoreWrites = true;
  1040. }
  1041. else
  1042. {
  1043. // Just for memory testing! This breaks everything.
  1044. //mBfIRBuilder->mIgnoreWrites = true;
  1045. // For "deep" verification testing
  1046. //mBfIRBuilder->mDbgVerifyCodeGen = true;
  1047. }
  1048. #endif
  1049. mWantsIRIgnoreWrites = mBfIRBuilder->mIgnoreWrites;
  1050. }
  1051. void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen)
  1052. {
  1053. BF_ASSERT(!mIsDeleting);
  1054. if (mBfIRBuilder == NULL)
  1055. {
  1056. if ((!mIsScratchModule) && (!mAddedToCount))
  1057. {
  1058. mCompiler->mStats.mModulesStarted++;
  1059. mAddedToCount = true;
  1060. }
  1061. BF_ASSERT(mStaticFieldRefs.GetCount() == 0);
  1062. /*if (mCompiler->mIsResolveOnly)
  1063. BF_ASSERT(mIsResolveOnly);*/
  1064. mBfIRBuilder = new BfIRBuilder(this);
  1065. BfLogSysM("Created mBfIRBuilder %p in %p %s Reified: %d\n", mBfIRBuilder, this, mModuleName.c_str(), mIsReified);
  1066. SetupIRBuilder(dbgVerifyCodeGen);
  1067. }
  1068. }
  1069. BfIRValue BfModule::CreateForceLinkMarker(BfModule* module, String* outName)
  1070. {
  1071. String name = "FORCELINKMOD_" + module->mModuleName;
  1072. if (outName != NULL)
  1073. *outName = name;
  1074. auto markerType = GetPrimitiveType(BfTypeCode_Int8);
  1075. return mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(markerType), true, BfIRLinkageType_External, (module == this) ? mBfIRBuilder->CreateConst(BfTypeCode_Int8, 0) : BfIRValue(), name);
  1076. }
  1077. void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
  1078. {
  1079. BP_ZONE("BfModule::StartNewRevision");
  1080. // The project MAY be deleted because disabling a project can cause types to be deleted which
  1081. // causes other types rebuild BEFORE they get deleted, which is okay (though wasteful)
  1082. //BF_ASSERT((mProject == NULL) || (!mProject->mDisabled));
  1083. if (mCompiler->mCompileState == BfCompiler::CompileState_Cleanup)
  1084. {
  1085. // Cleaning up local methods may cause some necessary NewRevisions
  1086. force = true;
  1087. }
  1088. // Already on new revision?
  1089. if ((mRevision == mCompiler->mRevision) && (!force))
  1090. return;
  1091. mHadBuildError = false;
  1092. mHadBuildWarning = false;
  1093. mExtensionCount = 0;
  1094. mRevision = mCompiler->mRevision;
  1095. mRebuildIdx++;
  1096. ClearModuleData(!force);
  1097. // Clear this here, not in ClearModuleData, so we preserve those references even after writing out module
  1098. if (rebuildKind != BfModule::RebuildKind_None) // Leave string pool refs for when we need to use things like [LinkName("")] methods bofore re-reification
  1099. {
  1100. mStringPoolRefs.Clear();
  1101. mUnreifiedStringPoolRefs.Clear();
  1102. }
  1103. mDllImportEntries.Clear();
  1104. mImportFileNames.Clear();
  1105. for (auto& pairVal : mDeferredMethodCallData)
  1106. delete pairVal.mValue;
  1107. mDeferredMethodCallData.Clear();
  1108. mDeferredMethodIds.Clear();
  1109. mModuleRefs.Clear();
  1110. mOutFileNames.Clear();
  1111. mTypeDataRefs.Clear();
  1112. mInterfaceSlotRefs.Clear();
  1113. if (rebuildKind == BfModule::RebuildKind_None)
  1114. {
  1115. for (auto& specPair : mSpecializedMethodModules)
  1116. {
  1117. auto specModule = specPair.mValue;
  1118. if (specModule->mIsReified != mIsReified)
  1119. {
  1120. if (mIsReified)
  1121. specModule->ReifyModule();
  1122. else
  1123. specModule->UnreifyModule();
  1124. }
  1125. }
  1126. }
  1127. else
  1128. {
  1129. for (auto& specPair : mSpecializedMethodModules)
  1130. {
  1131. auto specModule = specPair.mValue;
  1132. BfLogSysM("Setting module mIsDeleting %p due to parent module starting a new revision\n", specModule);
  1133. // This module is no longer needed
  1134. specModule->RemoveModuleData();
  1135. specModule->mIsDeleting = true;
  1136. mContext->mDeletingModules.Add(specModule);
  1137. }
  1138. }
  1139. mSpecializedMethodModules.Clear();
  1140. delete mNextAltModule;
  1141. mNextAltModule = NULL;
  1142. BF_ASSERT(mModuleOptions == NULL);
  1143. BfLogSysM("Mod:%p StartNewRevision: %s Revision: %d\n", this, mModuleName.c_str(), mRevision);
  1144. bool needsTypePopulated = false;
  1145. int oldOnDemandCount = 0;
  1146. // We don't have to rebuild types in the unspecialized module because there is no
  1147. // data that's needed -- their method instances are all NULL and the module
  1148. // doesn't get included in the build
  1149. if (this != mContext->mScratchModule)
  1150. {
  1151. for (int typeIdx = 0; typeIdx < (int)mOwnedTypeInstances.size(); typeIdx++)
  1152. {
  1153. auto typeInst = mOwnedTypeInstances[typeIdx];
  1154. if (!typeInst->IsDeleting())
  1155. {
  1156. typeInst->mIsReified = mIsReified;
  1157. if (rebuildKind != BfModule::RebuildKind_None)
  1158. {
  1159. if (typeInst->IsOnDemand())
  1160. {
  1161. // Changing config should require on demand types to be recreated, but reifying a module shouldn't cause the type to be deleted
  1162. if (rebuildKind == BfModule::RebuildKind_All)
  1163. mContext->DeleteType(typeInst);
  1164. else
  1165. {
  1166. RebuildMethods(typeInst);
  1167. }
  1168. }
  1169. else
  1170. //TODO: Why weren't we placing specialzied in purgatory here originally? This caused failed types to stick around too long
  1171. mContext->RebuildType(typeInst, false, false, true);
  1172. //mContext->RebuildType(typeInst, false, false, false);
  1173. }
  1174. else
  1175. {
  1176. auto _HandleMethod = [&](BfMethodInstance* methodInstance)
  1177. {
  1178. if ((methodInstance != NULL) && (methodInstance->mDeclModule != NULL))
  1179. methodInstance->mDeclModule = this;
  1180. };
  1181. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  1182. {
  1183. if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
  1184. (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
  1185. (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
  1186. (methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList))
  1187. {
  1188. oldOnDemandCount++;
  1189. }
  1190. _HandleMethod(methodGroup.mDefault);
  1191. if (methodGroup.mMethodSpecializationMap != NULL)
  1192. for (auto& kv : *methodGroup.mMethodSpecializationMap)
  1193. _HandleMethod(kv.mValue);
  1194. }
  1195. }
  1196. if (typeInst->IsDeleting())
  1197. typeIdx--;
  1198. }
  1199. }
  1200. }
  1201. if (!mIsDeleting)
  1202. Init();
  1203. mOnDemandMethodCount += oldOnDemandCount;
  1204. VerifyOnDemandMethods();
  1205. }
  1206. void BfModule::StartExtension()
  1207. {
  1208. BF_ASSERT(!mIsModuleMutable);
  1209. BfLogSysM("Extension started of module %p\n", this);
  1210. mExtensionCount++;
  1211. if (mBfIRBuilder != NULL)
  1212. mPrevIRBuilders.push_back(mBfIRBuilder);
  1213. mBfIRBuilder = NULL;
  1214. mWantsIRIgnoreWrites = false;
  1215. mFuncReferences.Clear();
  1216. mClassVDataRefs.Clear();
  1217. mClassVDataExtRefs.Clear();
  1218. for (auto& kv : mTypeDataRefs)
  1219. kv.mValue = BfIRValue();
  1220. mDbgRawAllocDataRefs.Clear();
  1221. mStringCharPtrPool.Clear();
  1222. mStringObjectPool.Clear();
  1223. mStaticFieldRefs.Clear();
  1224. for (auto& kv : mInterfaceSlotRefs)
  1225. kv.mValue = BfIRValue();
  1226. for (auto& pairVal : mDeferredMethodCallData)
  1227. delete pairVal.mValue;
  1228. mDeferredMethodCallData.Clear();
  1229. mDeferredMethodIds.Clear();
  1230. DisownMethods();
  1231. BfLogSysM("Mod:%p StartExtension: %s\n", this, mModuleName.c_str());
  1232. bool wasAwaitingInitFinish = mAwaitingInitFinish;
  1233. int prevOnDemandMethodCount = mOnDemandMethodCount;
  1234. Init(false);
  1235. if (!wasAwaitingInitFinish)
  1236. FinishInit();
  1237. mOnDemandMethodCount = prevOnDemandMethodCount;
  1238. }
  1239. void BfModule::GetConstClassValueParam(BfIRValue classVData, SizedArrayImpl<BfIRValue>& typeValueParams)
  1240. {
  1241. auto hasObjectDebugFlags = mContext->mBfObjectType->mFieldInstances[0].mResolvedType->IsInteger();
  1242. BfIRValue vDataValue;
  1243. if (hasObjectDebugFlags)
  1244. vDataValue = mBfIRBuilder->CreatePtrToInt(classVData, BfTypeCode_IntPtr);
  1245. else
  1246. vDataValue = mBfIRBuilder->CreateBitCast(classVData, mBfIRBuilder->MapType(mContext->mBfClassVDataPtrType));
  1247. typeValueParams.push_back(vDataValue);
  1248. if (hasObjectDebugFlags)
  1249. {
  1250. auto primType = GetPrimitiveType(BfTypeCode_IntPtr);
  1251. typeValueParams.push_back(GetDefaultValue(primType));
  1252. }
  1253. }
  1254. BfIRValue BfModule::GetConstValue(int64 val)
  1255. {
  1256. return mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)val);
  1257. }
  1258. BfIRValue BfModule::GetConstValue(int64 val, BfType* type)
  1259. {
  1260. BfType* checkType = type;
  1261. if (type->IsTypedPrimitive())
  1262. {
  1263. checkType = type->GetUnderlyingType();
  1264. }
  1265. if (checkType->IsPrimitiveType())
  1266. {
  1267. auto primType = (BfPrimitiveType*)checkType;
  1268. if (checkType->IsFloat())
  1269. return mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (double)val);
  1270. else
  1271. return mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)val);
  1272. }
  1273. return BfIRValue();
  1274. }
  1275. BfIRValue BfModule::GetConstValue8(int val)
  1276. {
  1277. return mBfIRBuilder->CreateConst(BfTypeCode_Int8, (uint64)val);
  1278. }
  1279. BfIRValue BfModule::GetConstValue32(int32 val)
  1280. {
  1281. return mBfIRBuilder->CreateConst(BfTypeCode_Int32, (uint64)val);
  1282. }
  1283. BfIRValue BfModule::GetConstValue64(int64 val)
  1284. {
  1285. return mBfIRBuilder->CreateConst(BfTypeCode_Int64, (uint64)val);
  1286. }
  1287. BfIRValue BfModule::GetDefaultValue(BfType* type)
  1288. {
  1289. PopulateType(type, BfPopulateType_Data);
  1290. mBfIRBuilder->PopulateType(type, BfIRPopulateType_Declaration);
  1291. if (type->IsTypedPrimitive())
  1292. {
  1293. auto underlyingType = type->GetUnderlyingType();
  1294. if (underlyingType == NULL)
  1295. return mBfIRBuilder->CreateConst(BfTypeCode_Int64, 0);
  1296. return GetDefaultValue(type->GetUnderlyingType());
  1297. }
  1298. if (type->IsPointer() || type->IsObjectOrInterface() || type->IsGenericParam() || type->IsVar() || type->IsRef() || type->IsNull() ||
  1299. type->IsModifiedTypeType() || type->IsConcreteInterfaceType())
  1300. return mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(type));
  1301. if ((type->IsIntegral()) || (type->IsBoolean()))
  1302. {
  1303. auto primType = (BfPrimitiveType*)type;
  1304. return mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, (uint64)0);
  1305. }
  1306. if (type->IsFloat())
  1307. {
  1308. auto primType = (BfPrimitiveType*)type;
  1309. return mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, 0.0);
  1310. }
  1311. return mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(type));
  1312. }
  1313. BfTypedValue BfModule::GetFakeTypedValue(BfType* type)
  1314. {
  1315. // This is a conservative "IsValueless", since it's not an error to use a fakeVal even if we don't need one
  1316. if (type->mSize == 0)
  1317. return BfTypedValue(BfIRValue::sValueless, type);
  1318. else if (mBfIRBuilder != NULL)
  1319. return BfTypedValue(mBfIRBuilder->GetFakeVal(), type);
  1320. else
  1321. return BfTypedValue(BfIRValue(BfIRValueFlags_Value, -1), type);
  1322. }
  1323. BfTypedValue BfModule::GetDefaultTypedValue(BfType* type, bool allowRef, BfDefaultValueKind defaultValueKind)
  1324. {
  1325. if (type->IsVar())
  1326. return BfTypedValue(mBfIRBuilder->GetFakeVal(), type);
  1327. PopulateType(type, BfPopulateType_Data);
  1328. mBfIRBuilder->PopulateType(type, type->IsValueType() ? BfIRPopulateType_Full : BfIRPopulateType_Declaration);
  1329. if (defaultValueKind == BfDefaultValueKind_Undef)
  1330. {
  1331. return BfTypedValue(mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(type)), type);
  1332. }
  1333. BfTypedValue typedValue;
  1334. if ((defaultValueKind != BfDefaultValueKind_Const) && (!type->IsValuelessType()))
  1335. {
  1336. if (type->IsRef())
  1337. {
  1338. BfRefType* refType = (BfRefType*)type;
  1339. BfType* underlyingType = refType->GetUnderlyingType();
  1340. typedValue = BfTypedValue(CreateAlloca(underlyingType), underlyingType, BfTypedValueKind_Addr);
  1341. }
  1342. else
  1343. {
  1344. typedValue = BfTypedValue(CreateAlloca(type), type, BfTypedValueKind_Addr);
  1345. }
  1346. if (!mBfIRBuilder->mIgnoreWrites)
  1347. {
  1348. mBfIRBuilder->CreateMemSet(typedValue.mValue, GetConstValue(0, GetPrimitiveType(BfTypeCode_Int8)),
  1349. GetConstValue(type->mSize), type->mAlign);
  1350. }
  1351. if ((defaultValueKind == BfDefaultValueKind_Value) && (!type->IsRef()))
  1352. typedValue = LoadValue(typedValue);
  1353. return typedValue;
  1354. }
  1355. if ((type->IsRef()) && (!allowRef))
  1356. {
  1357. BfRefType* refType = (BfRefType*)type;
  1358. BfType* underlyingType = refType->GetUnderlyingType();
  1359. if (underlyingType->IsValuelessType())
  1360. typedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), underlyingType, true);
  1361. else
  1362. typedValue = BfTypedValue(mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(type)), underlyingType, true);
  1363. }
  1364. else
  1365. {
  1366. typedValue = BfTypedValue(GetDefaultValue(type), type, (defaultValueKind == BfDefaultValueKind_Addr) ? BfTypedValueKind_Addr : BfTypedValueKind_Value);
  1367. }
  1368. return typedValue;
  1369. }
  1370. BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, bool define)
  1371. {
  1372. String stringDataName = StrFormat("__bfStrData%d", stringId);
  1373. auto charType = GetPrimitiveType(BfTypeCode_Char8);
  1374. BfIRType irStrCharType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(charType), (int)str.length() + 1);
  1375. BfIRValue strConstant;
  1376. if (define)
  1377. {
  1378. strConstant = mBfIRBuilder->CreateConstString(str);
  1379. }
  1380. BfIRValue gv = mBfIRBuilder->CreateGlobalVariable(irStrCharType,
  1381. true, BfIRLinkageType_External,
  1382. strConstant, stringDataName);
  1383. if (define)
  1384. mBfIRBuilder->GlobalVar_SetUnnamedAddr(gv, true);
  1385. return mBfIRBuilder->CreateInBoundsGEP(gv, 0, 0);
  1386. }
  1387. void BfModule::FixConstValueParams(BfTypeInstance* typeInst, SizedArrayImpl<BfIRValue>& valueParams, bool fillInPadding)
  1388. {
  1389. if ((!typeInst->mTypeDef->mIsCombinedPartial) && (!fillInPadding))
  1390. return;
  1391. int prevDataIdx = -1;
  1392. int usedDataIdx = 0;
  1393. int valueParamIdx = 0;
  1394. if (typeInst->mBaseType != NULL)
  1395. {
  1396. usedDataIdx++;
  1397. valueParamIdx++;
  1398. prevDataIdx++;
  1399. }
  1400. int startingParamsSize = (int)valueParams.mSize;
  1401. for (int fieldIdx = 0; fieldIdx < (int)typeInst->mFieldInstances.size(); fieldIdx++)
  1402. {
  1403. auto fieldInstance = &typeInst->mFieldInstances[fieldIdx];
  1404. if (fieldInstance->mDataIdx < 0)
  1405. continue;
  1406. BF_ASSERT(fieldInstance->mDataIdx > prevDataIdx);
  1407. if (fillInPadding)
  1408. {
  1409. for (int i = prevDataIdx + 1; i < fieldInstance->mDataIdx; i++)
  1410. valueParams.Insert(valueParamIdx++, mBfIRBuilder->CreateConstArrayZero(0));
  1411. }
  1412. valueParamIdx++;
  1413. prevDataIdx = fieldInstance->mDataIdx;
  1414. usedDataIdx++;
  1415. if (usedDataIdx <= valueParams.mSize)
  1416. continue;
  1417. valueParams.Add(GetDefaultValue(fieldInstance->mResolvedType));
  1418. }
  1419. }
  1420. BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId, bool define)
  1421. {
  1422. auto stringTypeInst = ResolveTypeDef(mCompiler->mStringTypeDef, define ? BfPopulateType_Data : BfPopulateType_Declaration)->ToTypeInstance();
  1423. mBfIRBuilder->PopulateType(stringTypeInst);
  1424. auto classVDataGlobal = CreateClassVDataGlobal(stringTypeInst);
  1425. String stringObjName = StrFormat("__bfStrObj%d", stringId);
  1426. BfIRValue stringValData;
  1427. if (define)
  1428. {
  1429. BfIRValue stringCharsVal = CreateStringCharPtr(str, stringId, define);
  1430. mStringCharPtrPool[stringId] = stringCharsVal;
  1431. SizedArray<BfIRValue, 8> typeValueParams;
  1432. GetConstClassValueParam(classVDataGlobal, typeValueParams);
  1433. FixConstValueParams(stringTypeInst->mBaseType, typeValueParams);
  1434. auto objData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst->mBaseType, BfIRPopulateType_Full), typeValueParams);
  1435. auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
  1436. typeValueParams.clear();
  1437. typeValueParams.push_back(objData);
  1438. if (lenByteCount == 4)
  1439. {
  1440. typeValueParams.push_back(GetConstValue32((int)str.length())); // mLength
  1441. typeValueParams.push_back(GetConstValue32((int32)(0x40000000 + str.length() + 1))); // mAllocSizeAndFlags
  1442. }
  1443. else
  1444. {
  1445. typeValueParams.push_back(GetConstValue64(str.length())); // mLength
  1446. typeValueParams.push_back(GetConstValue64(0x4000000000000000LL + str.length() + 1)); // mAllocSizeAndFlags
  1447. }
  1448. typeValueParams.push_back(stringCharsVal); // mPtr
  1449. FixConstValueParams(stringTypeInst, typeValueParams);
  1450. stringValData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams);
  1451. }
  1452. mBfIRBuilder->PopulateType(stringTypeInst);
  1453. auto stringValLiteral = mBfIRBuilder->CreateGlobalVariable(
  1454. mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full),
  1455. true,
  1456. BfIRLinkageType_External,
  1457. define ? stringValData : BfIRValue(),
  1458. stringObjName);
  1459. return stringValLiteral;
  1460. }
  1461. int BfModule::GetStringPoolIdx(BfIRValue constantStr, BfIRConstHolder* constHolder)
  1462. {
  1463. BF_ASSERT(constantStr.IsConst());
  1464. if (constHolder == NULL)
  1465. constHolder = mBfIRBuilder;
  1466. auto constant = constHolder->GetConstant(constantStr);
  1467. if (constant->mTypeCode == BfTypeCode_StringId)
  1468. {
  1469. return constant->mInt32;
  1470. }
  1471. while (constant->mConstType == BfConstType_BitCast)
  1472. {
  1473. auto constBitCast = (BfConstantBitCast*)constant;
  1474. constant = constHolder->GetConstantById(constBitCast->mTarget);
  1475. }
  1476. if (constant->mConstType == BfConstType_GEP32_2)
  1477. {
  1478. auto constGEP = (BfConstantGEP32_2*)constant;
  1479. constant = constHolder->GetConstantById(constGEP->mTarget);
  1480. }
  1481. if (constant->mConstType == BfConstType_GlobalVar)
  1482. {
  1483. auto constGV = (BfGlobalVar*)constant;
  1484. const char* strDataPrefix = "__bfStrData";
  1485. if (strncmp(constGV->mName, strDataPrefix, strlen(strDataPrefix)) == 0)
  1486. return atoi(constGV->mName + strlen(strDataPrefix));
  1487. const char* strObjPrefix = "__bfStrObj";
  1488. if (strncmp(constGV->mName, strObjPrefix, strlen(strObjPrefix)) == 0)
  1489. return atoi(constGV->mName + strlen(strObjPrefix));
  1490. }
  1491. return -1;
  1492. }
  1493. String* BfModule::GetStringPoolString(BfIRValue constantStr, BfIRConstHolder * constHolder)
  1494. {
  1495. int strId = GetStringPoolIdx(constantStr, constHolder);
  1496. if (strId != -1)
  1497. {
  1498. auto& entry = mContext->mStringObjectIdMap[strId];
  1499. return &entry.mString;
  1500. }
  1501. return NULL;
  1502. }
  1503. CeDbgState* BfModule::GetCeDbgState()
  1504. {
  1505. if (!mIsComptimeModule)
  1506. return NULL;
  1507. if ((mCompiler->mCeMachine != NULL) && (mCompiler->mCeMachine->mDebugger != NULL))
  1508. return mCompiler->mCeMachine->mDebugger->mCurDbgState;
  1509. return NULL;
  1510. }
  1511. BfIRValue BfModule::GetStringCharPtr(int stringId, bool force)
  1512. {
  1513. if ((mBfIRBuilder->mIgnoreWrites) && (!force))
  1514. {
  1515. mUnreifiedStringPoolRefs.Add(stringId);
  1516. return mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId);
  1517. }
  1518. BfIRValue* irValue = NULL;
  1519. if (!mStringCharPtrPool.TryAdd(stringId, NULL, &irValue))
  1520. return *irValue;
  1521. // If this wasn't in neither dictionary yet, add to mStringPoolRefs
  1522. if (!mStringObjectPool.ContainsKey(stringId))
  1523. mStringPoolRefs.Add(stringId);
  1524. const StringImpl& str = mContext->mStringObjectIdMap[stringId].mString;
  1525. BfIRValue strCharPtrConst = CreateStringCharPtr(str, stringId, false);
  1526. *irValue = strCharPtrConst;
  1527. return strCharPtrConst;
  1528. }
  1529. BfIRValue BfModule::GetStringCharPtr(BfIRValue strValue, bool force)
  1530. {
  1531. if (strValue.IsConst())
  1532. {
  1533. int stringId = GetStringPoolIdx(strValue);
  1534. BF_ASSERT(stringId != -1);
  1535. return GetStringCharPtr(stringId, force);
  1536. }
  1537. BfIRValue charPtrPtr = mBfIRBuilder->CreateInBoundsGEP(strValue, 0, 1);
  1538. BfIRValue charPtr = mBfIRBuilder->CreateLoad(charPtrPtr);
  1539. return charPtr;
  1540. }
  1541. BfIRValue BfModule::GetStringCharPtr(const StringImpl& str, bool force)
  1542. {
  1543. return GetStringCharPtr(GetStringObjectValue(str, force), force);
  1544. }
  1545. BfIRValue BfModule::GetStringObjectValue(int strId, bool define, bool force)
  1546. {
  1547. BfIRValue* objValue;
  1548. if (mStringObjectPool.TryGetValue(strId, &objValue))
  1549. return *objValue;
  1550. auto stringPoolEntry = mContext->mStringObjectIdMap[strId];
  1551. return GetStringObjectValue(stringPoolEntry.mString, define, force);
  1552. }
  1553. BfIRValue BfModule::GetStringObjectValue(const StringImpl& str, bool define, bool force)
  1554. {
  1555. auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef, define ? BfPopulateType_Data : BfPopulateType_Declaration);
  1556. mBfIRBuilder->PopulateType(stringType);
  1557. int strId = mContext->GetStringLiteralId(str);
  1558. if ((mBfIRBuilder->mIgnoreWrites) && (!force))
  1559. {
  1560. auto refModule = this;
  1561. if ((this == mContext->mUnreifiedModule) && (mCurTypeInstance != NULL))
  1562. refModule = mCurTypeInstance->mModule;
  1563. refModule->mUnreifiedStringPoolRefs.Add(strId);
  1564. return mBfIRBuilder->CreateConst(BfTypeCode_StringId, strId);
  1565. }
  1566. BfIRValue* irValuePtr = NULL;
  1567. if (mStringObjectPool.TryGetValue(strId, &irValuePtr))
  1568. return *irValuePtr;
  1569. // If this wasn't in neither dictionary yet, add to mStringPoolRefs
  1570. if (!mStringCharPtrPool.ContainsKey(strId))
  1571. mStringPoolRefs.Add(strId);
  1572. BfIRValue strObject = CreateStringObjectValue(str, strId, define);
  1573. mStringObjectPool[strId] = strObject;
  1574. mStringPoolRefs.Add(strId);
  1575. return strObject;
  1576. }
  1577. BfIRValue BfModule::CreateGlobalConstValue(const StringImpl& name, BfIRValue constant, BfIRType type, bool external)
  1578. {
  1579. auto newConst = mBfIRBuilder->CreateGlobalVariable(
  1580. type,
  1581. true,
  1582. external ? BfIRLinkageType_External : BfIRLinkageType_Internal,
  1583. constant,
  1584. name.c_str());
  1585. return newConst;
  1586. }
  1587. void BfModule::NewScopeState(bool createLexicalBlock, bool flushValueScope)
  1588. {
  1589. auto curScope = mCurMethodState->mCurScope;
  1590. if (curScope->mLabelNode != NULL)
  1591. {
  1592. curScope->mLabelNode->ToString(curScope->mLabel);
  1593. auto rootMethodState = mCurMethodState->GetRootMethodState();
  1594. curScope->mScopeLocalId = rootMethodState->mCurLocalVarId++;
  1595. auto autoComplete = mCompiler->GetAutoComplete();
  1596. if (autoComplete != NULL)
  1597. autoComplete->CheckLabel(curScope->mLabelNode, NULL, curScope);
  1598. }
  1599. if (!mCurMethodState->mCurScope->mLabel.IsEmpty())
  1600. {
  1601. auto checkScope = mCurMethodState->mCurScope->mPrevScope;
  1602. while (checkScope != NULL)
  1603. {
  1604. if (checkScope->mLabel == mCurMethodState->mCurScope->mLabel)
  1605. {
  1606. auto errorNode = Fail("Duplicate scope label", curScope->mLabelNode);
  1607. if (errorNode != NULL)
  1608. mCompiler->mPassInstance->MoreInfo("See previous scope label", checkScope->mLabelNode);
  1609. break;
  1610. }
  1611. checkScope = checkScope->mPrevScope;
  1612. }
  1613. }
  1614. auto prevScope = mCurMethodState->mCurScope->mPrevScope;
  1615. if ((flushValueScope) && (prevScope != NULL) && (prevScope->mValueScopeStart))
  1616. {
  1617. if (prevScope->mHadScopeValueRetain)
  1618. mBfIRBuilder->CreateValueScopeSoftEnd(prevScope->mValueScopeStart);
  1619. else
  1620. mBfIRBuilder->CreateValueScopeHardEnd(prevScope->mValueScopeStart);
  1621. }
  1622. mCurMethodState->mBlockNestLevel++;
  1623. if ((createLexicalBlock) && (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo))
  1624. {
  1625. // DIScope could be NULL if we're in an unspecialized method (for example)
  1626. if (mCurMethodState->mCurScope->mDIScope)
  1627. mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateLexicalBlock(mCurMethodState->mCurScope->mDIScope, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mCurFilePosition.mCurColumn);
  1628. }
  1629. mCurMethodState->mCurScope->mLocalVarStart = (int)mCurMethodState->mLocals.size();
  1630. mCurMethodState->mCurScope->mBlock = mBfIRBuilder->MaybeChainNewBlock((!mCurMethodState->mCurScope->mLabel.empty()) ? mCurMethodState->mCurScope->mLabel : "newScope");
  1631. mCurMethodState->mCurScope->mMixinState = mCurMethodState->mMixinState;
  1632. }
  1633. void BfModule::RestoreScoreState_LocalVariables()
  1634. {
  1635. while (mCurMethodState->mCurScope->mLocalVarStart < (int)mCurMethodState->mLocals.size())
  1636. {
  1637. auto localVar = mCurMethodState->mLocals.back();
  1638. LocalVariableDone(localVar, false);
  1639. mCurMethodState->mLocals.pop_back();
  1640. if (localVar->mShadowedLocal != NULL)
  1641. {
  1642. BfLocalVarEntry* localVarEntryPtr;
  1643. if (mCurMethodState->mLocalVarSet.TryGet(BfLocalVarEntry(localVar), &localVarEntryPtr))
  1644. {
  1645. localVarEntryPtr->mLocalVar = localVar->mShadowedLocal;
  1646. }
  1647. }
  1648. else
  1649. {
  1650. mCurMethodState->mLocalVarSet.Remove(BfLocalVarEntry(localVar));
  1651. }
  1652. if (localVar->mIsBumpAlloc)
  1653. localVar->~BfLocalVariable();
  1654. else
  1655. delete localVar;
  1656. }
  1657. }
  1658. void BfModule::RestoreScopeState()
  1659. {
  1660. BfScopeData* prevScopeData = mCurMethodState->mCurScope->mPrevScope;
  1661. mCurMethodState->mBlockNestLevel--;
  1662. if (!mCurMethodState->mCurScope->mAtEndBlocks.empty())
  1663. {
  1664. BfIRBlock afterEndBlock;
  1665. if (!mCurMethodState->mLeftBlockUncond)
  1666. {
  1667. afterEndBlock = mBfIRBuilder->CreateBlock("scopeAfterEnd");
  1668. mBfIRBuilder->CreateBr(afterEndBlock);
  1669. mBfIRBuilder->ClearDebugLocation_Last();
  1670. }
  1671. for (auto preExitBlock : mCurMethodState->mCurScope->mAtEndBlocks)
  1672. mBfIRBuilder->MoveBlockToEnd(preExitBlock);
  1673. if (afterEndBlock)
  1674. {
  1675. mBfIRBuilder->AddBlock(afterEndBlock);
  1676. mBfIRBuilder->SetInsertPoint(afterEndBlock);
  1677. }
  1678. }
  1679. if (!mCurMethodState->mLeftBlockUncond)
  1680. EmitDeferredScopeCalls(true, mCurMethodState->mCurScope);
  1681. RestoreScoreState_LocalVariables();
  1682. if (mCurMethodState->mCurScope->mValueScopeStart)
  1683. mBfIRBuilder->CreateValueScopeHardEnd(mCurMethodState->mCurScope->mValueScopeStart);
  1684. mCurMethodState->mCurScope = prevScopeData;
  1685. mCurMethodState->mTailScope = mCurMethodState->mCurScope;
  1686. }
  1687. BfIRValue BfModule::CreateAlloca(BfType* type, bool addLifetime, const char* name, BfIRValue arraySize)
  1688. {
  1689. if (mBfIRBuilder->mIgnoreWrites)
  1690. return mBfIRBuilder->GetFakeVal();
  1691. BF_ASSERT((*(int8*)&addLifetime == 1) || (*(int8*)&addLifetime == 0));
  1692. mBfIRBuilder->PopulateType(type);
  1693. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  1694. if (!mBfIRBuilder->mIgnoreWrites)
  1695. BF_ASSERT(!prevInsertBlock.IsFake());
  1696. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  1697. BfIRValue allocaInst;
  1698. if (arraySize)
  1699. allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(type), arraySize);
  1700. else
  1701. allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(type));
  1702. mBfIRBuilder->SetAllocaAlignment(allocaInst, type->mAlign);
  1703. mBfIRBuilder->ClearDebugLocation(allocaInst);
  1704. if (name != NULL)
  1705. mBfIRBuilder->SetName(allocaInst, name);
  1706. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  1707. if ((addLifetime) && (WantsLifetimes()))
  1708. {
  1709. auto lifetimeStart = mBfIRBuilder->CreateLifetimeStart(allocaInst);
  1710. mBfIRBuilder->ClearDebugLocation(lifetimeStart);
  1711. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(allocaInst);
  1712. }
  1713. return allocaInst;
  1714. }
  1715. BfIRValue BfModule::CreateAllocaInst(BfTypeInstance* typeInst, bool addLifetime, const char* name)
  1716. {
  1717. if (mBfIRBuilder->mIgnoreWrites)
  1718. return mBfIRBuilder->GetFakeVal();
  1719. BF_ASSERT((*(int8*)&addLifetime == 1) || (*(int8*)&addLifetime == 0));
  1720. mBfIRBuilder->PopulateType(typeInst);
  1721. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  1722. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  1723. auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapTypeInst(typeInst));
  1724. mBfIRBuilder->SetAllocaAlignment(allocaInst, typeInst->mInstAlign);
  1725. mBfIRBuilder->ClearDebugLocation(allocaInst);
  1726. if (name != NULL)
  1727. mBfIRBuilder->SetName(allocaInst, name);
  1728. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  1729. if ((addLifetime) && (WantsLifetimes()))
  1730. {
  1731. auto lifetimeStart = mBfIRBuilder->CreateLifetimeStart(allocaInst);
  1732. mBfIRBuilder->ClearDebugLocation(lifetimeStart);
  1733. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(allocaInst);
  1734. }
  1735. return allocaInst;
  1736. }
  1737. BfDeferredCallEntry* BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* refNode, BfScopeData* scopeData, bool condAlloca, bool mayEscape, BfIRBlock valBlock)
  1738. {
  1739. //This was removed because we want the alloc to be added to the __deferred list if it's actually a "stack"
  1740. // 'stack' in a head scopeData is really the same as 'scopeData', so use the simpler scopeData handling
  1741. /*if (mCurMethodState->mInHeadScope)
  1742. isScopeAlloc = true;*/
  1743. if (scopeData == NULL)
  1744. return NULL;
  1745. auto checkBaseType = val.mType->ToTypeInstance();
  1746. if ((checkBaseType != NULL) && (checkBaseType->IsObject()) && (!arraySize))
  1747. {
  1748. bool hadDtorCall = false;
  1749. while (checkBaseType != NULL)
  1750. {
  1751. BfMethodDef* dtorMethodDef = checkBaseType->mTypeDef->GetMethodByName("~this");
  1752. if (dtorMethodDef != NULL)
  1753. {
  1754. auto dtorMethodInstance = GetMethodInstance(checkBaseType, dtorMethodDef, BfTypeVector());
  1755. if (dtorMethodInstance)
  1756. {
  1757. bool isDynAlloc = (scopeData != NULL) && (mCurMethodState->mCurScope->IsDyn(scopeData));
  1758. BfIRValue useVal = val.mValue;
  1759. BfIRBlock prevBlock = mBfIRBuilder->GetInsertBlock();
  1760. if (valBlock)
  1761. mBfIRBuilder->SetInsertPoint(valBlock);
  1762. useVal = mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapTypeInstPtr(checkBaseType));
  1763. if (!useVal.IsConst())
  1764. mBfIRBuilder->ClearDebugLocation(useVal);
  1765. if (valBlock)
  1766. mBfIRBuilder->SetInsertPoint(prevBlock);
  1767. if (isDynAlloc)
  1768. {
  1769. //
  1770. }
  1771. else if (condAlloca)
  1772. {
  1773. BF_ASSERT(!IsTargetingBeefBackend());
  1774. BF_ASSERT(!isDynAlloc);
  1775. auto valPtr = CreateAlloca(checkBaseType);
  1776. mBfIRBuilder->ClearDebugLocation_Last();
  1777. mBfIRBuilder->CreateAlignedStore(useVal, valPtr, checkBaseType->mAlign);
  1778. mBfIRBuilder->ClearDebugLocation_Last();
  1779. useVal = valPtr;
  1780. }
  1781. SizedArray<BfIRValue, 1> llvmArgs;
  1782. llvmArgs.push_back(useVal);
  1783. auto deferredCall = AddDeferredCall(dtorMethodInstance, llvmArgs, scopeData, refNode, true);
  1784. if (deferredCall != NULL)
  1785. {
  1786. deferredCall->mCastThis = (val.mType != checkBaseType) && (!isDynAlloc);
  1787. if (condAlloca)
  1788. deferredCall->mArgsNeedLoad = true;
  1789. }
  1790. hadDtorCall = true;
  1791. break;
  1792. }
  1793. }
  1794. checkBaseType = checkBaseType->mBaseType;
  1795. }
  1796. return NULL;
  1797. }
  1798. //TODO: In the future we could be smarter about statically determining that our value hasn't escaped and eliding this
  1799. if (mayEscape)
  1800. {
  1801. if ((!IsOptimized()) && (!mIsComptimeModule) && (!val.mType->IsValuelessType()) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly))
  1802. {
  1803. auto nullPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  1804. bool isDyn = mCurMethodState->mCurScope->IsDyn(scopeData);
  1805. if (!isDyn)
  1806. {
  1807. const char* methodName = arraySize ? "SetDeletedArray" : "SetDeleted";
  1808. BfModuleMethodInstance dtorMethodInstance = GetInternalMethod(methodName);
  1809. BF_ASSERT(dtorMethodInstance.mMethodInstance != NULL);
  1810. if (!dtorMethodInstance.mMethodInstance)
  1811. {
  1812. Fail(StrFormat("Unable to find %s", methodName));
  1813. }
  1814. else
  1815. {
  1816. SizedArray<BfIRValue, 1> llvmArgs;
  1817. if (IsTargetingBeefBackend())
  1818. {
  1819. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
  1820. //mBfIRBuilder->ClearDebugLocation_Last();
  1821. }
  1822. else
  1823. llvmArgs.push_back(val.mValue);
  1824. llvmArgs.push_back(GetConstValue(val.mType->mSize));
  1825. llvmArgs.push_back(GetConstValue32(val.mType->mAlign));
  1826. if (arraySize)
  1827. llvmArgs.push_back(arraySize);
  1828. return AddDeferredCall(dtorMethodInstance, llvmArgs, scopeData, refNode, true);
  1829. }
  1830. }
  1831. else
  1832. {
  1833. if ((arraySize) && (!arraySize.IsConst()) && (val.mType->mSize < mSystem->mPtrSize))
  1834. {
  1835. BfIRValue clearSize = arraySize;
  1836. if (val.mType->GetStride() > 1)
  1837. clearSize = mBfIRBuilder->CreateMul(clearSize, GetConstValue(val.mType->GetStride()));
  1838. const char* methodName = "SetDeletedX";
  1839. BfModuleMethodInstance dtorMethodInstance = GetInternalMethod(methodName);
  1840. BF_ASSERT(dtorMethodInstance);
  1841. if (!dtorMethodInstance)
  1842. {
  1843. Fail(StrFormat("Unable to find %s", methodName));
  1844. }
  1845. else
  1846. {
  1847. SizedArray<BfIRValue, 1> llvmArgs;
  1848. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
  1849. //mBfIRBuilder->ClearDebugLocation_Last();
  1850. llvmArgs.push_back(clearSize);
  1851. return AddDeferredCall(dtorMethodInstance, llvmArgs, scopeData, refNode, true);
  1852. }
  1853. }
  1854. else
  1855. {
  1856. intptr clearSize = val.mType->mSize;
  1857. auto constant = mBfIRBuilder->GetConstant(arraySize);
  1858. if (constant != NULL)
  1859. clearSize = (intptr)(clearSize * constant->mInt64);
  1860. const char* funcName = "SetDeleted1";
  1861. if (clearSize >= 16)
  1862. funcName = "SetDeleted16";
  1863. else if (clearSize >= 8)
  1864. funcName = "SetDeleted8";
  1865. else if (clearSize >= 4)
  1866. funcName = "SetDeleted4";
  1867. BfModuleMethodInstance dtorMethodInstance = GetInternalMethod(funcName);
  1868. BF_ASSERT(dtorMethodInstance.mMethodInstance != NULL);
  1869. if (!dtorMethodInstance)
  1870. {
  1871. Fail(StrFormat("Unable to find %s", funcName));
  1872. }
  1873. else
  1874. {
  1875. SizedArray<BfIRValue, 1> llvmArgs;
  1876. llvmArgs.push_back(mBfIRBuilder->CreateBitCast(val.mValue, mBfIRBuilder->MapType(nullPtrType)));
  1877. //mBfIRBuilder->ClearDebugLocation_Last();
  1878. return AddDeferredCall(dtorMethodInstance, llvmArgs, scopeData, refNode, true);
  1879. }
  1880. }
  1881. }
  1882. }
  1883. }
  1884. return NULL;
  1885. }
  1886. bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
  1887. {
  1888. auto startTypeInstance = localVar->mResolvedType->ToTypeInstance();
  1889. if ((startTypeInstance == NULL) || (!startTypeInstance->IsStruct()))
  1890. return false;
  1891. auto checkTypeInstance = startTypeInstance;
  1892. while (checkTypeInstance != NULL)
  1893. {
  1894. for (auto& fieldInstance : checkTypeInstance->mFieldInstances)
  1895. {
  1896. if (fieldInstance.mMergedDataIdx != -1)
  1897. {
  1898. int64 checkMask = (int64)1 << fieldInstance.mMergedDataIdx;
  1899. if ((localVar->mUnassignedFieldFlags & checkMask) != 0)
  1900. {
  1901. // For fields added in extensions, we automatically initialize those if necessary
  1902. auto fieldDef = fieldInstance.GetFieldDef();
  1903. if (!fieldDef->mDeclaringType->IsExtension())
  1904. return false;
  1905. if ((fieldInstance.mDataIdx != -1) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly) && (!mIsComptimeModule))
  1906. {
  1907. auto curInsertBlock = mBfIRBuilder->GetInsertBlock();
  1908. mBfIRBuilder->SaveDebugLocation();
  1909. if (localVar->IsParam())
  1910. mBfIRBuilder->SetInsertPointAtStart(mCurMethodState->mIRInitBlock);
  1911. else
  1912. {
  1913. BF_ASSERT(localVar->mDeclBlock);
  1914. mBfIRBuilder->SetInsertPointAtStart(localVar->mDeclBlock);
  1915. }
  1916. mBfIRBuilder->ClearDebugLocation();
  1917. BfIRValue curVal;
  1918. if (localVar->mIsThis)
  1919. curVal = mBfIRBuilder->GetArgument(0);
  1920. else
  1921. curVal = localVar->mAddr;
  1922. auto subTypeInstance = startTypeInstance;
  1923. while (subTypeInstance != checkTypeInstance)
  1924. {
  1925. curVal = mBfIRBuilder->CreateInBoundsGEP(curVal, 0, 0);
  1926. subTypeInstance = subTypeInstance->mBaseType;
  1927. }
  1928. auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(curVal, 0, fieldInstance.mDataIdx);
  1929. auto defVal = GetDefaultValue(fieldInstance.mResolvedType);
  1930. auto storeInst = mBfIRBuilder->CreateStore(defVal, fieldPtr);
  1931. mBfIRBuilder->SetInsertPoint(curInsertBlock);
  1932. mBfIRBuilder->RestoreDebugLocation();
  1933. }
  1934. localVar->mUnassignedFieldFlags &= ~checkMask;
  1935. if (localVar->mUnassignedFieldFlags == 0)
  1936. localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  1937. }
  1938. }
  1939. }
  1940. checkTypeInstance = checkTypeInstance->mBaseType;
  1941. }
  1942. return localVar->mAssignedKind != BfLocalVarAssignKind_None;
  1943. }
  1944. void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
  1945. {
  1946. BfAstNode* localNameNode = localVar->mNameNode;
  1947. if (localVar->mIsThis)
  1948. {
  1949. localNameNode = mCurMethodInstance->mMethodDef->GetRefNode();
  1950. }
  1951. if (localNameNode != NULL)
  1952. {
  1953. bool isOut = false;
  1954. if (localVar->mResolvedType->IsRef())
  1955. {
  1956. auto refType = (BfRefType*)localVar->mResolvedType;
  1957. isOut = refType->mRefKind == BfRefType::RefKind_Out;
  1958. }
  1959. if ((localVar->mReadFromId == -1) || (isOut) || ((localVar->mIsThis) && (mCurTypeInstance->IsStruct())))
  1960. {
  1961. if ((localVar->mAssignedKind != BfLocalVarAssignKind_Unconditional) & (localVar->IsParam()))
  1962. TryLocalVariableInit(localVar);
  1963. // We may skip processing of local methods, so we won't know if it bind to any of our local variables or not
  1964. bool deferFullAnalysis = mCurMethodState->GetRootMethodState()->mLocalMethodCache.size() != 0;
  1965. // We may have init blocks that we aren't processing here...
  1966. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsAutocompleteMethod) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Ctor))
  1967. deferFullAnalysis = true;
  1968. //bool deferFullAnalysis = true;
  1969. bool deferUsageWarning = deferFullAnalysis && (mCompiler->IsAutocomplete()) &&
  1970. (mCompiler->mResolvePassData->mAutoComplete->mResolveType != BfResolveType_GetFixits);
  1971. if (((localVar->mAssignedKind != BfLocalVarAssignKind_Unconditional) || (localVar->mHadExitBeforeAssign)) &&
  1972. (!localVar->mIsImplicitParam))
  1973. {
  1974. if (deferUsageWarning)
  1975. {
  1976. // Ignore
  1977. }
  1978. else if (localVar->mIsThis)
  1979. {
  1980. bool foundFields = false;
  1981. auto checkTypeInstance = mCurTypeInstance;
  1982. while (checkTypeInstance != NULL)
  1983. {
  1984. for (auto& fieldInstance : checkTypeInstance->mFieldInstances)
  1985. {
  1986. if (fieldInstance.mMergedDataIdx == -1)
  1987. continue;
  1988. int checkMask = 1 << fieldInstance.mMergedDataIdx;
  1989. if ((localVar->mUnassignedFieldFlags & checkMask) != 0)
  1990. {
  1991. auto fieldDef = fieldInstance.GetFieldDef();
  1992. if (mCurMethodInstance->mMethodDef->mDeclaringType->mIsPartial)
  1993. {
  1994. if (mCurMethodInstance->mMethodDef->mDeclaringType != fieldInstance.GetFieldDef()->mDeclaringType)
  1995. {
  1996. // This extension is only responsible for its own fields
  1997. foundFields = true;
  1998. continue;
  1999. }
  2000. if (fieldDef->GetInitializer() != NULL)
  2001. {
  2002. // This initializer was handled in CtorNoBody
  2003. foundFields = true;
  2004. continue;
  2005. }
  2006. }
  2007. if (auto propertyDeclaration = BfNodeDynCast<BfPropertyDeclaration>(fieldDef->mFieldDeclaration))
  2008. {
  2009. String propName;
  2010. if (propertyDeclaration->mNameNode != NULL)
  2011. propertyDeclaration->mNameNode->ToString(propName);
  2012. if (checkTypeInstance == mCurTypeInstance)
  2013. {
  2014. Fail(StrFormat("Auto-implemented property '%s' must be fully assigned before control is returned to the caller",
  2015. propName.c_str()), localNameNode, deferFullAnalysis); // 0171
  2016. }
  2017. else
  2018. {
  2019. Fail(StrFormat("Auto-implemented property '%s.%s' must be fully assigned before control is returned to the caller",
  2020. TypeToString(checkTypeInstance).c_str(),
  2021. propName.c_str()), localNameNode, deferFullAnalysis); // 0171
  2022. }
  2023. }
  2024. else
  2025. {
  2026. if (checkTypeInstance == mCurTypeInstance)
  2027. {
  2028. Fail(StrFormat("Field '%s' must be fully assigned before control is returned to the caller",
  2029. fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
  2030. }
  2031. else
  2032. {
  2033. Fail(StrFormat("Field '%s.%s' must be fully assigned before control is returned to the caller",
  2034. TypeToString(checkTypeInstance).c_str(),
  2035. fieldDef->mName.c_str()), localNameNode, deferFullAnalysis); // 0171
  2036. }
  2037. }
  2038. foundFields = true;
  2039. }
  2040. }
  2041. checkTypeInstance = checkTypeInstance->mBaseType;
  2042. }
  2043. if (!foundFields)
  2044. {
  2045. if (mCurTypeInstance->mInstSize > 0)
  2046. Fail(StrFormat("The variable '%s' must be fully assigned to before control leaves the current method", localVar->mName.c_str()), localNameNode); // 0177
  2047. }
  2048. }
  2049. else if (localVar->IsParam())
  2050. Fail(StrFormat("The out parameter '%s' must be assigned to before control leaves the current method", localVar->mName.c_str()), localNameNode, deferFullAnalysis); // 0177
  2051. else if (!deferUsageWarning)
  2052. Warn(BfWarning_CS0168_VariableDeclaredButNeverUsed, StrFormat("The variable '%s' is declared but never used", localVar->mName.c_str()), localNameNode, deferFullAnalysis);
  2053. }
  2054. else if ((localVar->mReadFromId == -1) && (!localVar->IsParam()) && (!deferUsageWarning))
  2055. Warn(BfWarning_CS0168_VariableDeclaredButNeverUsed, StrFormat("The variable '%s' is assigned but its value is never used", localVar->mName.c_str()), localNameNode, deferFullAnalysis);
  2056. }
  2057. }
  2058. }
  2059. void BfModule::CreateRetValLocal()
  2060. {
  2061. if (mCurMethodState->mRetVal)
  2062. {
  2063. BfLocalVariable* localDef = new BfLocalVariable();
  2064. localDef->mName = "return";
  2065. localDef->mResolvedType = mCurMethodState->mRetVal.mType;
  2066. localDef->mAddr = mCurMethodState->mRetVal.mValue;
  2067. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  2068. AddLocalVariableDef(localDef);
  2069. }
  2070. else if (mCurMethodState->mRetValAddr)
  2071. {
  2072. BfLocalVariable* localDef = new BfLocalVariable();
  2073. localDef->mName = "return";
  2074. localDef->mResolvedType = CreateRefType(mCurMethodInstance->mReturnType);
  2075. localDef->mAddr = mCurMethodState->mRetValAddr;
  2076. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  2077. AddLocalVariableDef(localDef);
  2078. }
  2079. }
  2080. void BfModule::MarkDynStack(BfScopeData* scopeData)
  2081. {
  2082. auto checkScope = mCurMethodState->mCurScope;
  2083. while (true)
  2084. {
  2085. if (checkScope == scopeData)
  2086. break;
  2087. checkScope->mHadOuterDynStack = true;
  2088. checkScope = checkScope->mPrevScope;
  2089. }
  2090. }
  2091. void BfModule::SaveStackState(BfScopeData* scopeData)
  2092. {
  2093. // If we push a value on the stack that needs to survive until the end of scopeData, we need to make sure that no
  2094. // scopes within scopeData restore the stack
  2095. auto checkScope = mCurMethodState->mCurScope;
  2096. while (true)
  2097. {
  2098. if (checkScope == scopeData)
  2099. {
  2100. if ((!checkScope->mSavedStack) && (checkScope->mBlock) && (!checkScope->mIsScopeHead) && (!checkScope->mHadOuterDynStack))
  2101. {
  2102. if (mBfIRBuilder->mHasDebugInfo)
  2103. mBfIRBuilder->SaveDebugLocation();
  2104. auto prevPos = mBfIRBuilder->GetInsertBlock();
  2105. mBfIRBuilder->SetInsertPointAtStart(checkScope->mBlock);
  2106. checkScope->mSavedStack = mBfIRBuilder->CreateStackSave();
  2107. mBfIRBuilder->ClearDebugLocation(checkScope->mSavedStack);
  2108. mBfIRBuilder->SetInsertPoint(prevPos);
  2109. if (mBfIRBuilder->mHasDebugInfo)
  2110. mBfIRBuilder->RestoreDebugLocation();
  2111. }
  2112. break;
  2113. }
  2114. if (checkScope->mSavedStack)
  2115. {
  2116. for (auto usage : checkScope->mSavedStackUses)
  2117. mBfIRBuilder->EraseInstFromParent(usage);
  2118. checkScope->mSavedStackUses.Clear();
  2119. mBfIRBuilder->EraseInstFromParent(checkScope->mSavedStack);
  2120. checkScope->mSavedStack = BfIRValue();
  2121. }
  2122. checkScope = checkScope->mPrevScope;
  2123. }
  2124. }
  2125. BfIRValue BfModule::ValueScopeStart()
  2126. {
  2127. if (IsTargetingBeefBackend())
  2128. return mBfIRBuilder->CreateValueScopeStart();
  2129. return BfIRValue();
  2130. }
  2131. void BfModule::ValueScopeEnd(BfIRValue valueScopeStart)
  2132. {
  2133. if (valueScopeStart)
  2134. mBfIRBuilder->CreateValueScopeHardEnd(valueScopeStart);
  2135. }
  2136. BfProjectSet* BfModule::GetVisibleProjectSet()
  2137. {
  2138. if (mCurMethodState == NULL)
  2139. return NULL;
  2140. if (mCurMethodState->mVisibleProjectSet.IsEmpty())
  2141. {
  2142. HashSet<BfType*> seenTypes;
  2143. std::function<void(BfProject* project)> _AddProject = [&](BfProject* project)
  2144. {
  2145. if (mCurMethodState->mVisibleProjectSet.Add(project))
  2146. {
  2147. for (auto dep : project->mDependencies)
  2148. _AddProject(dep);
  2149. }
  2150. };
  2151. std::function<void(BfType* type)> _AddType = [&](BfType* type)
  2152. {
  2153. auto typeInstance = type->ToTypeInstance();
  2154. if (typeInstance == NULL)
  2155. {
  2156. if (type->IsSizedArray())
  2157. _AddType(type->GetUnderlyingType());
  2158. return;
  2159. }
  2160. if (typeInstance->IsTuple())
  2161. {
  2162. for (auto& fieldInst : typeInstance->mFieldInstances)
  2163. {
  2164. if (fieldInst.mDataIdx != -1)
  2165. _AddType(fieldInst.mResolvedType);
  2166. }
  2167. }
  2168. _AddProject(typeInstance->mTypeDef->mProject);
  2169. if (typeInstance->mGenericTypeInfo == NULL)
  2170. return;
  2171. for (auto type : typeInstance->mGenericTypeInfo->mTypeGenericArguments)
  2172. {
  2173. if (seenTypes.Add(type))
  2174. _AddType(type);
  2175. }
  2176. };
  2177. if (mCurTypeInstance != NULL)
  2178. _AddType(mCurTypeInstance);
  2179. auto methodState = mCurMethodState;
  2180. while (methodState != NULL)
  2181. {
  2182. if (methodState->mMethodInstance != NULL)
  2183. {
  2184. _AddProject(methodState->mMethodInstance->mMethodDef->mDeclaringType->mProject);
  2185. if (methodState->mMethodInstance->mMethodInfoEx != NULL)
  2186. {
  2187. for (auto type : methodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments)
  2188. _AddType(type);
  2189. }
  2190. }
  2191. methodState = methodState->mPrevMethodState;
  2192. }
  2193. }
  2194. return &mCurMethodState->mVisibleProjectSet;
  2195. }
  2196. BfFileInstance* BfModule::GetFileFromNode(BfAstNode* astNode)
  2197. {
  2198. auto bfParser = astNode->GetSourceData()->ToParserData();
  2199. if (bfParser == NULL)
  2200. return NULL;
  2201. BfFileInstance** fileInstancePtr = NULL;
  2202. if (!mFileInstanceMap.TryAdd(bfParser, NULL, &fileInstancePtr))
  2203. {
  2204. return *fileInstancePtr;
  2205. }
  2206. else
  2207. {
  2208. // It's possible two parsers have the same file name (ie: mNextRevision)
  2209. BfFileInstance** namedFileInstancePtr = NULL;
  2210. if (!mNamedFileInstanceMap.TryAdd(bfParser->mFileName, NULL, &namedFileInstancePtr))
  2211. {
  2212. auto bfFileInstance = *namedFileInstancePtr;
  2213. *fileInstancePtr = bfFileInstance;
  2214. return bfFileInstance;
  2215. }
  2216. int slashPos = (int)bfParser->mFileName.LastIndexOf(DIR_SEP_CHAR);
  2217. auto bfFileInstance = new BfFileInstance();
  2218. *fileInstancePtr = bfFileInstance;
  2219. *namedFileInstancePtr = bfFileInstance;
  2220. bfFileInstance->mPrevPosition.mFileInstance = bfFileInstance;
  2221. bfFileInstance->mParser = bfParser;
  2222. BfLogSysM("GetFileFromNode new file. Mod: %p FileInstance: %p Parser: %p\n", this, bfFileInstance, bfParser);
  2223. if ((mBfIRBuilder != NULL) && (mBfIRBuilder->DbgHasLineInfo()))
  2224. {
  2225. String fileName = bfParser->mFileName;
  2226. for (int i = 0; i < (int)fileName.length(); i++)
  2227. {
  2228. if (fileName[i] == DIR_SEP_CHAR_ALT)
  2229. fileName[i] = DIR_SEP_CHAR;
  2230. }
  2231. bfFileInstance->mDIFile = mBfIRBuilder->DbgCreateFile(fileName.Substring(slashPos + 1), fileName.Substring(0, BF_MAX(slashPos, 0)), bfParser->mMD5Hash);
  2232. }
  2233. return bfFileInstance;
  2234. }
  2235. }
  2236. void BfModule::UpdateSrcPos(BfAstNode* astNode, BfSrcPosFlags flags, int debugLocOffset)
  2237. {
  2238. // We set force to true when we MUST get the line position set (for navigation purposes, for example)
  2239. if (((mBfIRBuilder->mIgnoreWrites)) && ((flags & BfSrcPosFlag_Force) == 0))
  2240. return;
  2241. BF_ASSERT((!mAwaitingInitFinish) || (mBfIRBuilder->mIgnoreWrites));
  2242. if (astNode == NULL)
  2243. return;
  2244. auto bfParser = astNode->GetSourceData()->ToParserData();
  2245. if (bfParser == NULL)
  2246. return;
  2247. if ((mCurFilePosition.mFileInstance == NULL) || (mCurFilePosition.mFileInstance->mParser != bfParser))
  2248. {
  2249. if (mCurFilePosition.mFileInstance != NULL)
  2250. {
  2251. BF_ASSERT(mFileInstanceMap.GetCount() != 0);
  2252. mCurFilePosition.mFileInstance->mPrevPosition = mCurFilePosition;
  2253. }
  2254. auto bfFileInstance = GetFileFromNode(astNode);
  2255. if (bfFileInstance->mPrevPosition.mFileInstance != NULL)
  2256. {
  2257. mCurFilePosition = bfFileInstance->mPrevPosition;
  2258. }
  2259. else
  2260. {
  2261. mCurFilePosition.mFileInstance = bfFileInstance;
  2262. mCurFilePosition.mCurLine = 0;
  2263. mCurFilePosition.mCurSrcPos = 0;
  2264. }
  2265. }
  2266. int srcPos = astNode->GetSrcStart() + debugLocOffset;
  2267. BF_ASSERT(srcPos < bfParser->mSrcLength);
  2268. auto* jumpEntry = bfParser->mJumpTable + (srcPos / PARSER_JUMPTABLE_DIVIDE);
  2269. if (jumpEntry->mCharIdx > srcPos)
  2270. jumpEntry--;
  2271. mCurFilePosition.mCurLine = jumpEntry->mLineNum;
  2272. mCurFilePosition.mCurSrcPos = jumpEntry->mCharIdx;
  2273. mCurFilePosition.mCurColumn = 0;
  2274. while (mCurFilePosition.mCurSrcPos < srcPos)
  2275. {
  2276. if (bfParser->mSrc[mCurFilePosition.mCurSrcPos] == '\n')
  2277. {
  2278. mCurFilePosition.mCurLine++;
  2279. mCurFilePosition.mCurColumn = 0;
  2280. }
  2281. else
  2282. {
  2283. mCurFilePosition.mCurColumn++;
  2284. }
  2285. mCurFilePosition.mCurSrcPos++;
  2286. }
  2287. //TODO: if we bail on the "mCurMethodState == NULL" case then we don't get it set during type declarations
  2288. if (((flags & BfSrcPosFlag_NoSetDebugLoc) == 0) && (mBfIRBuilder->DbgHasLineInfo()) && (mCurMethodState != NULL))
  2289. {
  2290. int column = mCurFilePosition.mCurColumn + 1;
  2291. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
  2292. {
  2293. // Set to illegal position
  2294. column = 0;
  2295. }
  2296. if (mSetIllegalSrcPosition)
  2297. column = 0;
  2298. BfIRMDNode useDIScope = mCurMethodState->mCurScope->mDIScope;
  2299. auto wantDIFile = mCurFilePosition.mFileInstance->mDIFile;
  2300. if ((wantDIFile != mCurMethodState->mDIFile) && (mCurMethodState->mDIFile))
  2301. {
  2302. // This is from a different scope...
  2303. if (wantDIFile != mCurMethodState->mCurScope->mAltDIFile)
  2304. {
  2305. mCurMethodState->mCurScope->mAltDIFile = wantDIFile;
  2306. mCurMethodState->mCurScope->mAltDIScope = mBfIRBuilder->DbgCreateLexicalBlock(mCurMethodState->mCurScope->mDIScope, wantDIFile, mCurFilePosition.mCurLine + 1, column);
  2307. }
  2308. if (mCurMethodState->mCurScope->mAltDIScope) // This may not be set if mAltDIFile is set by a mixin
  2309. useDIScope = mCurMethodState->mCurScope->mAltDIScope;
  2310. }
  2311. else
  2312. {
  2313. if (mCurMethodState->mCurScope->mAltDIFile)
  2314. {
  2315. mCurMethodState->mCurScope->mAltDIFile = BfIRMDNode();
  2316. mCurMethodState->mCurScope->mAltDIScope = BfIRMDNode();
  2317. }
  2318. }
  2319. auto inlineAt = mCurMethodState->mCurScope->mDIInlinedAt;
  2320. if (mCurMethodState->mCrossingMixin)
  2321. inlineAt = BfIRMDNode();
  2322. if ((!useDIScope) && (mIsComptimeModule))
  2323. useDIScope = wantDIFile;
  2324. if (!useDIScope)
  2325. mBfIRBuilder->ClearDebugLocation();
  2326. else
  2327. mBfIRBuilder->SetCurrentDebugLocation(mCurFilePosition.mCurLine + 1, column, useDIScope, inlineAt);
  2328. if ((flags & BfSrcPosFlag_Expression) == 0)
  2329. mBfIRBuilder->CreateStatementStart();
  2330. }
  2331. }
  2332. void BfModule::UpdateExprSrcPos(BfAstNode* astNode, BfSrcPosFlags flags)
  2333. {
  2334. // We've turned off expr src pos (for now?)
  2335. //UpdateSrcPos(astNode, (BfSrcPosFlags)(flags | BfSrcPosFlag_Expression));
  2336. }
  2337. void BfModule::UseDefaultSrcPos(BfSrcPosFlags flags, int debugLocOffset)
  2338. {
  2339. if (mCompiler->mBfObjectTypeDef != NULL)
  2340. UpdateSrcPos(mCompiler->mBfObjectTypeDef->mTypeDeclaration, flags, debugLocOffset);
  2341. SetIllegalSrcPos();
  2342. }
  2343. void BfModule::SetIllegalSrcPos(BfSrcPosFlags flags)
  2344. {
  2345. if ((mBfIRBuilder->DbgHasInfo()) && (mCurMethodState != NULL))
  2346. {
  2347. auto curScope = mCurMethodState->mCurScope->mDIScope;
  2348. if (curScope)
  2349. {
  2350. if ((mCurMethodState->mCurScope->mDIInlinedAt) && (mCompiler->mOptions.IsCodeView()))
  2351. {
  2352. // Currently, CodeView does not record column positions so we can't use an illegal column position as an "invalid" marker
  2353. mBfIRBuilder->SetCurrentDebugLocation(0, 0, curScope, mCurMethodState->mCurScope->mDIInlinedAt);
  2354. }
  2355. else
  2356. {
  2357. // Set to whatever it previously was but at column zero, which we will know to be illegal
  2358. mBfIRBuilder->SetCurrentDebugLocation(mCurFilePosition.mCurLine + 1, 0, curScope, mCurMethodState->mCurScope->mDIInlinedAt);
  2359. }
  2360. }
  2361. if ((flags & BfSrcPosFlag_Expression) == 0)
  2362. mBfIRBuilder->CreateStatementStart();
  2363. }
  2364. }
  2365. void BfModule::SetIllegalExprSrcPos(BfSrcPosFlags flags)
  2366. {
  2367. // We've turned off expr src pos (for now?)
  2368. //SetIllegalSrcPos((BfSrcPosFlags)(flags | BfSrcPosFlag_Expression));
  2369. }
  2370. bool BfModule::CheckProtection(BfProtection protection, BfTypeDef* checkType, bool allowProtected, bool allowPrivate)
  2371. {
  2372. if ((protection == BfProtection_Public) ||
  2373. (((protection == BfProtection_Protected) || (protection == BfProtection_ProtectedInternal)) && (allowProtected)) ||
  2374. ((protection == BfProtection_Private) && (allowPrivate)))
  2375. return true;
  2376. if ((mAttributeState != NULL) && (mAttributeState->mCustomAttributes != NULL) && (mAttributeState->mCustomAttributes->Contains(mCompiler->mFriendAttributeTypeDef)))
  2377. {
  2378. mAttributeState->mUsed = true;
  2379. return true;
  2380. }
  2381. if (((protection == BfProtection_Internal) || (protection == BfProtection_ProtectedInternal)) && (checkType != NULL))
  2382. {
  2383. if (CheckInternalProtection(checkType))
  2384. return true;
  2385. }
  2386. return false;
  2387. }
  2388. void BfModule::GetAccessAllowed(BfTypeInstance* checkType, bool &allowProtected, bool &allowPrivate)
  2389. {
  2390. allowPrivate = (checkType == mCurTypeInstance) || (IsInnerType(mCurTypeInstance, checkType));
  2391. if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL))
  2392. {
  2393. auto mixinOwner = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
  2394. allowPrivate |= (checkType == mixinOwner) || (IsInnerType(mixinOwner, checkType));
  2395. }
  2396. allowProtected = allowPrivate;
  2397. }
  2398. bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType)
  2399. {
  2400. if (memberProtection == BfProtection_Hidden)
  2401. return false;
  2402. if (memberProtection == BfProtection_Public)
  2403. return true;
  2404. if ((flags & BfProtectionCheckFlag_CheckedPrivate) == 0)
  2405. {
  2406. BfTypeInstance* curCheckType = mCurTypeInstance;
  2407. if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL))
  2408. {
  2409. auto mixinOwner = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
  2410. curCheckType = mixinOwner;
  2411. }
  2412. bool allowPrivate = (curCheckType != NULL) && (memberOwner->IsInstanceOf(curCheckType->mTypeDef));
  2413. if (curCheckType != NULL)
  2414. allowPrivate |= IsInnerType(curCheckType->mTypeDef, memberOwner->mTypeDef);
  2415. if (allowPrivate)
  2416. flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate);
  2417. else
  2418. flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_CheckedPrivate);
  2419. }
  2420. if ((flags & BfProtectionCheckFlag_AllowPrivate) != 0)
  2421. return true;
  2422. if ((memberProtection == BfProtection_Protected) || (memberProtection == BfProtection_ProtectedInternal))
  2423. {
  2424. if ((flags & BfProtectionCheckFlag_CheckedProtected) == 0)
  2425. {
  2426. bool allowProtected = false;
  2427. auto memberOwnerTypeDef = memberOwner->mTypeDef;
  2428. auto curCheckType = mCurTypeInstance;
  2429. if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL))
  2430. {
  2431. auto mixinOwner = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
  2432. curCheckType = mixinOwner;
  2433. }
  2434. if ((flags & BfProtectionCheckFlag_InstanceLookup) != 0)
  2435. {
  2436. auto lookupCheckType = lookupStartType;
  2437. while (lookupCheckType->mInheritDepth >= curCheckType->mInheritDepth)
  2438. {
  2439. if (lookupCheckType == curCheckType)
  2440. {
  2441. allowProtected = true;
  2442. break;
  2443. }
  2444. if (lookupCheckType == memberOwner)
  2445. break;
  2446. lookupCheckType = lookupCheckType->mBaseType;
  2447. if (lookupCheckType == NULL)
  2448. break;
  2449. }
  2450. }
  2451. else
  2452. {
  2453. auto lookupCheckType = curCheckType;
  2454. while (lookupCheckType->mInheritDepth >= memberOwner->mInheritDepth)
  2455. {
  2456. if (lookupCheckType == memberOwner)
  2457. {
  2458. allowProtected = true;
  2459. break;
  2460. }
  2461. lookupCheckType = lookupCheckType->mBaseType;
  2462. if (lookupCheckType == NULL)
  2463. break;
  2464. }
  2465. }
  2466. if (!allowProtected)
  2467. {
  2468. // It's possible our outer type is derived from 'memberOwner'
  2469. while (curCheckType->mTypeDef->mNestDepth > 0)
  2470. {
  2471. curCheckType = GetOuterType(curCheckType);
  2472. if (curCheckType == NULL)
  2473. break;
  2474. auto lookupCheckType = lookupStartType;
  2475. while (lookupCheckType->mInheritDepth >= curCheckType->mInheritDepth)
  2476. {
  2477. if (lookupCheckType == curCheckType)
  2478. {
  2479. allowProtected = true;
  2480. break;
  2481. }
  2482. if (lookupCheckType == memberOwner)
  2483. break;
  2484. lookupCheckType = lookupCheckType->mBaseType;
  2485. if (lookupCheckType == NULL)
  2486. break;
  2487. }
  2488. }
  2489. }
  2490. if (allowProtected)
  2491. flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_CheckedProtected | BfProtectionCheckFlag_AllowProtected);
  2492. else
  2493. flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_CheckedProtected);
  2494. }
  2495. if ((flags & BfProtectionCheckFlag_AllowProtected) != 0)
  2496. return true;
  2497. }
  2498. if ((mAttributeState != NULL) && (mAttributeState->mCustomAttributes != NULL) && (mAttributeState->mCustomAttributes->Contains(mCompiler->mFriendAttributeTypeDef)))
  2499. {
  2500. mAttributeState->mUsed = true;
  2501. return true;
  2502. }
  2503. if (((memberProtection == BfProtection_Internal) || (memberProtection == BfProtection_ProtectedInternal)) && (memberOwner != NULL))
  2504. {
  2505. if (CheckInternalProtection(memberOwner->mTypeDef))
  2506. return true;
  2507. }
  2508. return false;
  2509. }
  2510. void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementType)
  2511. {
  2512. if (mCompiler->mResolvePassData != NULL)
  2513. {
  2514. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(astNode))
  2515. sourceClassifier->SetElementType(astNode, elementType);
  2516. }
  2517. }
  2518. bool BfModule::PreFail()
  2519. {
  2520. if (!mIgnoreErrors)
  2521. return true;
  2522. SetFail();
  2523. return false;
  2524. }
  2525. void BfModule::SetFail()
  2526. {
  2527. if (mIgnoreErrors)
  2528. {
  2529. if (mAttributeState != NULL)
  2530. mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
  2531. }
  2532. }
  2533. void BfModule::VerifyOnDemandMethods()
  2534. {
  2535. #ifdef _DEBUG
  2536. // if (mParentModule != NULL)
  2537. // {
  2538. // BF_ASSERT(mOnDemandMethodCount == 0);
  2539. // mParentModule->VerifyOnDemandMethods();
  2540. // return;
  2541. // }
  2542. //
  2543. // int onDemandCount = 0;
  2544. // for (auto type : mOwnedTypeInstances)
  2545. // {
  2546. // auto typeInst = type->ToTypeInstance();
  2547. // for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  2548. // {
  2549. // if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
  2550. // (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
  2551. // (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
  2552. // (methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList))
  2553. // onDemandCount++;
  2554. // }
  2555. // }
  2556. //
  2557. // BF_ASSERT(mOnDemandMethodCount == onDemandCount);
  2558. #endif
  2559. }
  2560. bool BfModule::IsSkippingExtraResolveChecks()
  2561. {
  2562. if (mIsComptimeModule)
  2563. return false;
  2564. return mCompiler->IsSkippingExtraResolveChecks();
  2565. }
  2566. bool BfModule::AddErrorContext(StringImpl& errorString, BfAstNode* refNode, BfWhileSpecializingFlags& isWhileSpecializing, bool isWarning)
  2567. {
  2568. bool isWhileSpecializingMethod = false;
  2569. if ((mIsSpecialModule) && (mModuleName == "vdata"))
  2570. errorString += StrFormat("\n while generating vdata for project '%s'", mProject->mName.c_str());
  2571. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend))
  2572. errorString += StrFormat("\n while generating append size calculating method");
  2573. else if (refNode == NULL)
  2574. {
  2575. if (mCurTypeInstance != NULL)
  2576. errorString += StrFormat("\n while compiling '%s'", TypeToString(mCurTypeInstance, BfTypeNameFlags_None).c_str());
  2577. else if (mProject != NULL)
  2578. errorString += StrFormat("\n while compiling project '%s'", mProject->mName.c_str());
  2579. }
  2580. if (mCurTypeInstance != NULL)
  2581. {
  2582. auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance)
  2583. {
  2584. // Propogate the fail all the way to the main method (assuming we're in a local method or lambda)
  2585. if (isWarning)
  2586. methodInstance->mHasWarning = true;
  2587. else
  2588. methodInstance->mHasFailed = true;
  2589. if (!methodInstance->mHasStartedDeclaration)
  2590. StartMethodDeclaration(methodInstance, NULL);
  2591. bool isSpecializedMethod = ((methodInstance != NULL) && (!methodInstance->mIsUnspecialized) && (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0));
  2592. if (isSpecializedMethod)
  2593. {
  2594. //auto unspecializedMethod = &mCurMethodInstance->mMethodInstanceGroup->mMethodSpecializationMap.begin()->second;
  2595. auto unspecializedMethod = methodInstance->mMethodInstanceGroup->mDefault;
  2596. if (unspecializedMethod == methodInstance)
  2597. {
  2598. // This is a local method inside a generic method
  2599. BF_ASSERT(methodInstance->mMethodDef->mIsLocalMethod);
  2600. }
  2601. else
  2602. {
  2603. if (isWarning)
  2604. {
  2605. if (unspecializedMethod->mHasWarning)
  2606. return false; // At least SOME error has already been reported
  2607. }
  2608. else
  2609. {
  2610. if (unspecializedMethod->mHasFailed)
  2611. return false; // At least SOME error has already been reported
  2612. }
  2613. }
  2614. }
  2615. if (isSpecializedMethod)
  2616. {
  2617. errorString += StrFormat("\n while specializing method '%s'", MethodToString(methodInstance).c_str());
  2618. isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Method);
  2619. isWhileSpecializingMethod = true;
  2620. }
  2621. else if ((methodInstance != NULL) && (methodInstance->mIsForeignMethodDef))
  2622. {
  2623. errorString += StrFormat("\n while implementing default interface method '%s'", MethodToString(methodInstance).c_str());
  2624. isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Method);
  2625. isWhileSpecializingMethod = true;
  2626. }
  2627. if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))
  2628. {
  2629. errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str());
  2630. isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Type);
  2631. }
  2632. return true;
  2633. };
  2634. bool hadMethodInstance = false;
  2635. if (mCurMethodState != NULL)
  2636. {
  2637. auto checkMethodState = mCurMethodState;
  2638. while (checkMethodState != NULL)
  2639. {
  2640. auto methodInstance = checkMethodState->mMethodInstance;
  2641. if (methodInstance == NULL)
  2642. {
  2643. checkMethodState = checkMethodState->mPrevMethodState;
  2644. continue;
  2645. }
  2646. hadMethodInstance = true;
  2647. if (!_CheckMethodInstance(methodInstance))
  2648. return false;
  2649. checkMethodState = checkMethodState->mPrevMethodState;
  2650. }
  2651. }
  2652. if ((!hadMethodInstance) && (mCurMethodInstance != NULL))
  2653. {
  2654. if (!_CheckMethodInstance(mCurMethodInstance))
  2655. return false;
  2656. }
  2657. }
  2658. if ((!isWhileSpecializing) && (mCurTypeInstance != NULL) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
  2659. {
  2660. errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str());
  2661. isWhileSpecializing = (BfWhileSpecializingFlags)(isWhileSpecializing | BfWhileSpecializingFlag_Type);
  2662. }
  2663. return true;
  2664. }
  2665. BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPersistent, bool deferError)
  2666. {
  2667. BP_ZONE("BfModule::Fail");
  2668. if (mIgnoreErrors)
  2669. {
  2670. mHadIgnoredError = true;
  2671. if (mAttributeState != NULL)
  2672. mAttributeState->mFlags = (BfAttributeState::Flags)(mAttributeState->mFlags | BfAttributeState::Flag_HadError);
  2673. return NULL;
  2674. }
  2675. if (!mReportErrors)
  2676. {
  2677. mCompiler->mPassInstance->SilentFail();
  2678. return NULL;
  2679. }
  2680. if (refNode != NULL)
  2681. refNode = BfNodeToNonTemporary(refNode);
  2682. //BF_ASSERT(refNode != NULL);
  2683. if (mIsComptimeModule)
  2684. {
  2685. if (auto ceDbgState = GetCeDbgState())
  2686. {
  2687. // Follow normal fail path
  2688. }
  2689. else
  2690. {
  2691. mHadBuildError = true;
  2692. if ((mCompiler->mCeMachine->mCurContext != NULL) && (mCompiler->mCeMachine->mCurContext->mCurCallSource != NULL) &&
  2693. (mCompiler->mCeMachine->mCurContext->mCurCallSource->mRefNode != NULL))
  2694. {
  2695. BfError* bfError = mCompiler->mPassInstance->Fail("Comptime method generation had errors",
  2696. mCompiler->mCeMachine->mCurContext->mCurCallSource->mRefNode);
  2697. if (bfError != NULL)
  2698. mCompiler->mPassInstance->MoreInfo(error, refNode);
  2699. return bfError;
  2700. }
  2701. return NULL;
  2702. }
  2703. }
  2704. if (mCurMethodInstance != NULL)
  2705. mCurMethodInstance->mHasFailed = true;
  2706. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsUnspecializedTypeVariation()))
  2707. return NULL;
  2708. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->IsOrInUnspecializedVariation()))
  2709. return NULL; // Ignore errors on unspecialized variations, they are always dups
  2710. if (!mHadBuildError)
  2711. mHadBuildError = true;
  2712. if (mParentModule != NULL)
  2713. mParentModule->mHadBuildError = true;
  2714. if (mCurTypeInstance != NULL)
  2715. AddFailType(mCurTypeInstance);
  2716. BfLogSysM("BfModule::Fail module %p type %p %s\n", this, mCurTypeInstance, error.c_str());
  2717. String errorString = error;
  2718. BfWhileSpecializingFlags isWhileSpecializing = BfWhileSpecializingFlag_None;
  2719. if (!AddErrorContext(errorString, refNode, isWhileSpecializing, false))
  2720. return NULL;
  2721. BfError* bfError = NULL;
  2722. if (isWhileSpecializing)
  2723. deferError = true;
  2724. if (!mHadBuildError)
  2725. mHadBuildError = true;
  2726. // Check mixins
  2727. {
  2728. auto checkMethodState = mCurMethodState;
  2729. while (checkMethodState != NULL)
  2730. {
  2731. auto rootMixinState = checkMethodState->GetRootMixinState();
  2732. if (rootMixinState != NULL)
  2733. {
  2734. String mixinErr = StrFormat("Failed to inject mixin '%s'", MethodToString(rootMixinState->mMixinMethodInstance).c_str());
  2735. if (deferError)
  2736. bfError = mCompiler->mPassInstance->DeferFail(mixinErr, rootMixinState->mSource);
  2737. else
  2738. bfError = mCompiler->mPassInstance->Fail(mixinErr, rootMixinState->mSource);
  2739. if (bfError == NULL)
  2740. return NULL;
  2741. bfError->mIsWhileSpecializing = isWhileSpecializing;
  2742. mCompiler->mPassInstance->MoreInfo(errorString, refNode);
  2743. auto mixinState = checkMethodState->mMixinState;
  2744. while ((mixinState != NULL) && (mixinState->mPrevMixinState != NULL))
  2745. {
  2746. mCompiler->mPassInstance->MoreInfo(StrFormat("Injected from mixin '%s'", MethodToString(mixinState->mPrevMixinState->mMixinMethodInstance).c_str()), mixinState->mSource);
  2747. mixinState = mixinState->mPrevMixinState;
  2748. }
  2749. return bfError;
  2750. }
  2751. checkMethodState = checkMethodState->mPrevMethodState;
  2752. }
  2753. }
  2754. if (deferError)
  2755. bfError = mCompiler->mPassInstance->Fail(errorString, refNode);
  2756. else if (refNode == NULL)
  2757. bfError = mCompiler->mPassInstance->Fail(errorString);
  2758. else
  2759. bfError = mCompiler->mPassInstance->Fail(errorString, refNode);
  2760. if (bfError != NULL)
  2761. {
  2762. bfError->mIsWhileSpecializing = isWhileSpecializing;
  2763. bfError->mProject = mProject;
  2764. bfError->mIsPersistent = isPersistent;
  2765. if ((mCurMethodState != NULL) && (mCurMethodState->mDeferredCallEmitState != NULL) && (mCurMethodState->mDeferredCallEmitState->mCloseNode != NULL))
  2766. mCompiler->mPassInstance->MoreInfo("Error during deferred statement handling", mCurMethodState->mDeferredCallEmitState->mCloseNode);
  2767. else if ((mCurMethodState != NULL) && (mCurMethodState->mEmitRefNode != NULL))
  2768. mCompiler->mPassInstance->MoreInfo("Error in emitted code", mCurMethodState->mEmitRefNode);
  2769. }
  2770. return bfError;
  2771. }
  2772. BfError* BfModule::FailInternal(const StringImpl& error, BfAstNode* refNode)
  2773. {
  2774. if (mHadBuildError)
  2775. return NULL;
  2776. return Fail(error, refNode);
  2777. }
  2778. BfError* BfModule::FailAfter(const StringImpl& error, BfAstNode* refNode)
  2779. {
  2780. if (mIgnoreErrors)
  2781. return NULL;
  2782. if (refNode != NULL)
  2783. refNode = BfNodeToNonTemporary(refNode);
  2784. mHadBuildError = true;
  2785. BfError* bfError = mCompiler->mPassInstance->FailAfter(error, refNode);
  2786. if (bfError != NULL)
  2787. bfError->mProject = mProject;
  2788. return bfError;
  2789. }
  2790. BfError* BfModule::Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode, bool isPersistent, bool showInSpecialized)
  2791. {
  2792. if (mIgnoreErrors || mIgnoreWarnings)
  2793. return NULL;
  2794. if (!mReportErrors)
  2795. {
  2796. mCompiler->mPassInstance->SilentFail();
  2797. return NULL;
  2798. }
  2799. BfAstNode* unwarnNode = refNode;
  2800. //
  2801. {
  2802. BfParentNodeEntry* parentNodeEntry = mParentNodeEntry;
  2803. while (parentNodeEntry != NULL)
  2804. {
  2805. if (auto block = BfNodeDynCast<BfBlock>(parentNodeEntry->mNode))
  2806. break;
  2807. unwarnNode = parentNodeEntry->mNode;
  2808. parentNodeEntry = parentNodeEntry->mPrev;
  2809. }
  2810. }
  2811. auto parser = unwarnNode->GetSourceData()->ToParserData();
  2812. if ((parser != NULL) && (parser->IsUnwarnedAt(unwarnNode)))
  2813. {
  2814. return NULL;
  2815. }
  2816. // Right now we're only warning on the unspecialized declarations, we may revisit this
  2817. if (mCurMethodInstance != NULL)
  2818. {
  2819. if (mCurMethodInstance->IsSpecializedGenericMethodOrType())
  2820. {
  2821. if (!showInSpecialized)
  2822. return NULL;
  2823. }
  2824. if (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend)
  2825. return NULL; // No ctorCalcAppend warnings
  2826. }
  2827. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType()))
  2828. {
  2829. if (!showInSpecialized)
  2830. return NULL;
  2831. }
  2832. if (refNode != NULL)
  2833. refNode = BfNodeToNonTemporary(refNode);
  2834. String warningString = warning;
  2835. BfWhileSpecializingFlags isWhileSpecializing = BfWhileSpecializingFlag_None;
  2836. if (!AddErrorContext(warningString, refNode, isWhileSpecializing, true))
  2837. return NULL;
  2838. bool deferWarning = isWhileSpecializing != BfWhileSpecializingFlag_None;
  2839. if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL))
  2840. {
  2841. // We used to bubble up warnings into the mixin injection site, BUT
  2842. // we are now assuming any relevant warnings will be given at the declaration site
  2843. return NULL;
  2844. }
  2845. if ((mCurMethodState != NULL) && (mCurMethodState->mEmitRefNode != NULL))
  2846. {
  2847. BfError* bfError = mCompiler->mPassInstance->Warn(warningNum, "Emitted code had errors", mCurMethodState->mEmitRefNode);
  2848. if (bfError != NULL)
  2849. mCompiler->mPassInstance->MoreInfo(warningString, refNode);
  2850. return bfError;
  2851. }
  2852. BfError* bfError;
  2853. if (refNode != NULL)
  2854. bfError = mCompiler->mPassInstance->WarnAt(warningNum, warningString, refNode->GetSourceData(), refNode->GetSrcStart(), refNode->GetSrcLength());
  2855. else
  2856. bfError = mCompiler->mPassInstance->Warn(warningNum, warningString);
  2857. if (bfError != NULL)
  2858. {
  2859. bfError->mIsWhileSpecializing = isWhileSpecializing;
  2860. bfError->mProject = mProject;
  2861. AddFailType(mCurTypeInstance);
  2862. mHadBuildWarning = true;
  2863. bfError->mIsPersistent = isPersistent;
  2864. if ((mCompiler->IsAutocomplete()) && (mCompiler->mResolvePassData->mAutoComplete->CheckFixit((refNode))))
  2865. {
  2866. BfParserData* parser = refNode->GetSourceData()->ToParserData();
  2867. if (parser != NULL)
  2868. {
  2869. int fileLoc = BfFixitFinder::FindLineStartBefore(refNode);
  2870. mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("#unwarn\tunwarn|%s|%d|#unwarn|", parser->mFileName.c_str(), fileLoc).c_str()));
  2871. if (warningNum != 0)
  2872. {
  2873. mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("#pragma warning disable %d\t.pragma|%s|%d||#pragma warning disable %d",
  2874. warningNum, parser->mFileName.c_str(), 0, warningNum).c_str()));
  2875. }
  2876. }
  2877. }
  2878. }
  2879. return bfError;
  2880. }
  2881. void BfModule::CheckErrorAttributes(BfTypeInstance* typeInstance, BfMethodInstance* methodInstance, BfCustomAttributes* customAttributes, BfAstNode* targetSrc)
  2882. {
  2883. if (customAttributes == NULL)
  2884. return;
  2885. auto _AddDeclarationMoreInfo = [&]()
  2886. {
  2887. if (methodInstance != NULL)
  2888. {
  2889. if (methodInstance->mMethodDef->mMethodDeclaration != NULL)
  2890. mCompiler->mPassInstance->MoreInfo(
  2891. StrFormat("See method declaration '%s'", MethodToString(methodInstance).c_str()),
  2892. methodInstance->mMethodDef->GetRefNode());
  2893. }
  2894. else
  2895. {
  2896. mCompiler->mPassInstance->MoreInfo(
  2897. StrFormat("See type declaration '%s'", TypeToString(typeInstance, BfTypeNameFlag_UseUnspecializedGenericParamNames).c_str()),
  2898. typeInstance->mTypeDef->GetRefNode());
  2899. }
  2900. };
  2901. BfIRConstHolder* constHolder = typeInstance->mConstHolder;
  2902. auto customAttribute = customAttributes->Get(mCompiler->mObsoleteAttributeTypeDef);
  2903. if ((customAttribute != NULL) && (!customAttribute->mCtorArgs.IsEmpty()) && (targetSrc != NULL))
  2904. {
  2905. String err;
  2906. if (methodInstance != NULL)
  2907. err = StrFormat("'%s' is obsolete", MethodToString(methodInstance).c_str());
  2908. else
  2909. err = StrFormat("'%s' is obsolete", TypeToString(typeInstance, BfTypeNameFlag_UseUnspecializedGenericParamNames).c_str());
  2910. bool isError = false;
  2911. auto constant = constHolder->GetConstant(customAttribute->mCtorArgs[0]);
  2912. if (constant->mTypeCode == BfTypeCode_Boolean)
  2913. {
  2914. isError = constant->mBool;
  2915. }
  2916. else if (customAttribute->mCtorArgs.size() >= 2)
  2917. {
  2918. String* str = GetStringPoolString(customAttribute->mCtorArgs[0], constHolder);
  2919. if (str != NULL)
  2920. {
  2921. err += ":\n '";
  2922. err += *str;
  2923. err += "'";
  2924. }
  2925. constant = constHolder->GetConstant(customAttribute->mCtorArgs[1]);
  2926. isError = constant->mBool;
  2927. }
  2928. BfError* error = NULL;
  2929. if (isError)
  2930. error = Fail(err, targetSrc);
  2931. else
  2932. error = Warn(0, err, targetSrc, false, true);
  2933. if (error != NULL)
  2934. _AddDeclarationMoreInfo();
  2935. }
  2936. customAttribute = customAttributes->Get(mCompiler->mErrorAttributeTypeDef);
  2937. if ((customAttribute != NULL) && (!customAttribute->mCtorArgs.IsEmpty()))
  2938. {
  2939. String err;
  2940. if (methodInstance != NULL)
  2941. err += StrFormat("Method error: '", MethodToString(methodInstance).c_str());
  2942. else
  2943. err += StrFormat("Type error: '", TypeToString(typeInstance, BfTypeNameFlag_UseUnspecializedGenericParamNames).c_str());
  2944. String* str = GetStringPoolString(customAttribute->mCtorArgs[0], constHolder);
  2945. if (str != NULL)
  2946. err += *str;
  2947. err += "'";
  2948. if (Fail(err, targetSrc) != NULL)
  2949. _AddDeclarationMoreInfo();
  2950. }
  2951. customAttribute = customAttributes->Get(mCompiler->mWarnAttributeTypeDef);
  2952. if ((customAttribute != NULL) && (!customAttribute->mCtorArgs.IsEmpty()) && (targetSrc != NULL))
  2953. {
  2954. String err;
  2955. if (methodInstance != NULL)
  2956. err += StrFormat("Method warning: '", MethodToString(methodInstance).c_str());
  2957. else
  2958. err += StrFormat("Type warning: '", TypeToString(typeInstance, BfTypeNameFlag_UseUnspecializedGenericParamNames).c_str());
  2959. String* str = GetStringPoolString(customAttribute->mCtorArgs[0], constHolder);
  2960. if (str != NULL)
  2961. err += *str;
  2962. err += "'";
  2963. if (Warn(0, err, targetSrc, false, true) != NULL)
  2964. _AddDeclarationMoreInfo();
  2965. }
  2966. }
  2967. void BfModule::CheckRangeError(BfType* type, BfAstNode* refNode)
  2968. {
  2969. if (mBfIRBuilder->mOpFailed)
  2970. Fail(StrFormat("Result out of range for type '%s'", TypeToString(type).c_str()), refNode);
  2971. }
  2972. void BfModule::FatalError(const StringImpl& error, const char* file, int line)
  2973. {
  2974. static bool sHadFatalError = false;
  2975. static bool sHadReentrancy = false;
  2976. if (sHadFatalError)
  2977. {
  2978. return;
  2979. sHadReentrancy = true;
  2980. }
  2981. sHadFatalError = true;
  2982. String fullError = error;
  2983. if (file != NULL)
  2984. fullError += StrFormat(" at %s:%d", file, line);
  2985. fullError += StrFormat("\nModule: %s", mModuleName.c_str());
  2986. if (mCurTypeInstance != NULL)
  2987. fullError += StrFormat("\nType: %s", TypeToString(mCurTypeInstance).c_str());
  2988. if (mCurMethodInstance != NULL)
  2989. fullError += StrFormat("\nMethod: %s", MethodToString(mCurMethodInstance).c_str());
  2990. if ((mCurFilePosition.mFileInstance != NULL) && (mCurFilePosition.mFileInstance->mParser != NULL))
  2991. fullError += StrFormat("\nSource Location: %s:%d", mCurFilePosition.mFileInstance->mParser->mFileName.c_str(), mCurFilePosition.mCurLine + 1);
  2992. if (sHadReentrancy)
  2993. fullError += "\nError had reentrancy";
  2994. BfpSystem_FatalError(fullError.c_str(), "FATAL MODULE ERROR");
  2995. }
  2996. void BfModule::NotImpl(BfAstNode* astNode)
  2997. {
  2998. Fail("INTERNAL ERROR: Not implemented", astNode);
  2999. }
  3000. bool BfModule::CheckAccessMemberProtection(BfProtection protection, BfTypeInstance* memberType)
  3001. {
  3002. bool allowPrivate = (memberType == mCurTypeInstance) || (IsInnerType(mCurTypeInstance, memberType));
  3003. if (!allowPrivate)
  3004. allowPrivate |= memberType->IsInterface();
  3005. bool allowProtected = allowPrivate;
  3006. //TODO: We had this commented out, but this makes accessing protected properties fail
  3007. if (mCurTypeInstance != NULL)
  3008. allowProtected |= TypeIsSubTypeOf(mCurTypeInstance, memberType->ToTypeInstance());
  3009. if (!CheckProtection(protection, memberType->mTypeDef, allowProtected, allowPrivate))
  3010. {
  3011. return false;
  3012. }
  3013. return true;
  3014. }
  3015. bool BfModule::CheckDefineMemberProtection(BfProtection protection, BfType* memberType)
  3016. {
  3017. // Use 'min' - exporting a 'public' from a 'private' class is really just 'private' still
  3018. protection = std::min(protection, mCurTypeInstance->mTypeDef->mProtection);
  3019. auto memberTypeInstance = memberType->ToTypeInstance();
  3020. if (memberTypeInstance == NULL)
  3021. {
  3022. auto underlyingType = memberType->GetUnderlyingType();
  3023. if (underlyingType != NULL)
  3024. return CheckDefineMemberProtection(protection, underlyingType);
  3025. return true;
  3026. }
  3027. if (memberTypeInstance->mTypeDef->mProtection < protection)
  3028. return false;
  3029. if (memberTypeInstance->IsGenericTypeInstance())
  3030. {
  3031. // When we're a generic struct, our data layout can depend on our generic parameters as well
  3032. auto genericTypeInstance = (BfTypeInstance*) memberTypeInstance;
  3033. for (auto typeGenericArg : genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments)
  3034. {
  3035. if (!CheckDefineMemberProtection(protection, typeGenericArg))
  3036. return false;
  3037. }
  3038. }
  3039. return true;
  3040. }
  3041. void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap::DependencyFlags flags, BfDepContext* depContext)
  3042. {
  3043. if (usedType == userType)
  3044. return;
  3045. if (((flags & BfDependencyMap::DependencyFlag_ConstValue) != 0) && (mContext->mCurTypeState != NULL) && (mContext->mCurTypeState->mResolveKind == BfTypeState::ResolveKind_FieldType))
  3046. {
  3047. // This can be an `int32[UsedType.cVal]` type reference
  3048. flags = (BfDependencyMap::DependencyFlags)(flags | BfDependencyMap::DependencyFlag_ValueTypeSizeDep);
  3049. }
  3050. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsAutocompleteMethod))
  3051. {
  3052. if (userType->IsMethodRef())
  3053. {
  3054. // We cannot short-circuit dependencies because of method group ref counting
  3055. }
  3056. else
  3057. return;
  3058. }
  3059. if (usedType->IsSpecializedByAutoCompleteMethod())
  3060. {
  3061. if ((flags & (BfDependencyMap::DependencyFlag_TypeGenericArg | BfDependencyMap::DependencyFlag_OuterType | BfDependencyMap::DependencyFlag_DerivedFrom)) == 0)
  3062. return;
  3063. }
  3064. // if (usedType->IsBoxed())
  3065. // {
  3066. // NOP;
  3067. // auto underlyingType = usedType->GetUnderlyingType()->ToTypeInstance();
  3068. // if ((underlyingType != NULL) && (underlyingType->IsInstanceOf(mCompiler->mSizedArrayTypeDef)))
  3069. // {
  3070. // BfLogSysM("AddDependency UsedType:%p UserType:%p Method:%p\n", usedType, userType, mCurMethodInstance);
  3071. // }
  3072. // }
  3073. // TODO: It seems this was bogus - it kept the root array from being marked as a dependency (for example)
  3074. // BfType* origUsedType = usedType;
  3075. bool isDataAccess = ((flags & (BfDependencyMap::DependencyFlag_ReadFields | BfDependencyMap::DependencyFlag_LocalUsage | BfDependencyMap::DependencyFlag_Allocates)) != 0);
  3076. // if (isDataAccess)
  3077. // {
  3078. // while (true)
  3079. // {
  3080. // if ((usedType->IsPointer()) || (usedType->IsRef()) || (usedType->IsSizedArray()))
  3081. // usedType = usedType->GetUnderlyingType();
  3082. // else if (usedType->IsArray())
  3083. // {
  3084. // usedType = ((BfTypeInstance*)usedType)->mGenericTypeInfo->mTypeGenericArguments[0];
  3085. // }
  3086. // else
  3087. // break;
  3088. // }
  3089. // }
  3090. if ((mCurMethodState != NULL) && (mCurMethodState->mHotDataReferenceBuilder != NULL) && (usedType != mCurTypeInstance) && (isDataAccess))
  3091. {
  3092. bool addType = true;
  3093. auto checkType = usedType;
  3094. PopulateType(checkType, BfPopulateType_Data);
  3095. if (checkType->IsValuelessType())
  3096. addType = false;
  3097. else if (checkType->IsPrimitiveType())
  3098. addType = false;
  3099. else
  3100. {
  3101. auto checkTypeInst = checkType->ToTypeInstance();
  3102. if (checkTypeInst == NULL)
  3103. {
  3104. addType = false;
  3105. }
  3106. else
  3107. {
  3108. if (TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst))
  3109. addType = false;
  3110. }
  3111. }
  3112. if (addType)
  3113. {
  3114. auto checkTypeInst = checkType->ToTypeInstance();
  3115. if (checkTypeInst->mHotTypeData != NULL)
  3116. {
  3117. auto hotTypeVersion = checkTypeInst->mHotTypeData->GetLatestVersion();
  3118. BF_ASSERT(hotTypeVersion != NULL);
  3119. if (hotTypeVersion != NULL)
  3120. {
  3121. bool isAllocation = ((flags & BfDependencyMap::DependencyFlag_Allocates) != 0);
  3122. if (((flags & BfDependencyMap::DependencyFlag_LocalUsage) != 0) &&
  3123. (checkType->IsComposite()))
  3124. isAllocation = true;
  3125. if (isAllocation)
  3126. {
  3127. mCurMethodState->mHotDataReferenceBuilder->mAllocatedData.Add(hotTypeVersion);
  3128. }
  3129. else
  3130. mCurMethodState->mHotDataReferenceBuilder->mUsedData.Add(hotTypeVersion);
  3131. }
  3132. }
  3133. }
  3134. }
  3135. if ((!mCompiler->mIsResolveOnly) && (mIsReified))
  3136. {
  3137. auto usingModule = userType->GetModule();
  3138. BfModule* usedModule;
  3139. if (usedType->IsFunction())
  3140. {
  3141. if (mCompiler->mFunctionTypeDef != NULL)
  3142. {
  3143. auto functionType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance();
  3144. usedModule = functionType->GetModule();
  3145. }
  3146. }
  3147. else
  3148. usedModule = usedType->GetModule();
  3149. if ((usingModule != NULL) && (!usingModule->mIsSpecialModule) &&
  3150. (usedModule != NULL) && (!usedModule->mIsSpecialModule))
  3151. {
  3152. if ((flags & ~(BfDependencyMap::DependencyFlag_OuterType)) == 0)
  3153. {
  3154. // Not a 'use' dependency
  3155. }
  3156. else
  3157. {
  3158. usingModule->mModuleRefs.Add(usedModule);
  3159. }
  3160. }
  3161. }
  3162. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (flags != BfDependencyMap::DependencyFlag_MethodGenericArg))
  3163. {
  3164. // When we are specializing a method, usage of that specialized type is already handled with DependencyFlag_MethodGenericArg
  3165. for (auto genericArg : mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments)
  3166. if (genericArg == usedType)
  3167. return;
  3168. }
  3169. auto depFlag = flags;
  3170. if ((flags & (BfDependencyMap::DependencyFlag_MethodGenericArg | BfDependencyMap::DependencyFlag_TypeGenericArg)) != 0)
  3171. {
  3172. if (usedType->IsDependendType())
  3173. {
  3174. // Cause a rebuild but not an outright deletion of the type
  3175. // We can only do this if the 'usedType' can actually hold the dependency which can actually trigger a deletion chain
  3176. depFlag = BfDependencyMap::DependencyFlag_GenericArgRef;
  3177. }
  3178. }
  3179. if (usedType->IsTypeAlias())
  3180. {
  3181. auto underlyingType = usedType->GetUnderlyingType();
  3182. if (underlyingType != NULL)
  3183. {
  3184. BfDepContext newDepContext;
  3185. if (depContext == NULL)
  3186. depContext = &newDepContext;
  3187. if (++depContext->mAliasDepth > 8)
  3188. {
  3189. if (!depContext->mDeepSeenAliases.Add(underlyingType))
  3190. return; // Circular!
  3191. }
  3192. AddDependency(underlyingType, userType, depFlag);
  3193. }
  3194. }
  3195. else if (!usedType->IsGenericTypeInstance())
  3196. {
  3197. auto underlyingType = usedType->GetUnderlyingType();
  3198. if (underlyingType != NULL)
  3199. AddDependency(underlyingType, userType, depFlag);
  3200. }
  3201. BfDependedType* checkDType = usedType->ToDependedType();
  3202. if (checkDType == NULL)
  3203. return;
  3204. if ((usedType->mRebuildFlags & BfTypeRebuildFlag_AwaitingReference) != 0)
  3205. mContext->MarkAsReferenced(checkDType);
  3206. #ifdef _DEBUG
  3207. // If a MethodRef depends ON US, that means it's a local method that we own
  3208. if (userType->IsMethodRef())
  3209. {
  3210. auto methodRefType = (BfMethodRefType*)userType;
  3211. BF_ASSERT(methodRefType->mOwner == checkDType);
  3212. }
  3213. #endif
  3214. if (!checkDType->mDependencyMap.AddUsedBy(userType, flags))
  3215. return;
  3216. if ((checkDType->IsGenericTypeInstance()) && (!userType->IsMethodRef()))
  3217. {
  3218. auto genericTypeInstance = (BfTypeInstance*) checkDType;
  3219. for (auto genericArg : genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments)
  3220. {
  3221. AddDependency(genericArg, userType, depFlag);
  3222. }
  3223. }
  3224. if (checkDType->IsTuple())
  3225. {
  3226. for (auto& field : checkDType->ToTypeInstance()->mFieldInstances)
  3227. {
  3228. if (field.mDataIdx != -1)
  3229. AddDependency(field.mResolvedType, userType, depFlag);
  3230. }
  3231. }
  3232. }
  3233. void BfModule::AddDependency(BfGenericParamInstance* genericParam, BfTypeInstance* usingType)
  3234. {
  3235. if ((genericParam->mExternType != NULL) && (!genericParam->mExternType->IsGenericParam()))
  3236. AddDependency(genericParam->mExternType, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
  3237. for (auto constraintTypeInst : genericParam->mInterfaceConstraints)
  3238. AddDependency(constraintTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
  3239. for (auto& operatorConstraint : genericParam->mOperatorConstraints)
  3240. {
  3241. if (operatorConstraint.mLeftType != NULL)
  3242. AddDependency(operatorConstraint.mLeftType, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
  3243. if (operatorConstraint.mRightType != NULL)
  3244. AddDependency(operatorConstraint.mRightType, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
  3245. }
  3246. if (genericParam->mTypeConstraint != NULL)
  3247. AddDependency(genericParam->mTypeConstraint, mCurTypeInstance, BfDependencyMap::DependencyFlag_Constraint);
  3248. }
  3249. void BfModule::AddCallDependency(BfMethodInstance* methodInstance, bool devirtualized)
  3250. {
  3251. if ((mCurMethodState != NULL) && (mCurMethodState->mHotDataReferenceBuilder != NULL))
  3252. {
  3253. if (methodInstance->mHotMethod == NULL)
  3254. CheckHotMethod(methodInstance, "");
  3255. BF_ASSERT(methodInstance->mHotMethod != NULL);
  3256. if (devirtualized)
  3257. mCurMethodState->mHotDataReferenceBuilder->mDevirtualizedCalledMethods.Add(methodInstance->mHotMethod);
  3258. else
  3259. mCurMethodState->mHotDataReferenceBuilder->mCalledMethods.Add(methodInstance->mHotMethod);
  3260. }
  3261. }
  3262. bool BfModule::IsAttribute(BfTypeInstance* typeInst)
  3263. {
  3264. auto checkTypeInst = typeInst;
  3265. while (checkTypeInst != NULL)
  3266. {
  3267. if (checkTypeInst->IsInstanceOf(mCompiler->mAttributeTypeDef))
  3268. return true;
  3269. checkTypeInst = checkTypeInst->mBaseType;
  3270. }
  3271. return false;
  3272. }
  3273. void BfModule::PopulateGlobalContainersList(const BfGlobalLookup& globalLookup)
  3274. {
  3275. if (mContext->mCurTypeState == NULL)
  3276. return;
  3277. BP_ZONE("PopulateGlobalContainersList");
  3278. BfTypeDef* userTypeDef = mContext->mCurTypeState->mCurTypeDef;
  3279. if ((userTypeDef == NULL) && (mCurMethodInstance != NULL))
  3280. userTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;
  3281. if (userTypeDef == NULL)
  3282. userTypeDef = mCurTypeInstance->mTypeDef;
  3283. if (mContext->mCurTypeState->mGlobalContainerCurUserTypeDef != userTypeDef)
  3284. {
  3285. mContext->mCurTypeState->mGlobalContainers.Clear();
  3286. for (int namespaceIdx = -1; namespaceIdx < (int)userTypeDef->mNamespaceSearch.size(); namespaceIdx++)
  3287. {
  3288. BfAtomComposite findStr;
  3289. if (namespaceIdx != -1)
  3290. findStr.Reference(userTypeDef->mNamespaceSearch[namespaceIdx]);
  3291. auto typeDefItr = mSystem->mTypeDefs.TryGet(findStr);
  3292. while (typeDefItr)
  3293. {
  3294. auto typeDef = *typeDefItr;
  3295. if ((typeDef->mFullName == findStr) && (typeDef->mIsCombinedPartial) && (typeDef->IsGlobalsContainer()))
  3296. {
  3297. if (typeDef->mProject->ContainsReference(typeDef->mProject))
  3298. {
  3299. BfGlobalContainerEntry globalEntry;
  3300. globalEntry.mTypeDef = typeDef;
  3301. globalEntry.mTypeInst = NULL;
  3302. typeDef->PopulateMemberSets();
  3303. mContext->mCurTypeState->mGlobalContainers.Add(globalEntry);
  3304. }
  3305. }
  3306. else if (!typeDef->mIsPartial)
  3307. {
  3308. //break;
  3309. }
  3310. typeDefItr.MoveToNextHashMatch();
  3311. }
  3312. }
  3313. mContext->mCurTypeState->mGlobalContainerCurUserTypeDef = userTypeDef;
  3314. }
  3315. // Only create actual typeInst when we have an applicable member. This helps in keeping unused globals from
  3316. // reifing types
  3317. for (auto& globalEntry : mContext->mCurTypeState->mGlobalContainers)
  3318. {
  3319. if (globalEntry.mTypeInst == NULL)
  3320. {
  3321. bool include = false;
  3322. if (globalLookup.mKind == BfGlobalLookup::Kind_All)
  3323. include = true;
  3324. else if (globalLookup.mKind == BfGlobalLookup::Kind_Field)
  3325. {
  3326. if (globalEntry.mTypeDef->mFieldSet.ContainsWith(globalLookup.mName))
  3327. include = true;
  3328. if (globalEntry.mTypeDef->mPropertySet.ContainsWith(globalLookup.mName))
  3329. include = true;
  3330. }
  3331. else if (globalLookup.mKind == BfGlobalLookup::Kind_Method)
  3332. {
  3333. if (globalEntry.mTypeDef->mMethodSet.ContainsWith(globalLookup.mName))
  3334. include = true;
  3335. }
  3336. if (include)
  3337. {
  3338. auto type = ResolveTypeDef(globalEntry.mTypeDef);
  3339. if (type != NULL)
  3340. globalEntry.mTypeInst = type->ToTypeInstance();
  3341. }
  3342. }
  3343. }
  3344. }
  3345. BfStaticSearch* BfModule::GetStaticSearch()
  3346. {
  3347. auto activeTypeDef = GetActiveTypeDef();
  3348. BfStaticSearch* staticSearch = NULL;
  3349. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->mStaticSearchMap.TryGetValue(activeTypeDef, &staticSearch)))
  3350. return staticSearch;
  3351. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mStaticSearchMap.TryGetValue(activeTypeDef, &staticSearch)))
  3352. return staticSearch;
  3353. return NULL;
  3354. }
  3355. BfInternalAccessSet* BfModule::GetInternalAccessSet()
  3356. {
  3357. auto activeTypeDef = GetActiveTypeDef();
  3358. BfInternalAccessSet* internalAccessSet = NULL;
  3359. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->mInternalAccessMap.TryGetValue(activeTypeDef, &internalAccessSet)))
  3360. return internalAccessSet;
  3361. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mInternalAccessMap.TryGetValue(activeTypeDef, &internalAccessSet)))
  3362. return internalAccessSet;
  3363. return NULL;
  3364. }
  3365. bool BfModule::CheckInternalProtection(BfTypeDef* usingTypeDef)
  3366. {
  3367. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType()))
  3368. return true;
  3369. if ((mCurMethodInstance != NULL) &&
  3370. ((mCurMethodInstance->mIsUnspecializedVariation) || (mCurMethodInstance->IsSpecializedGenericMethod())))
  3371. return true;
  3372. auto internalAccessSet = GetInternalAccessSet();
  3373. if (internalAccessSet == NULL)
  3374. return false;
  3375. for (auto& nameComposite : internalAccessSet->mNamespaces)
  3376. {
  3377. if (usingTypeDef->mNamespace.StartsWith(nameComposite))
  3378. return true;
  3379. }
  3380. for (auto internalType : internalAccessSet->mTypes)
  3381. {
  3382. auto checkTypeDef = usingTypeDef->GetDefinition();
  3383. while (checkTypeDef != NULL)
  3384. {
  3385. if (checkTypeDef == internalType->mTypeDef->GetDefinition())
  3386. return true;
  3387. checkTypeDef = checkTypeDef->mOuterType;
  3388. }
  3389. }
  3390. return false;
  3391. }
  3392. void PrintUsers(llvm::MDNode* md);
  3393. BfModuleOptions BfModule::GetModuleOptions()
  3394. {
  3395. if (mIsScratchModule)
  3396. return BfModuleOptions();
  3397. if (mModuleOptions != NULL)
  3398. return *mModuleOptions;
  3399. BfModuleOptions moduleOptions;
  3400. moduleOptions.mEmitDebugInfo = mCompiler->mOptions.mEmitDebugInfo ? 1 : mCompiler->mOptions.mEmitLineInfo ? 2 : 0;
  3401. if (mProject != NULL)
  3402. {
  3403. moduleOptions.mSIMDSetting = mProject->mCodeGenOptions.mSIMDSetting;
  3404. moduleOptions.mOptLevel = mProject->mCodeGenOptions.mOptLevel;
  3405. }
  3406. auto headModule = this;
  3407. while (headModule->mParentModule != NULL)
  3408. headModule = headModule->mParentModule;
  3409. BF_ASSERT((headModule->mOwnedTypeInstances.size() > 0) || (mModuleName == "vdata") || mIsSpecialModule);
  3410. if (headModule->mOwnedTypeInstances.size() > 0)
  3411. {
  3412. auto typeInst = headModule->mOwnedTypeInstances[0];
  3413. if (typeInst->mTypeOptionsIdx == -2)
  3414. PopulateType(typeInst);
  3415. if (typeInst->mTypeOptionsIdx != -1)
  3416. {
  3417. auto typeOptions = mSystem->GetTypeOptions(typeInst->mTypeOptionsIdx);
  3418. moduleOptions.mSIMDSetting = (BfSIMDSetting)BfTypeOptions::Apply((int)moduleOptions.mSIMDSetting, typeOptions->mSIMDSetting);
  3419. moduleOptions.mEmitDebugInfo = BfTypeOptions::Apply(moduleOptions.mEmitDebugInfo, typeOptions->mEmitDebugInfo);
  3420. moduleOptions.mOptLevel = (BfOptLevel)BfTypeOptions::Apply((int)moduleOptions.mOptLevel, (int)typeOptions->mOptimizationLevel);
  3421. }
  3422. }
  3423. return moduleOptions;
  3424. }
  3425. BfCheckedKind BfModule::GetDefaultCheckedKind()
  3426. {
  3427. if ((mCurMethodState != NULL) && (mCurMethodState->mDisableChecks))
  3428. return BfCheckedKind_Unchecked;
  3429. bool runtimeChecks = mCompiler->mOptions.mRuntimeChecks;
  3430. auto typeOptions = GetTypeOptions();
  3431. if (typeOptions != NULL)
  3432. runtimeChecks = typeOptions->Apply(runtimeChecks, BfOptionFlags_RuntimeChecks);
  3433. return runtimeChecks ? BfCheckedKind_Checked : BfCheckedKind_Unchecked;
  3434. }
  3435. void BfModule::AddFailType(BfTypeInstance* typeInstance)
  3436. {
  3437. BF_ASSERT(typeInstance != NULL);
  3438. if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_InFailTypes) != 0)
  3439. return;
  3440. typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_InFailTypes);
  3441. mContext->mFailTypes.Add(typeInstance);
  3442. }
  3443. void BfModule::DeferRebuildType(BfTypeInstance* typeInstance)
  3444. {
  3445. if ((typeInstance->mRebuildFlags & BfTypeRebuildFlag_RebuildQueued) != 0)
  3446. return;
  3447. mCompiler->mHasQueuedTypeRebuilds = true;
  3448. typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags | BfTypeRebuildFlag_RebuildQueued);
  3449. AddFailType(typeInstance);
  3450. }
  3451. void BfModule::CheckAddFailType()
  3452. {
  3453. //TODO: We removed this line, because failures in resolve-only generic method can occur in non-owning modules
  3454. // but we still need to add the owning type to the FailTypes list
  3455. //.. OLD:
  3456. // While we're inlining, it's possible that mCurTypeInstance belongs to another module, ignore it
  3457. /*if (mCurTypeInstance->mModule != this)
  3458. return;*/
  3459. // Using mHadBuildWarning to insert into mFailTypes is our core of our strategy for reasserting
  3460. // warnings on rebuilds where otherwise the warnings wouldn't be generated because no code was
  3461. // being recompiled. This forces types with warnings to be recompiled.
  3462. // We had this 'mIsResolveOnly' check for speed in resolveOnly, but we removed it so the IDE can be
  3463. // constantly warning-aware
  3464. if ((mHadBuildError) ||
  3465. (mHadBuildWarning /*&& !mCompiler->mIsResolveOnly*/))
  3466. {
  3467. //mContext->mFailTypes.Add(mCurTypeInstance);
  3468. }
  3469. }
  3470. void BfModule::MarkDerivedDirty(BfTypeInstance* typeInst)
  3471. {
  3472. if (!mCompiler->IsHotCompile())
  3473. return;
  3474. typeInst->mDirty = true;
  3475. for (auto& dep : typeInst->mDependencyMap)
  3476. {
  3477. auto depType = dep.mKey;
  3478. auto depFlags = dep.mValue.mFlags;
  3479. if ((depFlags & BfDependencyMap::DependencyFlag_DerivedFrom) != 0)
  3480. {
  3481. MarkDerivedDirty(depType->ToTypeInstance());
  3482. }
  3483. }
  3484. }
  3485. void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal)
  3486. {
  3487. auto fieldType = fieldInstance->GetResolvedType();
  3488. auto field = fieldInstance->GetFieldDef();
  3489. if (fieldType->IsVar())
  3490. return;
  3491. BfIRValue initValue;
  3492. if (field->mIsConst)
  3493. {
  3494. if (fieldType->IsPointer())
  3495. fieldType = fieldType->GetUnderlyingType();
  3496. }
  3497. BfIRStorageKind storageKind = BfIRStorageKind_Normal;
  3498. if ((fieldInstance->mCustomAttributes != NULL) && (fieldInstance->mCustomAttributes->Get(mCompiler->mExportAttributeTypeDef)))
  3499. storageKind = BfIRStorageKind_Export;
  3500. else if ((fieldInstance->mCustomAttributes != NULL) && (fieldInstance->mCustomAttributes->Get(mCompiler->mImportAttributeTypeDef)))
  3501. storageKind = BfIRStorageKind_Import;
  3502. if ((!field->mIsExtern) && (storageKind != BfIRStorageKind_Import))
  3503. initValue = GetDefaultValue(fieldType);
  3504. if (fieldInstance->mOwner->IsUnspecializedType())
  3505. {
  3506. // Placeholder
  3507. auto ptrVal = CreatePointerType(fieldType);
  3508. mStaticFieldRefs[fieldInstance] = GetDefaultValue(ptrVal);
  3509. }
  3510. else
  3511. {
  3512. BfLogSysM("Creating static field Module:%p Type:%p\n", this, fieldType);
  3513. StringT<4096> staticVarName;
  3514. BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), fieldInstance);
  3515. if ((!fieldType->IsValuelessType()) && (!staticVarName.StartsWith("#")))
  3516. {
  3517. BfIRValue globalVar = mBfIRBuilder->CreateGlobalVariable(
  3518. mBfIRBuilder->MapType(fieldType, BfIRPopulateType_Eventually_Full),
  3519. false,
  3520. BfIRLinkageType_External,
  3521. initValue,
  3522. staticVarName,
  3523. isThreadLocal);
  3524. mBfIRBuilder->GlobalVar_SetAlignment(globalVar, fieldType->mAlign);
  3525. if (storageKind != BfIRStorageKind_Normal)
  3526. mBfIRBuilder->GlobalVar_SetStorageKind(globalVar, storageKind);
  3527. BF_ASSERT(globalVar);
  3528. mStaticFieldRefs[fieldInstance] = globalVar;
  3529. }
  3530. }
  3531. }
  3532. void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfFieldDef* fieldDef, bool forceResolve)
  3533. {
  3534. bool autoCompleteOnly = mCompiler->IsAutocomplete();
  3535. BfType* fieldType = NULL;
  3536. if (fieldInstance != NULL)
  3537. {
  3538. fieldType = fieldInstance->GetResolvedType();
  3539. if (fieldType == NULL)
  3540. fieldType = ResolveTypeRef(fieldDef->mTypeRef);
  3541. }
  3542. else
  3543. {
  3544. BF_ASSERT(mCompiler->IsAutocomplete());
  3545. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3546. if ((typeInstance->IsEnum()) && (fieldDef->mTypeRef == NULL))
  3547. {
  3548. fieldType = typeInstance;
  3549. }
  3550. else
  3551. {
  3552. auto isLet = (fieldDef->mTypeRef != NULL) && (fieldDef->mTypeRef->IsExact<BfLetTypeReference>());
  3553. auto isVar = (fieldDef->mTypeRef != NULL) && (fieldDef->mTypeRef->IsExact<BfVarTypeReference>());
  3554. if (isLet || isVar)
  3555. fieldType = GetPrimitiveType(BfTypeCode_Var);
  3556. else
  3557. fieldType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowInferredSizedArray);
  3558. if (fieldType == NULL)
  3559. fieldType = mContext->mBfObjectType;
  3560. }
  3561. }
  3562. if ((fieldInstance != NULL) && (fieldInstance->mConstIdx != -1) && (!forceResolve))
  3563. return;
  3564. if (mContext->mFieldResolveReentrys.size() > 1)
  3565. {
  3566. if (mContext->mFieldResolveReentrys.IndexOf(fieldInstance, 1) != -1)
  3567. {
  3568. String failStr = "Circular data reference detected between the following fields:";
  3569. for (int i = 1; i < (int)mContext->mFieldResolveReentrys.size(); i++)
  3570. {
  3571. if (i > 1)
  3572. failStr += ",";
  3573. failStr += "\n '" + TypeToString(typeInstance) + "." + mContext->mFieldResolveReentrys[i]->GetFieldDef()->mName + "'";
  3574. }
  3575. BfError* err = Fail(failStr, fieldDef->mFieldDeclaration);
  3576. if (err)
  3577. err->mIsPersistent = true;
  3578. return;
  3579. }
  3580. }
  3581. mContext->mFieldResolveReentrys.push_back(fieldInstance);
  3582. AutoPopBack<decltype (mContext->mFieldResolveReentrys)> popTypeResolveReentry(&mContext->mFieldResolveReentrys);
  3583. if (fieldInstance == NULL)
  3584. popTypeResolveReentry.Pop();
  3585. auto typeDef = typeInstance->mTypeDef;
  3586. BfIRValue constValue;
  3587. if (fieldDef->mIsExtern)
  3588. {
  3589. if (!fieldDef->mTypeRef->IsA<BfPointerTypeRef>())
  3590. {
  3591. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3592. Fail("Extern consts must be pointer types", fieldDef->mTypeRef);
  3593. }
  3594. if (fieldDef->GetInitializer() != NULL)
  3595. {
  3596. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3597. Fail("Extern consts cannot have initializers", fieldDef->GetNameNode());
  3598. }
  3599. }
  3600. else if (fieldDef->GetInitializer() == NULL)
  3601. {
  3602. if (fieldDef->IsEnumCaseEntry())
  3603. {
  3604. if (typeInstance->IsTypedPrimitive())
  3605. {
  3606. BfFieldInstance* prevFieldInstance = NULL;
  3607. for (int i = fieldDef->mIdx - 1; i >= 0; i--)
  3608. {
  3609. BfFieldInstance* checkFieldInst = &typeInstance->mFieldInstances[i];
  3610. if (checkFieldInst->GetFieldDef()->IsEnumCaseEntry())
  3611. {
  3612. prevFieldInstance = checkFieldInst;
  3613. break;
  3614. }
  3615. }
  3616. if (prevFieldInstance == NULL)
  3617. constValue = GetConstValue(0, typeInstance);
  3618. else
  3619. {
  3620. ResolveConstField(typeInstance, prevFieldInstance, prevFieldInstance->GetFieldDef());
  3621. if (prevFieldInstance->mConstIdx == -1)
  3622. {
  3623. if (!mCompiler->IsAutocomplete())
  3624. AssertErrorState();
  3625. constValue = GetConstValue(0, typeInstance);
  3626. }
  3627. else
  3628. {
  3629. auto prevConstant = ConstantToCurrent(typeInstance->mConstHolder->GetConstantById(prevFieldInstance->mConstIdx), typeInstance->mConstHolder, typeInstance);
  3630. constValue = mBfIRBuilder->CreateAdd(prevConstant, GetConstValue(1, typeInstance));
  3631. }
  3632. }
  3633. }
  3634. }
  3635. else
  3636. {
  3637. Fail("Const requires initializer", fieldDef->GetNameNode());
  3638. }
  3639. }
  3640. else if (mBfIRBuilder != NULL)
  3641. {
  3642. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3643. SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
  3644. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
  3645. BfMethodState methodState;
  3646. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  3647. methodState.mTempKind = BfMethodState::TempKind_Static;
  3648. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  3649. if ((fieldType->IsVar()) || (fieldType->IsUndefSizedArray()))
  3650. {
  3651. auto initValue = GetFieldInitializerValue(fieldInstance, fieldDef->GetInitializer(), fieldDef, fieldType);
  3652. if (!initValue)
  3653. {
  3654. AssertErrorState();
  3655. initValue = GetDefaultTypedValue(mContext->mBfObjectType);
  3656. }
  3657. if (fieldInstance != NULL)
  3658. {
  3659. if (fieldType->IsUndefSizedArray())
  3660. {
  3661. if ((initValue.mType->IsSizedArray()) && (initValue.mType->GetUnderlyingType() == fieldType->GetUnderlyingType()))
  3662. {
  3663. fieldInstance->mResolvedType = initValue.mType;
  3664. }
  3665. }
  3666. else
  3667. fieldInstance->mResolvedType = initValue.mType;
  3668. }
  3669. constValue = initValue.mValue;
  3670. }
  3671. else
  3672. {
  3673. auto uncastedInitValue = GetFieldInitializerValue(fieldInstance, fieldDef->GetInitializer(), fieldDef, fieldType);
  3674. constValue = uncastedInitValue.mValue;
  3675. }
  3676. if ((mCurTypeInstance->IsPayloadEnum()) && (fieldDef->IsEnumCaseEntry()))
  3677. {
  3678. // Illegal
  3679. constValue = BfIRValue();
  3680. }
  3681. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  3682. }
  3683. if (fieldInstance != NULL)
  3684. {
  3685. fieldType = fieldInstance->GetResolvedType();
  3686. if ((fieldType == NULL) || (fieldType->IsVar()))
  3687. {
  3688. SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
  3689. AssertErrorState();
  3690. // Default const type is 'int'
  3691. BfTypedValue initValue = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_IntPtr));
  3692. if (fieldInstance != NULL)
  3693. {
  3694. fieldInstance->mResolvedType = initValue.mType;
  3695. }
  3696. constValue = initValue.mValue;
  3697. }
  3698. if ((constValue) && (fieldInstance->mConstIdx == -1))
  3699. {
  3700. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3701. CurrentAddToConstHolder(constValue);
  3702. fieldInstance->mConstIdx = constValue.mId;
  3703. }
  3704. }
  3705. }
  3706. BfType* BfModule::ResolveVarFieldType(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfFieldDef* field)
  3707. {
  3708. bool isDeclType = (field->mFieldDeclaration != NULL) && BfNodeDynCastExact<BfExprModTypeRef>(field->mTypeRef) != NULL;
  3709. auto fieldType = fieldInstance->GetResolvedType();
  3710. if ((field->mIsConst) && (!isDeclType))
  3711. {
  3712. ResolveConstField(typeInstance, fieldInstance, field);
  3713. return fieldInstance->GetResolvedType();
  3714. }
  3715. bool staticOnly = (field->mIsStatic) && (!isDeclType);
  3716. if (!fieldInstance->mIsInferredType)
  3717. return fieldType;
  3718. if ((!fieldType->IsVar()) && (!fieldType->IsUndefSizedArray()))
  3719. return fieldType;
  3720. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  3721. BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState);
  3722. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState, mContext->mCurTypeState->mType != typeInstance);
  3723. auto typeDef = typeInstance->mTypeDef;
  3724. if ((!field->mIsStatic) && (typeDef->mIsStatic))
  3725. {
  3726. AssertErrorState();
  3727. return fieldType;
  3728. }
  3729. bool hadInferenceCycle = false;
  3730. if (mContext->mFieldResolveReentrys.size() > 1)
  3731. {
  3732. if (mContext->mFieldResolveReentrys.IndexOf(fieldInstance, 1) != -1)
  3733. {
  3734. for (int i = 1; i < (int)mContext->mFieldResolveReentrys.size(); i++)
  3735. {
  3736. auto fieldInst = mContext->mFieldResolveReentrys[i];
  3737. auto fieldDef = fieldInst->GetFieldDef();
  3738. auto fieldOwner = fieldInst->mOwner;
  3739. auto fieldModule = fieldOwner->mModule;
  3740. SetAndRestoreValue<bool> prevIgnoreError(fieldModule->mIgnoreErrors, false);
  3741. fieldModule->Fail(StrFormat("Field '%s.%s' creates a type inference cycle", TypeToString(fieldOwner).c_str(), fieldDef->mName.c_str()), fieldDef->mTypeRef, true);
  3742. }
  3743. return fieldType;
  3744. }
  3745. }
  3746. mContext->mFieldResolveReentrys.push_back(fieldInstance);
  3747. AutoPopBack<decltype (mContext->mFieldResolveReentrys)> popTypeResolveReentry(&mContext->mFieldResolveReentrys);
  3748. SetAndRestoreValue<bool> prevResolvingVar(typeInstance->mResolvingVarField, true);
  3749. SetAndRestoreValue<bool> prevCtxResolvingVar(mContext->mResolvingVarField, true);
  3750. if ((field->GetInitializer() == NULL) && (!isDeclType))
  3751. {
  3752. if ((field->mTypeRef->IsA<BfVarTypeReference>()) || (field->mTypeRef->IsA<BfLetTypeReference>()))
  3753. Fail("Implicitly-typed fields must be initialized", field->GetRefNode());
  3754. return fieldType;
  3755. }
  3756. BfType* resolvedType = NULL;
  3757. if (!hadInferenceCycle)
  3758. {
  3759. BfTypeState typeState;
  3760. typeState.mPrevState = mContext->mCurTypeState;
  3761. typeState.mType = typeInstance;
  3762. typeState.mCurFieldDef = field;
  3763. typeState.mResolveKind = BfTypeState::ResolveKind_ResolvingVarType;
  3764. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  3765. SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
  3766. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL/*ctorMethod.mMethodInstance*/);
  3767. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  3768. BfMethodState methodState;
  3769. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  3770. methodState.mTempKind = staticOnly ? BfMethodState::TempKind_Static : BfMethodState::TempKind_NonStatic;
  3771. if (!staticOnly)
  3772. {
  3773. //BfLocalVariable localVar;
  3774. //methodState.mLocals.push_back(localVar);
  3775. }
  3776. if (isDeclType)
  3777. {
  3778. auto fieldDef = fieldInstance->GetFieldDef();
  3779. resolvedType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Identity);
  3780. }
  3781. else
  3782. {
  3783. BfTypedValue valueFromExpr;
  3784. valueFromExpr = GetFieldInitializerValue(fieldInstance);
  3785. FixIntUnknown(valueFromExpr);
  3786. if (fieldType->IsUndefSizedArray())
  3787. {
  3788. if ((valueFromExpr.mType != NULL) && (valueFromExpr.mType->IsSizedArray()) && (valueFromExpr.mType->GetUnderlyingType() == fieldType->GetUnderlyingType()))
  3789. resolvedType = valueFromExpr.mType;
  3790. }
  3791. else
  3792. resolvedType = valueFromExpr.mType;
  3793. }
  3794. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  3795. }
  3796. if (resolvedType == NULL)
  3797. return fieldType;
  3798. fieldInstance->SetResolvedType(resolvedType);
  3799. if (field->mIsStatic)
  3800. {
  3801. }
  3802. else if (fieldInstance->mDataIdx >= 0)
  3803. {
  3804. }
  3805. else
  3806. {
  3807. BF_ASSERT(typeInstance->IsIncomplete());
  3808. }
  3809. return resolvedType;
  3810. }
  3811. void BfModule::MarkFieldInitialized(BfFieldInstance* fieldInstance)
  3812. {
  3813. BF_ASSERT(fieldInstance->mOwner == mCurTypeInstance);
  3814. auto fieldType = fieldInstance->GetResolvedType();
  3815. if ((fieldInstance->mMergedDataIdx != -1) && (mCurMethodState != NULL))
  3816. {
  3817. int fieldIdx = 0;
  3818. int fieldCount = 0;
  3819. fieldInstance->GetDataRange(fieldIdx, fieldCount);
  3820. fieldIdx--;
  3821. int count = fieldCount;
  3822. if (fieldIdx == -1)
  3823. count = 1;
  3824. //TODO: Under what circumstances could 'thisVariable' be NULL?
  3825. auto thisVariable = GetThisVariable();
  3826. if (thisVariable != NULL)
  3827. {
  3828. for (int i = 0; i < count; i++)
  3829. mCurMethodState->LocalDefined(thisVariable, fieldIdx + i);
  3830. }
  3831. }
  3832. }
  3833. bool BfModule::IsThreadLocal(BfFieldInstance * fieldInstance)
  3834. {
  3835. if (fieldInstance->mCustomAttributes == NULL)
  3836. return false;
  3837. auto fieldDef = fieldInstance->GetFieldDef();
  3838. if (!fieldDef->mIsStatic)
  3839. return false;
  3840. bool isThreadLocal = false;
  3841. if (fieldInstance->mCustomAttributes != NULL)
  3842. {
  3843. for (auto customAttr : fieldInstance->mCustomAttributes->mAttributes)
  3844. {
  3845. if (customAttr.mType->ToTypeInstance()->IsInstanceOf(mCompiler->mThreadStaticAttributeTypeDef))
  3846. return true;
  3847. }
  3848. }
  3849. return false;
  3850. }
  3851. BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer, BfFieldDef* fieldDef, BfType* fieldType, bool doStore)
  3852. {
  3853. if (fieldDef == NULL)
  3854. fieldDef = fieldInstance->GetFieldDef();
  3855. if (fieldType == NULL)
  3856. fieldType = fieldInstance->GetResolvedType();
  3857. if (initializer == NULL)
  3858. {
  3859. if (fieldDef == NULL)
  3860. return BfTypedValue();
  3861. initializer = fieldDef->GetInitializer();
  3862. }
  3863. BfTypedValue staticVarRef;
  3864. BfTypedValue result;
  3865. if (initializer == NULL)
  3866. {
  3867. result = GetDefaultTypedValue(fieldInstance->mResolvedType);
  3868. }
  3869. else
  3870. {
  3871. if (mCompiler->mIsResolveOnly)
  3872. {
  3873. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(initializer))
  3874. {
  3875. sourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
  3876. sourceClassifier->VisitChildNoRef(initializer);
  3877. }
  3878. }
  3879. if ((mCurTypeInstance->IsPayloadEnum()) && (fieldDef->IsEnumCaseEntry()))
  3880. {
  3881. Fail("Enums with payloads cannot have explicitly-defined discriminators", initializer);
  3882. BfConstResolver constResolver(this);
  3883. constResolver.Resolve(initializer);
  3884. return GetDefaultTypedValue(fieldType);
  3885. }
  3886. else if (mCurTypeInstance->IsUnspecializedTypeVariation())
  3887. {
  3888. return GetDefaultTypedValue(fieldType);
  3889. }
  3890. else if (fieldDef->mIsConst)
  3891. {
  3892. int ceExecuteId = -1;
  3893. if (mCompiler->mCeMachine != NULL)
  3894. ceExecuteId = mCompiler->mCeMachine->mExecuteId;
  3895. BfTypeState typeState;
  3896. typeState.mType = mCurTypeInstance;
  3897. typeState.mCurTypeDef = fieldDef->mDeclaringType;
  3898. typeState.mCurFieldDef = fieldDef;
  3899. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  3900. BfConstResolver constResolver(this);
  3901. if (fieldType->IsVar())
  3902. return constResolver.Resolve(initializer);
  3903. else
  3904. {
  3905. BfConstResolveFlags resolveFlags = BfConstResolveFlag_None;
  3906. if ((mCompiler->mResolvePassData != NULL) && (mCurTypeInstance->IsEnum()) && (fieldDef->IsEnumCaseEntry()) &&
  3907. (mCompiler->mResolvePassData->mAutoCompleteTempTypes.Contains(fieldDef->mDeclaringType)))
  3908. {
  3909. // We avoid doing the cast here because the value we're typing may not be in the range of the current
  3910. // auto-created underlying type and it will cause an 'error flash'. We defer errors until the full resolve for that purpose
  3911. resolveFlags = BfConstResolveFlag_NoCast;
  3912. }
  3913. UpdateSrcPos(initializer);
  3914. auto result = constResolver.Resolve(initializer, fieldType, resolveFlags);
  3915. if ((mCompiler->mCeMachine != NULL) && (fieldInstance != NULL))
  3916. {
  3917. if (mCompiler->mCeMachine->mExecuteId != ceExecuteId)
  3918. fieldInstance->mHadConstEval = true;
  3919. }
  3920. return result;
  3921. }
  3922. }
  3923. BfExprEvaluator exprEvaluator(this);
  3924. if (doStore)
  3925. {
  3926. staticVarRef = ReferenceStaticField(fieldInstance);
  3927. exprEvaluator.mReceivingValue = &staticVarRef;
  3928. }
  3929. if (fieldType->IsVar())
  3930. result = CreateValueFromExpression(exprEvaluator, initializer, NULL, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer));
  3931. else
  3932. result = CreateValueFromExpression(exprEvaluator, initializer, fieldType, (BfEvalExprFlags)(BfEvalExprFlags_NoValueAddr | BfEvalExprFlags_FieldInitializer));
  3933. if (doStore)
  3934. {
  3935. if (exprEvaluator.mReceivingValue == NULL)
  3936. doStore = false; // Already stored
  3937. }
  3938. }
  3939. if (fieldInstance != NULL)
  3940. MarkFieldInitialized(fieldInstance);
  3941. if ((doStore) && (result))
  3942. {
  3943. if (fieldInstance->mResolvedType->IsUndefSizedArray())
  3944. {
  3945. if ((!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mFastFinish))
  3946. AssertErrorState();
  3947. }
  3948. else
  3949. {
  3950. result = LoadValue(result);
  3951. if (!result.mType->IsValuelessType())
  3952. mBfIRBuilder->CreateAlignedStore(result.mValue, staticVarRef.mValue, result.mType->mAlign);
  3953. }
  3954. }
  3955. return result;
  3956. }
  3957. void BfModule::CheckInterfaceMethod(BfMethodInstance* methodInstance)
  3958. {
  3959. }
  3960. void BfModule::FindSubTypes(BfTypeInstance* classType, SizedArrayImpl<int>* outVals, SizedArrayImpl<BfTypeInstance*>* exChecks, bool isInterfacePass)
  3961. {
  3962. PopulateType(classType);
  3963. if (isInterfacePass)
  3964. {
  3965. for (auto ifaceInst : classType->mInterfaces)
  3966. {
  3967. if (exChecks->Contains(ifaceInst.mInterfaceType))
  3968. continue;
  3969. if (outVals->Contains(ifaceInst.mInterfaceType->mTypeId))
  3970. continue;
  3971. if (ifaceInst.mDeclaringType->IsExtension())
  3972. {
  3973. bool needsExCheck = false;
  3974. if (ifaceInst.mDeclaringType->mProject != classType->mTypeDef->mProject)
  3975. {
  3976. PopulateType(ifaceInst.mInterfaceType, BfPopulateType_DataAndMethods);
  3977. if (ifaceInst.mInterfaceType->mVirtualMethodTableSize > 0)
  3978. {
  3979. exChecks->push_back(ifaceInst.mInterfaceType);
  3980. continue;
  3981. }
  3982. else
  3983. {
  3984. // We can only do an 'exCheck' if we're actually going to slot this interface
  3985. }
  3986. }
  3987. }
  3988. outVals->push_back(ifaceInst.mInterfaceType->mTypeId);
  3989. }
  3990. }
  3991. else
  3992. {
  3993. outVals->push_back(classType->mTypeId);
  3994. }
  3995. if (classType->mBaseType != NULL)
  3996. {
  3997. FindSubTypes(classType->mBaseType, outVals, exChecks, isInterfacePass);
  3998. }
  3999. }
  4000. void BfModule::CreateDynamicCastMethod()
  4001. {
  4002. auto objType = mContext->mBfObjectType;
  4003. if ((mCompiler->mIsResolveOnly) || (!mIsReified))
  4004. {
  4005. // The main reason to punt on this method for ResolveOnly is because types can be created
  4006. // and destroyed quickly during autocomplete and the typeId creep can generate lots of
  4007. // entries in the LLVM ConstantInt pool, primarily from the FindSubTypes call. We can
  4008. // remove this punt when we recycle typeId's
  4009. mBfIRBuilder->CreateRet(mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapTypeInstPtr(objType)));
  4010. mCurMethodState->mHadReturn = true;
  4011. return;
  4012. }
  4013. bool isInterfacePass = mCurMethodInstance->mMethodDef->mName == BF_METHODNAME_DYNAMICCAST_INTERFACE;
  4014. auto func = mCurMethodState->mIRFunction;
  4015. auto thisValue = mBfIRBuilder->GetArgument(0);
  4016. auto typeIdValue = mBfIRBuilder->GetArgument(1);
  4017. auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  4018. auto int32Type = GetPrimitiveType(BfTypeCode_Int32);
  4019. typeIdValue = CastToValue(NULL, BfTypedValue(typeIdValue, intPtrType), int32Type, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
  4020. auto thisObject = mBfIRBuilder->CreateBitCast(thisValue, mBfIRBuilder->MapType(objType));
  4021. auto trueBB = mBfIRBuilder->CreateBlock("check.true");
  4022. //auto falseBB = mBfIRBuilder->CreateBlock("check.false");
  4023. auto exitBB = mBfIRBuilder->CreateBlock("exit");
  4024. SizedArray<int, 8> typeMatches;
  4025. SizedArray<BfTypeInstance*, 8> exChecks;
  4026. FindSubTypes(mCurTypeInstance, &typeMatches, &exChecks, isInterfacePass);
  4027. if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType()))
  4028. {
  4029. // Add 'unbound' type id to cast list so things like "List<int> is List<>" work
  4030. auto genericTypeInst = mCurTypeInstance->mTypeDef;
  4031. BfTypeVector genericArgs;
  4032. for (int i = 0; i < (int) genericTypeInst->mGenericParamDefs.size(); i++)
  4033. genericArgs.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
  4034. auto unboundType = ResolveTypeDef(mCurTypeInstance->mTypeDef->GetDefinition(), genericArgs, BfPopulateType_Declaration);
  4035. typeMatches.push_back(unboundType->mTypeId);
  4036. }
  4037. if (mCurTypeInstance->IsBoxed())
  4038. {
  4039. BfBoxedType* boxedType = (BfBoxedType*)mCurTypeInstance;
  4040. BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
  4041. FindSubTypes(innerType, &typeMatches, &exChecks, isInterfacePass);
  4042. if (innerType->IsTypedPrimitive())
  4043. {
  4044. auto underlyingType = innerType->GetUnderlyingType();
  4045. typeMatches.push_back(underlyingType->mTypeId);
  4046. }
  4047. auto innerTypeInst = innerType->ToTypeInstance();
  4048. if ((innerTypeInst->IsInstanceOf(mCompiler->mSizedArrayTypeDef)) ||
  4049. (innerTypeInst->IsInstanceOf(mCompiler->mPointerTTypeDef)) ||
  4050. (innerTypeInst->IsInstanceOf(mCompiler->mMethodRefTypeDef)))
  4051. {
  4052. PopulateType(innerTypeInst);
  4053. //TODO: What case was this supposed to handle?
  4054. //typeMatches.push_back(innerTypeInst->mFieldInstances[0].mResolvedType->mTypeId);
  4055. }
  4056. }
  4057. auto curBlock = mBfIRBuilder->GetInsertBlock();
  4058. BfIRValue vDataPtr;
  4059. if (!exChecks.empty())
  4060. {
  4061. BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  4062. auto ptrPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(intPtrType)));
  4063. auto vDataPtrPtr = mBfIRBuilder->CreateBitCast(thisValue, ptrPtrType);
  4064. vDataPtr = FixClassVData(mBfIRBuilder->CreateLoad(vDataPtrPtr/*, "vtable"*/));
  4065. }
  4066. auto switchStatement = mBfIRBuilder->CreateSwitch(typeIdValue, exitBB, (int)typeMatches.size() + (int)exChecks.size());
  4067. for (auto typeMatch : typeMatches)
  4068. mBfIRBuilder->AddSwitchCase(switchStatement, GetConstValue32(typeMatch), trueBB);
  4069. Array<BfIRValue> incomingFalses;
  4070. for (auto ifaceTypeInst : exChecks)
  4071. {
  4072. BfIRBlock nextBB = mBfIRBuilder->CreateBlock("exCheck", true);
  4073. mBfIRBuilder->AddSwitchCase(switchStatement, GetConstValue32(ifaceTypeInst->mTypeId), nextBB);
  4074. mBfIRBuilder->SetInsertPoint(nextBB);
  4075. BfIRValue slotOfs = GetInterfaceSlotNum(ifaceTypeInst);
  4076. auto ifacePtrPtr = mBfIRBuilder->CreateInBoundsGEP(vDataPtr, slotOfs/*, "iface"*/);
  4077. auto ifacePtr = mBfIRBuilder->CreateLoad(ifacePtrPtr);
  4078. auto cmpResult = mBfIRBuilder->CreateCmpNE(ifacePtr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0));
  4079. mBfIRBuilder->CreateCondBr(cmpResult, trueBB, exitBB);
  4080. incomingFalses.push_back(nextBB);
  4081. }
  4082. mBfIRBuilder->AddBlock(trueBB);
  4083. mBfIRBuilder->SetInsertPoint(trueBB);
  4084. mBfIRBuilder->CreateBr(exitBB);
  4085. mBfIRBuilder->AddBlock(exitBB);
  4086. mBfIRBuilder->SetInsertPoint(exitBB);
  4087. auto phi = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapTypeInstPtr(objType), 2);
  4088. mBfIRBuilder->AddPhiIncoming(phi, thisObject, trueBB);
  4089. auto nullValue = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapTypeInstPtr(objType));
  4090. for (auto incomingFalseBlock : incomingFalses)
  4091. mBfIRBuilder->AddPhiIncoming(phi, nullValue, incomingFalseBlock);
  4092. mBfIRBuilder->AddPhiIncoming(phi, nullValue, curBlock);
  4093. mBfIRBuilder->CreateRet(phi);
  4094. mCurMethodState->mHadReturn = true;
  4095. }
  4096. void BfModule::EmitEquals(BfTypedValue leftValue, BfTypedValue rightValue, BfIRBlock exitBB, bool strictEquals)
  4097. {
  4098. BfExprEvaluator exprEvaluator(this);
  4099. exprEvaluator.mExpectingType = mCurMethodInstance->mReturnType;
  4100. auto typeInst = rightValue.mType->ToTypeInstance();
  4101. exprEvaluator.PerformBinaryOperation((BfAstNode*)NULL, (BfAstNode*)NULL, strictEquals ? BfBinaryOp_StrictEquality : BfBinaryOp_Equality, NULL, BfBinOpFlag_IgnoreOperatorWithWrongResult, leftValue, rightValue);
  4102. BfTypedValue result = exprEvaluator.GetResult();
  4103. if (result.mType != GetPrimitiveType(BfTypeCode_Boolean))
  4104. {
  4105. // Fail?
  4106. }
  4107. if ((result) && (!result.mType->IsVar()))
  4108. {
  4109. auto nextBB = mBfIRBuilder->CreateBlock("next");
  4110. mBfIRBuilder->CreateCondBr(result.mValue, nextBB, exitBB);
  4111. mBfIRBuilder->AddBlock(nextBB);
  4112. mBfIRBuilder->SetInsertPoint(nextBB);
  4113. }
  4114. }
  4115. void BfModule::CreateFakeCallerMethod(const String& funcName)
  4116. {
  4117. if (mCurMethodInstance->mHasFailed)
  4118. return;
  4119. if (mCurMethodInstance->mMethodDef->mIsSkipCall)
  4120. return;
  4121. BF_ASSERT(mCurMethodInstance->mIRFunction);
  4122. auto voidType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_None));
  4123. SizedArray<BfIRType, 4> paramTypes;
  4124. BfIRFunctionType funcType = mBfIRBuilder->CreateFunctionType(voidType, paramTypes);
  4125. BfIRFunction func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_Internal, "FORCELINK_" + funcName);
  4126. mBfIRBuilder->SetActiveFunction(func);
  4127. auto entryBlock = mBfIRBuilder->CreateBlock("main", true);
  4128. mBfIRBuilder->SetInsertPoint(entryBlock);
  4129. BfMethodState methodState;
  4130. methodState.mIRHeadBlock = entryBlock;
  4131. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  4132. SizedArray<BfIRValue, 8> args;
  4133. BfExprEvaluator exprEvaluator(this);
  4134. if (mCurMethodInstance->GetStructRetIdx() == 0)
  4135. {
  4136. auto retPtrType = CreatePointerType(mCurMethodInstance->mReturnType);
  4137. exprEvaluator.PushArg(GetDefaultTypedValue(retPtrType, true, BfDefaultValueKind_Const), args);
  4138. }
  4139. if (mCurMethodInstance->HasThis())
  4140. {
  4141. auto thisValue = GetDefaultTypedValue(mCurMethodInstance->GetOwner(), true, mCurTypeInstance->IsComposite() ? BfDefaultValueKind_Addr : BfDefaultValueKind_Const);
  4142. exprEvaluator.PushThis(NULL, thisValue, mCurMethodInstance, args);
  4143. }
  4144. if (mCurMethodInstance->GetStructRetIdx() == 1)
  4145. {
  4146. auto retPtrType = CreatePointerType(mCurMethodInstance->mReturnType);
  4147. exprEvaluator.PushArg(GetDefaultTypedValue(retPtrType, true, BfDefaultValueKind_Const), args);
  4148. }
  4149. for (int paramIdx = 0; paramIdx < mCurMethodInstance->GetParamCount(); paramIdx++)
  4150. {
  4151. auto paramType = mCurMethodInstance->GetParamType(paramIdx);
  4152. if (paramType->IsValuelessType())
  4153. continue;
  4154. exprEvaluator.PushArg(GetDefaultTypedValue(paramType, true, paramType->IsComposite() ? BfDefaultValueKind_Addr : BfDefaultValueKind_Const), args);
  4155. }
  4156. mBfIRBuilder->CreateCall(mCurMethodInstance->mIRFunction, args);
  4157. mBfIRBuilder->CreateRetVoid();
  4158. }
  4159. void BfModule::CreateDelegateEqualsMethod()
  4160. {
  4161. if (mBfIRBuilder->mIgnoreWrites)
  4162. return;
  4163. auto refNode = mCurTypeInstance->mTypeDef->GetRefNode();
  4164. if (refNode == NULL)
  4165. refNode = mCompiler->mValueTypeTypeDef->GetRefNode();
  4166. UpdateSrcPos(refNode);
  4167. SetIllegalSrcPos();
  4168. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  4169. auto resultVal = CreateAlloca(boolType);
  4170. mBfIRBuilder->CreateStore(GetConstValue(0, boolType), resultVal);
  4171. auto exitBB = mBfIRBuilder->CreateBlock("exit");
  4172. auto delegateType = ResolveTypeDef(mCompiler->mDelegateTypeDef)->ToTypeInstance();
  4173. mBfIRBuilder->PopulateType(delegateType);
  4174. BfExprEvaluator exprEvaluator(this);
  4175. BfTypedValue leftTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]);
  4176. BfTypedValue lhsDelegate = BfTypedValue(mBfIRBuilder->CreateBitCast(leftTypedVal.mValue, mBfIRBuilder->MapType(delegateType)), delegateType);
  4177. BfTypedValue rhsDelegate = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  4178. rhsDelegate = LoadValue(rhsDelegate);
  4179. BfTypedValue rightTypedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(rhsDelegate.mValue, mBfIRBuilder->MapType(mCurTypeInstance)), mCurTypeInstance);
  4180. auto& targetFieldInstance = delegateType->mFieldInstances[0];
  4181. BfTypedValue leftValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(lhsDelegate.mValue, 0, targetFieldInstance.mDataIdx), targetFieldInstance.mResolvedType, true);
  4182. BfTypedValue rightValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(rhsDelegate.mValue, 0, targetFieldInstance.mDataIdx), targetFieldInstance.mResolvedType, true);
  4183. leftValue = LoadValue(leftValue);
  4184. rightValue = LoadValue(rightValue);
  4185. EmitEquals(leftValue, rightValue, exitBB, false);
  4186. bool hadComparison = false;
  4187. for (auto& fieldRef : mCurTypeInstance->mFieldInstances)
  4188. {
  4189. BfFieldInstance* fieldInstance = &fieldRef;
  4190. if (fieldInstance->mDataOffset == -1)
  4191. continue;
  4192. auto fieldType = fieldInstance->mResolvedType;
  4193. if (fieldType->IsValuelessType())
  4194. continue;
  4195. if (fieldType->IsVar())
  4196. continue;
  4197. if (fieldType->IsMethodRef())
  4198. continue;
  4199. if (fieldType->IsRef())
  4200. fieldType = CreatePointerType(fieldType->GetUnderlyingType());
  4201. BfTypedValue leftValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(leftTypedVal.mValue, 0, fieldInstance->mDataIdx), fieldType, true);
  4202. BfTypedValue rightValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(rightTypedVal.mValue, 0, fieldInstance->mDataIdx), fieldType, true);
  4203. if (!fieldInstance->mResolvedType->IsComposite())
  4204. {
  4205. leftValue = LoadValue(leftValue);
  4206. rightValue = LoadValue(rightValue);
  4207. }
  4208. EmitEquals(leftValue, rightValue, exitBB, false);
  4209. }
  4210. mBfIRBuilder->CreateStore(GetConstValue(1, boolType), resultVal);
  4211. mBfIRBuilder->CreateBr(exitBB);
  4212. mBfIRBuilder->AddBlock(exitBB);
  4213. mBfIRBuilder->SetInsertPoint(exitBB);
  4214. auto loadedResult = mBfIRBuilder->CreateLoad(resultVal);
  4215. ClearLifetimeEnds();
  4216. mBfIRBuilder->CreateRet(loadedResult);
  4217. mCurMethodState->mHadReturn = true;
  4218. }
  4219. void BfModule::CreateValueTypeEqualsMethod(bool strictEquals)
  4220. {
  4221. if (mCurMethodInstance->mIsUnspecialized)
  4222. return;
  4223. if (mBfIRBuilder->mIgnoreWrites)
  4224. return;
  4225. BF_ASSERT(!mCurTypeInstance->IsBoxed());
  4226. auto compareType = mCurMethodInstance->mParams[0].mResolvedType;
  4227. bool isValid = true;
  4228. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  4229. if (compareType->IsValuelessType())
  4230. {
  4231. mBfIRBuilder->CreateRet(GetDefaultValue(boolType));
  4232. return;
  4233. }
  4234. if (compareType->IsTypedPrimitive())
  4235. {
  4236. BfExprEvaluator exprEvaluator(this);
  4237. BfTypedValue leftTypedVal = LoadValue(exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]));
  4238. BfTypedValue rightTypedVal = LoadValue(exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]));
  4239. auto cmpResult = mBfIRBuilder->CreateCmpEQ(leftTypedVal.mValue, rightTypedVal.mValue);
  4240. mBfIRBuilder->CreateRet(cmpResult);
  4241. return;
  4242. }
  4243. auto compareDType = compareType->ToDependedType();
  4244. BfTypeInstance* compareTypeInst = compareType->ToTypeInstance();
  4245. if (compareTypeInst != NULL)
  4246. {
  4247. if (compareType->IsPrimitiveType())
  4248. compareTypeInst = GetWrappedStructType(compareType);
  4249. if ((compareTypeInst == NULL) || (!compareTypeInst->IsValueType()))
  4250. {
  4251. isValid = false;
  4252. }
  4253. mBfIRBuilder->PopulateType(compareTypeInst);
  4254. }
  4255. if (!isValid)
  4256. {
  4257. ClearLifetimeEnds();
  4258. mBfIRBuilder->CreateRet(GetDefaultValue(boolType));
  4259. return;
  4260. }
  4261. AddDependency(compareDType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
  4262. auto refNode = mCurTypeInstance->mTypeDef->GetRefNode();
  4263. if (refNode == NULL)
  4264. refNode = mCompiler->mValueTypeTypeDef->GetRefNode();
  4265. UpdateSrcPos(refNode);
  4266. SetIllegalSrcPos();
  4267. auto resultVal = CreateAlloca(boolType);
  4268. mBfIRBuilder->CreateStore(GetConstValue(0, boolType), resultVal);
  4269. auto exitBB = mBfIRBuilder->CreateBlock("exit");
  4270. if (compareType->IsValuelessType())
  4271. {
  4272. // Always equal, nothing to do
  4273. }
  4274. else if (compareType->IsSizedArray())
  4275. {
  4276. auto sizedArrayType = (BfSizedArrayType*)compareType;
  4277. auto _SizedIndex = [&](BfIRValue target, BfIRValue index)
  4278. {
  4279. BfTypedValue result;
  4280. auto indexResult = CreateIndexedValue(sizedArrayType->mElementType, target, index, true);
  4281. result = BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
  4282. if (!result.mType->IsValueType())
  4283. result = LoadValue(result);
  4284. return result;
  4285. };
  4286. if (sizedArrayType->mElementCount > 6)
  4287. {
  4288. auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  4289. auto itr = CreateAlloca(intPtrType);
  4290. mBfIRBuilder->CreateStore(GetDefaultValue(intPtrType), itr);
  4291. auto loopBB = mBfIRBuilder->CreateBlock("loop", true);
  4292. auto bodyBB = mBfIRBuilder->CreateBlock("body", true);
  4293. auto doneBB = mBfIRBuilder->CreateBlock("done", true);
  4294. mBfIRBuilder->CreateBr(loopBB);
  4295. mBfIRBuilder->SetInsertPoint(loopBB);
  4296. auto loadedItr = mBfIRBuilder->CreateLoad(itr);
  4297. auto cmpRes = mBfIRBuilder->CreateCmpGTE(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)sizedArrayType->mElementCount), true);
  4298. mBfIRBuilder->CreateCondBr(cmpRes, doneBB, bodyBB);
  4299. mBfIRBuilder->SetInsertPoint(bodyBB);
  4300. BfTypedValue leftValue = _SizedIndex(mCurMethodState->mLocals[0]->mValue, loadedItr);
  4301. BfTypedValue rightValue = _SizedIndex(mCurMethodState->mLocals[1]->mValue, loadedItr);
  4302. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4303. auto incValue = mBfIRBuilder->CreateAdd(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1));
  4304. mBfIRBuilder->CreateStore(incValue, itr);
  4305. mBfIRBuilder->CreateBr(loopBB);
  4306. mBfIRBuilder->SetInsertPoint(doneBB);
  4307. }
  4308. else
  4309. {
  4310. for (int dataIdx = 0; dataIdx < sizedArrayType->mElementCount; dataIdx++)
  4311. {
  4312. BfTypedValue leftValue = _SizedIndex(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, dataIdx));
  4313. BfTypedValue rightValue = _SizedIndex(mCurMethodState->mLocals[1]->mValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, dataIdx));
  4314. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4315. }
  4316. }
  4317. }
  4318. else if (compareType->IsMethodRef())
  4319. {
  4320. auto methodRefType = (BfMethodRefType*)compareType;
  4321. BfMethodInstance* methodInstance = methodRefType->mMethodRef;
  4322. BfExprEvaluator exprEvaluator(this);
  4323. BfTypedValue leftTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]);
  4324. BfTypedValue rightTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  4325. // We only need to compare the 'this' capture. The rationale is that it's impossible to capture any other non-matching
  4326. // values for the same method reference -- they will always refer back to the same local variables.
  4327. int dataIdx = methodRefType->GetDataIdxFromParamIdx(-1);
  4328. if (dataIdx != -1)
  4329. {
  4330. bool failed = false;
  4331. BfTypedValue leftValue = exprEvaluator.DoImplicitArgCapture(NULL, methodInstance, methodRefType->GetParamIdxFromDataIdx(dataIdx), failed, BfImplicitParamKind_General, leftTypedVal);
  4332. BfTypedValue rightValue = exprEvaluator.DoImplicitArgCapture(NULL, methodInstance, methodRefType->GetParamIdxFromDataIdx(dataIdx), failed, BfImplicitParamKind_General, rightTypedVal);
  4333. BF_ASSERT(!failed);
  4334. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4335. }
  4336. }
  4337. else if (compareTypeInst->IsEnum())
  4338. {
  4339. //auto intType = GetPrimitiveType(BfTypeCode_Int32);
  4340. BfExprEvaluator exprEvaluator(this);
  4341. BfTypedValue leftTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]);
  4342. BfTypedValue rightTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  4343. auto dscrType = compareTypeInst->GetDiscriminatorType();
  4344. BfTypedValue leftValue = ExtractValue(leftTypedVal, NULL, 2);
  4345. leftValue = LoadValue(leftValue);
  4346. BfTypedValue rightValue = ExtractValue(rightTypedVal, NULL, 2);
  4347. rightValue = LoadValue(rightValue);
  4348. BfTypedValue leftPayload = ExtractValue(leftTypedVal, NULL, 1);
  4349. BfTypedValue rightPayload = ExtractValue(rightTypedVal, NULL, 1);
  4350. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4351. int enumCount = 0;
  4352. for (auto& fieldRef : compareTypeInst->mFieldInstances)
  4353. {
  4354. BfFieldInstance* fieldInstance = &fieldRef;
  4355. BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
  4356. if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
  4357. {
  4358. enumCount = -fieldInstance->mDataIdx;
  4359. }
  4360. }
  4361. if (enumCount > 0)
  4362. {
  4363. BfIRBlock matchedBlock = mBfIRBuilder->CreateBlock("matched");
  4364. auto switchVal = mBfIRBuilder->CreateSwitch(leftValue.mValue, exitBB, enumCount);
  4365. for (auto& fieldRef : compareTypeInst->mFieldInstances)
  4366. {
  4367. BfFieldInstance* fieldInstance = &fieldRef;
  4368. BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
  4369. if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
  4370. {
  4371. int enumIdx = -fieldInstance->mDataIdx - 1;
  4372. if (fieldInstance->mResolvedType->mSize == 0)
  4373. {
  4374. mBfIRBuilder->AddSwitchCase(switchVal, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, enumIdx), matchedBlock);
  4375. }
  4376. else
  4377. {
  4378. auto caseBlock = mBfIRBuilder->CreateBlock("case", true);
  4379. mBfIRBuilder->SetInsertPoint(caseBlock);
  4380. auto tuplePtr = CreatePointerType(fieldInstance->mResolvedType);
  4381. BfTypedValue leftTuple;
  4382. BfTypedValue rightTuple;
  4383. if (leftPayload.IsAddr())
  4384. {
  4385. leftTuple = BfTypedValue(mBfIRBuilder->CreateBitCast(leftPayload.mValue, mBfIRBuilder->MapType(tuplePtr)), fieldInstance->mResolvedType, true);
  4386. rightTuple = BfTypedValue(mBfIRBuilder->CreateBitCast(rightPayload.mValue, mBfIRBuilder->MapType(tuplePtr)), fieldInstance->mResolvedType, true);
  4387. }
  4388. else
  4389. {
  4390. leftTuple = Cast(NULL, leftPayload, fieldInstance->mResolvedType, BfCastFlags_Force);
  4391. rightTuple = Cast(NULL, rightPayload, fieldInstance->mResolvedType, BfCastFlags_Force);
  4392. }
  4393. EmitEquals(leftTuple, rightTuple, exitBB, strictEquals);
  4394. mBfIRBuilder->CreateBr(matchedBlock);
  4395. mBfIRBuilder->AddSwitchCase(switchVal, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, enumIdx), caseBlock);
  4396. }
  4397. }
  4398. }
  4399. mBfIRBuilder->AddBlock(matchedBlock);
  4400. mBfIRBuilder->SetInsertPoint(matchedBlock);
  4401. }
  4402. }
  4403. else if (compareTypeInst->IsUnion())
  4404. {
  4405. auto innerType = compareTypeInst->GetUnionInnerType();
  4406. if (!innerType->IsValuelessType())
  4407. {
  4408. BfExprEvaluator exprEvaluator(this);
  4409. BfTypedValue leftTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]);
  4410. leftTypedVal = AggregateSplat(leftTypedVal);
  4411. BfTypedValue leftUnionTypedVal = ExtractValue(leftTypedVal, NULL, 1);
  4412. BfTypedValue rightTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  4413. rightTypedVal = AggregateSplat(rightTypedVal);
  4414. BfTypedValue rightUnionTypedVal = ExtractValue(rightTypedVal, NULL, 1);
  4415. EmitEquals(leftUnionTypedVal, rightUnionTypedVal, exitBB, strictEquals);
  4416. }
  4417. }
  4418. else
  4419. {
  4420. BfExprEvaluator exprEvaluator(this);
  4421. BfTypedValue leftTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[0]);
  4422. BfTypedValue rightTypedVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  4423. bool hadComparison = false;
  4424. for (auto& fieldRef : compareTypeInst->mFieldInstances)
  4425. {
  4426. BfFieldInstance* fieldInstance = &fieldRef;
  4427. if (fieldInstance->mDataOffset == -1)
  4428. continue;
  4429. if (fieldInstance->mResolvedType->IsValuelessType())
  4430. continue;
  4431. if (fieldInstance->mResolvedType->IsVar())
  4432. continue;
  4433. BfTypedValue leftValue = ExtractValue(leftTypedVal, fieldInstance, fieldInstance->mDataIdx);
  4434. BfTypedValue rightValue = ExtractValue(rightTypedVal, fieldInstance, fieldInstance->mDataIdx);
  4435. if (!fieldInstance->mResolvedType->IsComposite())
  4436. {
  4437. leftValue = LoadValue(leftValue);
  4438. rightValue = LoadValue(rightValue);
  4439. }
  4440. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4441. }
  4442. auto baseTypeInst = compareTypeInst->mBaseType;
  4443. if ((baseTypeInst != NULL) && (baseTypeInst->mTypeDef != mCompiler->mValueTypeTypeDef))
  4444. {
  4445. BfTypedValue leftValue = Cast(NULL, leftTypedVal, baseTypeInst);
  4446. BfTypedValue rightValue = Cast(NULL, rightTypedVal, baseTypeInst);
  4447. EmitEquals(leftValue, rightValue, exitBB, strictEquals);
  4448. }
  4449. }
  4450. mBfIRBuilder->CreateStore(GetConstValue(1, boolType), resultVal);
  4451. mBfIRBuilder->CreateBr(exitBB);
  4452. mBfIRBuilder->AddBlock(exitBB);
  4453. mBfIRBuilder->SetInsertPoint(exitBB);
  4454. auto loadedResult = mBfIRBuilder->CreateLoad(resultVal);
  4455. ClearLifetimeEnds();
  4456. mBfIRBuilder->CreateRet(loadedResult);
  4457. mCurMethodState->mHadReturn = true;
  4458. }
  4459. BfIRValue BfModule::CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* outNumElements, String* outMangledName)
  4460. {
  4461. if (mBfIRBuilder->mIgnoreWrites)
  4462. return mBfIRBuilder->GetFakeVal();
  4463. PopulateType(typeInstance, mIsComptimeModule ? BfPopulateType_Data : BfPopulateType_DataAndMethods);
  4464. BfType* classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
  4465. if (mIsComptimeModule)
  4466. {
  4467. auto idVal = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, typeInstance->mTypeId);
  4468. return mBfIRBuilder->CreateIntToPtr(idVal, mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
  4469. }
  4470. BfIRValue* globalVariablePtr = NULL;
  4471. mClassVDataRefs.TryGetValue(typeInstance, &globalVariablePtr);
  4472. int numElements = 1;
  4473. if ((outNumElements != NULL) || (globalVariablePtr == NULL))
  4474. {
  4475. numElements += mCompiler->mMaxInterfaceSlots;
  4476. auto maxIFaceVirtIdx = 0;
  4477. if (!typeInstance->IsInterface())
  4478. {
  4479. int dynCastDataElems = 1 + mCompiler->mMaxInterfaceSlots;
  4480. numElements += ((dynCastDataElems * 4) + mSystem->mPtrSize - 1) / mSystem->mPtrSize;
  4481. numElements += typeInstance->GetOrigVTableSize();
  4482. int ifaceMethodLen = typeInstance->GetIFaceVMethodSize();
  4483. if (typeInstance->mHotTypeData != NULL)
  4484. {
  4485. if (typeInstance->mHotTypeData->mOrigInterfaceMethodsLength != -1)
  4486. ifaceMethodLen = typeInstance->mHotTypeData->mOrigInterfaceMethodsLength;
  4487. }
  4488. numElements += ifaceMethodLen;
  4489. }
  4490. if (outNumElements != NULL)
  4491. *outNumElements = numElements;
  4492. }
  4493. StringT<128> classVDataName;
  4494. String memberName = "sBfClassVData";
  4495. if ((typeInstance->mHotTypeData != NULL) && ((typeInstance->mHotTypeData->mHadDataChange) || (typeInstance->mHotTypeData->mPendingDataChange)))
  4496. {
  4497. auto curVersion = typeInstance->mHotTypeData->GetLatestVersion();
  4498. memberName += "_";
  4499. memberName += BfTypeUtils::HashEncode64(curVersion->mDataHash.mLow);
  4500. memberName += BfTypeUtils::HashEncode64(curVersion->mDataHash.mHigh);
  4501. }
  4502. BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), typeInstance, memberName, classVDataType);
  4503. if (outMangledName != NULL)
  4504. *outMangledName = classVDataName;
  4505. /*if (itr != mClassVDataRefs.end())
  4506. {
  4507. globalVariable = itr->second;
  4508. }*/
  4509. BfIRValue globalVariable;
  4510. if (globalVariablePtr != NULL)
  4511. {
  4512. globalVariable = *globalVariablePtr;
  4513. }
  4514. else
  4515. {
  4516. BfLogSysM("Creating VData %s\n", classVDataName.c_str());
  4517. auto arrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr), numElements);
  4518. globalVariable = mBfIRBuilder->CreateGlobalVariable(
  4519. arrayType,
  4520. true,
  4521. BfIRLinkageType_External,
  4522. BfIRValue(),
  4523. classVDataName);
  4524. mClassVDataRefs[typeInstance] = globalVariable;
  4525. }
  4526. return globalVariable;
  4527. }
  4528. BfIRValue BfModule::GetClassVDataPtr(BfTypeInstance* typeInstance)
  4529. {
  4530. auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
  4531. if (mIsComptimeModule)
  4532. return mBfIRBuilder->Comptime_GetBfType(typeInstance->mTypeId, mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
  4533. return mBfIRBuilder->CreateBitCast(CreateClassVDataGlobal(typeInstance), mBfIRBuilder->MapType(CreatePointerType(classVDataType)));
  4534. }
  4535. BfIRValue BfModule::CreateClassVDataExtGlobal(BfTypeInstance* declTypeInst, BfTypeInstance* implTypeInst, int startVirtIdx)
  4536. {
  4537. if (mBfIRBuilder->mIgnoreWrites)
  4538. return mBfIRBuilder->GetFakeVal();
  4539. int numElements = declTypeInst->GetSelfVTableSize() - declTypeInst->GetOrigSelfVTableSize();
  4540. BF_ASSERT(numElements >= 0);
  4541. if (numElements <= 0)
  4542. return BfIRValue();
  4543. BF_ASSERT(implTypeInst->mVirtualMethodTable[startVirtIdx].mDeclaringMethod.mMethodNum == -1);
  4544. BF_ASSERT(implTypeInst->mVirtualMethodTable[startVirtIdx].mDeclaringMethod.mTypeInstance == declTypeInst);
  4545. if (declTypeInst->mInheritDepth == implTypeInst->mInheritDepth)
  4546. BF_ASSERT(declTypeInst == implTypeInst);
  4547. else
  4548. BF_ASSERT(implTypeInst->mInheritDepth > declTypeInst->mInheritDepth);
  4549. if (declTypeInst != implTypeInst)
  4550. {
  4551. BfTypeInstance* highestImpl = declTypeInst;
  4552. for (int virtIdx = startVirtIdx + 1; virtIdx < (int)declTypeInst->mVirtualMethodTable.size(); virtIdx++)
  4553. {
  4554. if (implTypeInst->mVirtualMethodTable[virtIdx].mDeclaringMethod.mMethodNum == -1)
  4555. break; // Start of an ext entry for another type
  4556. auto checkImplTypeInst = implTypeInst->mVirtualMethodTable[virtIdx].mImplementingMethod.mTypeInstance;
  4557. if ((checkImplTypeInst != NULL) && (checkImplTypeInst->mInheritDepth > highestImpl->mInheritDepth))
  4558. highestImpl = checkImplTypeInst;
  4559. }
  4560. if (highestImpl != implTypeInst)
  4561. return CreateClassVDataExtGlobal(declTypeInst, highestImpl, startVirtIdx);
  4562. }
  4563. BfVDataExtEntry mapEntry;
  4564. mapEntry.mDeclTypeInst = declTypeInst;
  4565. mapEntry.mImplTypeInst = implTypeInst;
  4566. BfIRValue* irValuePtr = NULL;
  4567. if (mClassVDataExtRefs.TryGetValue(mapEntry, &irValuePtr))
  4568. return *irValuePtr;
  4569. PopulateType(declTypeInst, BfPopulateType_DataAndMethods);
  4570. PopulateType(implTypeInst, BfPopulateType_DataAndMethods);
  4571. StringT<512> classVDataName;
  4572. BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), implTypeInst, "bf_hs_replace_VDataExt");
  4573. if (declTypeInst != implTypeInst)
  4574. {
  4575. classVDataName += StrFormat("_%d", implTypeInst->mInheritDepth - declTypeInst->mInheritDepth);
  4576. }
  4577. auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  4578. auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
  4579. SizedArray<BfIRValue, 32> vData;
  4580. auto voidPtrNull = GetDefaultValue(voidPtrType);
  4581. for (int virtIdx = startVirtIdx + declTypeInst->GetOrigSelfVTableSize(); virtIdx < (int)declTypeInst->mVirtualMethodTable.size(); virtIdx++)
  4582. {
  4583. if (implTypeInst->mVirtualMethodTable[virtIdx].mDeclaringMethod.mMethodNum == -1)
  4584. break; // Start of an ext entry for another type
  4585. BfIRValue vValue;
  4586. auto& entry = implTypeInst->mVirtualMethodTable[virtIdx];
  4587. BfMethodInstance* declaringMethodInstance = (BfMethodInstance*)entry.mDeclaringMethod;
  4588. if ((declaringMethodInstance != NULL) && (declaringMethodInstance->mMethodInstanceGroup->IsImplemented()) && (declaringMethodInstance->mIsReified))
  4589. {
  4590. BF_ASSERT(entry.mImplementingMethod.mTypeInstance->mMethodInstanceGroups[entry.mImplementingMethod.mMethodNum].IsImplemented());
  4591. BF_ASSERT(entry.mImplementingMethod.mTypeInstance->mMethodInstanceGroups[entry.mImplementingMethod.mMethodNum].mDefault->mIsReified);
  4592. BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod;
  4593. if ((methodInstance != NULL) && (!methodInstance->mMethodDef->mIsAbstract))
  4594. {
  4595. BF_ASSERT(implTypeInst->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject));
  4596. auto moduleMethodInst = GetMethodInstanceAtIdx(methodInstance->mMethodInstanceGroup->mOwner, methodInstance->mMethodInstanceGroup->mMethodIdx, NULL, BfGetMethodInstanceFlag_NoInline);
  4597. auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
  4598. vValue = funcPtr;
  4599. }
  4600. }
  4601. if (!vValue)
  4602. vValue = voidPtrNull;
  4603. vData.Add(vValue);
  4604. }
  4605. BF_ASSERT((int)vData.size() == numElements);
  4606. BfLogSysM("Creating VDataExt %s\n", classVDataName.c_str());
  4607. auto arrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr), numElements);
  4608. auto globalVariable = mBfIRBuilder->CreateGlobalVariable(arrayType, true,
  4609. BfIRLinkageType_External, BfIRValue(), classVDataName);
  4610. BfIRType extVTableType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
  4611. BfIRValue extVTableConst = mBfIRBuilder->CreateConstAgg_Value(extVTableType, vData);
  4612. mBfIRBuilder->GlobalVar_SetInitializer(globalVariable, extVTableConst);
  4613. mClassVDataExtRefs[mapEntry] = globalVariable;
  4614. return globalVariable;
  4615. }
  4616. BfIRValue BfModule::CreateTypeDataRef(BfType* type)
  4617. {
  4618. if (mBfIRBuilder->mIgnoreWrites)
  4619. {
  4620. return mBfIRBuilder->CreateTypeOf(type);
  4621. }
  4622. if (mIsComptimeModule)
  4623. {
  4624. auto typeTypeDef = ResolveTypeDef(mCompiler->mTypeTypeDef);
  4625. auto typeTypeInst = typeTypeDef->ToTypeInstance();
  4626. return mBfIRBuilder->Comptime_GetReflectType(type->mTypeId, mBfIRBuilder->MapType(typeTypeInst));
  4627. }
  4628. PopulateType(type);
  4629. BfIRValue globalVariable;
  4630. BfIRValue* globalVariablePtr = NULL;
  4631. if (mTypeDataRefs.TryGetValue(type, &globalVariablePtr))
  4632. {
  4633. if (*globalVariablePtr)
  4634. return mBfIRBuilder->CreateTypeOf(type, *globalVariablePtr);
  4635. }
  4636. auto typeTypeDef = ResolveTypeDef(mCompiler->mTypeTypeDef);
  4637. auto typeTypeInst = typeTypeDef->ToTypeInstance();
  4638. auto typeInstance = type->ToTypeInstance();
  4639. StringT<4096> typeDataName;
  4640. if (typeInstance != NULL)
  4641. {
  4642. BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
  4643. }
  4644. else
  4645. {
  4646. typeDataName += "sBfTypeData.";
  4647. BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, this);
  4648. }
  4649. BfLogSysM("Creating TypeData %s\n", typeDataName.c_str());
  4650. globalVariable = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeTypeInst, BfIRPopulateType_Full), true, BfIRLinkageType_External, BfIRValue(), typeDataName);
  4651. mBfIRBuilder->SetReflectTypeData(mBfIRBuilder->MapType(type), globalVariable);
  4652. mTypeDataRefs[type] = globalVariable;
  4653. return mBfIRBuilder->CreateTypeOf(type, globalVariable);
  4654. }
  4655. void BfModule::EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap)
  4656. {
  4657. #define PUSH_INT8(val) data.push_back((uint8)val)
  4658. #define PUSH_INT16(val) { data.push_back(val & 0xFF); data.push_back((val >> 8) & 0xFF); }
  4659. #define PUSH_INT32(val) { data.push_back(val & 0xFF); data.push_back((val >> 8) & 0xFF); data.push_back((val >> 16) & 0xFF); data.push_back((val >> 24) & 0xFF); }
  4660. #define PUSH_INT64(val) { data.push_back(val & 0xFF); data.push_back((val >> 8) & 0xFF); data.push_back((val >> 16) & 0xFF); data.push_back((val >> 24) & 0xFF); \
  4661. data.push_back((val >> 32) & 0xFF); data.push_back((val >> 40) & 0xFF); data.push_back((val >> 48) & 0xFF); data.push_back((val >> 56) & 0xFF); }
  4662. auto constant = typeInstance->mConstHolder->GetConstant(arg);
  4663. bool handled = false;
  4664. if (constant == NULL)
  4665. {
  4666. Fail(StrFormat("Unhandled attribute constant data in '%s'", TypeToString(typeInstance).c_str()));
  4667. return;
  4668. }
  4669. if (argType->IsObject())
  4670. {
  4671. if (argType->IsInstanceOf(mCompiler->mStringTypeDef))
  4672. {
  4673. int stringId = constant->mInt32;
  4674. int* orderedIdPtr;
  4675. if (usedStringIdMap.TryAdd(stringId, NULL, &orderedIdPtr))
  4676. {
  4677. *orderedIdPtr = (int)usedStringIdMap.size() - 1;
  4678. }
  4679. GetStringObjectValue(stringId, true, true);
  4680. PUSH_INT8(0xFF); // String
  4681. PUSH_INT32(*orderedIdPtr);
  4682. return;
  4683. }
  4684. }
  4685. if (argType->IsPointer())
  4686. {
  4687. if (argType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))
  4688. {
  4689. if (constant->mTypeCode == BfTypeCode_StringId)
  4690. {
  4691. int stringId = constant->mInt32;
  4692. int* orderedIdPtr;
  4693. if (usedStringIdMap.TryAdd(stringId, NULL, &orderedIdPtr))
  4694. {
  4695. *orderedIdPtr = (int)usedStringIdMap.size() - 1;
  4696. }
  4697. GetStringObjectValue(stringId, true, true);
  4698. PUSH_INT8(0xFF); // String
  4699. PUSH_INT32(*orderedIdPtr);
  4700. return;
  4701. }
  4702. }
  4703. }
  4704. PUSH_INT8(constant->mTypeCode);
  4705. if ((constant->mTypeCode == BfTypeCode_Int64) ||
  4706. (constant->mTypeCode == BfTypeCode_UInt64) ||
  4707. (constant->mTypeCode == BfTypeCode_Double))
  4708. {
  4709. PUSH_INT64(constant->mInt64);
  4710. }
  4711. else if ((constant->mTypeCode == BfTypeCode_Int32) ||
  4712. (constant->mTypeCode == BfTypeCode_UInt32) ||
  4713. (constant->mTypeCode == BfTypeCode_Char32))
  4714. {
  4715. PUSH_INT32(constant->mInt32);
  4716. }
  4717. else if (constant->mTypeCode == BfTypeCode_Float)
  4718. {
  4719. float val = (float)constant->mDouble;
  4720. PUSH_INT32(*(int*)&val);
  4721. }
  4722. else if ((constant->mTypeCode == BfTypeCode_Int16) ||
  4723. (constant->mTypeCode == BfTypeCode_UInt16) ||
  4724. (constant->mTypeCode == BfTypeCode_Char16))
  4725. {
  4726. PUSH_INT16(constant->mInt16);
  4727. }
  4728. else if ((constant->mTypeCode == BfTypeCode_Int8) ||
  4729. (constant->mTypeCode == BfTypeCode_UInt8) ||
  4730. (constant->mTypeCode == BfTypeCode_Boolean) ||
  4731. (constant->mTypeCode == BfTypeCode_Char8))
  4732. {
  4733. PUSH_INT8(constant->mInt8);
  4734. }
  4735. else if (constant->mConstType == BfConstType_TypeOf)
  4736. {
  4737. auto typeOf = (BfTypeOf_Const*)constant;
  4738. PUSH_INT32(typeOf->mType->mTypeId);
  4739. }
  4740. else if (constant->mConstType == BfConstType_AggZero)
  4741. {
  4742. for (int i = 0; i < argType->mSize; i++)
  4743. data.Add(0);
  4744. }
  4745. // else if (constant->mConstType == BfConstType_Agg)
  4746. // {
  4747. // BF_ASSERT(argType->IsComposite());
  4748. // if (argType->IsSizedArray())
  4749. // {
  4750. // auto argSizedArrayType = (BfSizedArrayType*)argType;
  4751. // }
  4752. // else
  4753. // {
  4754. // auto argTypeInstance = argType->ToTypeInstance();
  4755. // }
  4756. // }
  4757. else
  4758. {
  4759. Fail(StrFormat("Unhandled attribute constant data in '%s'", TypeToString(typeInstance).c_str()));
  4760. }
  4761. }
  4762. BfIRValue BfModule::CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx)
  4763. {
  4764. bool isComptimeArg = mBfIRBuilder->mIgnoreWrites;
  4765. BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
  4766. auto typeInstance = fieldInstance->mOwner;
  4767. BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
  4768. BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  4769. BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
  4770. BfType* typeIdType = intType;
  4771. BfTypeInstance* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef)->ToTypeInstance();
  4772. BfIRValue emptyValueType = mBfIRBuilder->mIgnoreWrites ?
  4773. mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapTypeInst(reflectFieldDataType->mBaseType), SizedArray<BfIRValue, 1>()) :
  4774. mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->mBaseType), SizedArray<BfIRValue, 1>());
  4775. BfIRValue fieldNameConst = GetStringObjectValue(fieldDef->mName, !mIsComptimeModule);
  4776. bool is32Bit = mCompiler->mSystem->mPtrSize == 4;
  4777. int typeId = 0;
  4778. auto fieldType = fieldInstance->GetResolvedType();
  4779. if (fieldType->IsGenericParam())
  4780. {
  4781. //TODO:
  4782. }
  4783. else
  4784. typeId = fieldType->mTypeId;
  4785. BfFieldFlags fieldFlags = (BfFieldFlags)0;
  4786. if (fieldDef->mProtection == BfProtection_Protected)
  4787. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Protected);
  4788. if (fieldDef->mProtection == BfProtection_Public)
  4789. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Public);
  4790. if (fieldDef->mIsStatic)
  4791. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Static);
  4792. if (fieldDef->mIsConst)
  4793. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_Const);
  4794. if (fieldDef->IsEnumCaseEntry())
  4795. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_EnumCase);
  4796. if (fieldDef->mIsReadOnly)
  4797. fieldFlags = (BfFieldFlags)(fieldFlags | BfFieldFlags_ReadOnly);
  4798. BfIRValue constValue;
  4799. BfIRValue constValue2;
  4800. if (fieldInstance->GetFieldDef()->mIsConst)
  4801. {
  4802. if (fieldInstance->mConstIdx != -1)
  4803. {
  4804. auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
  4805. uint64 val = constant->mUInt64;
  4806. if (constant->mTypeCode == BfTypeCode_Float)
  4807. {
  4808. float f = (float)*(double*)&val;
  4809. val = *(uint32*)&f;
  4810. }
  4811. constValue = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, val);
  4812. if (is32Bit)
  4813. constValue2 = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, val >> 32);
  4814. }
  4815. }
  4816. else if (fieldInstance->GetFieldDef()->mIsStatic)
  4817. {
  4818. BfTypedValue refVal;
  4819. if (!mIsComptimeModule) // This can create circular reference issues for a `Self` static
  4820. refVal = ReferenceStaticField(fieldInstance);
  4821. if (refVal.mValue.IsConst())
  4822. {
  4823. auto constant = mBfIRBuilder->GetConstant(refVal.mValue);
  4824. if (constant->mConstType == BfConstType_GlobalVar)
  4825. {
  4826. auto globalVar = (BfGlobalVar*)constant;
  4827. if (globalVar->mName[0] == '#')
  4828. refVal = BfTypedValue();
  4829. }
  4830. }
  4831. if ((refVal.IsAddr()) && (!isComptimeArg))
  4832. constValue = mBfIRBuilder->CreatePtrToInt(refVal.mValue, BfTypeCode_IntPtr);
  4833. }
  4834. if (!constValue)
  4835. constValue = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, fieldInstance->mDataOffset);
  4836. BfIRValue result;
  4837. if (is32Bit)
  4838. {
  4839. if (!constValue2)
  4840. constValue2 = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0);
  4841. SizedArray<BfIRValue, 8> fieldVals =
  4842. {
  4843. emptyValueType,
  4844. fieldNameConst, // mName
  4845. GetConstValue(typeId, typeIdType), // mFieldTypeId
  4846. constValue, // mData
  4847. constValue2, // mDataHi
  4848. GetConstValue(fieldFlags, shortType), // mFlags
  4849. GetConstValue((isComptimeArg || mIsComptimeModule) ? fieldInstance->mFieldIdx : customAttrIdx, intType), // mCustomAttributesIdx
  4850. };
  4851. FixConstValueParams(reflectFieldDataType, fieldVals, isComptimeArg);
  4852. result = isComptimeArg ?
  4853. mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapTypeInst(reflectFieldDataType, BfIRPopulateType_Full), fieldVals) :
  4854. mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType, BfIRPopulateType_Full), fieldVals);
  4855. }
  4856. else
  4857. {
  4858. SizedArray<BfIRValue, 8> fieldVals =
  4859. {
  4860. emptyValueType,
  4861. fieldNameConst, // mName
  4862. GetConstValue(typeId, typeIdType), // mFieldTypeId
  4863. constValue, // mData
  4864. GetConstValue(fieldFlags, shortType), // mFlags
  4865. GetConstValue((isComptimeArg || mIsComptimeModule) ? fieldInstance->mFieldIdx : customAttrIdx, intType), // mCustomAttributesIdx
  4866. };
  4867. FixConstValueParams(reflectFieldDataType, fieldVals, isComptimeArg);
  4868. result = isComptimeArg ?
  4869. mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapTypeInst(reflectFieldDataType, BfIRPopulateType_Full), fieldVals) :
  4870. mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType, BfIRPopulateType_Full), fieldVals);
  4871. }
  4872. return result;
  4873. }
  4874. BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStringIdMap, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
  4875. {
  4876. if ((IsHotCompile()) && (!type->mDirty))
  4877. return BfIRValue();
  4878. BfIRValue* irValuePtr = NULL;
  4879. if (mTypeDataRefs.TryGetValue(type, &irValuePtr))
  4880. {
  4881. return *irValuePtr;
  4882. }
  4883. BfTypeInstance* typeInstance = type->ToTypeInstance();
  4884. BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
  4885. mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
  4886. if (typeInstanceType == NULL)
  4887. {
  4888. AssertErrorState();
  4889. return BfIRValue();
  4890. }
  4891. BfIRValue typeTypeData;
  4892. int typeFlags = 0;
  4893. if (needsTypeData)
  4894. {
  4895. BfTypeInstance* typeInstanceTypeInstance = typeInstanceType->ToTypeInstance();
  4896. BfTypeInstance* typeDataSource = NULL;
  4897. if (typeInstance != NULL)
  4898. {
  4899. if (typeInstance->IsUnspecializedType())
  4900. {
  4901. typeDataSource = ResolveTypeDef(mCompiler->mReflectUnspecializedGenericType)->ToTypeInstance();
  4902. typeFlags |= BfTypeFlags_UnspecializedGeneric;
  4903. }
  4904. else if (typeInstance->IsArray())
  4905. {
  4906. typeDataSource = ResolveTypeDef(mCompiler->mReflectArrayType)->ToTypeInstance();
  4907. typeFlags |= BfTypeFlags_Array;
  4908. }
  4909. else if (typeInstance->IsGenericTypeInstance())
  4910. {
  4911. typeDataSource = ResolveTypeDef(mCompiler->mReflectSpecializedGenericType)->ToTypeInstance();
  4912. typeFlags |= BfTypeFlags_SpecializedGeneric;
  4913. }
  4914. else
  4915. typeDataSource = typeInstanceTypeInstance;
  4916. }
  4917. else if (type->IsPointer())
  4918. typeDataSource = ResolveTypeDef(mCompiler->mReflectPointerType)->ToTypeInstance();
  4919. else if (type->IsRef())
  4920. typeDataSource = ResolveTypeDef(mCompiler->mReflectRefType)->ToTypeInstance();
  4921. else if (type->IsSizedArray())
  4922. typeDataSource = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance();
  4923. else if (type->IsConstExprValue())
  4924. typeDataSource = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance();
  4925. else if (type->IsGenericParam())
  4926. {
  4927. typeFlags |= BfTypeFlags_GenericParam;
  4928. typeDataSource = ResolveTypeDef(mCompiler->mReflectGenericParamType)->ToTypeInstance();
  4929. }
  4930. else
  4931. typeDataSource = mContext->mBfTypeType;
  4932. if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
  4933. {
  4934. CreateTypeData(typeDataSource, usedStringIdMap, false, true, needsTypeNames, true);
  4935. }
  4936. typeTypeData = CreateClassVDataGlobal(typeDataSource);
  4937. }
  4938. else
  4939. typeTypeData = CreateClassVDataGlobal(typeInstanceType->ToTypeInstance());
  4940. BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
  4941. BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
  4942. BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  4943. BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
  4944. BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
  4945. BfType* typeIdType = intType;
  4946. auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  4947. auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
  4948. auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType);
  4949. auto voidPtrNull = GetDefaultValue(voidPtrType);
  4950. SizedArray<BfIRValue, 4> typeValueParams;
  4951. GetConstClassValueParam(typeTypeData, typeValueParams);
  4952. FixConstValueParams(mContext->mBfObjectType, typeValueParams);
  4953. BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
  4954. StringT<512> typeDataName;
  4955. if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
  4956. {
  4957. BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
  4958. if (typeInstance->mTypeDef->IsGlobalsContainer())
  4959. typeDataName += "`G`" + typeInstance->mTypeDef->mProject->mName;
  4960. }
  4961. else
  4962. {
  4963. typeDataName += "sBfTypeData.";
  4964. BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
  4965. }
  4966. int typeCode = BfTypeCode_None;
  4967. if (typeInstance != NULL)
  4968. {
  4969. BF_ASSERT((type->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || mIsComptimeModule);
  4970. typeCode = typeInstance->mTypeDef->mTypeCode;
  4971. }
  4972. else if (type->IsPrimitiveType())
  4973. {
  4974. BfPrimitiveType* primType = (BfPrimitiveType*)type;
  4975. typeCode = primType->mTypeDef->mTypeCode;
  4976. }
  4977. else if (type->IsPointer())
  4978. {
  4979. typeCode = BfTypeCode_Pointer;
  4980. typeFlags |= BfTypeFlags_Pointer;
  4981. }
  4982. else if (type->IsRef())
  4983. {
  4984. typeCode = BfTypeCode_Pointer;
  4985. typeFlags |= BfTypeFlags_Pointer;
  4986. }
  4987. if (type->IsObject())
  4988. {
  4989. typeFlags |= BfTypeFlags_Object;
  4990. if (typeInstance->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted)
  4991. {
  4992. BfMethodInstance* methodInstance = typeInstance->mVirtualMethodTable[mCompiler->GetVTableMethodOffset() + 0].mImplementingMethod;
  4993. if (methodInstance->GetOwner() != mContext->mBfObjectType)
  4994. typeFlags |= BfTypeFlags_HasDestructor;
  4995. }
  4996. }
  4997. if (type->IsStruct())
  4998. typeFlags |= BfTypeFlags_Struct;
  4999. if (type->IsInterface())
  5000. typeFlags |= BfTypeFlags_Interface;
  5001. if (type->IsBoxed())
  5002. {
  5003. typeFlags |= BfTypeFlags_Boxed;
  5004. if (((BfBoxedType*)type)->IsBoxedStructPtr())
  5005. typeFlags |= BfTypeFlags_Pointer;
  5006. }
  5007. if (type->IsPrimitiveType())
  5008. typeFlags |= BfTypeFlags_Primitive;
  5009. if (type->IsTypedPrimitive())
  5010. typeFlags |= BfTypeFlags_TypedPrimitive;
  5011. if (type->IsTuple())
  5012. typeFlags |= BfTypeFlags_Tuple;
  5013. if (type->IsNullable())
  5014. typeFlags |= BfTypeFlags_Nullable;
  5015. if (type->IsSizedArray())
  5016. typeFlags |= BfTypeFlags_SizedArray;
  5017. if (type->IsConstExprValue())
  5018. typeFlags |= BfTypeFlags_ConstExpr;
  5019. if (type->IsSplattable())
  5020. typeFlags |= BfTypeFlags_Splattable;
  5021. if (type->IsUnion())
  5022. typeFlags |= BfTypeFlags_Union;
  5023. if (type->IsDelegate())
  5024. typeFlags |= BfTypeFlags_Delegate;
  5025. if (type->IsFunction())
  5026. typeFlags |= BfTypeFlags_Function;
  5027. if ((type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking()))
  5028. typeFlags |= BfTypeFlags_WantsMarking;
  5029. int virtSlotIdx = -1;
  5030. if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
  5031. virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount();
  5032. int memberDataOffset = 0;
  5033. if (type->IsInterface())
  5034. memberDataOffset = virtSlotIdx * mSystem->mPtrSize;
  5035. else if (typeInstance != NULL)
  5036. {
  5037. for (auto& fieldInstance : typeInstance->mFieldInstances)
  5038. {
  5039. if (fieldInstance.mDataOffset != -1)
  5040. {
  5041. memberDataOffset = fieldInstance.mDataOffset;
  5042. break;
  5043. }
  5044. }
  5045. }
  5046. int boxedTypeId = 0;
  5047. if ((type->IsValueType()) || (type->IsWrappableType()))
  5048. {
  5049. auto boxedType = CreateBoxedType(type, false);
  5050. if ((boxedType != NULL) && (boxedType->mIsReified))
  5051. boxedTypeId = boxedType->mTypeId;
  5052. }
  5053. int stackCount = 0;
  5054. if ((typeInstance != NULL) && (typeInstance->mTypeOptionsIdx != -1))
  5055. {
  5056. auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
  5057. if (typeOptions->mAllocStackTraceDepth != -1)
  5058. stackCount = BF_MIN(0xFF, BF_MAX(0x01, typeOptions->mAllocStackTraceDepth));
  5059. }
  5060. SizedArray<BfIRValue, 9> typeDataParams =
  5061. {
  5062. objectData,
  5063. GetConstValue(type->mSize, intType), // mSize
  5064. GetConstValue(type->mTypeId, typeIdType), // mTypeId
  5065. GetConstValue(boxedTypeId, typeIdType), // mBoxedType
  5066. GetConstValue(typeFlags, intType), // mTypeFlags
  5067. GetConstValue(memberDataOffset, intType), // mMemberDataOffset
  5068. GetConstValue(typeCode, byteType), // mTypeCode
  5069. GetConstValue(type->mAlign, byteType), // mAlign
  5070. GetConstValue(stackCount, byteType), // mAllocStackCountOverride
  5071. };
  5072. FixConstValueParams(mContext->mBfTypeType, typeDataParams);
  5073. auto typeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType, BfIRPopulateType_Full), typeDataParams);
  5074. if (typeInstance == NULL)
  5075. {
  5076. BfIRValue typeDataVar;
  5077. if (needsTypeData)
  5078. {
  5079. if (type->IsPointer())
  5080. {
  5081. auto pointerType = (BfPointerType*)type;
  5082. SizedArray<BfIRValue, 3> pointerTypeDataParms =
  5083. {
  5084. typeData,
  5085. GetConstValue(pointerType->mElementType->mTypeId, typeIdType),
  5086. };
  5087. auto reflectPointerType = ResolveTypeDef(mCompiler->mReflectPointerType)->ToTypeInstance();
  5088. FixConstValueParams(reflectPointerType, pointerTypeDataParms);
  5089. auto pointerTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectPointerType, BfIRPopulateType_Full), pointerTypeDataParms);
  5090. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectPointerType), true,
  5091. BfIRLinkageType_External, pointerTypeData, typeDataName);
  5092. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5093. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  5094. }
  5095. else if (type->IsRef())
  5096. {
  5097. auto refType = (BfRefType*)type;
  5098. SizedArray<BfIRValue, 3> refTypeDataParms =
  5099. {
  5100. typeData,
  5101. GetConstValue(refType->mElementType->mTypeId, typeIdType),
  5102. GetConstValue((int8)refType->mRefKind, byteType),
  5103. };
  5104. auto reflectRefType = ResolveTypeDef(mCompiler->mReflectRefType)->ToTypeInstance();
  5105. FixConstValueParams(reflectRefType, refTypeDataParms);
  5106. auto refTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectRefType, BfIRPopulateType_Full), refTypeDataParms);
  5107. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectRefType), true,
  5108. BfIRLinkageType_External, refTypeData, typeDataName);
  5109. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5110. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  5111. }
  5112. else if (type->IsSizedArray())
  5113. {
  5114. auto sizedArrayType = (BfSizedArrayType*)type;
  5115. SizedArray<BfIRValue, 3> sizedArrayTypeDataParms =
  5116. {
  5117. typeData,
  5118. GetConstValue(sizedArrayType->mElementType->mTypeId, typeIdType),
  5119. GetConstValue(sizedArrayType->mElementCount, intType)
  5120. };
  5121. auto reflectSizedArrayType = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance();
  5122. FixConstValueParams(reflectSizedArrayType, sizedArrayTypeDataParms);
  5123. auto sizedArrayTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectSizedArrayType, BfIRPopulateType_Full), sizedArrayTypeDataParms);
  5124. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectSizedArrayType), true,
  5125. BfIRLinkageType_External, sizedArrayTypeData, typeDataName);
  5126. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5127. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  5128. }
  5129. else if (type->IsConstExprValue())
  5130. {
  5131. auto constExprType = (BfConstExprValueType*)type;
  5132. SizedArray<BfIRValue, 3> constExprTypeDataParms =
  5133. {
  5134. typeData,
  5135. GetConstValue(constExprType->mType->mTypeId, typeIdType),
  5136. GetConstValue(constExprType->mValue.mInt64, longType)
  5137. };
  5138. auto reflectConstExprType = ResolveTypeDef(mCompiler->mReflectConstExprType)->ToTypeInstance();
  5139. FixConstValueParams(reflectConstExprType, constExprTypeDataParms);
  5140. auto ConstExprTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectConstExprType, BfIRPopulateType_Full), constExprTypeDataParms);
  5141. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectConstExprType), true,
  5142. BfIRLinkageType_External, ConstExprTypeData, typeDataName);
  5143. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5144. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  5145. }
  5146. else if (type->IsGenericParam())
  5147. {
  5148. auto genericParamType = (BfGenericParamType*)type;
  5149. SizedArray<BfIRValue, 3> genericParamTypeDataParms =
  5150. {
  5151. typeData
  5152. };
  5153. auto reflectGenericParamType = ResolveTypeDef(mCompiler->mReflectGenericParamType)->ToTypeInstance();
  5154. FixConstValueParams(reflectGenericParamType, genericParamTypeDataParms);
  5155. auto genericParamTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectGenericParamType, BfIRPopulateType_Full), genericParamTypeDataParms);
  5156. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectGenericParamType), true,
  5157. BfIRLinkageType_External, genericParamTypeData, typeDataName);
  5158. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5159. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  5160. }
  5161. else
  5162. {
  5163. typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType), true,
  5164. BfIRLinkageType_External, typeData, typeDataName);
  5165. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  5166. }
  5167. }
  5168. else
  5169. typeDataVar = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(mContext->mBfTypeType));
  5170. mTypeDataRefs[type] = typeDataVar;
  5171. return typeDataVar;
  5172. }
  5173. // Reserve position
  5174. mTypeDataRefs[typeInstance] = BfIRValue();
  5175. if ((typeInstance->IsReified()) && (!mIsComptimeModule))
  5176. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  5177. BfTypeDef* typeDef = typeInstance->mTypeDef;
  5178. StringT<512> mangledName;
  5179. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), typeInstance, typeInstance->mModule);
  5180. if (!mIsComptimeModule)
  5181. {
  5182. for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++)
  5183. {
  5184. auto methodDef = typeDef->mMethods[methodIdx];
  5185. auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
  5186. if (methodInstance == NULL)
  5187. continue;
  5188. if (typeInstance->IsUnspecializedType())
  5189. continue;
  5190. if (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject))
  5191. {
  5192. if (methodInstance->mChainType == BfMethodChainType_ChainMember)
  5193. {
  5194. BF_ASSERT(!methodInstance->GetOwner()->IsUnspecializedType());
  5195. // We need to create an empty thunk for this chained method
  5196. BfIRFunction func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline);
  5197. mBfIRBuilder->SetActiveFunction(func);
  5198. auto block = mBfIRBuilder->CreateBlock("entry", true);
  5199. mBfIRBuilder->SetInsertPoint(block);
  5200. mBfIRBuilder->CreateRetVoid();
  5201. mBfIRBuilder->SetActiveFunction(BfIRFunction());
  5202. }
  5203. }
  5204. }
  5205. }
  5206. SizedArray<BfIRValue, 32> vData;
  5207. BfIRValue classVDataVar;
  5208. String classVDataName;
  5209. if (typeInstance->mSlotNum >= 0)
  5210. {
  5211. // For interfaces we ONLY emit the slot num
  5212. StringT<512> slotVarName;
  5213. BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs");
  5214. auto intType = GetPrimitiveType(BfTypeCode_Int32);
  5215. auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External,
  5216. GetConstValue32(virtSlotIdx), slotVarName);
  5217. }
  5218. else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData))
  5219. {
  5220. int dynCastDataElems = 0;
  5221. int numElements = 1;
  5222. int vDataOfs = 1; // The number of intptrs before the iface slot map
  5223. numElements += mCompiler->mMaxInterfaceSlots;
  5224. if (!typeInstance->IsInterface())
  5225. {
  5226. dynCastDataElems = 1 + mCompiler->mMaxInterfaceSlots;
  5227. numElements += mCompiler->GetDynCastVDataCount();
  5228. numElements += typeInstance->mVirtualMethodTableSize;
  5229. }
  5230. int expectNumElements = 0;
  5231. if (!typeDef->mIsStatic)
  5232. {
  5233. classVDataVar = CreateClassVDataGlobal(typeInstance, &expectNumElements, &classVDataName);
  5234. }
  5235. vData.push_back(BfIRValue()); // Type*
  5236. SizedArray<BfIRValue, 1> extVTableData;
  5237. SizedArrayImpl<BfIRValue>* vFuncDataExt = &extVTableData;
  5238. if (!typeInstance->IsInterface())
  5239. {
  5240. Array<int32> dynCastData;
  5241. if (typeInstance->IsBoxed())
  5242. {
  5243. auto underlyingType = typeInstance->GetUnderlyingType()->ToTypeInstance();
  5244. dynCastData.Add(underlyingType->mInheritanceId);
  5245. }
  5246. else
  5247. dynCastData.Add(typeInstance->mInheritanceId);
  5248. for (int i = 0; i < mCompiler->mMaxInterfaceSlots; i++)
  5249. dynCastData.Add(0);
  5250. dynCastData.Add(0);
  5251. auto checkTypeInst = typeInstance;
  5252. while (checkTypeInst != NULL)
  5253. {
  5254. for (auto&& interfaceEntry : checkTypeInst->mInterfaces)
  5255. {
  5256. if (interfaceEntry.mInterfaceType->mSlotNum >= 0)
  5257. {
  5258. if (dynCastData[interfaceEntry.mInterfaceType->mSlotNum + 1] == 0)
  5259. dynCastData[interfaceEntry.mInterfaceType->mSlotNum + 1] = interfaceEntry.mInterfaceType->mTypeId;
  5260. }
  5261. }
  5262. checkTypeInst = checkTypeInst->GetImplBaseType();
  5263. }
  5264. if (mSystem->mPtrSize == 8)
  5265. {
  5266. int intPtrCount = (dynCastDataElems + 1) / 2;
  5267. vDataOfs += intPtrCount;
  5268. uint64* intPtrData = (uint64*)&dynCastData[0];
  5269. for (int i = 0; i < intPtrCount; i++)
  5270. {
  5271. uint64 val = intPtrData[i];
  5272. if (val == 0)
  5273. {
  5274. vData.push_back(voidPtrNull);
  5275. }
  5276. else
  5277. {
  5278. auto intPtrVal = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, val);
  5279. vData.push_back(mBfIRBuilder->CreateBitCast(intPtrVal, voidPtrIRType));
  5280. }
  5281. }
  5282. }
  5283. else
  5284. {
  5285. int intPtrCount = dynCastDataElems;
  5286. vDataOfs += intPtrCount;
  5287. uint32* intPtrData = (uint32*)&dynCastData[0];
  5288. for (int i = 0; i < intPtrCount; i++)
  5289. {
  5290. uint32 val = intPtrData[i];
  5291. if (val == 0)
  5292. {
  5293. vData.push_back(voidPtrNull);
  5294. }
  5295. else
  5296. {
  5297. auto intPtrVal = mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (int)val);
  5298. vData.push_back(mBfIRBuilder->CreateBitCast(intPtrVal, voidPtrIRType));
  5299. }
  5300. }
  5301. }
  5302. }
  5303. for (int iSlotIdx = 0; iSlotIdx < mCompiler->mMaxInterfaceSlots; iSlotIdx++)
  5304. vData.push_back(voidPtrNull);
  5305. struct _InterfaceMatchEntry
  5306. {
  5307. BfTypeInterfaceEntry* mEntry;
  5308. BfTypeInstance* mEntrySource;
  5309. Array<BfTypeInterfaceEntry*> mAmbiguousEntries;
  5310. };
  5311. int highestIFaceVirtIdx = 0;
  5312. Dictionary<BfTypeInstance*, _InterfaceMatchEntry> interfaceMap;
  5313. auto checkTypeInst = typeInstance;
  5314. bool forceInterfaceSet = false;
  5315. while (checkTypeInst != NULL)
  5316. {
  5317. for (auto&& interfaceEntry : checkTypeInst->mInterfaces)
  5318. {
  5319. highestIFaceVirtIdx = BF_MAX(highestIFaceVirtIdx, interfaceEntry.mStartVirtualIdx + interfaceEntry.mInterfaceType->mVirtualMethodTableSize);
  5320. if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry.mDeclaringType, mProject)))
  5321. continue;
  5322. _InterfaceMatchEntry* matchEntry = NULL;
  5323. if (interfaceMap.TryGetValue(interfaceEntry.mInterfaceType, &matchEntry))
  5324. {
  5325. BfTypeInstance* compareCheckTypeInst = checkTypeInst;
  5326. if (compareCheckTypeInst->IsBoxed())
  5327. compareCheckTypeInst = compareCheckTypeInst->GetUnderlyingType()->ToTypeInstance();
  5328. BfTypeInstance* compareEntrySource = matchEntry->mEntrySource;
  5329. if (compareEntrySource->IsBoxed())
  5330. compareEntrySource = compareEntrySource->GetUnderlyingType()->ToTypeInstance();
  5331. auto prevEntry = matchEntry->mEntry;
  5332. bool isBetter = TypeIsSubTypeOf(compareCheckTypeInst, compareEntrySource);
  5333. bool isWorse = TypeIsSubTypeOf(compareEntrySource, compareCheckTypeInst);
  5334. if ((!isBetter) && (!isWorse))
  5335. {
  5336. // Unboxed comparison to Object fix
  5337. if (compareCheckTypeInst == mContext->mBfObjectType)
  5338. isWorse = true;
  5339. else if (compareEntrySource == mContext->mBfObjectType)
  5340. isBetter = true;
  5341. }
  5342. if (forceInterfaceSet)
  5343. {
  5344. isBetter = true;
  5345. isWorse = false;
  5346. }
  5347. if (isBetter == isWorse)
  5348. CompareDeclTypes(interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse);
  5349. if (isBetter == isWorse)
  5350. {
  5351. if (matchEntry->mAmbiguousEntries.empty())
  5352. matchEntry->mAmbiguousEntries.push_back(prevEntry);
  5353. matchEntry->mAmbiguousEntries.push_back(&interfaceEntry);
  5354. continue;
  5355. }
  5356. else if (isBetter)
  5357. {
  5358. matchEntry->mEntry = &interfaceEntry;
  5359. matchEntry->mEntrySource = checkTypeInst;
  5360. matchEntry->mAmbiguousEntries.Clear();
  5361. }
  5362. else
  5363. continue;
  5364. }
  5365. else
  5366. {
  5367. _InterfaceMatchEntry matchEntry;
  5368. matchEntry.mEntry = &interfaceEntry;
  5369. matchEntry.mEntrySource = checkTypeInst;
  5370. interfaceMap[interfaceEntry.mInterfaceType] = matchEntry;
  5371. }
  5372. }
  5373. checkTypeInst = checkTypeInst->GetImplBaseType();
  5374. }
  5375. for (auto interfacePair : interfaceMap)
  5376. {
  5377. auto& interfaceMatchEntry = interfacePair.mValue;
  5378. if (!interfaceMatchEntry.mAmbiguousEntries.empty())
  5379. {
  5380. auto error = Fail(StrFormat("Type '%s' has an ambiguous declaration for interface '%s'", TypeToString(typeInstance).c_str(), TypeToString(interfaceMatchEntry.mEntry->mInterfaceType).c_str()), interfaceMatchEntry.mEntry->mDeclaringType->GetRefNode());
  5381. if (error != NULL)
  5382. {
  5383. for (auto ambiguiousEntry : interfaceMatchEntry.mAmbiguousEntries)
  5384. mCompiler->mPassInstance->MoreInfo("See other declaration", ambiguiousEntry->mDeclaringType->GetRefNode());
  5385. }
  5386. }
  5387. }
  5388. if ((!mIsComptimeModule) && (!typeInstance->IsInterface()) && (typeInstance->mVirtualMethodTableSize > 0) && (needsVData))
  5389. {
  5390. int startTabIdx = (int)vData.size();
  5391. SizedArray<BfTypeInstance*, 8> origVirtTypeStack;
  5392. BfTypeInstance* checkTypeInst = typeInstance;
  5393. while (checkTypeInst != NULL)
  5394. {
  5395. origVirtTypeStack.push_back(checkTypeInst);
  5396. checkTypeInst = checkTypeInst->GetImplBaseType();
  5397. }
  5398. Array<BfVirtualMethodEntry> origVTable;
  5399. int origVirtIdx = 0;
  5400. if (typeInstance->mTypeDef->mIsCombinedPartial)
  5401. {
  5402. HashSet<String> reslotNames;
  5403. for (int virtIdx = 0; virtIdx < (int)typeInstance->mVirtualMethodTable.size(); virtIdx++)
  5404. {
  5405. auto& entry = typeInstance->mVirtualMethodTable[virtIdx];
  5406. if (entry.mDeclaringMethod.mMethodNum == -1)
  5407. continue;
  5408. BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod;
  5409. if ((methodInstance == NULL) ||
  5410. ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject))))
  5411. {
  5412. if (origVTable.empty())
  5413. origVTable = typeInstance->mVirtualMethodTable;
  5414. BfMethodInstance* declMethodInstance = entry.mDeclaringMethod;
  5415. if ((mIsComptimeModule) || (typeInstance->IsTypeMemberAccessible(declMethodInstance->mMethodDef->mDeclaringType, mProject)))
  5416. {
  5417. // Prepare to reslot...
  5418. entry.mImplementingMethod = entry.mDeclaringMethod;
  5419. reslotNames.Add(declMethodInstance->mMethodDef->mName);
  5420. }
  5421. else
  5422. {
  5423. // Decl isn't accessible, null out entry
  5424. entry.mImplementingMethod = BfMethodRef();
  5425. }
  5426. }
  5427. }
  5428. if (!reslotNames.IsEmpty())
  5429. {
  5430. BfAmbiguityContext ambiguityContext;
  5431. ambiguityContext.mTypeInstance = typeInstance;
  5432. ambiguityContext.mModule = this;
  5433. ambiguityContext.mIsProjectSpecific = true;
  5434. ambiguityContext.mIsReslotting = true;
  5435. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  5436. for (auto& methodGroup : typeInstance->mMethodInstanceGroups)
  5437. {
  5438. auto methodInstance = methodGroup.mDefault;
  5439. if ((methodInstance == NULL) || (!methodInstance->mMethodDef->mIsOverride))
  5440. continue;
  5441. if (!reslotNames.Contains(methodInstance->mMethodDef->mName))
  5442. continue;
  5443. if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject)))
  5444. continue;
  5445. if ((methodInstance->mChainType != BfMethodChainType_None) && (methodInstance->mChainType != BfMethodChainType_ChainHead))
  5446. continue;
  5447. SlotVirtualMethod(methodInstance, &ambiguityContext);
  5448. }
  5449. ambiguityContext.Finish();
  5450. }
  5451. }
  5452. bool isInExts = false;
  5453. for (int virtIdx = 0; virtIdx < (int)typeInstance->mVirtualMethodTable.size(); virtIdx++)
  5454. {
  5455. BfIRValue vValue = voidPtrNull;
  5456. auto& entry = typeInstance->mVirtualMethodTable[virtIdx];
  5457. BfModuleMethodInstance moduleMethodInst;
  5458. if (entry.mDeclaringMethod.mMethodNum == -1)
  5459. {
  5460. // mMethodNum of -1 indicates a vExt slot rather than an actual method reference
  5461. isInExts = true;
  5462. BfIRValue vExt = CreateClassVDataExtGlobal(entry.mDeclaringMethod.mTypeInstance, typeInstance, virtIdx);
  5463. if (vExt)
  5464. vValue = mBfIRBuilder->CreateBitCast(vExt, voidPtrIRType);
  5465. }
  5466. else
  5467. {
  5468. BfMethodInstance* declaringMethodInstance = (BfMethodInstance*)entry.mDeclaringMethod;
  5469. if ((declaringMethodInstance != NULL) && (declaringMethodInstance->mMethodInstanceGroup->IsImplemented()) && (declaringMethodInstance->mIsReified))
  5470. {
  5471. BF_ASSERT(entry.mImplementingMethod.mTypeInstance->mMethodInstanceGroups[entry.mImplementingMethod.mMethodNum].IsImplemented());
  5472. BF_ASSERT(entry.mImplementingMethod.mTypeInstance->mMethodInstanceGroups[entry.mImplementingMethod.mMethodNum].mDefault->mIsReified);
  5473. BfMethodInstance* methodInstance = (BfMethodInstance*)entry.mImplementingMethod;
  5474. if ((methodInstance != NULL) && (!methodInstance->mMethodDef->mIsAbstract))
  5475. {
  5476. BF_ASSERT((mIsComptimeModule) || typeInstance->IsTypeMemberAccessible(methodInstance->mMethodDef->mDeclaringType, mProject));
  5477. moduleMethodInst = GetMethodInstanceAtIdx(methodInstance->mMethodInstanceGroup->mOwner, methodInstance->mMethodInstanceGroup->mMethodIdx, NULL, BfGetMethodInstanceFlag_NoInline);
  5478. auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
  5479. vValue = funcPtr;
  5480. }
  5481. }
  5482. }
  5483. while (origVirtTypeStack.size() != 0)
  5484. {
  5485. BfTypeInstance* useTypeInst = origVirtTypeStack[origVirtTypeStack.size() - 1];
  5486. if (virtIdx >= useTypeInst->mVirtualMethodTableSize)
  5487. {
  5488. // Moved past current base vtable size
  5489. origVirtTypeStack.pop_back();
  5490. continue;
  5491. }
  5492. if (origVirtIdx < useTypeInst->GetOrigVTableSize())
  5493. {
  5494. // We are within the original vtable size
  5495. int idx = startTabIdx + origVirtIdx;
  5496. origVirtIdx++;
  5497. vData.push_back(vValue);
  5498. }
  5499. else
  5500. {
  5501. // This is a new entry, it only gets added to the ext
  5502. BF_ASSERT(isInExts);
  5503. }
  5504. break;
  5505. }
  5506. }
  5507. if (!origVTable.empty())
  5508. typeInstance->mVirtualMethodTable = origVTable;
  5509. }
  5510. int ifaceMethodExtStart = (int)typeInstance->GetIFaceVMethodSize();
  5511. if (typeInstance->mHotTypeData != NULL)
  5512. {
  5513. if (typeInstance->mHotTypeData->mOrigInterfaceMethodsLength != -1)
  5514. ifaceMethodExtStart = typeInstance->mHotTypeData->mOrigInterfaceMethodsLength;
  5515. }
  5516. SizedArray<BfIRValue, 32> ifaceMethodExtData;
  5517. int iFaceMethodStartIdx = (int)vData.size();
  5518. vData.resize(iFaceMethodStartIdx + ifaceMethodExtStart);
  5519. for (int i = iFaceMethodStartIdx; i < iFaceMethodStartIdx + ifaceMethodExtStart; i++)
  5520. vData[i] = voidPtrNull;
  5521. if (expectNumElements != 0)
  5522. BF_ASSERT(expectNumElements == vData.size());
  5523. //BF_ASSERT(vData.size() == expectNumElements);
  5524. // for (int i = 0; i < (int)typeInstance->mInterfaceMethodTable.size() - ifaceMethodExtStart; i++)
  5525. // ifaceMethodExtData.Add(voidPtrNull);
  5526. int ifaceEntryIdx = iFaceMethodStartIdx;
  5527. for (auto& interfacePair : interfaceMap)
  5528. {
  5529. auto interfaceEntry = interfacePair.mValue.mEntry;
  5530. if (typeInstance->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
  5531. {
  5532. BF_ASSERT(mIsComptimeModule);
  5533. break;
  5534. }
  5535. bool makeEmpty = false;
  5536. if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(interfaceEntry->mDeclaringType, mProject)))
  5537. makeEmpty = true;
  5538. int endVirtualIdx = interfaceEntry->mStartVirtualIdx + interfaceEntry->mInterfaceType->mVirtualMethodTableSize;
  5539. bool useExt = endVirtualIdx > ifaceMethodExtStart;
  5540. for (int methodIdx = 0; methodIdx < (int)interfaceEntry->mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
  5541. {
  5542. BfIRValue pushValue;
  5543. BfMethodInstance* ifaceMethodInstance = interfaceEntry->mInterfaceType->mMethodInstanceGroups[methodIdx].mDefault;
  5544. if ((ifaceMethodInstance == NULL) || (ifaceMethodInstance->mVirtualTableIdx == -1))
  5545. continue;
  5546. if ((!ifaceMethodInstance->mIsReified) || (!ifaceMethodInstance->mMethodInstanceGroup->IsImplemented()))
  5547. continue;
  5548. if (makeEmpty)
  5549. {
  5550. pushValue = voidPtrNull;
  5551. }
  5552. else
  5553. {
  5554. auto& methodRef = typeInstance->mInterfaceMethodTable[interfaceEntry->mStartInterfaceTableIdx + methodIdx].mMethodRef;
  5555. auto methodInstance = (BfMethodInstance*)methodRef;
  5556. if ((methodInstance != NULL) && (!methodInstance->mMethodDef->mIsAbstract))
  5557. {
  5558. BF_ASSERT(methodInstance->mIsReified);
  5559. // This doesn't work because we may have FOREIGN methods from implicit interface methods
  5560. //auto moduleMethodInst = GetMethodInstanceAtIdx(methodRef.mTypeInstance, methodRef.mMethodNum);
  5561. auto moduleMethodInst = ReferenceExternalMethodInstance(methodInstance, BfGetMethodInstanceFlag_NoInline);
  5562. auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
  5563. pushValue = funcPtr;
  5564. }
  5565. else
  5566. {
  5567. pushValue = voidPtrNull;
  5568. }
  5569. }
  5570. int idx = interfaceEntry->mStartVirtualIdx + ifaceMethodInstance->mVirtualTableIdx;
  5571. if (idx < ifaceMethodExtStart)
  5572. {
  5573. BF_ASSERT(iFaceMethodStartIdx + idx < (int)vData.size());
  5574. vData[iFaceMethodStartIdx + idx] = pushValue;
  5575. }
  5576. else
  5577. {
  5578. BF_ASSERT(useExt);
  5579. int extIdx = idx - ifaceMethodExtStart;
  5580. while (extIdx >= ifaceMethodExtData.size())
  5581. ifaceMethodExtData.Add(voidPtrNull);
  5582. ifaceMethodExtData[extIdx] = pushValue;
  5583. }
  5584. }
  5585. }
  5586. if (typeInstance->IsBoxed())
  5587. {
  5588. BfBoxedType* boxedType = (BfBoxedType*)typeInstance;
  5589. if (boxedType->IsBoxedStructPtr())
  5590. {
  5591. // Force override of GetHashCode so we use the pointer address as the hash code
  5592. checkTypeInst = CreateBoxedType(ResolveTypeDef(mCompiler->mPointerTypeDef));
  5593. // Force override of GetHashCode so we use the pointer address as the hash code
  5594. for (auto& checkIFace : checkTypeInst->mInterfaces)
  5595. {
  5596. for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
  5597. {
  5598. BfIRValue pushValue;
  5599. BfMethodInstance* ifaceMethodInstance = checkIFace.mInterfaceType->mMethodInstanceGroups[methodIdx].mDefault;
  5600. if ((ifaceMethodInstance == NULL) || (ifaceMethodInstance->mVirtualTableIdx == -1))
  5601. continue;
  5602. if ((!ifaceMethodInstance->mIsReified) || (!ifaceMethodInstance->mMethodInstanceGroup->IsImplemented()))
  5603. continue;
  5604. auto& methodRef = checkTypeInst->mInterfaceMethodTable[checkIFace.mStartInterfaceTableIdx + methodIdx].mMethodRef;
  5605. auto methodInstance = (BfMethodInstance*)methodRef;
  5606. BF_ASSERT(methodInstance->mIsReified);
  5607. // This doesn't work because we may have FOREIGN methods from implicit interface methods
  5608. //auto moduleMethodInst = GetMethodInstanceAtIdx(methodRef.mTypeInstance, methodRef.mMethodNum);
  5609. auto moduleMethodInst = ReferenceExternalMethodInstance(methodInstance, BfGetMethodInstanceFlag_NoInline);
  5610. auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
  5611. int idx = checkIFace.mStartVirtualIdx + ifaceMethodInstance->mVirtualTableIdx;
  5612. vData[iFaceMethodStartIdx + idx] = funcPtr;
  5613. }
  5614. }
  5615. }
  5616. }
  5617. if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic) && (!mIsComptimeModule))
  5618. {
  5619. BfIRValue ifaceMethodExtVar;
  5620. if ((!ifaceMethodExtData.IsEmpty()) && (!mIsComptimeModule))
  5621. {
  5622. StringT<512> classVDataName;
  5623. BfMangler::MangleStaticFieldName(classVDataName, mCompiler->GetMangleKind(), typeInstance, "bf_hs_replace_IFaceExt");
  5624. auto arrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr), (int)ifaceMethodExtData.size());
  5625. ifaceMethodExtVar = mBfIRBuilder->CreateGlobalVariable(arrayType, true,
  5626. BfIRLinkageType_External, BfIRValue(), classVDataName);
  5627. BfIRType extVTableType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)ifaceMethodExtData.size());
  5628. BfIRValue extVTableConst = mBfIRBuilder->CreateConstAgg_Value(extVTableType, ifaceMethodExtData);
  5629. mBfIRBuilder->GlobalVar_SetInitializer(ifaceMethodExtVar, extVTableConst);
  5630. }
  5631. for (auto& ifaceInstPair : interfaceMap)
  5632. {
  5633. auto interfaceEntry = ifaceInstPair.mValue.mEntry;
  5634. int slotNum = interfaceEntry->mInterfaceType->mSlotNum;
  5635. if (slotNum >= 0)
  5636. {
  5637. BfIRValue vtablePtr;
  5638. int idx = interfaceEntry->mStartVirtualIdx;
  5639. int endVirtualIdx = interfaceEntry->mStartVirtualIdx + interfaceEntry->mInterfaceType->mVirtualMethodTableSize;
  5640. if ((endVirtualIdx > ifaceMethodExtStart) && (ifaceMethodExtVar))
  5641. vtablePtr = mBfIRBuilder->CreateInBoundsGEP(ifaceMethodExtVar, 0, interfaceEntry->mStartVirtualIdx - ifaceMethodExtStart);
  5642. else
  5643. vtablePtr = mBfIRBuilder->CreateInBoundsGEP(classVDataVar, 0, iFaceMethodStartIdx + interfaceEntry->mStartVirtualIdx);
  5644. int slotVirtIdx = slotNum + vDataOfs;
  5645. if (vData[slotVirtIdx] == voidPtrNull)
  5646. {
  5647. vData[slotVirtIdx] = mBfIRBuilder->CreateBitCast(vtablePtr, voidPtrIRType);
  5648. }
  5649. else
  5650. {
  5651. if (mCompiler->IsHotCompile())
  5652. Fail("Interface slot collision error. Restart program or undo interface changes.", typeDef->GetRefNode());
  5653. else
  5654. Fail("Interface slot collision error", typeDef->GetRefNode());
  5655. }
  5656. }
  5657. }
  5658. }
  5659. }
  5660. BfIRValue typeNameConst;
  5661. BfIRValue namespaceConst;
  5662. if (needsTypeNames)
  5663. {
  5664. typeNameConst = GetStringObjectValue(typeDef->mName->mString, !mIsComptimeModule);
  5665. namespaceConst = GetStringObjectValue(typeDef->mNamespace.ToString(), !mIsComptimeModule);
  5666. }
  5667. else
  5668. {
  5669. auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef);
  5670. typeNameConst = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(stringType));
  5671. namespaceConst = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(stringType));
  5672. }
  5673. int baseTypeId = 0;
  5674. if (typeInstance->mBaseType != NULL)
  5675. {
  5676. baseTypeId = typeInstance->mBaseType->mTypeId;
  5677. }
  5678. BfTypeOptions* typeOptions = NULL;
  5679. if (typeInstance->mTypeOptionsIdx >= 0)
  5680. typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
  5681. SizedArray<BfIRValue, 16> customAttrs;
  5682. BfTypeInstance* attributeType = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
  5683. BfIRValue castedClassVData;
  5684. if (classVDataVar)
  5685. castedClassVData = mBfIRBuilder->CreateBitCast(classVDataVar, mBfIRBuilder->MapType(mContext->mBfClassVDataPtrType));
  5686. else
  5687. castedClassVData = GetDefaultValue(mContext->mBfClassVDataPtrType);
  5688. bool freflectIncludeTypeData = false;
  5689. bool reflectIncludeAllFields = false;
  5690. bool reflectIncludeAllMethods = false;
  5691. if (TypeIsSubTypeOf(typeInstance, attributeType))
  5692. {
  5693. reflectIncludeAllFields = true;
  5694. reflectIncludeAllMethods = true;
  5695. }
  5696. BfReflectKind reflectKind = BfReflectKind_Type;
  5697. auto _GetReflectUserFromDirective = [&](BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget)
  5698. {
  5699. BfReflectKind reflectKind = BfReflectKind_None;
  5700. auto customAttrs = GetCustomAttributes(attributesDirective, attrTarget);
  5701. if (customAttrs != NULL)
  5702. {
  5703. for (auto& attr : customAttrs->mAttributes)
  5704. {
  5705. reflectKind = (BfReflectKind)(reflectKind | GetUserReflectKind(attr.mType));
  5706. }
  5707. delete customAttrs;
  5708. }
  5709. return reflectKind;
  5710. };
  5711. reflectKind = GetReflectKind(reflectKind, typeInstance);
  5712. // Fields
  5713. BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef);
  5714. BfIRValue emptyValueType = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray<BfIRValue, 1>());
  5715. auto _HandleCustomAttrs = [&](BfCustomAttributes* customAttributes)
  5716. {
  5717. if (customAttributes == NULL)
  5718. return -1;
  5719. Array<BfCustomAttribute*> reflectAttributes;
  5720. for (auto& attr : customAttributes->mAttributes)
  5721. {
  5722. bool wantAttribute = false;
  5723. if (attr.mType->mCustomAttributes != NULL)
  5724. {
  5725. auto usageAttribute = attr.mType->mCustomAttributes->Get(mCompiler->mAttributeUsageAttributeTypeDef);
  5726. if (usageAttribute != NULL)
  5727. {
  5728. // Check for Flags arg
  5729. if (usageAttribute->mCtorArgs.size() < 2)
  5730. continue;
  5731. auto constant = attr.mType->mConstHolder->GetConstant(usageAttribute->mCtorArgs[1]);
  5732. if (constant == NULL)
  5733. continue;
  5734. if (constant->mTypeCode == BfTypeCode_Boolean)
  5735. continue;
  5736. if ((constant->mInt8 & BfCustomAttributeFlags_ReflectAttribute) != 0)
  5737. wantAttribute = true;
  5738. }
  5739. }
  5740. if ((wantAttribute) && (attr.mType->mIsReified))
  5741. {
  5742. reflectAttributes.Add(&attr);
  5743. }
  5744. }
  5745. if (reflectAttributes.size() == 0)
  5746. return -1;
  5747. #define PUSH_INT8(val) data.push_back((uint8)val)
  5748. #define PUSH_INT16(val) { data.push_back(val & 0xFF); data.push_back((val >> 8) & 0xFF); }
  5749. #define PUSH_INT32(val) { data.push_back(val & 0xFF); data.push_back((val >> 8) & 0xFF); data.push_back((val >> 16) & 0xFF); data.push_back((val >> 24) & 0xFF); }
  5750. SizedArray<uint8, 16> data;
  5751. int customAttrIdx = (int)customAttrs.size();
  5752. data.push_back((uint8)reflectAttributes.size());
  5753. for (auto attr : reflectAttributes)
  5754. {
  5755. // Size prefix
  5756. int sizeIdx = (int)data.size();
  5757. PUSH_INT16(0); // mSize
  5758. PUSH_INT32(attr->mType->mTypeId); // mType
  5759. int ctorIdx = -1;
  5760. int ctorCount = 0;
  5761. attr->mType->mTypeDef->PopulateMemberSets();
  5762. BfMemberSetEntry* entry;
  5763. if (attr->mType->mTypeDef->mMethodSet.TryGetWith(String("__BfCtor"), &entry))
  5764. {
  5765. BfMethodDef* nextMethodDef = (BfMethodDef*)entry->mMemberDef;
  5766. while (nextMethodDef != NULL)
  5767. {
  5768. if (nextMethodDef == attr->mCtor)
  5769. ctorIdx = ctorCount;
  5770. nextMethodDef = nextMethodDef->mNextWithSameName;
  5771. ctorCount++;
  5772. }
  5773. }
  5774. BF_ASSERT(ctorIdx != -1);
  5775. if (ctorIdx != -1)
  5776. ctorIdx = (ctorCount - 1) - ctorIdx;
  5777. PUSH_INT16(ctorIdx);
  5778. auto ctorMethodInstance = GetRawMethodInstanceAtIdx(attr->mType, attr->mCtor->mIdx);
  5779. int argIdx = 0;
  5780. for (auto arg : attr->mCtorArgs)
  5781. {
  5782. auto argType = ctorMethodInstance->GetParamType(argIdx);
  5783. EncodeAttributeData(typeInstance, argType, arg, data, usedStringIdMap);
  5784. argIdx++;
  5785. }
  5786. int size = (int)data.size() - sizeIdx;
  5787. *((uint16*)&data[sizeIdx]) = size;
  5788. }
  5789. #undef PUSH_INT8
  5790. #undef PUSH_INT16
  5791. #undef PUSH_INT32
  5792. SizedArray<BfIRValue, 16> dataValues;
  5793. for (uint8 val : data)
  5794. dataValues.push_back(GetConstValue8(val));
  5795. auto dataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(byteType), (int)data.size());
  5796. auto customAttrConst = mBfIRBuilder->CreateConstAgg_Value(dataArrayType, dataValues);
  5797. BfIRValue customAttrArray = mBfIRBuilder->CreateGlobalVariable(dataArrayType, true, BfIRLinkageType_Internal,
  5798. customAttrConst, typeDataName + StrFormat(".customAttr%d", customAttrIdx));
  5799. BfIRValue customAttrArrayPtr = mBfIRBuilder->CreateBitCast(customAttrArray, voidPtrIRType);
  5800. customAttrs.push_back(customAttrArrayPtr);
  5801. return customAttrIdx;
  5802. };
  5803. int typeCustomAttrIdx = _HandleCustomAttrs(typeInstance->mCustomAttributes);
  5804. SizedArray<int, 16> reflectFieldIndices;
  5805. for (int pass = 0; pass < 2; pass++)
  5806. {
  5807. bool skippedField = false;
  5808. reflectFieldIndices.clear();
  5809. for (int fieldIdx = 0; fieldIdx < (int)typeInstance->mFieldInstances.size(); fieldIdx++)
  5810. {
  5811. BfFieldInstance* fieldInstance = &typeInstance->mFieldInstances[fieldIdx];
  5812. BfFieldDef* fieldDef = fieldInstance->GetFieldDef();
  5813. if (fieldDef == NULL)
  5814. continue;
  5815. auto fieldReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User);
  5816. bool includeField = reflectIncludeAllFields;
  5817. if (fieldInstance->mCustomAttributes != NULL)
  5818. {
  5819. for (auto& customAttr : fieldInstance->mCustomAttributes->mAttributes)
  5820. {
  5821. if (customAttr.mType->mTypeDef->mName->ToString() == "ReflectAttribute")
  5822. {
  5823. includeField = true;
  5824. }
  5825. else
  5826. {
  5827. auto userReflectKind = GetUserReflectKind(customAttr.mType);
  5828. fieldReflectKind = (BfReflectKind)(fieldReflectKind | userReflectKind);
  5829. }
  5830. }
  5831. }
  5832. if ((fieldReflectKind & BfReflectKind_User) != 0)
  5833. includeField = true;
  5834. if ((!fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_NonStaticFields) != 0))
  5835. includeField = true;
  5836. if ((fieldDef->mIsStatic) && ((fieldReflectKind & BfReflectKind_StaticFields) != 0))
  5837. includeField = true;
  5838. if ((!fieldDef->mIsStatic) && (typeOptions != NULL))
  5839. includeField = typeOptions->Apply(includeField, BfOptionFlags_ReflectNonStaticFields);
  5840. if ((fieldDef->mIsStatic) && (typeOptions != NULL))
  5841. includeField = typeOptions->Apply(includeField, BfOptionFlags_ReflectStaticFields);
  5842. includeField |= forceReflectFields;
  5843. if (!includeField)
  5844. {
  5845. skippedField = true;
  5846. continue;
  5847. }
  5848. reflectFieldIndices.Add(fieldIdx);
  5849. }
  5850. // For a splattable type, we need to either include all fields or zero fields. This is to allow us to correctly splat
  5851. // params for reflected method calls even if we don't have reflection field info for the splatted type. This is
  5852. // possible because we write out a SplatData structure containing just TypeIds in that case
  5853. if (pass == 0)
  5854. {
  5855. if (!typeInstance->IsSplattable())
  5856. break;
  5857. if (!skippedField)
  5858. break;
  5859. if (reflectFieldIndices.size() == 0)
  5860. break;
  5861. }
  5862. }
  5863. SizedArray<BfIRValue, 16> fieldTypes;
  5864. bool is32Bit = mCompiler->mSystem->mPtrSize == 4;
  5865. if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
  5866. {
  5867. BfType* payloadType = typeInstance->GetUnionInnerType();
  5868. if (!payloadType->IsValuelessType())
  5869. {
  5870. BfIRValue payloadNameConst = GetStringObjectValue("$payload", !mIsComptimeModule);
  5871. SizedArray<BfIRValue, 8> payloadFieldVals;
  5872. if (is32Bit)
  5873. {
  5874. payloadFieldVals =
  5875. {
  5876. emptyValueType,
  5877. payloadNameConst, // mName
  5878. GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId
  5879. GetConstValue(0, intPtrType), // mData
  5880. GetConstValue(0, intPtrType), // mDataHi
  5881. GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags
  5882. GetConstValue(-1, intType), // mCustomAttributesIdx
  5883. };
  5884. }
  5885. else
  5886. {
  5887. payloadFieldVals =
  5888. {
  5889. emptyValueType,
  5890. payloadNameConst, // mName
  5891. GetConstValue(payloadType->mTypeId, typeIdType), // mFieldTypeId
  5892. GetConstValue(0, intPtrType), // mData
  5893. GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumPayload, shortType), // mFlags
  5894. GetConstValue(-1, intType), // mCustomAttributesIdx
  5895. };
  5896. }
  5897. FixConstValueParams(reflectFieldDataType->ToTypeInstance(), payloadFieldVals);
  5898. auto payloadFieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), payloadFieldVals);
  5899. fieldTypes.push_back(payloadFieldData);
  5900. }
  5901. BfType* dscrType = typeInstance->GetDiscriminatorType();
  5902. BfIRValue dscrNameConst = GetStringObjectValue("$discriminator", !mIsComptimeModule);
  5903. SizedArray<BfIRValue, 8> dscrFieldVals;
  5904. if (is32Bit)
  5905. {
  5906. dscrFieldVals =
  5907. {
  5908. emptyValueType,
  5909. dscrNameConst, // mName
  5910. GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId
  5911. GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData
  5912. GetConstValue(0, intPtrType), // mDataHi
  5913. GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags
  5914. GetConstValue(-1, intType), // mCustomAttributesIdx
  5915. };
  5916. }
  5917. else
  5918. {
  5919. dscrFieldVals =
  5920. {
  5921. emptyValueType,
  5922. dscrNameConst, // mName
  5923. GetConstValue(dscrType->mTypeId, typeIdType), // mFieldTypeId
  5924. GetConstValue(BF_ALIGN(payloadType->mSize, dscrType->mAlign), intPtrType), // mData
  5925. GetConstValue(BfFieldFlags_SpecialName | BfFieldFlags_EnumDiscriminator, shortType), // mFlags
  5926. GetConstValue(-1, intType), // mCustomAttributesIdx
  5927. };
  5928. }
  5929. auto dscrFieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), dscrFieldVals);
  5930. fieldTypes.push_back(dscrFieldData);
  5931. }
  5932. for (auto fieldIdx : reflectFieldIndices)
  5933. {
  5934. if (!needsTypeData)
  5935. break;
  5936. BfFieldInstance* fieldInstance = &typeInstance->mFieldInstances[fieldIdx];
  5937. fieldTypes.push_back(CreateFieldData(fieldInstance, _HandleCustomAttrs(fieldInstance->mCustomAttributes)));
  5938. }
  5939. auto reflectFieldDataIRType = mBfIRBuilder->MapType(reflectFieldDataType);
  5940. BfIRValue fieldDataPtr;
  5941. BfIRType fieldDataPtrType = mBfIRBuilder->GetPointerTo(reflectFieldDataIRType);
  5942. if (fieldTypes.size() == 0)
  5943. {
  5944. if ((type->IsSplattable()) && (type->IsStruct()) && (!type->IsValuelessType()) && (!typeInstance->mIsCRepr))
  5945. {
  5946. BfTypeInstance* reflectFieldSplatDataType = ResolveTypeDef(mCompiler->mReflectFieldSplatDataDef)->ToTypeInstance();
  5947. SizedArray<BfIRValue, 3> splatTypes;
  5948. SizedArray<BfIRValue, 3> splatOffsets;
  5949. std::function<void(BfType*, int)> _CheckSplat = [&](BfType* checkType, int offset)
  5950. {
  5951. auto checkTypeInstance = checkType->ToTypeInstance();
  5952. if ((checkTypeInstance != NULL) && (checkTypeInstance->IsValueType()) && (checkTypeInstance->IsDataIncomplete()))
  5953. PopulateType(checkTypeInstance);
  5954. if (checkType->IsStruct())
  5955. {
  5956. int dataEnd = offset;
  5957. if (checkTypeInstance->mBaseType != NULL)
  5958. _CheckSplat(checkTypeInstance->mBaseType, offset);
  5959. if (checkTypeInstance->mIsUnion)
  5960. {
  5961. BfType* unionInnerType = checkTypeInstance->GetUnionInnerType();
  5962. _CheckSplat(unionInnerType, offset);
  5963. }
  5964. else
  5965. {
  5966. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  5967. {
  5968. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  5969. if (fieldInstance->mDataIdx >= 0)
  5970. {
  5971. _CheckSplat(fieldInstance->GetResolvedType(), offset + fieldInstance->mDataOffset);
  5972. dataEnd = offset + fieldInstance->mDataOffset + fieldInstance->mResolvedType->mSize;
  5973. }
  5974. }
  5975. }
  5976. if (checkTypeInstance->IsEnum())
  5977. {
  5978. // Add discriminator
  5979. auto dscrType = checkTypeInstance->GetDiscriminatorType();
  5980. if (checkTypeInstance->mPacking > 0)
  5981. dataEnd = BF_ALIGN(dataEnd, dscrType->mAlign);
  5982. _CheckSplat(dscrType, dataEnd);
  5983. }
  5984. }
  5985. else if (checkType->IsMethodRef())
  5986. {
  5987. // auto methodRefType = (BfMethodRefType*)checkType;
  5988. // for (int dataIdx = 0; dataIdx < methodRefType->GetCaptureDataCount(); dataIdx++)
  5989. // {
  5990. // if (methodRefType->WantsDataPassedAsSplat(dataIdx))
  5991. // _CheckSplat(methodRefType->GetCaptureType(dataIdx), offsetof);
  5992. // else
  5993. // dataLambda(methodRefType->GetCaptureType(dataIdx));
  5994. // }
  5995. }
  5996. else if (!checkType->IsValuelessType())
  5997. {
  5998. splatTypes.Add(GetConstValue(checkType->mTypeId, typeIdType));
  5999. splatOffsets.Add(GetConstValue(offset, intType));
  6000. }
  6001. };
  6002. _CheckSplat(type, 0);
  6003. while (splatTypes.size() < 3)
  6004. {
  6005. splatTypes.Add(GetConstValue(0, typeIdType));
  6006. splatOffsets.Add(GetConstValue(0, intType));
  6007. }
  6008. BfIRValue splatTypesConst = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[0].mResolvedType), splatTypes);
  6009. BfIRValue splatOffsetsConst = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[1].mResolvedType), splatOffsets);
  6010. SizedArray<BfIRValue, 8> splatVals =
  6011. {
  6012. emptyValueType,
  6013. splatTypesConst,
  6014. splatOffsetsConst
  6015. };
  6016. auto fieldSplatData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldSplatDataType->ToTypeInstance(), BfIRPopulateType_Full), splatVals);
  6017. BfIRValue fieldDataArray = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(reflectFieldSplatDataType), true, BfIRLinkageType_Internal,
  6018. fieldSplatData, typeDataName + ".splats");
  6019. fieldDataPtr = mBfIRBuilder->CreateBitCast(fieldDataArray, fieldDataPtrType);
  6020. }
  6021. else
  6022. fieldDataPtr = mBfIRBuilder->CreateConstNull(fieldDataPtrType);
  6023. }
  6024. else
  6025. {
  6026. BfIRType fieldDataConstType = mBfIRBuilder->GetSizedArrayType(reflectFieldDataIRType, (int)fieldTypes.size());
  6027. BfIRValue fieldDataConst = mBfIRBuilder->CreateConstAgg_Value(fieldDataConstType, fieldTypes);
  6028. BfIRValue fieldDataArray = mBfIRBuilder->CreateGlobalVariable(fieldDataConstType, true, BfIRLinkageType_Internal,
  6029. fieldDataConst, "fields." + typeDataName);
  6030. fieldDataPtr = mBfIRBuilder->CreateBitCast(fieldDataArray, fieldDataPtrType);
  6031. }
  6032. /// Methods
  6033. BfType* reflectMethodDataType = ResolveTypeDef(mCompiler->mReflectMethodDataDef);
  6034. BfType* reflectParamDataType = ResolveTypeDef(mCompiler->mReflectParamDataDef);
  6035. BfType* reflectParamDataPtrType = CreatePointerType(reflectParamDataType);
  6036. struct _SortedMethodInfo
  6037. {
  6038. BfMethodDef* mMethodDef;
  6039. BfMethodCustomAttributes* mMethodCustomAttributes;
  6040. };
  6041. Array<_SortedMethodInfo> sortedMethodList;
  6042. SizedArray<BfIRValue, 16> methodTypes;
  6043. for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++)
  6044. {
  6045. if (!needsTypeData)
  6046. break;
  6047. // Disable const method reflection info for now
  6048. if (mIsComptimeModule)
  6049. break;
  6050. auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx];
  6051. if (!methodInstanceGroup->IsImplemented())
  6052. continue;
  6053. auto methodDef = typeDef->mMethods[methodIdx];
  6054. if (methodDef->mIsNoReflect)
  6055. continue;
  6056. if (methodDef->mHasComptime)
  6057. continue;
  6058. auto defaultMethod = methodInstanceGroup->mDefault;
  6059. if (defaultMethod == NULL)
  6060. continue;
  6061. if (defaultMethod->mIsUnspecialized)
  6062. continue;
  6063. if (!defaultMethod->mIsReified)
  6064. continue;
  6065. if ((defaultMethod->mChainType == BfMethodChainType_ChainMember) || (defaultMethod->mChainType == BfMethodChainType_ChainSkip))
  6066. continue;
  6067. if (defaultMethod->mMethodDef->mMethodType == BfMethodType_CtorNoBody)
  6068. continue;
  6069. auto methodReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User);
  6070. bool includeMethod = reflectIncludeAllMethods;
  6071. BfMethodCustomAttributes* methodCustomAttributes = NULL;
  6072. if ((defaultMethod->mMethodInfoEx != NULL) && (defaultMethod->mMethodInfoEx->mMethodCustomAttributes != NULL) && (defaultMethod->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes != NULL))
  6073. {
  6074. methodCustomAttributes = defaultMethod->mMethodInfoEx->mMethodCustomAttributes;
  6075. for (auto& customAttr : defaultMethod->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes->mAttributes)
  6076. {
  6077. if (customAttr.mType->mTypeDef->mName->ToString() == "ReflectAttribute")
  6078. {
  6079. includeMethod = true;
  6080. }
  6081. else
  6082. {
  6083. auto userReflectKind = GetUserReflectKind(customAttr.mType);
  6084. methodReflectKind = (BfReflectKind)(methodReflectKind | userReflectKind);
  6085. }
  6086. }
  6087. }
  6088. if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject)))
  6089. continue;
  6090. //
  6091. {
  6092. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  6093. if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  6094. {
  6095. for (BfParameterDeclaration* paramDecl : methodDeclaration->mParams)
  6096. {
  6097. if (paramDecl->mAttributes != NULL)
  6098. methodReflectKind = (BfReflectKind)(methodReflectKind | _GetReflectUserFromDirective(paramDecl->mAttributes, BfAttributeTargets_Parameter));
  6099. }
  6100. }
  6101. }
  6102. if ((methodReflectKind & (BfReflectKind_Methods | BfReflectKind_User)) != 0)
  6103. includeMethod = true;
  6104. if ((methodDef->mIsStatic) && ((methodReflectKind & BfReflectKind_StaticMethods) != 0))
  6105. includeMethod = true;
  6106. if ((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend))
  6107. {
  6108. if ((methodReflectKind & BfReflectKind_Constructors) != 0)
  6109. includeMethod = true;
  6110. if ((methodDef->IsDefaultCtor()) && ((methodReflectKind & BfReflectKind_DefaultConstructor) != 0))
  6111. includeMethod = true;
  6112. }
  6113. if ((!includeMethod) && (typeOptions != NULL))
  6114. includeMethod = ApplyTypeOptionMethodFilters(includeMethod, methodDef, typeOptions);
  6115. if (!includeMethod)
  6116. continue;
  6117. sortedMethodList.Add({ methodDef, methodCustomAttributes });
  6118. }
  6119. auto _GetMethodKind = [](BfMethodDef* methodDef)
  6120. {
  6121. if (methodDef->mMethodType == BfMethodType_Ctor)
  6122. return 0;
  6123. return 1;
  6124. };
  6125. std::sort(sortedMethodList.begin(), sortedMethodList.end(), [_GetMethodKind](const _SortedMethodInfo& lhs, const _SortedMethodInfo& rhs)
  6126. {
  6127. int lhsKind = _GetMethodKind(lhs.mMethodDef);
  6128. int rhsKind = _GetMethodKind(rhs.mMethodDef);
  6129. if (lhsKind != rhsKind)
  6130. return lhsKind < rhsKind;
  6131. if (lhs.mMethodDef->mName != rhs.mMethodDef->mName)
  6132. return lhs.mMethodDef->mName < rhs.mMethodDef->mName;
  6133. return lhs.mMethodDef->mIdx < rhs.mMethodDef->mIdx;
  6134. });
  6135. for (auto& methodInfo : sortedMethodList)
  6136. {
  6137. auto methodDef = methodInfo.mMethodDef;
  6138. int methodIdx = methodDef->mIdx;
  6139. auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx];
  6140. auto defaultMethod = methodInstanceGroup->mDefault;
  6141. BfModuleMethodInstance moduleMethodInstance;
  6142. BfIRValue funcVal = voidPtrNull;
  6143. if (((!typeInstance->IsBoxed()) || (!methodDef->mIsStatic)) &&
  6144. (!typeInstance->IsUnspecializedType()) &&
  6145. (methodDef->mMethodType != BfMethodType_Ignore) &&
  6146. (methodDef->mMethodType != BfMethodType_Mixin) &&
  6147. (!methodDef->mIsAbstract) &&
  6148. (methodDef->mGenericParams.size() == 0))
  6149. {
  6150. moduleMethodInstance = GetMethodInstanceAtIdx(typeInstance, methodIdx, NULL, BfGetMethodInstanceFlag_NoInline);
  6151. if (moduleMethodInstance.mFunc)
  6152. funcVal = mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, voidPtrIRType);
  6153. }
  6154. BfIRValue methodNameConst = GetStringObjectValue(methodDef->mName, !mIsComptimeModule);
  6155. BfMethodFlags methodFlags = defaultMethod->GetMethodFlags();
  6156. int customAttrIdx = -1;
  6157. int returnCustomAttrIdx = -1;
  6158. if (methodInfo.mMethodCustomAttributes != NULL)
  6159. {
  6160. customAttrIdx = _HandleCustomAttrs(methodInfo.mMethodCustomAttributes->mCustomAttributes);
  6161. returnCustomAttrIdx = _HandleCustomAttrs(methodInfo.mMethodCustomAttributes->mReturnCustomAttributes);
  6162. }
  6163. enum ParamFlags
  6164. {
  6165. ParamFlag_None = 0,
  6166. ParamFlag_Splat = 1,
  6167. ParamFlag_Implicit = 2,
  6168. ParamFlag_AppendIdx = 4
  6169. };
  6170. SizedArray<BfIRValue, 8> paramVals;
  6171. for (int paramIdx = 0; paramIdx < defaultMethod->GetParamCount(); paramIdx++)
  6172. {
  6173. String paramName = defaultMethod->GetParamName(paramIdx);
  6174. BfType* paramType = defaultMethod->GetParamType(paramIdx);
  6175. ParamFlags paramFlags = ParamFlag_None;
  6176. if (defaultMethod->GetParamIsSplat(paramIdx))
  6177. paramFlags = (ParamFlags)(paramFlags | ParamFlag_Splat);
  6178. if (defaultMethod->GetParamKind(paramIdx) == BfParamKind_AppendIdx)
  6179. paramFlags = (ParamFlags)(paramFlags | ParamFlag_Implicit | ParamFlag_AppendIdx);
  6180. BfIRValue paramNameConst = GetStringObjectValue(paramName, !mIsComptimeModule);
  6181. int paramCustomAttrIdx = -1;
  6182. if ((methodInfo.mMethodCustomAttributes != NULL) && (paramIdx < (int)methodInfo.mMethodCustomAttributes->mParamCustomAttributes.mSize))
  6183. paramCustomAttrIdx = _HandleCustomAttrs(methodInfo.mMethodCustomAttributes->mParamCustomAttributes[paramIdx]);
  6184. SizedArray<BfIRValue, 8> paramDataVals =
  6185. {
  6186. emptyValueType,
  6187. paramNameConst,
  6188. GetConstValue(paramType->mTypeId, typeIdType),
  6189. GetConstValue((int32)paramFlags, shortType),
  6190. GetConstValue(-1, intType), // defaultIdx
  6191. GetConstValue(paramCustomAttrIdx, intType) // customAttrIdx
  6192. };
  6193. auto paramData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectParamDataType, BfIRPopulateType_Full), paramDataVals);
  6194. paramVals.Add(paramData);
  6195. }
  6196. BfIRValue paramsVal;
  6197. if (paramVals.size() > 0)
  6198. {
  6199. BfIRType paramDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectParamDataType, BfIRPopulateType_Full), (int)paramVals.size());
  6200. BfIRValue paramDataConst = mBfIRBuilder->CreateConstAgg_Value(paramDataArrayType, paramVals);
  6201. BfIRValue paramDataArray = mBfIRBuilder->CreateGlobalVariable(paramDataArrayType, true, BfIRLinkageType_Internal,
  6202. paramDataConst, typeDataName + StrFormat(".params%d", methodIdx));
  6203. paramsVal = mBfIRBuilder->CreateBitCast(paramDataArray, mBfIRBuilder->MapType(reflectParamDataPtrType));
  6204. }
  6205. else
  6206. paramsVal = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(reflectParamDataPtrType));
  6207. int vDataVal = -1;
  6208. if (defaultMethod->mVirtualTableIdx != -1)
  6209. {
  6210. int vDataIdx = -1;
  6211. if (type->IsInterface())
  6212. {
  6213. vDataIdx = defaultMethod->mVirtualTableIdx;
  6214. }
  6215. else
  6216. {
  6217. vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
  6218. if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile()))
  6219. {
  6220. auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner;
  6221. int extMethodIdx = (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) - typeInst->GetOrigSelfVTableSize();
  6222. if (extMethodIdx >= 0)
  6223. {
  6224. // Extension?
  6225. int vExtOfs = typeInst->GetOrigImplBaseVTableSize();
  6226. vDataVal = ((vDataIdx + vExtOfs + 1) << 20) | (extMethodIdx);
  6227. }
  6228. else
  6229. {
  6230. // Map this new virtual index back to the original index
  6231. vDataIdx += (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) + typeInst->GetOrigImplBaseVTableSize();
  6232. }
  6233. }
  6234. else
  6235. {
  6236. vDataIdx += defaultMethod->mVirtualTableIdx;
  6237. }
  6238. }
  6239. if (vDataVal == -1)
  6240. vDataVal = vDataIdx * mSystem->mPtrSize;
  6241. }
  6242. SizedArray<BfIRValue, 8> methodDataVals =
  6243. {
  6244. emptyValueType,
  6245. methodNameConst, // mName
  6246. funcVal, // mFuncPtr
  6247. paramsVal,
  6248. GetConstValue(defaultMethod->mReturnType->mTypeId, typeIdType),
  6249. GetConstValue((int)paramVals.size(), shortType),
  6250. GetConstValue(methodFlags, shortType),
  6251. GetConstValue(methodIdx, intType),
  6252. GetConstValue(vDataVal, intType),
  6253. GetConstValue(customAttrIdx, intType),
  6254. GetConstValue(returnCustomAttrIdx, intType),
  6255. };
  6256. auto methodData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectMethodDataType->ToTypeInstance(), BfIRPopulateType_Full), methodDataVals);
  6257. methodTypes.push_back(methodData);
  6258. }
  6259. BfIRValue methodDataPtr;
  6260. BfIRType methodDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectMethodDataType));
  6261. if (methodTypes.size() == 0)
  6262. methodDataPtr = mBfIRBuilder->CreateConstNull(methodDataPtrType);
  6263. else
  6264. {
  6265. BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectMethodDataType, BfIRPopulateType_Full), (int)methodTypes.size());
  6266. BfIRValue methodDataConst = mBfIRBuilder->CreateConstAgg_Value(methodDataArrayType, methodTypes);
  6267. BfIRValue methodDataArray = mBfIRBuilder->CreateGlobalVariable(methodDataArrayType, true, BfIRLinkageType_Internal,
  6268. methodDataConst, "methods." + typeDataName);
  6269. methodDataPtr = mBfIRBuilder->CreateBitCast(methodDataArray, methodDataPtrType);
  6270. }
  6271. /////
  6272. int interfaceCount = 0;
  6273. BfIRValue interfaceDataPtr;
  6274. BfType* reflectInterfaceDataType = ResolveTypeDef(mCompiler->mReflectInterfaceDataDef);
  6275. BfIRType interfaceDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectInterfaceDataType));
  6276. Array<bool> wantsIfaceMethod;
  6277. bool wantsIfaceMethods = false;
  6278. if (typeInstance->mInterfaces.IsEmpty())
  6279. interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType);
  6280. else
  6281. {
  6282. SizedArray<BfIRValue, 16> interfaces;
  6283. for (auto& interface : typeInstance->mInterfaces)
  6284. {
  6285. SizedArray<BfIRValue, 8> interfaceDataVals =
  6286. {
  6287. emptyValueType,
  6288. GetConstValue(interface.mInterfaceType->mTypeId, typeIdType),
  6289. GetConstValue(interface.mStartInterfaceTableIdx, intType),
  6290. GetConstValue(interface.mStartVirtualIdx, intType),
  6291. };
  6292. auto interfaceData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectInterfaceDataType->ToTypeInstance(), BfIRPopulateType_Full), interfaceDataVals);
  6293. interfaces.push_back(interfaceData);
  6294. if (!mIsComptimeModule)
  6295. {
  6296. for (int methodIdx = 0; methodIdx < (int)interface.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
  6297. {
  6298. auto ifaceMethodGroup = &interface.mInterfaceType->mMethodInstanceGroups[methodIdx];
  6299. if (ifaceMethodGroup->mExplicitlyReflected)
  6300. {
  6301. wantsIfaceMethods = true;
  6302. int tableIdx = interface.mStartInterfaceTableIdx + methodIdx;
  6303. while (tableIdx >= wantsIfaceMethod.size())
  6304. wantsIfaceMethod.Add(false);
  6305. wantsIfaceMethod[tableIdx] = true;
  6306. }
  6307. }
  6308. }
  6309. }
  6310. BfIRType interfaceDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectInterfaceDataType, BfIRPopulateType_Full), (int)interfaces.size());
  6311. BfIRValue interfaceDataConst = mBfIRBuilder->CreateConstAgg_Value(interfaceDataArrayType, interfaces);
  6312. BfIRValue interfaceDataArray = mBfIRBuilder->CreateGlobalVariable(interfaceDataArrayType, true, BfIRLinkageType_Internal,
  6313. interfaceDataConst, "interfaces." + typeDataName);
  6314. interfaceDataPtr = mBfIRBuilder->CreateBitCast(interfaceDataArray, interfaceDataPtrType);
  6315. interfaceCount = (int)interfaces.size();
  6316. }
  6317. BfIRValue interfaceMethodTable;
  6318. int ifaceMethodTableSize = 0;
  6319. if ((wantsIfaceMethods) && (!typeInstance->IsInterface()) && (typeInstance->mIsReified) && (!typeInstance->IsUnspecializedType())
  6320. && (!typeInstance->mInterfaceMethodTable.IsEmpty()))
  6321. {
  6322. SizedArray<BfIRValue, 16> methods;
  6323. for (int tableIdx = 0; tableIdx < (int)typeInstance->mInterfaceMethodTable.size(); tableIdx++)
  6324. {
  6325. BfIRValue funcVal = voidPtrNull;
  6326. if ((tableIdx < (int)wantsIfaceMethod.size()) && (wantsIfaceMethod[tableIdx]))
  6327. {
  6328. auto methodEntry = typeInstance->mInterfaceMethodTable[tableIdx];
  6329. if (!methodEntry.mMethodRef.IsNull())
  6330. {
  6331. BfMethodInstance* methodInstance = methodEntry.mMethodRef;
  6332. if ((methodInstance->mIsReified) && (methodInstance->mMethodInstanceGroup->IsImplemented()) && (!methodInstance->mIsUnspecialized) &&
  6333. (!methodInstance->mMethodDef->mIsAbstract))
  6334. {
  6335. auto moduleMethodInstance = ReferenceExternalMethodInstance(methodInstance);
  6336. if (moduleMethodInstance.mFunc)
  6337. funcVal = mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, voidPtrIRType);
  6338. }
  6339. }
  6340. }
  6341. methods.Add(funcVal);
  6342. }
  6343. while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull))
  6344. methods.pop_back();
  6345. if (!methods.IsEmpty())
  6346. {
  6347. BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size());
  6348. BfIRValue methodDataConst = mBfIRBuilder->CreateConstAgg_Value(methodDataArrayType, methods);
  6349. BfIRValue methodDataArray = mBfIRBuilder->CreateGlobalVariable(methodDataArrayType, true, BfIRLinkageType_Internal,
  6350. methodDataConst, "imethods." + typeDataName);
  6351. interfaceMethodTable = mBfIRBuilder->CreateBitCast(methodDataArray, voidPtrPtrIRType);
  6352. ifaceMethodTableSize = (int)methods.size();
  6353. }
  6354. }
  6355. if (!interfaceMethodTable)
  6356. interfaceMethodTable = mBfIRBuilder->CreateConstNull(voidPtrPtrIRType);
  6357. /////
  6358. int underlyingType = 0;
  6359. if ((typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed()))
  6360. {
  6361. underlyingType = typeInstance->GetUnderlyingType()->mTypeId;
  6362. }
  6363. int outerTypeId = 0;
  6364. auto outerType = mContext->mUnreifiedModule->GetOuterType(typeInstance);
  6365. if (outerType != NULL)
  6366. {
  6367. outerTypeId = outerType->mTypeId;
  6368. }
  6369. //
  6370. BfIRValue customAttrDataPtr;
  6371. if (customAttrs.size() > 0)
  6372. {
  6373. BfIRType customAttrsArrayType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)customAttrs.size());
  6374. BfIRValue customAttrsConst = mBfIRBuilder->CreateConstAgg_Value(customAttrsArrayType, customAttrs);
  6375. BfIRValue customAttrsArray = mBfIRBuilder->CreateGlobalVariable(customAttrsArrayType, true, BfIRLinkageType_Internal,
  6376. customAttrsConst, "customAttrs." + typeDataName);
  6377. customAttrDataPtr = mBfIRBuilder->CreateBitCast(customAttrsArray, voidPtrPtrIRType);
  6378. }
  6379. else
  6380. {
  6381. customAttrDataPtr = mBfIRBuilder->CreateConstNull(voidPtrPtrIRType);
  6382. }
  6383. SizedArray<BfIRValue, 32> typeDataVals =
  6384. {
  6385. typeData,
  6386. castedClassVData, // mTypeClassVData
  6387. typeNameConst, // mName
  6388. namespaceConst, // mNamespace
  6389. GetConstValue(typeInstance->mInstSize, intType), // mInstSize
  6390. GetConstValue(typeInstance->mInstAlign, intType), // mInstAlign
  6391. GetConstValue(typeCustomAttrIdx, intType), // mCustomAttributes
  6392. GetConstValue(baseTypeId, typeIdType), // mBaseType
  6393. GetConstValue(underlyingType, typeIdType), // mUnderlyingType
  6394. GetConstValue(outerTypeId, typeIdType), // mOuterType
  6395. GetConstValue(typeInstance->mInheritanceId, intType), // mInheritanceId
  6396. GetConstValue(typeInstance->mInheritanceCount, intType), // mInheritanceCount
  6397. GetConstValue(typeInstance->mSlotNum, byteType), // mInterfaceSlot
  6398. GetConstValue(interfaceCount, byteType), // mInterfaceCount
  6399. GetConstValue(ifaceMethodTableSize, shortType), // mInterfaceMethodCount
  6400. GetConstValue((int)methodTypes.size(), shortType), // mMethodDataCount
  6401. GetConstValue(0, shortType), // mPropertyDataCount
  6402. GetConstValue((int)fieldTypes.size(), shortType), // mFieldDataCount
  6403. interfaceDataPtr, // mInterfaceDataPtr
  6404. interfaceMethodTable, // mInterfaceMethodTable
  6405. methodDataPtr, // mMethodDataPtr
  6406. voidPtrNull, // mPropertyDataPtr
  6407. fieldDataPtr, // mFieldDataPtr
  6408. customAttrDataPtr, // mCustomAttrDataPtr
  6409. };
  6410. BfIRType typeInstanceDataType = mBfIRBuilder->MapTypeInst(typeInstanceType->ToTypeInstance(), BfIRPopulateType_Full);
  6411. FixConstValueParams(typeInstanceType->ToTypeInstance(), typeDataVals);
  6412. auto typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, typeDataVals);
  6413. if (!needsTypeData)
  6414. {
  6415. // No need for anything beyond typeInstanceData
  6416. }
  6417. else if ((typeInstance->IsGenericTypeInstance()) && (typeInstance->IsUnspecializedType()))
  6418. {
  6419. auto genericTypeInstance = typeInstance->ToGenericTypeInstance();
  6420. SizedArray<BfIRValue, 4> unspecializedData =
  6421. {
  6422. typeInstanceData,
  6423. GetConstValue((int)genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments.size(), byteType), // mGenericParamCount
  6424. };
  6425. auto reflectUnspecializedGenericType = ResolveTypeDef(mCompiler->mReflectUnspecializedGenericType);
  6426. typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectUnspecializedGenericType->ToTypeInstance(), BfIRPopulateType_Full);
  6427. typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, unspecializedData);
  6428. }
  6429. else if (typeInstance->IsGenericTypeInstance())
  6430. {
  6431. auto genericTypeInstance = typeInstance->ToGenericTypeInstance();
  6432. auto reflectSpecializedGenericType = ResolveTypeDef(mCompiler->mReflectSpecializedGenericType);
  6433. auto unspecializedType = ResolveTypeDef(typeInstance->mTypeDef->GetDefinition());
  6434. SizedArray<BfIRValue, 4> resolvedTypes;
  6435. for (auto typeGenericArg : genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments)
  6436. resolvedTypes.push_back(GetConstValue(typeGenericArg->mTypeId, typeIdType));
  6437. auto typeIRType = mBfIRBuilder->MapType(typeIdType);
  6438. auto typePtrIRType = mBfIRBuilder->GetPointerTo(typeIRType);
  6439. auto genericArrayType = mBfIRBuilder->GetSizedArrayType(typeIRType, (int)resolvedTypes.size());
  6440. BfIRValue resolvedTypesConst = mBfIRBuilder->CreateConstAgg_Value(genericArrayType, resolvedTypes);
  6441. BfIRValue resolvedTypesArray = mBfIRBuilder->CreateGlobalVariable(genericArrayType, true, BfIRLinkageType_Internal,
  6442. resolvedTypesConst, "resolvedTypes." + typeDataName);
  6443. BfIRValue resovledTypesPtr = mBfIRBuilder->CreateBitCast(resolvedTypesArray, typePtrIRType);
  6444. SizedArray<BfIRValue, 3> specGenericData =
  6445. {
  6446. typeInstanceData,
  6447. GetConstValue(unspecializedType->mTypeId, typeIdType), // mUnspecialziedType
  6448. resovledTypesPtr, // mFieldDataPtr
  6449. };
  6450. typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectSpecializedGenericType->ToTypeInstance(), BfIRPopulateType_Full);
  6451. typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, specGenericData);
  6452. if (typeInstance->IsArray())
  6453. {
  6454. auto arrayType = (BfArrayType*)typeInstance;
  6455. BfType* elementType = genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments[0];
  6456. BfFieldInstance* elementFieldInstance = &genericTypeInstance->mFieldInstances[0];
  6457. SizedArray<BfIRValue, 4> arrayData =
  6458. {
  6459. typeInstanceData,
  6460. GetConstValue(elementType->mSize, intType), // mElementSize
  6461. GetConstValue(1, byteType), // mRank
  6462. GetConstValue(elementFieldInstance->mDataOffset, byteType), // mElementsDataOffset
  6463. };
  6464. auto reflectArrayType = ResolveTypeDef(mCompiler->mReflectArrayType);
  6465. typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectArrayType->ToTypeInstance(), BfIRPopulateType_Full);
  6466. typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, arrayData);
  6467. }
  6468. }
  6469. BfIRValue typeDataVar;
  6470. if (needsTypeData)
  6471. {
  6472. typeDataVar = mBfIRBuilder->CreateGlobalVariable(typeInstanceDataType, true,
  6473. BfIRLinkageType_External, typeInstanceData, typeDataName);
  6474. mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
  6475. if (mBfIRBuilder->DbgHasInfo())
  6476. {
  6477. mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, typeDataName, typeDataName, BfIRMDNode(), 0, mBfIRBuilder->DbgGetTypeInst(typeInstanceType->ToTypeInstance()), false, typeDataVar);
  6478. }
  6479. }
  6480. else
  6481. {
  6482. typeDataVar = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(mContext->mBfTypeType));
  6483. }
  6484. typeDataVar = mBfIRBuilder->CreateBitCast(typeDataVar, mBfIRBuilder->MapType(mContext->mBfTypeType));
  6485. mTypeDataRefs[typeInstance] = typeDataVar;
  6486. if ((!mIsComptimeModule) && (classVDataVar))
  6487. {
  6488. BF_ASSERT(!classVDataName.IsEmpty());
  6489. vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
  6490. auto classVDataConstDataType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
  6491. auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData);
  6492. mBfIRBuilder->GlobalVar_SetInitializer(classVDataVar, classVDataConstData);
  6493. if (mCompiler->mOptions.mObjectHasDebugFlags)
  6494. mBfIRBuilder->GlobalVar_SetAlignment(classVDataVar, 256);
  6495. else
  6496. mBfIRBuilder->GlobalVar_SetAlignment(classVDataVar, mContext->mBfClassVDataPtrType->mAlign);
  6497. if (mBfIRBuilder->DbgHasInfo())
  6498. {
  6499. BfType* voidType = GetPrimitiveType(BfTypeCode_None);
  6500. BfType* voidPtrType = CreatePointerType(voidType);
  6501. BfType* classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
  6502. BfIRMDNode arrayType = mBfIRBuilder->DbgCreateArrayType(vData.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, mBfIRBuilder->DbgGetType(voidPtrType), vData.size());
  6503. mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, classVDataName, classVDataName, BfIRMDNode(), 0, arrayType, false, classVDataVar);
  6504. }
  6505. }
  6506. return typeDataVar;
  6507. }
  6508. BfIRValue BfModule::FixClassVData(BfIRValue value)
  6509. {
  6510. if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule))
  6511. return value;
  6512. auto intptrValue = mBfIRBuilder->CreatePtrToInt(value, BfTypeCode_IntPtr);
  6513. auto maskedValue = mBfIRBuilder->CreateAnd(intptrValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
  6514. return mBfIRBuilder->CreateIntToPtr(maskedValue, mBfIRBuilder->GetType(value));
  6515. }
  6516. void BfModule::CheckStaticAccess(BfTypeInstance* typeInstance)
  6517. {
  6518. // Note: this is not just for perf, it fixes a field var-type resolution issue
  6519. if (mBfIRBuilder->mIgnoreWrites)
  6520. return;
  6521. if (mIsComptimeModule)
  6522. return;
  6523. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  6524. //TODO: Create a hashset of these, we don't need to repeatedly call static ctors for a given type
  6525. // When we access classes with static constructors FROM a static constructor,
  6526. // we call that other class's static constructor first. Recursion cannot occur, since
  6527. // we simply ignore subsequent attempts to re-enter the constructor
  6528. if (!typeInstance->mHasStaticInitMethod)
  6529. return;
  6530. if ((mCurMethodInstance == NULL) || ((mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Ctor) || (!mCurMethodInstance->mMethodDef->mIsStatic)))
  6531. return;
  6532. if (mCurMethodInstance->mMethodInstanceGroup->mOwner == typeInstance)
  6533. return;
  6534. auto checkTypeDef = typeInstance->mTypeDef;
  6535. checkTypeDef->PopulateMemberSets();
  6536. BfMethodDef* nextMethodDef = NULL;
  6537. BfMemberSetEntry* entry;
  6538. if (checkTypeDef->mMethodSet.TryGetWith(String("__BfStaticCtor"), &entry))
  6539. nextMethodDef = (BfMethodDef*)entry->mMemberDef;
  6540. while (nextMethodDef != NULL)
  6541. {
  6542. auto checkMethod = nextMethodDef;
  6543. nextMethodDef = nextMethodDef->mNextWithSameName;
  6544. auto methodModule = GetMethodInstance(typeInstance, checkMethod, BfTypeVector());
  6545. if (methodModule)
  6546. {
  6547. auto methodInstance = methodModule.mMethodInstance;
  6548. if ((methodInstance != NULL) &&
  6549. (methodInstance->mMethodDef->mIsStatic) &&
  6550. (methodInstance->mMethodDef->mMethodType == BfMethodType_Ctor) &&
  6551. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  6552. {
  6553. mBfIRBuilder->CreateCall(methodModule.mFunc, SizedArray<BfIRValue, 0>());
  6554. break;
  6555. }
  6556. }
  6557. }
  6558. }
  6559. BfIRFunction BfModule::GetIntrinsic(BfMethodInstance* methodInstance, bool reportFailure)
  6560. {
  6561. auto methodOwner = methodInstance->GetOwner();
  6562. auto methodDef = methodInstance->mMethodDef;
  6563. auto methodDeclaration = methodDef->GetMethodDeclaration();
  6564. if (!methodDef->mIsExtern)
  6565. return BfIRFunction();
  6566. if (methodInstance->GetCustomAttributes() == NULL)
  6567. return BfIRFunction();
  6568. for (auto& customAttribute : methodInstance->GetCustomAttributes()->mAttributes)
  6569. {
  6570. String typeName = TypeToString(customAttribute.mType);
  6571. if ((typeName == "System.IntrinsicAttribute") && (customAttribute.mCtorArgs.size() > 0))
  6572. {
  6573. methodInstance->mIsIntrinsic = true;
  6574. auto constant = methodOwner->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  6575. String error;
  6576. if ((constant != NULL) && (constant->mTypeCode == BfTypeCode_StringId))
  6577. {
  6578. int stringId = constant->mInt32;
  6579. auto entry = mContext->mStringObjectIdMap[stringId];
  6580. String intrinName = entry.mString;
  6581. // if (intrinName.StartsWith(":"))
  6582. // {
  6583. // SizedArray<BfIRType, 2> paramTypes;
  6584. // for (auto& param : methodInstance->mParams)
  6585. // paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
  6586. // return mBfIRBuilder->GetIntrinsic(intrinName.Substring(1), mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
  6587. // }
  6588. // else
  6589. {
  6590. int intrinId = BfIRCodeGen::GetIntrinsicId(intrinName);
  6591. if (intrinId != -1)
  6592. {
  6593. if (intrinId == BfIRIntrinsic_Malloc)
  6594. {
  6595. return GetBuiltInFunc(BfBuiltInFuncType_Malloc);
  6596. }
  6597. else if (intrinId == BfIRIntrinsic_Free)
  6598. {
  6599. return GetBuiltInFunc(BfBuiltInFuncType_Free);
  6600. }
  6601. SizedArray<BfIRType, 2> paramTypes;
  6602. for (auto& param : methodInstance->mParams)
  6603. paramTypes.push_back(mBfIRBuilder->MapType(param.mResolvedType));
  6604. return mBfIRBuilder->GetIntrinsic(intrinName, intrinId, mBfIRBuilder->MapType(methodInstance->mReturnType), paramTypes);
  6605. }
  6606. else if (reportFailure)
  6607. error = StrFormat("Unable to find intrinsic '%s'", entry.mString.c_str());
  6608. }
  6609. }
  6610. else if (reportFailure)
  6611. error = "Intrinsic name must be a constant string";
  6612. if (reportFailure)
  6613. {
  6614. Fail(error, customAttribute.mRef);
  6615. }
  6616. }
  6617. }
  6618. return BfIRFunction();
  6619. }
  6620. BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId)
  6621. {
  6622. if (mBfIRBuilder->mIgnoreWrites)
  6623. return mBfIRBuilder->GetFakeFunction();
  6624. if (!mBuiltInFuncs[(int)funcTypeId])
  6625. {
  6626. SizedArray<BfIRType, 4> paramTypes;
  6627. auto nullPtrType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr));
  6628. auto intType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_IntPtr));
  6629. auto int32Type = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_Int32));
  6630. auto intPtrType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_IntPtr));
  6631. auto byteType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_Int8));
  6632. auto voidType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_None));
  6633. auto objType = mBfIRBuilder->MapType(mContext->mBfObjectType);
  6634. BfIRFunctionType funcType;
  6635. BfIRFunction func;
  6636. switch (funcTypeId)
  6637. {
  6638. case BfBuiltInFuncType_PrintF:
  6639. paramTypes.Add(nullPtrType);
  6640. funcType = mBfIRBuilder->CreateFunctionType(int32Type, paramTypes, true);
  6641. func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, "PrintF");
  6642. break;
  6643. case BfBuiltInFuncType_Malloc:
  6644. {
  6645. if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  6646. {
  6647. func = GetInternalMethod("Dbg_RawAlloc", 1).mFunc;
  6648. }
  6649. else
  6650. {
  6651. String funcName = mCompiler->mOptions.mMallocLinkName;
  6652. if ((funcName.IsEmpty()) || (mIsComptimeModule))
  6653. funcName = "malloc";
  6654. func = mBfIRBuilder->GetFunction(funcName);
  6655. if (!func)
  6656. {
  6657. paramTypes.clear();
  6658. paramTypes.push_back(intType);
  6659. funcType = mBfIRBuilder->CreateFunctionType(nullPtrType, paramTypes);
  6660. func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, funcName);
  6661. mBfIRBuilder->Func_SetParamName(func, 1, "size");
  6662. }
  6663. }
  6664. }
  6665. break;
  6666. case BfBuiltInFuncType_Free:
  6667. {
  6668. if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  6669. {
  6670. func = GetInternalMethod("Dbg_RawFree").mFunc;
  6671. }
  6672. else
  6673. {
  6674. String funcName = mCompiler->mOptions.mFreeLinkName;
  6675. if ((funcName.IsEmpty()) || (mIsComptimeModule))
  6676. funcName = "free";
  6677. func = mBfIRBuilder->GetFunction(funcName);
  6678. if (!func)
  6679. {
  6680. paramTypes.clear();
  6681. paramTypes.push_back(nullPtrType);
  6682. funcType = mBfIRBuilder->CreateFunctionType(voidType, paramTypes);
  6683. func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, funcName);
  6684. mBfIRBuilder->Func_SetParamName(func, 1, "ptr");
  6685. }
  6686. }
  6687. }
  6688. break;
  6689. case BfBuiltInFuncType_LoadSharedLibraries:
  6690. paramTypes.clear();
  6691. funcType = mBfIRBuilder->CreateFunctionType(voidType, paramTypes);
  6692. func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, "BfLoadSharedLibraries");
  6693. break;
  6694. default: break;
  6695. }
  6696. mBuiltInFuncs[(int)funcTypeId] = func;
  6697. return func;
  6698. }
  6699. return mBuiltInFuncs[(int)funcTypeId];
  6700. }
  6701. void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized, Array<BfTypeReference*>* deferredResolveTypes)
  6702. {
  6703. BfGenericParamDef* genericParamDef = genericParamInstance->GetGenericParamDef();
  6704. BfExternalConstraintDef* externConstraintDef = genericParamInstance->GetExternConstraintDef();
  6705. BfConstraintDef* constraintDef = genericParamInstance->GetConstraintDef();
  6706. BfType* startingTypeConstraint = genericParamInstance->mTypeConstraint;
  6707. BfAutoComplete* bfAutocomplete = NULL;
  6708. if ((mCompiler->mResolvePassData != NULL) && (isUnspecialized))
  6709. bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
  6710. if ((bfAutocomplete != NULL) && (genericParamDef != NULL))
  6711. {
  6712. for (int nameIdx = 0; nameIdx < (int)genericParamDef->mNameNodes.size(); nameIdx++)
  6713. {
  6714. auto nameNode = genericParamDef->mNameNodes[nameIdx];
  6715. if (bfAutocomplete->IsAutocompleteNode(nameNode))
  6716. {
  6717. String filter = nameNode->ToString();
  6718. bfAutocomplete->mInsertStartIdx = nameNode->GetSrcStart();
  6719. bfAutocomplete->mInsertEndIdx = nameNode->GetSrcEnd();
  6720. if (nameIdx != 0)
  6721. {
  6722. bfAutocomplete->AddEntry(AutoCompleteEntry("generic", nameNode->ToString().c_str()), filter);
  6723. }
  6724. }
  6725. }
  6726. }
  6727. for (auto constraint : constraintDef->mConstraints)
  6728. {
  6729. if (auto opConstraint = BfNodeDynCast<BfGenericOperatorConstraint>(constraint))
  6730. {
  6731. BfGenericOperatorConstraintInstance opConstraintInstance;
  6732. if (opConstraint->mLeftType != NULL)
  6733. {
  6734. if (bfAutocomplete != NULL)
  6735. bfAutocomplete->CheckTypeRef(opConstraint->mLeftType, false);
  6736. opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType, BfPopulateType_Interfaces_All);
  6737. if (opConstraintInstance.mLeftType == NULL)
  6738. continue;
  6739. }
  6740. if (opConstraint->mRightType == NULL)
  6741. {
  6742. // We had a failure in parsing
  6743. continue;
  6744. }
  6745. if (opConstraint->mRightType != NULL)
  6746. {
  6747. if (bfAutocomplete != NULL)
  6748. bfAutocomplete->CheckTypeRef(opConstraint->mRightType, false);
  6749. opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType, BfPopulateType_Interfaces_All);
  6750. if (opConstraintInstance.mRightType == NULL)
  6751. continue;
  6752. }
  6753. if (opConstraint->mOpToken == NULL)
  6754. {
  6755. FailAfter("Missing operator", (opConstraint->mLeftType != NULL) ? (BfAstNode*)opConstraint->mLeftType : (BfAstNode*)opConstraint->mOperatorToken);
  6756. continue;
  6757. }
  6758. if (opConstraint->mLeftType != NULL)
  6759. {
  6760. if (opConstraint->mRightType == NULL)
  6761. {
  6762. // Parse should have failed
  6763. continue;
  6764. }
  6765. opConstraintInstance.mBinaryOp = BfTokenToBinaryOp(opConstraint->mOpToken->mToken);
  6766. if (opConstraintInstance.mBinaryOp == BfBinaryOp_None)
  6767. {
  6768. Fail("Invalid binary operator", opConstraint->mOpToken);
  6769. continue;
  6770. }
  6771. }
  6772. else if ((opConstraint->mOpToken->mToken == BfToken_Implicit) || (opConstraint->mOpToken->mToken == BfToken_Explicit))
  6773. {
  6774. opConstraintInstance.mCastToken = opConstraint->mOpToken->mToken;
  6775. }
  6776. else
  6777. {
  6778. opConstraintInstance.mUnaryOp = BfTokenToUnaryOp(opConstraint->mOpToken->mToken);
  6779. if (opConstraintInstance.mUnaryOp == BfUnaryOp_None)
  6780. {
  6781. Fail("Invalid unary operator", opConstraint->mOpToken);
  6782. continue;
  6783. }
  6784. }
  6785. genericParamInstance->mOperatorConstraints.Add(opConstraintInstance);
  6786. continue;
  6787. }
  6788. auto constraintTypeRef = BfNodeDynCast<BfTypeReference>(constraint);
  6789. if (bfAutocomplete != NULL)
  6790. bfAutocomplete->CheckTypeRef(constraintTypeRef, true);
  6791. //TODO: Constraints may refer to other generic params (of either type or method)
  6792. // TO allow resolution, perhaps move this generic param initialization into GetMethodInstance (passing a genericPass bool)
  6793. BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_AllowGenericMethodParamConstValue;
  6794. if (isUnspecialized)
  6795. resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime);
  6796. // We we have a deferredResolveTypes then we defer the generic validation, because we may have a case like
  6797. // `where T : Dictionay<TElem, int> and TElem : IHashable` and we don't want to throw the error on `T` before we build `TElem`
  6798. auto constraintType = ResolveTypeRef(constraintTypeRef, (deferredResolveTypes != NULL) ? BfPopulateType_Identity : BfPopulateType_Declaration, resolveFlags);
  6799. if (constraintType != NULL)
  6800. {
  6801. if (deferredResolveTypes != NULL)
  6802. {
  6803. PopulateType(constraintType, BfPopulateType_Declaration);
  6804. if (constraintType->IsUnspecializedTypeVariation())
  6805. deferredResolveTypes->Add(constraintTypeRef);
  6806. }
  6807. if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
  6808. {
  6809. bool isValidTypeCode = false;
  6810. BfTypeCode typeCode = BfTypeCode_None;
  6811. if (constraintType->IsTypedPrimitive())
  6812. {
  6813. auto underlyingType = constraintType->GetUnderlyingType();
  6814. if (underlyingType->IsPrimitiveType())
  6815. typeCode = ((BfPrimitiveType*)underlyingType)->mTypeDef->mTypeCode;
  6816. }
  6817. if (constraintType->IsPrimitiveType())
  6818. typeCode = ((BfPrimitiveType*)constraintType)->mTypeDef->mTypeCode;
  6819. if (constraintType->IsInstanceOf(mCompiler->mStringTypeDef))
  6820. isValidTypeCode = true;
  6821. switch (typeCode)
  6822. {
  6823. case BfTypeCode_StringId:
  6824. case BfTypeCode_Boolean:
  6825. case BfTypeCode_Int8:
  6826. case BfTypeCode_UInt8:
  6827. case BfTypeCode_Int16:
  6828. case BfTypeCode_UInt16:
  6829. case BfTypeCode_Int32:
  6830. case BfTypeCode_UInt32:
  6831. case BfTypeCode_Int64:
  6832. case BfTypeCode_UInt64:
  6833. case BfTypeCode_IntPtr:
  6834. case BfTypeCode_UIntPtr:
  6835. case BfTypeCode_IntUnknown:
  6836. case BfTypeCode_UIntUnknown:
  6837. case BfTypeCode_Float:
  6838. case BfTypeCode_Double:
  6839. case BfTypeCode_Char8:
  6840. case BfTypeCode_Char16:
  6841. case BfTypeCode_Char32:
  6842. isValidTypeCode = true;
  6843. break;
  6844. default: break;
  6845. }
  6846. if (isValidTypeCode)
  6847. {
  6848. genericParamInstance->mTypeConstraint = constraintType;
  6849. }
  6850. else
  6851. {
  6852. Fail("Const constraint must be a primitive type", constraintTypeRef);
  6853. }
  6854. }
  6855. else
  6856. {
  6857. bool checkEquality = false;
  6858. if (constraintType->IsVar())
  6859. {
  6860. // From a `comptype` generic undef resolution. Ignore.
  6861. genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_ComptypeExpr);
  6862. genericParamInstance->mComptypeConstraint.Add(constraintTypeRef);
  6863. continue;
  6864. }
  6865. else if (constraintType->IsPrimitiveType())
  6866. {
  6867. if (isUnspecialized)
  6868. {
  6869. Fail("Primitive constraints are not allowed unless preceded with 'const'", constraintTypeRef);
  6870. continue;
  6871. }
  6872. checkEquality = true;
  6873. }
  6874. if (constraintType->IsArray())
  6875. {
  6876. if (isUnspecialized)
  6877. {
  6878. Fail("Array constraints are not allowed. If a constant-sized array was intended, an type parameterized by a const generic param can be used (ie: where T : int[T2] where T2 : const int)", constraintTypeRef);
  6879. continue;
  6880. }
  6881. checkEquality = true;
  6882. }
  6883. if (constraintType->IsGenericParam())
  6884. {
  6885. checkEquality = true;
  6886. }
  6887. else if ((!constraintType->IsTypeInstance()) && (!constraintType->IsSizedArray()))
  6888. {
  6889. if (isUnspecialized)
  6890. {
  6891. Fail(StrFormat("Type '%s' is not allowed as a generic constraint", TypeToString(constraintType).c_str()), constraintTypeRef);
  6892. continue;
  6893. }
  6894. checkEquality = true;
  6895. }
  6896. if (checkEquality)
  6897. {
  6898. genericParamInstance->mTypeConstraint = constraintType;
  6899. }
  6900. else if (constraintType->IsInterface())
  6901. {
  6902. genericParamInstance->mInterfaceConstraints.push_back(constraintType->ToTypeInstance());
  6903. }
  6904. else
  6905. {
  6906. auto constraintTypeInst = constraintType->ToTypeInstance();
  6907. if (genericParamInstance->mTypeConstraint != NULL)
  6908. {
  6909. if ((constraintTypeInst != NULL) && (TypeIsSubTypeOf(constraintTypeInst, genericParamInstance->mTypeConstraint->ToTypeInstance(), false)))
  6910. {
  6911. // Allow more specific type
  6912. genericParamInstance->mTypeConstraint = constraintTypeInst;
  6913. }
  6914. else if ((constraintTypeInst != NULL) && (TypeIsSubTypeOf(genericParamInstance->mTypeConstraint->ToTypeInstance(), constraintTypeInst, false)))
  6915. {
  6916. // Silently ignore less-specific type
  6917. if ((startingTypeConstraint != NULL) && (startingTypeConstraint->IsDelegate()))
  6918. {
  6919. // 'System.Delegate' means that we are expecting an actual delegate instance. Simulate this by wanting a class.
  6920. genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_Class);
  6921. }
  6922. }
  6923. else
  6924. {
  6925. Fail("Only one concrete type constraint may be specified", constraintTypeRef);
  6926. return;
  6927. }
  6928. }
  6929. else
  6930. genericParamInstance->mTypeConstraint = constraintType;
  6931. }
  6932. }
  6933. }
  6934. }
  6935. if (((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) &&
  6936. (genericParamInstance->mTypeConstraint == NULL))
  6937. genericParamInstance->mTypeConstraint = GetPrimitiveType(BfTypeCode_IntPtr);
  6938. }
  6939. String BfModule::GenericParamSourceToString(const BfGenericParamSource & genericParamSource)
  6940. {
  6941. if (genericParamSource.mMethodInstance != NULL)
  6942. {
  6943. //auto methodInst = GetUnspecializedMethodInstance(genericParamSource.mMethodInstance, false);
  6944. //SetAndRestoreValue<BfMethodInstance*> prevMethodInst(mCurMethodInstance, methodInst);
  6945. return MethodToString(genericParamSource.mMethodInstance);
  6946. }
  6947. else
  6948. {
  6949. auto typeInst = GetUnspecializedTypeInstance(genericParamSource.mTypeInstance);
  6950. SetAndRestoreValue<BfMethodInstance*> prevMethodInst(mCurMethodInstance, NULL);
  6951. SetAndRestoreValue<BfTypeInstance*> prevTypeInst(mCurTypeInstance, typeInst);
  6952. return TypeToString(typeInst);
  6953. }
  6954. }
  6955. bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs, BfError** errorOut)
  6956. {
  6957. Array<String> methodParamNameOverrides;
  6958. auto _TypeToString = [&](BfType* type)
  6959. {
  6960. if (genericParamSource.mMethodInstance != NULL)
  6961. {
  6962. if (methodParamNameOverrides.IsEmpty())
  6963. {
  6964. for (auto genericParam : genericParamSource.mMethodInstance->mMethodDef->mGenericParams)
  6965. methodParamNameOverrides.Add(genericParam->mName);
  6966. }
  6967. return TypeToString(type, &methodParamNameOverrides);
  6968. }
  6969. return TypeToString(type);
  6970. };
  6971. bool ignoreErrors = (errorOut == NULL) ||
  6972. ((genericParamSource.mMethodInstance == NULL) && (genericParamSource.mTypeInstance == NULL));
  6973. BfType* origCheckArgType = checkArgType;
  6974. if (origCheckArgType->IsRef())
  6975. origCheckArgType = origCheckArgType->GetUnderlyingType();
  6976. bool argIsReferenceType = false;
  6977. int checkGenericParamFlags = 0;
  6978. if (checkArgType->IsGenericParam())
  6979. {
  6980. BfGenericParamInstance* checkGenericParamInst = GetGenericParamInstance((BfGenericParamType*)checkArgType);
  6981. checkGenericParamFlags = checkGenericParamInst->mGenericParamFlags;
  6982. if (checkGenericParamInst->mTypeConstraint != NULL)
  6983. checkArgType = checkGenericParamInst->mTypeConstraint;
  6984. // if ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0)
  6985. // {
  6986. // argMayBeReferenceType = false;
  6987. // }
  6988. // else
  6989. // {
  6990. // argMayBeReferenceType = true;
  6991. // }
  6992. }
  6993. if (checkArgType->IsObjectOrInterface())
  6994. argIsReferenceType = true;
  6995. BfTypeInstance* typeConstraintInst = NULL;
  6996. if (genericParamInst->mTypeConstraint != NULL)
  6997. typeConstraintInst = genericParamInst->mTypeConstraint->ToTypeInstance();
  6998. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Struct) &&
  6999. ((checkGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_Enum | BfGenericParamFlag_Var)) == 0) && (!checkArgType->IsValueType()))
  7000. {
  7001. if ((!ignoreErrors) && (PreFail()))
  7002. *errorOut = Fail(StrFormat("The type '%s' must be a value type in order to use it as parameter '%s' for '%s'",
  7003. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7004. return false;
  7005. }
  7006. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr) &&
  7007. ((checkGenericParamFlags & (BfGenericParamFlag_StructPtr | BfGenericParamFlag_Var)) == 0) && (!checkArgType->IsPointer()))
  7008. {
  7009. if ((!ignoreErrors) && (PreFail()))
  7010. *errorOut = Fail(StrFormat("The type '%s' must be a pointer type in order to use it as parameter '%s' for '%s'",
  7011. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7012. return false;
  7013. }
  7014. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Class) &&
  7015. ((checkGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Var)) == 0) && (!argIsReferenceType))
  7016. {
  7017. if ((!ignoreErrors) && (PreFail()))
  7018. *errorOut = Fail(StrFormat("The type '%s' must be a reference type in order to use it as parameter '%s' for '%s'",
  7019. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7020. return false;
  7021. }
  7022. if (genericParamInst->mGenericParamFlags & BfGenericParamFlag_Enum)
  7023. {
  7024. bool isEnum = checkArgType->IsEnum();
  7025. if ((origCheckArgType->IsGenericParam()) && (checkArgType->IsInstanceOf(mCompiler->mEnumTypeDef)))
  7026. isEnum = true;
  7027. if (((checkGenericParamFlags & (BfGenericParamFlag_Enum | BfGenericParamFlag_Var)) == 0) && (!isEnum))
  7028. {
  7029. if ((!ignoreErrors) && (PreFail()))
  7030. *errorOut = Fail(StrFormat("The type '%s' must be an enum type in order to use it as parameter '%s' for '%s'",
  7031. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7032. return false;
  7033. }
  7034. }
  7035. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Concrete) &&
  7036. ((checkGenericParamFlags & (BfGenericParamFlag_Interface | BfGenericParamFlag_Var)) == 0) && (checkArgType->IsInterface()))
  7037. {
  7038. if ((!ignoreErrors) && (PreFail()))
  7039. *errorOut = Fail(StrFormat("The type '%s' must be an concrete type in order to use it as parameter '%s' for '%s'",
  7040. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7041. return false;
  7042. }
  7043. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Interface) &&
  7044. ((checkGenericParamFlags & (BfGenericParamFlag_Interface | BfGenericParamFlag_Var)) == 0) && (!checkArgType->IsInterface()))
  7045. {
  7046. if ((!ignoreErrors) && (PreFail()))
  7047. *errorOut = Fail(StrFormat("The type '%s' must be an interface type in order to use it as parameter '%s' for '%s'",
  7048. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7049. return false;
  7050. }
  7051. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
  7052. {
  7053. if (((checkGenericParamFlags & BfGenericParamFlag_Const) == 0) && (!checkArgType->IsConstExprValue()))
  7054. {
  7055. if ((!ignoreErrors) && (PreFail()))
  7056. *errorOut = Fail(StrFormat("The type '%s' must be a const value in order to use it as parameter '%s' for '%s'",
  7057. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7058. return false;
  7059. }
  7060. }
  7061. else
  7062. {
  7063. if (checkArgType->IsConstExprValue())
  7064. {
  7065. if ((!ignoreErrors) && (PreFail()))
  7066. *errorOut = Fail(StrFormat("The value '%s' cannot be used for generic type parameter '%s' for '%s'",
  7067. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7068. return false;
  7069. }
  7070. }
  7071. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Delete) != 0)
  7072. {
  7073. bool canDelete = false;
  7074. if (checkArgType->IsPointer())
  7075. canDelete = true;
  7076. else if (checkArgType->IsObjectOrInterface())
  7077. canDelete = true;
  7078. else if ((checkGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var)) != 0)
  7079. canDelete = true;
  7080. if (!canDelete)
  7081. {
  7082. if ((!ignoreErrors) && (PreFail()))
  7083. {
  7084. if (checkArgType->IsGenericParam())
  7085. *errorOut = Fail(StrFormat("Must add 'where %s : delete' constraint in order to use type as parameter '%s' for '%s'",
  7086. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7087. else
  7088. *errorOut = Fail(StrFormat("The type '%s' must be a deletable type in order to use it as parameter '%s' for '%s'",
  7089. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7090. }
  7091. return false;
  7092. }
  7093. }
  7094. if (checkArgType->IsPointer())
  7095. {
  7096. auto ptrType = (BfPointerType*)checkArgType;
  7097. checkArgType = ptrType->mElementType;
  7098. }
  7099. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_New) != 0)
  7100. {
  7101. bool canAlloc = false;
  7102. if (auto checkTypeInst = checkArgType->ToTypeInstance())
  7103. {
  7104. if (checkTypeInst->IsObjectOrStruct())
  7105. {
  7106. checkTypeInst->mTypeDef->PopulateMemberSets();
  7107. BfMemberSetEntry* entry = NULL;
  7108. BfMethodDef* checkMethodDef = NULL;
  7109. checkTypeInst->mTypeDef->mMethodSet.TryGetWith(String("__BfCtor"), &entry);
  7110. if (entry != NULL)
  7111. checkMethodDef = (BfMethodDef*)entry->mMemberDef;
  7112. bool hadProtected = false;
  7113. while (checkMethodDef != NULL)
  7114. {
  7115. if (!checkMethodDef->mParams.IsEmpty())
  7116. {
  7117. auto firstParam = checkMethodDef->mParams[0];
  7118. if (((firstParam->mParamKind == BfParamKind_Params) || (firstParam->mParamKind == BfParamKind_AppendIdx) || (firstParam->mParamKind == BfParamKind_VarArgs)) ||
  7119. ((firstParam->mParamDeclaration != NULL) && (firstParam->mParamDeclaration->mInitializer != NULL)))
  7120. {
  7121. // Allow all-default params
  7122. }
  7123. else
  7124. {
  7125. checkMethodDef = checkMethodDef->mNextWithSameName;
  7126. continue;
  7127. }
  7128. }
  7129. if (checkMethodDef->mProtection == BfProtection_Public)
  7130. {
  7131. canAlloc = true;
  7132. break;
  7133. }
  7134. if ((checkMethodDef->mProtection == BfProtection_Protected) || (checkMethodDef->mProtection == BfProtection_ProtectedInternal))
  7135. hadProtected = true;
  7136. checkMethodDef = checkMethodDef->mNextWithSameName;
  7137. }
  7138. if ((!canAlloc) && (hadProtected) && (mCurTypeInstance != NULL))
  7139. canAlloc = TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst, false);
  7140. }
  7141. }
  7142. else if (checkArgType->IsGenericParam())
  7143. {
  7144. canAlloc = (checkGenericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Var)) != 0;
  7145. }
  7146. else if (checkArgType->IsPrimitiveType())
  7147. {
  7148. // Any primitive types and stuff can be allocated
  7149. canAlloc = true;
  7150. }
  7151. if (!canAlloc)
  7152. {
  7153. if ((!ignoreErrors) && (PreFail()))
  7154. {
  7155. if (checkArgType->IsGenericParam())
  7156. *errorOut = Fail(StrFormat("Must add 'where %s : new' constraint in order to use type as parameter '%s' for '%s'",
  7157. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7158. else
  7159. *errorOut = Fail(StrFormat("The type '%s' must have an accessible default constructor in order to use it as parameter '%s' for '%s'",
  7160. TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7161. }
  7162. return false;
  7163. }
  7164. }
  7165. if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
  7166. return true;
  7167. if (genericParamInst->mTypeConstraint != NULL)
  7168. {
  7169. bool constraintMatched = false;
  7170. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
  7171. {
  7172. if (checkArgType->IsConstExprValue())
  7173. {
  7174. auto constExprValueType = (BfConstExprValueType*)checkArgType;
  7175. if (genericParamInst->mTypeConstraint->IsPrimitiveType())
  7176. {
  7177. auto primType = (BfPrimitiveType*)genericParamInst->mTypeConstraint;
  7178. // Let either an exact typematch or an undef pass through. Eventually instead of undefs we may want to do
  7179. // actual expression comparisons, but we are overly permissive now and then we may fail on specialization
  7180. if ((constExprValueType->mValue.mTypeCode != primType->mTypeDef->mTypeCode) &&
  7181. (constExprValueType->mValue.mTypeCode != BfTypeCode_Let) &&
  7182. (primType->mTypeDef->mTypeCode != BfTypeCode_Let))
  7183. {
  7184. bool doError = true;
  7185. if (BfIRConstHolder::IsInt(constExprValueType->mValue.mTypeCode))
  7186. {
  7187. if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
  7188. {
  7189. if (mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue))
  7190. doError = false;
  7191. }
  7192. }
  7193. else if ((primType->mTypeDef->mTypeCode == BfTypeCode_Float) && ((constExprValueType->mValue.mTypeCode == BfTypeCode_Double)))
  7194. {
  7195. doError = false;
  7196. }
  7197. if (doError)
  7198. {
  7199. if ((!ignoreErrors) && (PreFail()))
  7200. *errorOut = Fail(StrFormat("Const generic argument '%s', declared with '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
  7201. _TypeToString(constExprValueType).c_str(), _TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7202. return false;
  7203. }
  7204. }
  7205. }
  7206. else if (genericParamInst->mTypeConstraint != constExprValueType->mType)
  7207. {
  7208. if ((!ignoreErrors) && (PreFail()))
  7209. *errorOut = Fail(StrFormat("Const generic argument '%s', declared as '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
  7210. _TypeToString(constExprValueType).c_str(), _TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
  7211. return false;
  7212. }
  7213. }
  7214. }
  7215. else
  7216. {
  7217. BfType* convCheckConstraint = genericParamInst->mTypeConstraint;
  7218. if ((convCheckConstraint->IsUnspecializedType()) && (methodGenericArgs != NULL))
  7219. convCheckConstraint = ResolveGenericType(convCheckConstraint, NULL, methodGenericArgs, mCurTypeInstance);
  7220. if (convCheckConstraint == NULL)
  7221. return false;
  7222. if ((checkArgType->IsMethodRef()) || (checkArgType->IsFunction()))
  7223. {
  7224. if (convCheckConstraint->IsDelegate())
  7225. {
  7226. BfMethodInstance* checkMethodInstance;
  7227. if (checkArgType->IsMethodRef())
  7228. {
  7229. auto methodRefType = (BfMethodRefType*)checkArgType;
  7230. checkMethodInstance = methodRefType->mMethodRef;
  7231. }
  7232. else
  7233. {
  7234. checkMethodInstance = GetRawMethodInstanceAtIdx(checkArgType->ToTypeInstance(), 0, "Invoke");
  7235. }
  7236. auto invokeMethod = GetRawMethodInstanceAtIdx(convCheckConstraint->ToTypeInstance(), 0, "Invoke");
  7237. BfExprEvaluator exprEvaluator(this);
  7238. if (exprEvaluator.IsExactMethodMatch(checkMethodInstance, invokeMethod))
  7239. constraintMatched = true;
  7240. }
  7241. else if (convCheckConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef))
  7242. constraintMatched = true;
  7243. }
  7244. else if (CanCast(GetFakeTypedValue(checkArgType), convCheckConstraint))
  7245. {
  7246. constraintMatched = true;
  7247. }
  7248. else if (origCheckArgType->IsWrappableType())
  7249. {
  7250. if (origCheckArgType->IsSizedArray())
  7251. {
  7252. auto sizedArrayType = (BfSizedArrayType*)origCheckArgType;
  7253. if (convCheckConstraint->IsGenericTypeInstance())
  7254. {
  7255. auto convCheckConstraintInst = (BfTypeInstance*)convCheckConstraint;
  7256. if (convCheckConstraintInst->IsInstanceOf(mCompiler->mSizedArrayTypeDef))
  7257. {
  7258. if (convCheckConstraintInst->mGenericTypeInfo->mTypeGenericArguments[0] == sizedArrayType->mElementType)
  7259. {
  7260. auto constExprValueType = (BfConstExprValueType*)convCheckConstraintInst->mGenericTypeInfo->mTypeGenericArguments[1];
  7261. if (sizedArrayType->mElementCount == constExprValueType->mValue.mInt64)
  7262. constraintMatched = true;
  7263. }
  7264. }
  7265. }
  7266. }
  7267. if (!constraintMatched)
  7268. {
  7269. BfType* wrappedStructType = GetWrappedStructType(origCheckArgType, false);
  7270. if (CanCast(GetFakeTypedValue(wrappedStructType), convCheckConstraint))
  7271. constraintMatched = true;
  7272. }
  7273. }
  7274. if (!constraintMatched)
  7275. {
  7276. if ((!ignoreErrors) && (PreFail()))
  7277. *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must derive from '%s'", genericParamInst->GetName().c_str(),
  7278. TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(convCheckConstraint).c_str(),
  7279. _TypeToString(genericParamInst->mTypeConstraint).c_str()), checkArgTypeRef);
  7280. return false;
  7281. }
  7282. }
  7283. }
  7284. for (auto checkConstraint : genericParamInst->mInterfaceConstraints)
  7285. {
  7286. BfType* convCheckConstraint = checkConstraint;
  7287. if (convCheckConstraint->IsUnspecializedType())
  7288. convCheckConstraint = ResolveGenericType(convCheckConstraint, NULL, methodGenericArgs, mCurTypeInstance);
  7289. if (convCheckConstraint == NULL)
  7290. return false;
  7291. BfTypeInstance* typeConstraintInst = convCheckConstraint->ToTypeInstance();
  7292. bool implementsInterface = false;
  7293. if (origCheckArgType != checkArgType)
  7294. {
  7295. implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, origCheckArgType), convCheckConstraint);
  7296. }
  7297. if (!implementsInterface)
  7298. implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, checkArgType), convCheckConstraint);
  7299. if ((!implementsInterface) && (origCheckArgType->IsWrappableType()))
  7300. {
  7301. BfTypeInstance* wrappedStructType = GetWrappedStructType(origCheckArgType, false);
  7302. if (TypeIsSubTypeOf(wrappedStructType, typeConstraintInst))
  7303. implementsInterface = true;
  7304. }
  7305. if ((!implementsInterface) && (origCheckArgType->IsTypedPrimitive()))
  7306. {
  7307. auto underlyingType = origCheckArgType->GetUnderlyingType();
  7308. BfTypeInstance* wrappedStructType = GetWrappedStructType(underlyingType, false);
  7309. if (TypeIsSubTypeOf(wrappedStructType, typeConstraintInst))
  7310. implementsInterface = true;
  7311. }
  7312. if (!implementsInterface)
  7313. {
  7314. if ((!ignoreErrors) && (PreFail()))
  7315. *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must implement '%s'", genericParamInst->GetName().c_str(),
  7316. TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(checkConstraint).c_str()), checkArgTypeRef);
  7317. return false;
  7318. }
  7319. }
  7320. for (auto& checkOpConstraint : genericParamInst->mOperatorConstraints)
  7321. {
  7322. auto leftType = checkOpConstraint.mLeftType;
  7323. if ((leftType != NULL) && (leftType->IsUnspecializedType()))
  7324. leftType = ResolveGenericType(leftType, NULL, methodGenericArgs, mCurTypeInstance);
  7325. if (leftType != NULL)
  7326. leftType = FixIntUnknown(leftType);
  7327. auto rightType = checkOpConstraint.mRightType;
  7328. if ((rightType != NULL) && (rightType->IsUnspecializedType()))
  7329. rightType = ResolveGenericType(rightType, NULL, methodGenericArgs, mCurTypeInstance);
  7330. if (rightType != NULL)
  7331. rightType = FixIntUnknown(rightType);
  7332. BfConstraintState constraintSet;
  7333. constraintSet.mPrevState = mContext->mCurConstraintState;
  7334. constraintSet.mGenericParamInstance = genericParamInst;
  7335. constraintSet.mLeftType = leftType;
  7336. constraintSet.mRightType = rightType;
  7337. SetAndRestoreValue<BfConstraintState*> prevConstraintSet(mContext->mCurConstraintState, &constraintSet);
  7338. if (!CheckConstraintState(NULL))
  7339. return false;
  7340. if (checkOpConstraint.mBinaryOp != BfBinaryOp_None)
  7341. {
  7342. BfExprEvaluator exprEvaluator(this);
  7343. BfTypedValue leftValue(mBfIRBuilder->GetFakeVal(), leftType);
  7344. BfTypedValue rightValue(mBfIRBuilder->GetFakeVal(), rightType);
  7345. //
  7346. {
  7347. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  7348. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  7349. exprEvaluator.PerformBinaryOperation(NULL, NULL, checkOpConstraint.mBinaryOp, NULL, (BfBinOpFlags)(BfBinOpFlag_NoClassify | BfBinOpFlag_IsConstraintCheck), leftValue, rightValue);
  7350. }
  7351. if ((!exprEvaluator.mResult) ||
  7352. (!CanCast(exprEvaluator.mResult, origCheckArgType, BfCastFlags_NoConversionOperator)))
  7353. {
  7354. if ((!ignoreErrors) && (PreFail()))
  7355. {
  7356. if (genericParamInst->mExternType != NULL)
  7357. *errorOut = Fail(StrFormat("Binary operation for '%s' must result in '%s' from binary operation '%s %s %s'",
  7358. GenericParamSourceToString(genericParamSource).c_str(), TypeToString(origCheckArgType).c_str(),
  7359. TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str()
  7360. ), checkArgTypeRef);
  7361. else
  7362. *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(),
  7363. TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(),
  7364. TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str()
  7365. ), checkArgTypeRef);
  7366. }
  7367. return false;
  7368. }
  7369. }
  7370. else
  7371. {
  7372. BfTypedValue rightValue(mBfIRBuilder->GetFakeVal(), rightType);
  7373. StringT<128> failedOpName;
  7374. if (checkOpConstraint.mCastToken == BfToken_Implicit)
  7375. {
  7376. if (!CanCast(rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_SilentFail | BfCastFlags_IsConstraintCheck)))
  7377. failedOpName = "implicit conversion from '";
  7378. }
  7379. else
  7380. {
  7381. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  7382. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  7383. if (checkOpConstraint.mCastToken == BfToken_Explicit)
  7384. {
  7385. if (!CastToValue(NULL, rightValue, origCheckArgType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail | BfCastFlags_IsConstraintCheck)))
  7386. failedOpName = "explicit conversion from '";
  7387. }
  7388. else
  7389. {
  7390. BfExprEvaluator exprEvaluator(this);
  7391. exprEvaluator.mResult = rightValue;
  7392. exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL, BfUnaryOpFlag_IsConstraintCheck);
  7393. if ((!exprEvaluator.mResult) ||
  7394. (!CanCast(exprEvaluator.mResult, origCheckArgType)))
  7395. {
  7396. failedOpName += "unary operation '";
  7397. failedOpName += BfGetOpName(checkOpConstraint.mUnaryOp);
  7398. }
  7399. }
  7400. }
  7401. if (!failedOpName.IsEmpty())
  7402. {
  7403. if ((!ignoreErrors) && (PreFail()))
  7404. *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from %s%s'", genericParamInst->GetName().c_str(),
  7405. TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(),
  7406. failedOpName.c_str(), TypeToString(rightType).c_str()
  7407. ), checkArgTypeRef);
  7408. return false;
  7409. }
  7410. }
  7411. }
  7412. return true;
  7413. }
  7414. BfGenericParamType* BfModule::GetGenericParamType(BfGenericParamKind paramKind, int paramIdx)
  7415. {
  7416. if (paramIdx < (int)mContext->mGenericParamTypes[paramKind].size())
  7417. {
  7418. auto genericParamType = mContext->mGenericParamTypes[paramKind][paramIdx];
  7419. return genericParamType;
  7420. }
  7421. auto genericParamType = new BfGenericParamType();
  7422. genericParamType->mContext = mContext;
  7423. genericParamType->mGenericParamKind = paramKind;
  7424. genericParamType->mGenericParamIdx = paramIdx;
  7425. PopulateType(genericParamType);
  7426. BF_ASSERT(paramIdx == (int)mContext->mGenericParamTypes[paramKind].size());
  7427. mContext->mGenericParamTypes[paramKind].push_back(genericParamType);
  7428. BfResolvedTypeSet::LookupContext lookupCtx;
  7429. lookupCtx.mModule = this;
  7430. BfResolvedTypeSet::EntryRef typeEntry;
  7431. auto inserted = mContext->mResolvedTypes.Insert(genericParamType, &lookupCtx, &typeEntry);
  7432. BF_ASSERT(inserted);
  7433. typeEntry->mValue = genericParamType;
  7434. return genericParamType;
  7435. }
  7436. static int sValueFromExprIdx = 0;
  7437. BfTypedValue BfModule::FlushNullConditional(BfTypedValue result, bool ignoreNullable)
  7438. {
  7439. auto pendingNullCond = mCurMethodState->mPendingNullConditional;
  7440. if ((result) && (!ignoreNullable))
  7441. {
  7442. if (result.mType->IsVar())
  7443. return result;
  7444. auto notNullBB = mBfIRBuilder->GetInsertBlock();
  7445. //TODO: Make this work, needed for 'void' and such
  7446. BfType* nullableType = NULL;
  7447. if ((result.mType->IsValueType()) && (!result.mType->IsNullable()))
  7448. {
  7449. BfTypeVector typeVec;
  7450. typeVec.push_back(result.mType);
  7451. nullableType = ResolveTypeDef(mCompiler->mNullableTypeDef, typeVec);
  7452. BF_ASSERT(nullableType != NULL);
  7453. }
  7454. // Go back to start and do any setup we need
  7455. mBfIRBuilder->SetInsertPoint(pendingNullCond->mPrevBB);
  7456. BfTypedValue nullableTypedValue;
  7457. if (nullableType != NULL)
  7458. {
  7459. nullableTypedValue = BfTypedValue(CreateAlloca(nullableType, true, "nullCond.nullable"), nullableType, true);
  7460. mBfIRBuilder->CreateMemSet(nullableTypedValue.mValue, GetConstValue(0, GetPrimitiveType(BfTypeCode_Int8)),
  7461. GetConstValue(nullableType->mSize), nullableType->mAlign);
  7462. }
  7463. mBfIRBuilder->CreateBr(pendingNullCond->mCheckBB);
  7464. // Now that we have the nullableTypedValue we can set that, or just jump if we didn't need it
  7465. mBfIRBuilder->SetInsertPoint(notNullBB);
  7466. result = LoadValue(result);
  7467. if (nullableTypedValue)
  7468. {
  7469. auto elementType = nullableType->GetUnderlyingType();
  7470. if (elementType->IsVar())
  7471. {
  7472. // Do nothing
  7473. }
  7474. else if (elementType->IsValuelessType())
  7475. {
  7476. BfIRValue ptrValue = mBfIRBuilder->CreateInBoundsGEP(nullableTypedValue.mValue, 0, 1); // mHasValue
  7477. mBfIRBuilder->CreateStore(GetConstValue(1, GetPrimitiveType(BfTypeCode_Boolean)), ptrValue);
  7478. }
  7479. else
  7480. {
  7481. BfIRValue ptrValue = mBfIRBuilder->CreateInBoundsGEP(nullableTypedValue.mValue, 0, 1); // mValue
  7482. mBfIRBuilder->CreateAlignedStore(result.mValue, ptrValue, result.mType->mAlign);
  7483. ptrValue = mBfIRBuilder->CreateInBoundsGEP(nullableTypedValue.mValue, 0, 2); // mHasValue
  7484. mBfIRBuilder->CreateAlignedStore(GetConstValue(1, GetPrimitiveType(BfTypeCode_Boolean)), ptrValue, 1);
  7485. }
  7486. result = nullableTypedValue;
  7487. }
  7488. mBfIRBuilder->CreateBr(pendingNullCond->mDoneBB);
  7489. AddBasicBlock(pendingNullCond->mDoneBB);
  7490. if (nullableType == NULL)
  7491. {
  7492. auto phi = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(result.mType), 1 + (int)pendingNullCond->mNotNullBBs.size());
  7493. mBfIRBuilder->AddPhiIncoming(phi, result.mValue, notNullBB);
  7494. mBfIRBuilder->AddPhiIncoming(phi, GetDefaultValue(result.mType), pendingNullCond->mCheckBB);
  7495. for (int notNullIdx = 0; notNullIdx < (int)pendingNullCond->mNotNullBBs.size() - 1; notNullIdx++)
  7496. {
  7497. auto prevNotNullBB = pendingNullCond->mNotNullBBs[notNullIdx];
  7498. mBfIRBuilder->AddPhiIncoming(phi, GetDefaultValue(result.mType), prevNotNullBB);
  7499. }
  7500. result.mValue = phi;
  7501. }
  7502. }
  7503. else
  7504. {
  7505. mBfIRBuilder->CreateBr(pendingNullCond->mDoneBB);
  7506. mBfIRBuilder->SetInsertPoint(pendingNullCond->mPrevBB);
  7507. mBfIRBuilder->CreateBr(pendingNullCond->mCheckBB);
  7508. AddBasicBlock(pendingNullCond->mDoneBB);
  7509. }
  7510. delete mCurMethodState->mPendingNullConditional;
  7511. mCurMethodState->mPendingNullConditional = NULL;
  7512. return result;
  7513. }
  7514. BF_NOINLINE void BfModule::EvaluateWithNewConditionalScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags)
  7515. {
  7516. BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
  7517. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData);
  7518. if (mCurMethodState != NULL)
  7519. {
  7520. deferredLocalAssignData.mIsIfCondition = true;
  7521. deferredLocalAssignData.mIfMayBeSkipped = true;
  7522. deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
  7523. deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
  7524. mCurMethodState->mDeferredLocalAssignData = &deferredLocalAssignData;
  7525. }
  7526. BfScopeData newScope;
  7527. newScope.mOuterIsConditional = true;
  7528. newScope.mAllowTargeting = false;
  7529. if (mCurMethodState != NULL)
  7530. {
  7531. mCurMethodState->AddScope(&newScope);
  7532. NewScopeState(true, false);
  7533. }
  7534. exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | flags);
  7535. exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, (flags & BfEvalExprFlags_AllowSplat) != 0);
  7536. if (mCurMethodState != NULL)
  7537. RestoreScopeState();
  7538. }
  7539. BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfType* wantTypeRef, BfEvalExprFlags flags, BfType** outOrigType)
  7540. {
  7541. //
  7542. {
  7543. BP_ZONE("CreateValueFromExpression:CheckStack");
  7544. StackHelper stackHelper;
  7545. if (!stackHelper.CanStackExpand(64 * 1024))
  7546. {
  7547. BfTypedValue result;
  7548. if (!stackHelper.Execute([&]()
  7549. {
  7550. result = CreateValueFromExpression(exprEvaluator, expr, wantTypeRef, flags, outOrigType);
  7551. }))
  7552. {
  7553. Fail("Expression too complex to compile", expr);
  7554. }
  7555. return result;
  7556. }
  7557. }
  7558. BP_ZONE("BfModule::CreateValueFromExpression");
  7559. if (outOrigType != NULL)
  7560. *outOrigType = NULL;
  7561. exprEvaluator.mExpectingType = wantTypeRef;
  7562. exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | flags);
  7563. exprEvaluator.mExplicitCast = (flags & BfEvalExprFlags_ExplicitCast) != 0;
  7564. if ((flags & BfEvalExprFlags_CreateConditionalScope) != 0)
  7565. {
  7566. if ((mCurMethodState == NULL) || (mCurMethodState->mCurScope->mScopeKind != BfScopeKind_StatementTarget_Conditional))
  7567. {
  7568. EvaluateWithNewConditionalScope(exprEvaluator, expr, flags);
  7569. }
  7570. else
  7571. {
  7572. SetAndRestoreValue<bool> prevIsConditional(mCurMethodState->mCurScope->mIsConditional, true);
  7573. exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, true);
  7574. }
  7575. }
  7576. else
  7577. exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, true);
  7578. if (!exprEvaluator.mResult)
  7579. {
  7580. if ((flags & BfEvalExprFlags_InferReturnType) != 0)
  7581. return exprEvaluator.mResult;
  7582. if (!mCompiler->mPassInstance->HasFailed())
  7583. {
  7584. if (PreFail())
  7585. Fail("INTERNAL ERROR: No expression result returned but no error caught in expression evaluator", expr);
  7586. }
  7587. return BfTypedValue();
  7588. }
  7589. auto typedVal = exprEvaluator.mResult;
  7590. if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
  7591. {
  7592. BF_ASSERT(typedVal.mType->IsGenericParam());
  7593. auto genericParamDef = GetGenericParamInstance((BfGenericParamType*)typedVal.mType);
  7594. bool handled = false;
  7595. if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
  7596. {
  7597. auto genericTypeConstraint = genericParamDef->mTypeConstraint;
  7598. if (genericTypeConstraint != NULL)
  7599. {
  7600. auto underlyingConstraint = genericTypeConstraint;
  7601. if ((underlyingConstraint != NULL) && (underlyingConstraint->IsBoxed()))
  7602. underlyingConstraint = underlyingConstraint->GetUnderlyingType();
  7603. if (underlyingConstraint != NULL)
  7604. {
  7605. BfTypedValue result;
  7606. result.mKind = BfTypedValueKind_Value;
  7607. result.mType = genericTypeConstraint;
  7608. result.mValue = mBfIRBuilder->GetUndefConstValue(mBfIRBuilder->MapType(underlyingConstraint));
  7609. typedVal = result;
  7610. handled = true;
  7611. }
  7612. }
  7613. }
  7614. if (!handled)
  7615. {
  7616. //Fail("Only const generic parameters can be used as values", expr);
  7617. AssertErrorState();
  7618. return BfTypedValue();
  7619. }
  7620. }
  7621. if ((flags & BfEvalExprFlags_AllowIntUnknown) == 0)
  7622. FixIntUnknown(typedVal);
  7623. if (!mBfIRBuilder->mIgnoreWrites)
  7624. FixValueActualization(typedVal);
  7625. exprEvaluator.CheckResultForReading(typedVal);
  7626. if ((wantTypeRef == NULL) || (!wantTypeRef->IsRef()))
  7627. {
  7628. if ((flags & BfEvalExprFlags_NoCast) == 0)
  7629. {
  7630. // Only allow a 'ref' type if we have an explicit 'ref' operator
  7631. bool allowRef = false;
  7632. BfExpression* checkExpr = expr;
  7633. while (auto parenExpr = BfNodeDynCast<BfParenthesizedExpression>(checkExpr))
  7634. checkExpr = parenExpr->mExpression;
  7635. if (auto unaryOp = BfNodeDynCast<BfUnaryOperatorExpression>(checkExpr))
  7636. {
  7637. if ((unaryOp->mOp == BfUnaryOp_Ref) || (unaryOp->mOp == BfUnaryOp_Mut))
  7638. allowRef = true;
  7639. }
  7640. if (!allowRef)
  7641. typedVal = RemoveRef(typedVal);
  7642. }
  7643. }
  7644. if ((!typedVal.mType->IsComposite()) && (!typedVal.mType->IsGenericParam())) // Load non-structs by default
  7645. {
  7646. if ((!mBfIRBuilder->mIgnoreWrites) && (!typedVal.mType->IsValuelessType()) && (!typedVal.mType->IsVar()))
  7647. {
  7648. BF_ASSERT(!typedVal.mValue.IsFake());
  7649. }
  7650. typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);
  7651. }
  7652. if (wantTypeRef != NULL)
  7653. {
  7654. if (outOrigType != NULL)
  7655. *outOrigType = typedVal.mType;
  7656. if (((flags & BfEvalExprFlags_NoCast) == 0) && (!wantTypeRef->IsVar()))
  7657. {
  7658. BfCastFlags castFlags = ((flags & BfEvalExprFlags_ExplicitCast) != 0) ? BfCastFlags_Explicit : BfCastFlags_None;
  7659. if ((flags & BfEvalExprFlags_FieldInitializer) != 0)
  7660. castFlags = (BfCastFlags)(castFlags | BfCastFlags_WarnOnBox);
  7661. typedVal = Cast(expr, typedVal, wantTypeRef, castFlags);
  7662. if (!typedVal)
  7663. return typedVal;
  7664. }
  7665. if (exprEvaluator.mIsVolatileReference)
  7666. typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);
  7667. }
  7668. if ((typedVal.mType->IsValueType()) && ((flags & BfEvalExprFlags_NoValueAddr) != 0))
  7669. typedVal = LoadValue(typedVal, 0, exprEvaluator.mIsVolatileReference);
  7670. return typedVal;
  7671. }
  7672. BfTypedValue BfModule::CreateValueFromExpression(BfExpression* expr, BfType* wantTypeRef, BfEvalExprFlags flags, BfType** outOrigType)
  7673. {
  7674. BfExprEvaluator exprEvaluator(this);
  7675. return CreateValueFromExpression(exprEvaluator, expr, wantTypeRef, flags, outOrigType);
  7676. }
  7677. BfTypedValue BfModule::GetOrCreateVarAddr(BfExpression* expr)
  7678. {
  7679. BfExprEvaluator exprEvaluator(this);
  7680. exprEvaluator.Evaluate(expr);
  7681. if (!exprEvaluator.mResult)
  7682. {
  7683. Fail("Invalid expression type", expr);
  7684. return BfTypedValue();
  7685. }
  7686. if (!exprEvaluator.mResult.IsAddr())
  7687. {
  7688. Fail("Cannot assign to value", expr);
  7689. return BfTypedValue();
  7690. }
  7691. return exprEvaluator.mResult;
  7692. }
  7693. // Clear memory, set classVData, call init. Actual ctor is called elsewhere.
  7694. void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, bool zeroMemory, BfIRValue sizeValue)
  7695. {
  7696. auto typeInstance = typedValue.mType->ToTypeInstance();
  7697. if (zeroMemory)
  7698. {
  7699. int zeroAlign = typedValue.mType->mAlign;
  7700. if (typeInstance != NULL)
  7701. zeroAlign = typeInstance->mInstAlign;
  7702. mBfIRBuilder->CreateMemSet(typedValue.mValue, GetConstValue8(0), sizeValue, zeroAlign);
  7703. }
  7704. if (!typedValue.mType->IsObject())
  7705. {
  7706. return;
  7707. }
  7708. if ((scopeData == NULL) && (mCurMethodState != NULL))
  7709. return; // Handled in heap alloc funcs
  7710. auto typeDef = typeInstance->mTypeDef;
  7711. mBfIRBuilder->PopulateType(typedValue.mType);
  7712. auto vObjectAddr = mBfIRBuilder->CreateInBoundsGEP(typedValue.mValue, 0, 0);
  7713. bool isAutocomplete = mCompiler->IsAutocomplete();
  7714. BfIRValue vDataRef;
  7715. if (!isAutocomplete)
  7716. {
  7717. vDataRef = GetClassVDataPtr(typeInstance);
  7718. }
  7719. auto i8Type = GetPrimitiveType(BfTypeCode_Int8);
  7720. auto ptrType = CreatePointerType(i8Type);
  7721. auto ptrPtrType = CreatePointerType(ptrType);
  7722. PopulateType(ptrPtrType, BfPopulateType_Declaration);
  7723. PopulateType(ptrType, BfPopulateType_Declaration);
  7724. auto destAddr = mBfIRBuilder->CreateBitCast(vObjectAddr, mBfIRBuilder->MapType(ptrPtrType));
  7725. if (!isAutocomplete)
  7726. {
  7727. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  7728. {
  7729. auto objectPtr = mBfIRBuilder->CreateBitCast(destAddr, mBfIRBuilder->MapType(mContext->mBfObjectType));
  7730. SizedArray<BfIRValue, 4> llvmArgs;
  7731. llvmArgs.push_back(objectPtr);
  7732. llvmArgs.push_back(vDataRef);
  7733. auto objectStackInitMethod = GetInternalMethod("Dbg_ObjectStackInit");
  7734. if (objectStackInitMethod)
  7735. mBfIRBuilder->CreateCall(objectStackInitMethod.mFunc, llvmArgs);
  7736. }
  7737. else
  7738. {
  7739. auto srcVal = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapType(ptrType));
  7740. auto objectPtr = mBfIRBuilder->CreateBitCast(destAddr, mBfIRBuilder->MapType(ptrType));
  7741. mBfIRBuilder->CreateStore(srcVal, destAddr);
  7742. }
  7743. }
  7744. }
  7745. BfIRValue BfModule::AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTarget, BfType* type, BfIRValue sizeValue, BfIRValue alignValue, BfAllocFlags allocFlags/*, bool zeroMemory, bool defaultToMalloc*/)
  7746. {
  7747. BfIRValue result;
  7748. BfType* ptrType;
  7749. if ((type->IsObject()) && ((allocFlags & BfAllocFlags_RawArray) == 0))
  7750. ptrType = type;
  7751. else
  7752. ptrType = CreatePointerType(type);
  7753. if ((allocTarget.mScopedInvocationTarget != NULL) || (allocTarget.mCustomAllocator))
  7754. {
  7755. auto intType = GetPrimitiveType(BfTypeCode_IntPtr);
  7756. SizedArray<BfExpression*, 2> argExprs;
  7757. BfTypedValueExpression typedValueExpr;
  7758. typedValueExpr.Init(BfTypedValue(sizeValue, intType));
  7759. typedValueExpr.mRefNode = refNode;
  7760. argExprs.push_back(&typedValueExpr);
  7761. BfTypedValueExpression appendSizeValueExpr;
  7762. appendSizeValueExpr.Init(BfTypedValue(alignValue, intType));
  7763. appendSizeValueExpr.mRefNode = refNode;
  7764. argExprs.push_back(&appendSizeValueExpr);
  7765. BfExprEvaluator exprEvaluator(this);
  7766. BfTypedValue allocResult;
  7767. if (allocTarget.mScopedInvocationTarget != NULL)
  7768. {
  7769. SizedArray<BfTypeReference*, 2> genericArgs;
  7770. exprEvaluator.DoInvocation(allocTarget.mScopedInvocationTarget, NULL, argExprs, BfMethodGenericArguments());
  7771. allocResult = LoadValue(exprEvaluator.mResult);
  7772. }
  7773. else if (allocTarget.mCustomAllocator)
  7774. {
  7775. auto customTypeInst = allocTarget.mCustomAllocator.mType->ToTypeInstance();
  7776. if (customTypeInst == NULL)
  7777. {
  7778. if (allocTarget.mCustomAllocator.mType->IsStructPtr())
  7779. customTypeInst = allocTarget.mCustomAllocator.mType->GetUnderlyingType()->ToTypeInstance();
  7780. }
  7781. if (customTypeInst == NULL)
  7782. {
  7783. Fail(StrFormat("Type '%s' cannot be used as a custom allocator", TypeToString(allocTarget.mCustomAllocator.mType).c_str()), refNode);
  7784. }
  7785. else
  7786. {
  7787. BfTypedValueExpression typeValueExpr;
  7788. String allocMethodName = "Alloc";
  7789. if (GetRawMethodByName(customTypeInst, "AllocTyped", -1, true, true))
  7790. {
  7791. allocMethodName = "AllocTyped";
  7792. auto typeType = ResolveTypeDef(mCompiler->mTypeTypeDef);
  7793. auto typeRefVal = CreateTypeDataRef(type);
  7794. typeValueExpr.Init(BfTypedValue(typeRefVal, typeType));
  7795. typeValueExpr.mRefNode = refNode;
  7796. argExprs.Insert(0, &typeValueExpr);
  7797. }
  7798. if (HasMixin(customTypeInst, allocMethodName, 2))
  7799. {
  7800. BfSizedArray<BfExpression*> argExprArr;
  7801. argExprArr.mSize = (int)argExprs.size();
  7802. argExprArr.mVals = &argExprs[0];
  7803. exprEvaluator.InjectMixin(refNode, allocTarget.mCustomAllocator, false, allocMethodName, argExprs, {});
  7804. allocResult = exprEvaluator.GetResult();
  7805. }
  7806. else
  7807. {
  7808. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  7809. BfResolvedArgs argValues(&sizedArgExprs);
  7810. exprEvaluator.ResolveArgValues(argValues);
  7811. SetAndRestoreValue<bool> prevNoBind(mCurMethodState->mNoBind, true);
  7812. allocResult = exprEvaluator.MatchMethod(refNode, NULL, allocTarget.mCustomAllocator, false, false, allocMethodName, argValues, BfMethodGenericArguments());
  7813. }
  7814. }
  7815. }
  7816. if (allocResult)
  7817. {
  7818. if (allocResult.mType->IsVoidPtr())
  7819. result = mBfIRBuilder->CreateBitCast(allocResult.mValue, mBfIRBuilder->MapType(ptrType));
  7820. else
  7821. result = CastToValue(refNode, allocResult, ptrType, BfCastFlags_Explicit);
  7822. return result;
  7823. }
  7824. }
  7825. if ((allocFlags & BfAllocFlags_NoDefaultToMalloc) != 0)
  7826. return result;
  7827. if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  7828. {
  7829. BfIRValue allocData = GetDbgRawAllocData(type);
  7830. BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_RawAlloc", 2);
  7831. SizedArray<BfIRValue, 2> llvmArgs;
  7832. llvmArgs.push_back(sizeValue);
  7833. llvmArgs.push_back(allocData);
  7834. BfIRValue bitData = mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
  7835. return mBfIRBuilder->CreateBitCast(bitData, mBfIRBuilder->MapType(ptrType));
  7836. }
  7837. BfModuleMethodInstance moduleMethodInstance;
  7838. moduleMethodInstance = GetInternalMethod("Malloc");
  7839. SizedArray<BfIRValue, 1> llvmArgs;
  7840. llvmArgs.push_back(sizeValue);
  7841. auto func = moduleMethodInstance.mFunc;
  7842. if ((!func) || (func.IsFake()))
  7843. {
  7844. BF_ASSERT((mCompiler->mIsResolveOnly) || (mBfIRBuilder->mIgnoreWrites));
  7845. return mBfIRBuilder->CreateUndefValue(mBfIRBuilder->MapType(ptrType));
  7846. }
  7847. BfIRValue bitData = mBfIRBuilder->CreateCall(func, llvmArgs);
  7848. if ((allocFlags & BfAllocFlags_ZeroMemory) != 0)
  7849. mBfIRBuilder->CreateMemSet(bitData, GetConstValue8(0), sizeValue, alignValue);
  7850. result = mBfIRBuilder->CreateBitCast(bitData, mBfIRBuilder->MapType(ptrType));
  7851. return result;
  7852. }
  7853. BfIRValue BfModule::GetMarkFuncPtr(BfType* type)
  7854. {
  7855. if (type->IsStruct())
  7856. {
  7857. auto typeInstance = type->ToTypeInstance();
  7858. BfModuleMethodInstance moduleMethodInst = GetMethodByName(typeInstance, BF_METHODNAME_MARKMEMBERS, 0, true);
  7859. return mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr)));
  7860. }
  7861. else if (type->IsObjectOrInterface())
  7862. {
  7863. auto gcType = ResolveTypeDef(mCompiler->mGCTypeDef)->ToTypeInstance();
  7864. BfModuleMethodInstance moduleMethodInst = GetMethodByName(gcType, "MarkDerefedObject");
  7865. BF_ASSERT(moduleMethodInst.mFunc);
  7866. return mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr)));
  7867. }
  7868. else
  7869. {
  7870. auto gcType = ResolveTypeDef(mCompiler->mGCTypeDef)->ToTypeInstance();
  7871. BfExprEvaluator exprEvaluator(this);
  7872. SizedArray<BfResolvedArg, 1> resolvedArgs;
  7873. BfResolvedArg resolvedArg;
  7874. resolvedArg.mTypedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), type, type->IsComposite());
  7875. resolvedArgs.Add(resolvedArg);
  7876. BfMethodMatcher methodMatcher(NULL, this, "Mark", resolvedArgs, BfMethodGenericArguments());
  7877. methodMatcher.CheckType(gcType, BfTypedValue(), false);
  7878. BfModuleMethodInstance moduleMethodInst = exprEvaluator.GetSelectedMethod(NULL, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
  7879. BF_ASSERT(moduleMethodInst.mFunc);
  7880. return mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr)));
  7881. }
  7882. return BfIRValue();
  7883. }
  7884. BfIRValue BfModule::GetDbgRawAllocData(BfType* type)
  7885. {
  7886. BfIRValue allocDataValue;
  7887. if (mDbgRawAllocDataRefs.TryGetValue(type, &allocDataValue))
  7888. return allocDataValue;
  7889. BfIRValue markFuncPtr;
  7890. if (type->WantsGCMarking())
  7891. markFuncPtr = GetMarkFuncPtr(type);
  7892. else
  7893. markFuncPtr = mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr)));
  7894. BfIRValue typeDataRef = CreateTypeDataRef(type);
  7895. auto dbgRawAllocDataType = ResolveTypeDef(mCompiler->mDbgRawAllocDataTypeDef)->ToTypeInstance();
  7896. BfTypeInstance* typeInstance = type->ToTypeInstance();
  7897. if (typeInstance == NULL)
  7898. {
  7899. typeInstance = GetWrappedStructType(type);
  7900. if (typeInstance != NULL)
  7901. AddDependency(typeInstance, mCurTypeInstance, BfDependencyMap::DependencyFlag_Allocates);
  7902. }
  7903. if (typeInstance != NULL)
  7904. PopulateType(typeInstance);
  7905. int stackCount = mCompiler->mOptions.mAllocStackCount;
  7906. if ((typeInstance != NULL) && (typeInstance->mTypeOptionsIdx != -1))
  7907. {
  7908. auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
  7909. stackCount = BfTypeOptions::Apply(stackCount, typeOptions->mAllocStackTraceDepth);
  7910. }
  7911. SizedArray<BfIRValue, 2> dataValues;
  7912. dataValues.Add(mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(dbgRawAllocDataType->mBaseType, BfIRPopulateType_Full)));
  7913. dataValues.Add(typeDataRef);
  7914. dataValues.Add(markFuncPtr);
  7915. dataValues.Add(mBfIRBuilder->CreateConst(BfTypeCode_Int32, stackCount));
  7916. BfIRValue dataStruct = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(dbgRawAllocDataType, BfIRPopulateType_Full), dataValues);
  7917. allocDataValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(dbgRawAllocDataType), true, BfIRLinkageType_Internal, dataStruct, "__allocData_" + BfSafeMangler::Mangle(type));
  7918. mDbgRawAllocDataRefs.TryAdd(type, allocDataValue);
  7919. return allocDataValue;
  7920. }
  7921. BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget, BfIRValue appendSizeValue, BfIRValue arraySize, int arrayDim, BfAllocFlags allocFlags, int alignOverride)
  7922. {
  7923. BP_ZONE("AllocFromType");
  7924. BfScopeData* scopeData = allocTarget.mScopeData;
  7925. BF_ASSERT(!type->IsVar());
  7926. auto typeInstance = type->ToTypeInstance();
  7927. if ((typeInstance == NULL) && (type->IsGenericParam()))
  7928. typeInstance = mContext->mBfObjectType;
  7929. bool isHeapAlloc = scopeData == NULL;
  7930. bool isScopeAlloc = scopeData != NULL;
  7931. bool isLoopedAlloc = (scopeData != NULL) && (mCurMethodState->mCurScope->IsLooped(scopeData));
  7932. bool isDynAlloc = (scopeData != NULL) && (mCurMethodState->mCurScope->IsDyn(scopeData));
  7933. bool isRawArrayAlloc = (allocFlags & BfAllocFlags_RawArray) != 0;
  7934. bool zeroMemory = (allocFlags & BfAllocFlags_ZeroMemory) != 0;
  7935. bool noDtorCall = (allocFlags & BfAllocFlags_NoDtorCall) != 0;
  7936. if ((type->IsValuelessType()) && ((!arraySize) || (isRawArrayAlloc)))
  7937. {
  7938. BfPointerType* ptrType = CreatePointerType(type);
  7939. auto val = mBfIRBuilder->CreateIntToPtr(mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1), mBfIRBuilder->MapType(ptrType));
  7940. return val;
  7941. }
  7942. if (typeInstance != NULL)
  7943. mBfIRBuilder->PopulateType(typeInstance);
  7944. bool hasCustomAllocator = (allocTarget.mCustomAllocator) || (allocTarget.mScopedInvocationTarget != NULL);
  7945. if ((!hasCustomAllocator) && (mBfIRBuilder->mIgnoreWrites))
  7946. {
  7947. return mBfIRBuilder->GetFakeVal();
  7948. }
  7949. AddDependency(type, mCurTypeInstance, BfDependencyMap::DependencyFlag_Allocates);
  7950. BfIRValue sizeValue;
  7951. BfIRType allocType = mBfIRBuilder->MapType(type);
  7952. int allocSize = type->mSize;
  7953. int allocAlign = type->mAlign;
  7954. if (typeInstance != NULL)
  7955. {
  7956. if ((!mBfIRBuilder->mIgnoreWrites) && (!mIsComptimeModule))
  7957. typeInstance->mHasBeenInstantiated = true;
  7958. allocSize = typeInstance->mInstSize;
  7959. allocAlign = typeInstance->mInstAlign;
  7960. //if (typeInstance->IsEnum())
  7961. //allocType = typeInstance->mIRType;
  7962. allocType = mBfIRBuilder->MapTypeInst(typeInstance);
  7963. }
  7964. if (alignOverride != -1)
  7965. allocAlign = alignOverride;
  7966. // The "dynSize" cases:
  7967. // If we are not dyn, but we are a variable size and could be looped over multiple times then we attempt to reuse
  7968. // the last stack space. We won't use StackSave and StackRestore because a scoped alloc that occurs after this but
  7969. // needs to be retained after the current scopeData (ie: scopeData::), then it would cause these allocs to accumulate even
  7970. // though we'd expect their stack space to be released
  7971. auto _CreateDynAlloc = [&](const BfIRValue& sizeValue, int align)
  7972. {
  7973. MarkDynStack(scopeData);
  7974. BfType* intType = GetPrimitiveType(BfTypeCode_IntPtr);
  7975. // For dynamically sized scoped allocs, we need to check the previous size to see if we need to realloc
  7976. BfType* voidType = GetPrimitiveType(BfTypeCode_None);
  7977. BfType* voidPtrType = CreatePointerType(voidType);
  7978. if (!mCurMethodState->mDynStackRevIdx)
  7979. {
  7980. mCurMethodState->mDynStackRevIdx = CreateAlloca(intType, false, "curDynStackRevIdx");
  7981. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  7982. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  7983. auto storeInst = mBfIRBuilder->CreateStore(GetConstValue(0), mCurMethodState->mDynStackRevIdx);
  7984. mBfIRBuilder->ClearDebugLocation(storeInst);
  7985. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  7986. }
  7987. auto byteType = GetPrimitiveType(BfTypeCode_Int8);
  7988. auto bytePtrType = CreatePointerType(byteType);
  7989. auto dynSizeAllocaInst = CreateAlloca(intType, false, "dynSize");
  7990. auto dynStackRevIdx = CreateAlloca(intType, false, "dynStackRevIdx");
  7991. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  7992. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  7993. auto storeInst = mBfIRBuilder->CreateStore(GetConstValue(0), dynSizeAllocaInst);
  7994. mBfIRBuilder->ClearDebugLocation(storeInst);
  7995. storeInst = mBfIRBuilder->CreateStore(GetConstValue(0), dynStackRevIdx);
  7996. mBfIRBuilder->ClearDebugLocation(storeInst);
  7997. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  7998. auto dynPtrAllocaInst = CreateAlloca(bytePtrType, false, "dynPtr");
  7999. if (IsTargetingBeefBackend())
  8000. {
  8001. // Since we don't allocate a debug variable for this, with LifetimeExtends, the easiest way
  8002. // to ensure there isn't any register collision during looping is just to not allow it to
  8003. // bind to a register at all
  8004. mBfIRBuilder->SetAllocaForceMem(dynSizeAllocaInst);
  8005. mBfIRBuilder->SetAllocaForceMem(dynPtrAllocaInst);
  8006. }
  8007. auto resizeBB = mBfIRBuilder->CreateBlock("dynAlloc.resize");
  8008. auto endBB = mBfIRBuilder->CreateBlock("dynAlloc.end");
  8009. auto verCheckBB = mBfIRBuilder->CreateBlock("dynAlloc.verCheck");
  8010. auto curDynStackRevIdx = mBfIRBuilder->CreateLoad(mCurMethodState->mDynStackRevIdx);
  8011. auto prevSize = mBfIRBuilder->CreateLoad(dynSizeAllocaInst);
  8012. auto isGreater = mBfIRBuilder->CreateCmpGT(sizeValue, prevSize, true);
  8013. mBfIRBuilder->CreateCondBr(isGreater, resizeBB, verCheckBB);
  8014. mBfIRBuilder->AddBlock(verCheckBB);
  8015. mBfIRBuilder->SetInsertPoint(verCheckBB);
  8016. auto prevDynStackRevIdx = mBfIRBuilder->CreateLoad(dynStackRevIdx);
  8017. auto dynStackChanged = mBfIRBuilder->CreateCmpNE(prevDynStackRevIdx, curDynStackRevIdx);
  8018. mBfIRBuilder->CreateCondBr(dynStackChanged, resizeBB, endBB);
  8019. mBfIRBuilder->AddBlock(resizeBB);
  8020. mBfIRBuilder->SetInsertPoint(resizeBB);
  8021. auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(byteType), sizeValue);
  8022. mBfIRBuilder->SetAllocaAlignment(allocaInst, align);
  8023. mBfIRBuilder->CreateStore(allocaInst, dynPtrAllocaInst);
  8024. mBfIRBuilder->CreateStore(sizeValue, dynSizeAllocaInst);
  8025. mBfIRBuilder->CreateStore(curDynStackRevIdx, dynStackRevIdx);
  8026. mBfIRBuilder->CreateBr(endBB);
  8027. mBfIRBuilder->AddBlock(endBB);
  8028. mBfIRBuilder->SetInsertPoint(endBB);
  8029. return mBfIRBuilder->CreateLoad(dynPtrAllocaInst);
  8030. };
  8031. if (isScopeAlloc)
  8032. {
  8033. if (arraySize)
  8034. {
  8035. bool isConstantArraySize = arraySize.IsConst();
  8036. if (isRawArrayAlloc)
  8037. {
  8038. BfPointerType* ptrType = CreatePointerType(type);
  8039. if ((!isDynAlloc) && (!isConstantArraySize) && (mCurMethodState->mCurScope->IsLooped(NULL)))
  8040. {
  8041. BfIRValue sizeValue = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySize);
  8042. auto loadedPtr = _CreateDynAlloc(sizeValue, type->mAlign);
  8043. InitTypeInst(BfTypedValue(loadedPtr, ptrType), scopeData, zeroMemory, sizeValue);
  8044. return mBfIRBuilder->CreateBitCast(loadedPtr, mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(type)));
  8045. }
  8046. else
  8047. {
  8048. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  8049. isDynAlloc = (isDynAlloc) || (!arraySize.IsConst());
  8050. if (!isDynAlloc)
  8051. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  8052. else
  8053. {
  8054. MarkDynStack(scopeData);
  8055. SaveStackState(scopeData);
  8056. }
  8057. int typeSize = type->GetStride();
  8058. BfIRValue allocaInst;
  8059. BfIRValue result;
  8060. if ((typeInstance == NULL) || (typeInstance->mIsCRepr))
  8061. {
  8062. allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(type), arraySize);
  8063. result = allocaInst;
  8064. }
  8065. else
  8066. {
  8067. if (typeInstance->IsStruct())
  8068. typeSize = typeInstance->GetInstStride();
  8069. auto byteType = GetPrimitiveStructType(BfTypeCode_Int8);
  8070. sizeValue = mBfIRBuilder->CreateMul(GetConstValue(typeSize), arraySize);
  8071. allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(byteType), sizeValue);
  8072. auto ptrType = CreatePointerType(typeInstance);
  8073. result = mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(ptrType));
  8074. if (!isDynAlloc)
  8075. mBfIRBuilder->ClearDebugLocation(result);
  8076. }
  8077. if (!isDynAlloc)
  8078. mBfIRBuilder->ClearDebugLocation(allocaInst);
  8079. mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
  8080. if (!isDynAlloc)
  8081. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  8082. auto typedVal = BfTypedValue(result, type, BfTypedValueKind_Addr);
  8083. if (arraySize.IsConst())
  8084. {
  8085. auto constant = mBfIRBuilder->GetConstant(arraySize);
  8086. if (constant->mInt64 == 0)
  8087. noDtorCall = true;
  8088. }
  8089. if (!noDtorCall)
  8090. {
  8091. bool isConstSize = arraySize.IsConst();
  8092. BfIRBlock clearBlock;
  8093. BfIRBlock contBlock;
  8094. bool wantsDeinit = ((!IsOptimized()) && (!mIsComptimeModule) && (!mBfIRBuilder->mIgnoreWrites) && (!mCompiler->mIsResolveOnly));
  8095. if (wantsDeinit)
  8096. {
  8097. BfIRBlock prevBlock;
  8098. if (!isConstSize)
  8099. {
  8100. clearBlock = mBfIRBuilder->CreateBlock("clear");
  8101. contBlock = mBfIRBuilder->CreateBlock("clearCont");
  8102. prevBlock = mBfIRBuilder->GetInsertBlock();
  8103. mBfIRBuilder->AddBlock(clearBlock);
  8104. mBfIRBuilder->SetInsertPoint(clearBlock);
  8105. }
  8106. auto deferredCall = AddStackAlloc(typedVal, arraySize, NULL, scopeData, false, true);
  8107. if (!isConstSize)
  8108. {
  8109. mBfIRBuilder->CreateBr(contBlock);
  8110. mBfIRBuilder->SetInsertPoint(prevBlock);
  8111. if (deferredCall != NULL)
  8112. {
  8113. // Zero out size args
  8114. for (int i = 1; i < deferredCall->mModuleMethodInstance.mMethodInstance->GetParamCount(); i++)
  8115. {
  8116. auto scopedArg = deferredCall->mScopeArgs[i];
  8117. if (scopedArg != deferredCall->mOrigScopeArgs[i])
  8118. mBfIRBuilder->CreateStore(GetDefaultValue(deferredCall->mModuleMethodInstance.mMethodInstance->GetParamType(i)), deferredCall->mScopeArgs[i]);
  8119. }
  8120. }
  8121. mBfIRBuilder->CreateCondBr(mBfIRBuilder->CreateCmpNE(arraySize, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 0)), clearBlock, contBlock);
  8122. mBfIRBuilder->AddBlock(contBlock);
  8123. mBfIRBuilder->SetInsertPoint(contBlock);
  8124. }
  8125. }
  8126. }
  8127. return result;
  8128. }
  8129. }
  8130. else
  8131. {
  8132. if ((!isDynAlloc) && (!arraySize.IsConst()) && (mCurMethodState->mCurScope->IsLooped(NULL)))
  8133. {
  8134. // Generate and check new size
  8135. BfArrayType* arrayType = CreateArrayType(type, arrayDim);
  8136. auto firstElementField = &arrayType->mFieldInstances.back();
  8137. int arrayClassSize = firstElementField->mDataOffset;
  8138. sizeValue = GetConstValue(arrayClassSize);
  8139. BfIRValue elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySize);
  8140. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, elementDataSize);
  8141. auto loadedPtr = _CreateDynAlloc(sizeValue, arrayType->mAlign);
  8142. auto typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(loadedPtr, mBfIRBuilder->MapType(arrayType)), arrayType);
  8143. if (!noDtorCall)
  8144. AddStackAlloc(typedVal, BfIRValue(), NULL, scopeData, false, true);
  8145. InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
  8146. return typedVal.mValue;
  8147. }
  8148. else
  8149. {
  8150. BfArrayType* arrayType = CreateArrayType(type, arrayDim);
  8151. auto firstElementField = &arrayType->mFieldInstances.back();
  8152. if (!type->IsValuelessType())
  8153. {
  8154. int arrayClassSize = firstElementField->mDataOffset;
  8155. sizeValue = GetConstValue(arrayClassSize);
  8156. BfIRValue elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySize);
  8157. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, elementDataSize);
  8158. }
  8159. else
  8160. sizeValue = GetConstValue(arrayType->mInstSize);
  8161. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  8162. isDynAlloc = (isDynAlloc) || (!sizeValue.IsConst());
  8163. if (!isDynAlloc)
  8164. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  8165. else
  8166. {
  8167. MarkDynStack(scopeData);
  8168. SaveStackState(scopeData);
  8169. }
  8170. BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
  8171. auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(byteType), sizeValue);
  8172. if (!isDynAlloc)
  8173. mBfIRBuilder->ClearDebugLocation(allocaInst);
  8174. auto allocaBlock = mBfIRBuilder->GetInsertBlock();
  8175. mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
  8176. BfTypedValue typedVal;
  8177. if (!isDynAlloc)
  8178. {
  8179. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  8180. typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(arrayType)), arrayType);
  8181. mBfIRBuilder->ClearDebugLocation_Last();
  8182. mBfIRBuilder->SetInsertPoint(prevBlock);
  8183. allocaBlock = mCurMethodState->mIRInitBlock;
  8184. }
  8185. else
  8186. typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(arrayType)), arrayType);
  8187. if (!noDtorCall)
  8188. AddStackAlloc(typedVal, BfIRValue(), NULL, scopeData, false, true, allocaBlock);
  8189. InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
  8190. return typedVal.mValue;
  8191. }
  8192. }
  8193. }
  8194. else if (appendSizeValue)
  8195. {
  8196. // It may seem that we should check IsLooped against only the requested scope, BUT- if later on we perform
  8197. // a scoped alloc that crosses our boundary then we won't be able to reclaim the stack space, so we always
  8198. // use the "dynSize" version conservatively
  8199. if ((!isDynAlloc) && (!appendSizeValue.IsConst()) && (mCurMethodState->mCurScope->IsLooped(NULL)))
  8200. {
  8201. // Generate and check new size
  8202. sizeValue = GetConstValue(typeInstance->mInstSize);
  8203. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, appendSizeValue);
  8204. auto loadedPtr = _CreateDynAlloc(sizeValue, typeInstance->mAlign);
  8205. auto typedVal = BfTypedValue(mBfIRBuilder->CreateBitCast(loadedPtr, mBfIRBuilder->MapTypeInstPtr(typeInstance)), typeInstance);
  8206. if (!noDtorCall)
  8207. AddStackAlloc(typedVal, arraySize, NULL, scopeData, mCurMethodState->mInConditionalBlock, true);
  8208. InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
  8209. return typedVal.mValue;
  8210. }
  8211. else // stack alloc, unlooped, with append
  8212. {
  8213. sizeValue = GetConstValue(typeInstance->mInstSize);
  8214. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, appendSizeValue);
  8215. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  8216. bool wasDynAlloc = isDynAlloc;
  8217. isDynAlloc = (isDynAlloc) || (!sizeValue.IsConst());
  8218. if (!isDynAlloc)
  8219. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  8220. else
  8221. {
  8222. MarkDynStack(scopeData);
  8223. SaveStackState(scopeData);
  8224. }
  8225. auto sbyteType = GetPrimitiveType(BfTypeCode_Int8);
  8226. auto allocaInst = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(sbyteType), sizeValue);
  8227. if (!isDynAlloc)
  8228. {
  8229. mBfIRBuilder->ClearDebugLocation(allocaInst);
  8230. }
  8231. mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
  8232. bool mayBeLarge = false;
  8233. if (sizeValue.IsConst())
  8234. {
  8235. auto constantInt = mBfIRBuilder->GetConstant(sizeValue);
  8236. if (constantInt->mInt64 >= 4096)
  8237. mayBeLarge = true;
  8238. }
  8239. else
  8240. mayBeLarge = true;
  8241. if (((type->IsObject() && (!mayBeLarge))) ||
  8242. // If we create a memset that can fill in backwards (or at least 4k chunked backward) then we can remove the '!mayBeLarge' cond
  8243. ((zeroMemory) && (!mayBeLarge)))
  8244. {
  8245. mBfIRBuilder->SetAllocaNoChkStkHint(allocaInst);
  8246. }
  8247. BfIRValue castedVal;
  8248. if (!isDynAlloc)
  8249. {
  8250. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  8251. castedVal = mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapTypeInstPtr(typeInstance));
  8252. mBfIRBuilder->ClearDebugLocation(castedVal);
  8253. mBfIRBuilder->SetInsertPoint(prevBlock);
  8254. if (WantsLifetimes())
  8255. {
  8256. mBfIRBuilder->CreateLifetimeStart(allocaInst);
  8257. scopeData->mDeferredLifetimeEnds.push_back(allocaInst);
  8258. }
  8259. }
  8260. else
  8261. {
  8262. castedVal = mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapTypeInstPtr(typeInstance));
  8263. }
  8264. auto typedVal = BfTypedValue(castedVal, typeInstance);
  8265. if (!noDtorCall)
  8266. {
  8267. bool doCondAlloca = false;
  8268. if (!IsTargetingBeefBackend())
  8269. doCondAlloca = !wasDynAlloc && isDynAlloc && mCurMethodState->mInConditionalBlock;
  8270. AddStackAlloc(typedVal, arraySize, NULL, scopeData, doCondAlloca, true);
  8271. }
  8272. InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
  8273. return typedVal.mValue;
  8274. }
  8275. }
  8276. else // "Normal" stack alloc
  8277. {
  8278. BF_ASSERT(!sizeValue);
  8279. //TODO: If sizeValue is a constant then do this in the head IR builder
  8280. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  8281. if (!isLoopedAlloc)
  8282. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  8283. else
  8284. {
  8285. MarkDynStack(scopeData);
  8286. SaveStackState(scopeData);
  8287. }
  8288. auto allocaInst = mBfIRBuilder->CreateAlloca(allocType);
  8289. if (!isLoopedAlloc)
  8290. mBfIRBuilder->ClearDebugLocation(allocaInst);
  8291. mBfIRBuilder->SetAllocaAlignment(allocaInst, allocAlign);
  8292. bool mayBeLarge = allocSize >= 4096;
  8293. if (((typeInstance != NULL) && (typeInstance->IsObject()) && (!mayBeLarge)) ||
  8294. // If we create a memset that can fill in backwards (or at least 4k chunked backward) then we can remove the '!mayBeLarge' cond
  8295. ((zeroMemory) && (!mayBeLarge)))
  8296. {
  8297. // With an object, we know we will at least set the vdata pointer which will probe the start of the new address,
  8298. // and memset is always safe
  8299. mBfIRBuilder->SetAllocaNoChkStkHint(allocaInst);
  8300. }
  8301. auto typedVal = BfTypedValue(allocaInst, type);
  8302. if (!isLoopedAlloc)
  8303. {
  8304. mBfIRBuilder->ClearDebugLocation(allocaInst);
  8305. mBfIRBuilder->SetInsertPoint(prevBlock);
  8306. if (WantsLifetimes())
  8307. {
  8308. mBfIRBuilder->CreateLifetimeStart(allocaInst);
  8309. scopeData->mDeferredLifetimeEnds.push_back(allocaInst);
  8310. }
  8311. }
  8312. if (!noDtorCall)
  8313. AddStackAlloc(typedVal, BfIRValue(), NULL, scopeData, false, true);
  8314. if (typeInstance != NULL)
  8315. {
  8316. InitTypeInst(typedVal, scopeData, zeroMemory, GetConstValue(typeInstance->mInstSize));
  8317. }
  8318. else
  8319. {
  8320. mBfIRBuilder->CreateMemSet(allocaInst, GetConstValue8(0), GetConstValue(allocSize), allocAlign);
  8321. }
  8322. return allocaInst;
  8323. }
  8324. }
  8325. else if (arraySize)
  8326. {
  8327. if (isRawArrayAlloc)
  8328. {
  8329. sizeValue = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySize);
  8330. return AllocBytes(allocTarget.mRefNode, allocTarget, type, sizeValue, GetConstValue(allocAlign), allocFlags);
  8331. }
  8332. else
  8333. {
  8334. BfArrayType* arrayType = CreateArrayType(type, arrayDim);
  8335. typeInstance = arrayType;
  8336. BfIRValue arraySizeMinusOne = mBfIRBuilder->CreateSub(arraySize, GetConstValue(1));
  8337. BfIRValue elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySizeMinusOne);
  8338. appendSizeValue = elementDataSize;
  8339. if (!type->IsSizeAligned())
  8340. {
  8341. appendSizeValue = mBfIRBuilder->CreateAdd(appendSizeValue, GetConstValue(type->GetStride() - type->mSize));
  8342. }
  8343. }
  8344. }
  8345. if ((typeInstance != NULL) && (typeInstance->IsObject()))
  8346. {
  8347. auto vDataRef = GetClassVDataPtr(typeInstance);
  8348. BfIRValue result;
  8349. bool isResultInitialized = false;
  8350. int stackCount = mCompiler->mOptions.mAllocStackCount;
  8351. if (typeInstance->mTypeOptionsIdx != -1)
  8352. {
  8353. auto typeOptions = mSystem->GetTypeOptions(typeInstance->mTypeOptionsIdx);
  8354. stackCount = BfTypeOptions::Apply(stackCount, typeOptions->mAllocStackTraceDepth);
  8355. }
  8356. if (mIsComptimeModule)
  8357. stackCount = 0;
  8358. if (!sizeValue)
  8359. sizeValue = GetConstValue(typeInstance->mInstSize);
  8360. if (appendSizeValue)
  8361. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, appendSizeValue);
  8362. BfIRValue origSizeValue = sizeValue;
  8363. bool isAllocEx = hasCustomAllocator && (stackCount > 1);
  8364. if (isAllocEx)
  8365. {
  8366. auto prepareStackTraceMethod = GetInternalMethod("Dbg_PrepareStackTrace");
  8367. if (prepareStackTraceMethod)
  8368. {
  8369. SizedArray<BfIRValue, 2> irArgs;
  8370. irArgs.Add(sizeValue);
  8371. irArgs.Add(GetConstValue(stackCount));
  8372. auto addlBytes = mBfIRBuilder->CreateCall(prepareStackTraceMethod.mFunc, irArgs);
  8373. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, addlBytes);
  8374. }
  8375. }
  8376. if (allocTarget.mCustomAllocator)
  8377. {
  8378. auto customAlloc = allocTarget.mCustomAllocator.mType->ToTypeInstance();
  8379. // Use AllocObject if we have it, otherwise we just use AllocBytes further down
  8380. if ((customAlloc != NULL) && (GetRawMethodByName(customAlloc, "AllocObject", -1, true, true) != NULL))
  8381. {
  8382. auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
  8383. mBfIRBuilder->PopulateType(classVDataType);
  8384. auto typeInstType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef)->ToTypeInstance();
  8385. mBfIRBuilder->PopulateType(typeInstType);
  8386. auto typePtrPtr = mBfIRBuilder->CreateInBoundsGEP(vDataRef, 0, 1); // mType
  8387. auto typePtr = mBfIRBuilder->CreateLoad(typePtrPtr);
  8388. auto typeInstPtr = mBfIRBuilder->CreateBitCast(typePtr, mBfIRBuilder->MapTypeInstPtr(typeInstType));
  8389. BfTypedValueExpression typedValueExpr;
  8390. typedValueExpr.Init(BfTypedValue(typeInstPtr, typeInstType));
  8391. typedValueExpr.mRefNode = allocTarget.mRefNode;
  8392. BfExprEvaluator exprEvaluator(this);
  8393. SizedArray<BfExpression*, 2> argExprs;
  8394. argExprs.push_back(&typedValueExpr);
  8395. BfTypedValueExpression sizeValueExpr;
  8396. sizeValueExpr.Init(BfTypedValue(sizeValue, GetPrimitiveType(BfTypeCode_IntPtr)));
  8397. sizeValueExpr.mRefNode = allocTarget.mRefNode;
  8398. argExprs.push_back(&sizeValueExpr);
  8399. BfSizedArray<BfExpression*> sizedArgExprs(argExprs);
  8400. BfResolvedArgs argValues(&sizedArgExprs);
  8401. exprEvaluator.ResolveArgValues(argValues);
  8402. exprEvaluator.mNoBind = true;
  8403. BfTypedValue allocResult = exprEvaluator.MatchMethod(allocTarget.mRefNode, NULL, allocTarget.mCustomAllocator, false, false, "AllocObject", argValues, BfMethodGenericArguments());
  8404. if (allocResult)
  8405. {
  8406. if ((allocResult.mType->IsVoidPtr()) || (allocResult.mType == mContext->mBfObjectType))
  8407. result = mBfIRBuilder->CreateBitCast(allocResult.mValue, mBfIRBuilder->MapType(typeInstance));
  8408. else
  8409. result = CastToValue(allocTarget.mRefNode, allocResult, typeInstance, BfCastFlags_Explicit);
  8410. isResultInitialized = true;
  8411. }
  8412. }
  8413. }
  8414. bool wasAllocated = false;
  8415. if (!result)
  8416. {
  8417. if (hasCustomAllocator)
  8418. result = AllocBytes(allocTarget.mRefNode, allocTarget, typeInstance, sizeValue, GetConstValue(typeInstance->mInstAlign), (BfAllocFlags)(BfAllocFlags_ZeroMemory | BfAllocFlags_NoDefaultToMalloc));
  8419. else if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  8420. {
  8421. SizedArray<BfIRValue, 4> llvmArgs;
  8422. llvmArgs.push_back(sizeValue);
  8423. auto irFunc = GetBuiltInFunc(BfBuiltInFuncType_Malloc);
  8424. result = mBfIRBuilder->CreateCall(irFunc, llvmArgs);
  8425. result = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapTypeInstPtr(typeInstance));
  8426. wasAllocated = true;
  8427. }
  8428. }
  8429. if (result)
  8430. {
  8431. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  8432. {
  8433. auto objectPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
  8434. SizedArray<BfIRValue, 4> llvmArgs;
  8435. llvmArgs.push_back(objectPtr);
  8436. llvmArgs.push_back(origSizeValue);
  8437. llvmArgs.push_back(vDataRef);
  8438. auto objectCreatedMethod = GetInternalMethod(isAllocEx ?
  8439. (isResultInitialized ? "Dbg_ObjectCreatedEx" : "Dbg_ObjectAllocatedEx") :
  8440. (isResultInitialized ? "Dbg_ObjectCreated" : "Dbg_ObjectAllocated"));
  8441. mBfIRBuilder->CreateCall(objectCreatedMethod.mFunc, llvmArgs);
  8442. if (wasAllocated)
  8443. {
  8444. auto byteType = GetPrimitiveType(BfTypeCode_UInt8);
  8445. auto bytePtrType = CreatePointerType(byteType);
  8446. auto flagsPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapType(bytePtrType));
  8447. auto flagsVal = mBfIRBuilder->CreateLoad(flagsPtr);
  8448. auto modifiedFlagsVal = mBfIRBuilder->CreateOr(flagsVal, mBfIRBuilder->CreateConst(BfTypeCode_UInt8, /*BF_OBJECTFLAG_ALLOCATED*/4));
  8449. mBfIRBuilder->CreateStore(modifiedFlagsVal, flagsPtr);
  8450. }
  8451. }
  8452. else
  8453. {
  8454. auto ptrType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr);
  8455. auto vDataPtr = mBfIRBuilder->CreateBitCast(vDataRef, ptrType);
  8456. auto vDataMemberPtr = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->GetPointerTo(ptrType));
  8457. mBfIRBuilder->CreateStore(vDataPtr, vDataMemberPtr);
  8458. }
  8459. }
  8460. else
  8461. {
  8462. if ((mBfIRBuilder->mIgnoreWrites) ||
  8463. ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule)))
  8464. return GetDefaultValue(typeInstance);
  8465. auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);
  8466. auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()));
  8467. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  8468. {
  8469. SizedArray<BfIRValue, 4> llvmArgs;
  8470. llvmArgs.push_back(vData);
  8471. llvmArgs.push_back(sizeValue);
  8472. llvmArgs.push_back(GetConstValue(typeInstance->mAlign));
  8473. llvmArgs.push_back(GetConstValue(stackCount));
  8474. auto moduleMethodInstance = GetInternalMethod("Dbg_ObjectAlloc", 4);
  8475. BfIRValue objectVal = mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, llvmArgs);
  8476. result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance));
  8477. }
  8478. else
  8479. {
  8480. SizedArray<BfIRValue, 4> llvmArgs;
  8481. llvmArgs.push_back(sizeValue);
  8482. BfIRFunction irFunc;
  8483. if ((mCompiler->mOptions.mDebugAlloc) && (!mIsComptimeModule))
  8484. {
  8485. auto moduleMethodInstance = GetInternalMethod("Dbg_RawObjectAlloc", 1);
  8486. irFunc = moduleMethodInstance.mFunc;
  8487. }
  8488. if (!irFunc)
  8489. irFunc = GetBuiltInFunc(BfBuiltInFuncType_Malloc);
  8490. BfIRValue objectVal = mBfIRBuilder->CreateCall(irFunc, llvmArgs);
  8491. auto objResult = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(mContext->mBfObjectType, BfIRPopulateType_Full));
  8492. auto vdataPtr = mBfIRBuilder->CreateInBoundsGEP(objResult, 0, 0);
  8493. if (mIsComptimeModule)
  8494. {
  8495. vdataPtr = mBfIRBuilder->CreateBitCast(vdataPtr, mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance())));
  8496. }
  8497. mBfIRBuilder->CreateStore(vData, vdataPtr);
  8498. result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance));
  8499. }
  8500. }
  8501. if ((zeroMemory) && (arraySize))
  8502. {
  8503. BfArrayType* arrayType = CreateArrayType(type, arrayDim);
  8504. typeInstance = arrayType;
  8505. auto firstElementField = &arrayType->mFieldInstances.back();
  8506. int arrayClassSize = firstElementField->mDataOffset;
  8507. BfIRValue elementDataSize;
  8508. bool skipZero = false;
  8509. if (arraySize.IsConst())
  8510. {
  8511. BfIRValue arraySizeMinusOne = mBfIRBuilder->CreateSub(arraySize, GetConstValue(1));
  8512. elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySizeMinusOne);
  8513. elementDataSize = mBfIRBuilder->CreateAdd(elementDataSize, GetConstValue(type->mSize));
  8514. auto constVal = mBfIRBuilder->GetConstant(elementDataSize);
  8515. if (constVal->mInt64 <= 0)
  8516. skipZero = true;
  8517. }
  8518. else
  8519. {
  8520. // For non const, don't use an unpadded last element - saves us checking against negative numbers going into memset for the zero-length case
  8521. elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->GetStride()), arraySize);
  8522. }
  8523. if (!skipZero)
  8524. {
  8525. auto i8Type = GetPrimitiveType(BfTypeCode_Int8);
  8526. auto ptrType = CreatePointerType(i8Type);
  8527. auto ptrVal = mBfIRBuilder->CreateBitCast(result, mBfIRBuilder->MapType(ptrType));
  8528. ptrVal = mBfIRBuilder->CreateInBoundsGEP(ptrVal, arrayClassSize);
  8529. mBfIRBuilder->CreateMemSet(ptrVal, GetConstValue8(0), elementDataSize, type->mAlign);
  8530. appendSizeValue = elementDataSize;
  8531. }
  8532. }
  8533. return result;
  8534. }
  8535. else
  8536. {
  8537. if (!sizeValue)
  8538. sizeValue = GetConstValue(allocSize);
  8539. return AllocBytes(allocTarget.mRefNode, allocTarget, type, sizeValue, GetConstValue(allocAlign), zeroMemory ? BfAllocFlags_ZeroMemory : BfAllocFlags_None);
  8540. }
  8541. }
  8542. void BfModule::ValidateAllocation(BfType* type, BfAstNode* refNode)
  8543. {
  8544. if ((type == NULL) || (refNode == NULL))
  8545. return;
  8546. auto typeInstance = type->ToTypeInstance();
  8547. if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsOpaque))
  8548. Fail(StrFormat("Unable to allocate opaque type '%s'", TypeToString(type).c_str()), refNode);
  8549. }
  8550. void BfModule::EmitAlign(BfIRValue& appendCurIdx, int align)
  8551. {
  8552. appendCurIdx = mBfIRBuilder->CreateAdd(appendCurIdx, GetConstValue(align - 1));
  8553. appendCurIdx = mBfIRBuilder->CreateAnd(appendCurIdx, GetConstValue(~(align - 1)));
  8554. }
  8555. void BfModule::EmitAppendAlign(int align, int sizeMultiple)
  8556. {
  8557. if (sizeMultiple == 0)
  8558. sizeMultiple = align;
  8559. if ((mCurMethodState->mCurAppendAlign != 0) && (mCurMethodState->mCurAppendAlign % align != 0))
  8560. {
  8561. if (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Ctor)
  8562. {
  8563. auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1];
  8564. BF_ASSERT(localVar->mName == "appendIdx");
  8565. auto appendIdxVal = BfTypedValue(localVar->mValue, localVar->mResolvedType, true);
  8566. BfIRValue appendCurIdx = mBfIRBuilder->CreateLoad(appendIdxVal.mValue);
  8567. if (align > 1)
  8568. {
  8569. appendCurIdx = mBfIRBuilder->CreateAdd(appendCurIdx, GetConstValue(align - 1));
  8570. appendCurIdx = mBfIRBuilder->CreateAnd(appendCurIdx, GetConstValue(~(align - 1)));
  8571. }
  8572. mBfIRBuilder->CreateStore(appendCurIdx, appendIdxVal.mValue);
  8573. }
  8574. else
  8575. {
  8576. BF_ASSERT(mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend);
  8577. BfIRValue appendCurIdxPtr = mCurMethodState->mRetVal.mValue;
  8578. BfIRValue appendCurIdx = mBfIRBuilder->CreateLoad(appendCurIdxPtr);
  8579. appendCurIdx = mBfIRBuilder->CreateAdd(appendCurIdx, GetConstValue(align - 1));
  8580. appendCurIdx = mBfIRBuilder->CreateAnd(appendCurIdx, GetConstValue(~(align - 1)));
  8581. mBfIRBuilder->CreateStore(appendCurIdx, appendCurIdxPtr);
  8582. }
  8583. }
  8584. if (mCurMethodState->mCurAppendAlign == 0)
  8585. mCurMethodState->mCurAppendAlign = sizeMultiple;
  8586. else
  8587. {
  8588. if (sizeMultiple % align == 0)
  8589. mCurMethodState->mCurAppendAlign = align;
  8590. else
  8591. mCurMethodState->mCurAppendAlign = sizeMultiple % align;
  8592. }
  8593. }
  8594. BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue, int appendAllocAlign, BfIRValue arraySize, int arrayDim, bool isRawArrayAlloc, bool zeroMemory)
  8595. {
  8596. auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1];
  8597. BF_ASSERT(localVar->mName == "appendIdx");
  8598. BfTypedValue appendIdxVal(localVar->mValue, localVar->mResolvedType, true);
  8599. BfIRValue retValue;
  8600. BfTypeInstance* retTypeInstance = NULL;
  8601. auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  8602. auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
  8603. if (arraySize)
  8604. {
  8605. if (isRawArrayAlloc)
  8606. {
  8607. EmitAppendAlign(type->mAlign);
  8608. BfPointerType* ptrType = CreatePointerType(type);
  8609. BfIRValue sizeValue = mBfIRBuilder->CreateMul(GetConstValue(type->mSize), arraySize);
  8610. auto curIdxVal = mBfIRBuilder->CreateLoad(appendIdxVal.mValue);
  8611. if (mSystem->mPtrSize != 4)
  8612. sizeValue = mBfIRBuilder->CreateNumericCast(sizeValue, true, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64);
  8613. auto newIdxVal = mBfIRBuilder->CreateAdd(curIdxVal, sizeValue);
  8614. mBfIRBuilder->CreateStore(newIdxVal, appendIdxVal.mValue);
  8615. if (zeroMemory)
  8616. {
  8617. auto ptr = mBfIRBuilder->CreateIntToPtr(curIdxVal, mBfIRBuilder->MapType(voidPtrType));
  8618. mBfIRBuilder->CreateMemSet(ptr, GetConstValue8(0), sizeValue, type->mAlign);
  8619. }
  8620. return mBfIRBuilder->CreateIntToPtr(curIdxVal, mBfIRBuilder->MapType(ptrType));
  8621. }
  8622. else
  8623. {
  8624. BfArrayType* arrayType = CreateArrayType(type, arrayDim);
  8625. EmitAppendAlign(arrayType->mAlign, type->mSize);
  8626. auto firstElementField = &arrayType->mFieldInstances.back();
  8627. int arrayClassSize = arrayType->mInstSize - firstElementField->mDataSize;
  8628. BfIRValue sizeValue = GetConstValue(arrayClassSize);
  8629. BfIRValue elementDataSize = mBfIRBuilder->CreateMul(GetConstValue(type->mSize), arraySize);
  8630. sizeValue = mBfIRBuilder->CreateAdd(sizeValue, elementDataSize);
  8631. auto curIdxVal = mBfIRBuilder->CreateLoad(appendIdxVal.mValue);
  8632. if (mSystem->mPtrSize != 4)
  8633. sizeValue = mBfIRBuilder->CreateNumericCast(sizeValue, true, (intPtrType->mSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64);
  8634. auto newIdxVal = mBfIRBuilder->CreateAdd(curIdxVal, sizeValue);
  8635. mBfIRBuilder->CreateStore(newIdxVal, appendIdxVal.mValue);
  8636. if (zeroMemory)
  8637. {
  8638. // Only zero out the actual elements
  8639. int dataOffset = arrayType->mFieldInstances.back().mDataOffset;
  8640. auto newOffset = mBfIRBuilder->CreateAdd(curIdxVal, GetConstValue(dataOffset));
  8641. auto newSize = mBfIRBuilder->CreateSub(sizeValue, GetConstValue(dataOffset));
  8642. auto ptr = mBfIRBuilder->CreateIntToPtr(newOffset, mBfIRBuilder->MapType(voidPtrType));
  8643. mBfIRBuilder->CreateMemSet(ptr, GetConstValue8(0), newSize, type->mAlign);
  8644. }
  8645. retTypeInstance = arrayType;
  8646. retValue = mBfIRBuilder->CreateIntToPtr(curIdxVal, mBfIRBuilder->MapType(arrayType));
  8647. }
  8648. }
  8649. else
  8650. {
  8651. auto typeInst = type->ToTypeInstance();
  8652. BfIRValue sizeValue;
  8653. BfIRType toType;
  8654. if (typeInst != NULL)
  8655. {
  8656. EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize);
  8657. sizeValue = GetConstValue(typeInst->mInstSize);
  8658. toType = mBfIRBuilder->MapTypeInstPtr(typeInst);
  8659. }
  8660. else
  8661. {
  8662. EmitAppendAlign(type->mAlign, type->mSize);
  8663. sizeValue = GetConstValue(type->mSize);
  8664. auto toPtrType = CreatePointerType(type);
  8665. toType = mBfIRBuilder->MapType(toPtrType);
  8666. }
  8667. auto curIdxVal = mBfIRBuilder->CreateLoad(appendIdxVal.mValue);
  8668. auto newIdxVal = mBfIRBuilder->CreateAdd(curIdxVal, sizeValue);
  8669. mBfIRBuilder->CreateStore(newIdxVal, appendIdxVal.mValue);
  8670. retTypeInstance = typeInst;
  8671. retValue = mBfIRBuilder->CreateIntToPtr(curIdxVal, toType);
  8672. }
  8673. if ((retTypeInstance != NULL) && (retTypeInstance->IsObject()))
  8674. {
  8675. mBfIRBuilder->PopulateType(retTypeInstance);
  8676. auto int8Type = mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8);
  8677. auto ptrType = mBfIRBuilder->GetPointerTo(int8Type);
  8678. auto ptrPtrType = mBfIRBuilder->GetPointerTo(ptrType);
  8679. auto curThis = GetThis();
  8680. BfIRValue newFlags;
  8681. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  8682. {
  8683. auto thisFlagsPtr = mBfIRBuilder->CreateBitCast(curThis.mValue, ptrType);
  8684. auto thisFlags = mBfIRBuilder->CreateLoad(thisFlagsPtr);
  8685. auto maskedThisFlags = mBfIRBuilder->CreateAnd(thisFlags, GetConstValue8(BfObjectFlag_StackAlloc)); // Take 'stack' flag from 'this'
  8686. newFlags = mBfIRBuilder->CreateOr(maskedThisFlags, GetConstValue8(BfObjectFlag_AppendAlloc));
  8687. }
  8688. auto vObjectAddr = mBfIRBuilder->CreateInBoundsGEP(retValue, 0, 0);
  8689. auto vDataRef = CreateClassVDataGlobal(retTypeInstance);
  8690. auto destAddr = mBfIRBuilder->CreateBitCast(vObjectAddr, ptrPtrType);
  8691. auto srcVal = mBfIRBuilder->CreateBitCast(vDataRef, ptrType);
  8692. mBfIRBuilder->CreateStore(srcVal, destAddr);
  8693. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  8694. {
  8695. auto flagsPtr = mBfIRBuilder->CreateBitCast(destAddr, ptrType);
  8696. mBfIRBuilder->CreateStore(newFlags, flagsPtr);
  8697. }
  8698. }
  8699. if (appendSizeValue)
  8700. {
  8701. EmitAppendAlign(appendAllocAlign);
  8702. auto curIdxVal = mBfIRBuilder->CreateLoad(appendIdxVal.mValue);
  8703. auto newIdxVal = mBfIRBuilder->CreateAdd(curIdxVal, appendSizeValue);
  8704. mBfIRBuilder->CreateStore(newIdxVal, appendIdxVal.mValue);
  8705. }
  8706. return retValue;
  8707. }
  8708. bool BfModule::IsOptimized()
  8709. {
  8710. if (mProject == NULL)
  8711. return false;
  8712. if (mIsComptimeModule)
  8713. return false;
  8714. int optLevel = GetModuleOptions().mOptLevel;
  8715. return (optLevel >= BfOptLevel_O1) && (optLevel <= BfOptLevel_O3);
  8716. }
  8717. bool BfModule::IsTargetingBeefBackend()
  8718. {
  8719. if (mProject == NULL)
  8720. return true;
  8721. return GetModuleOptions().mOptLevel == BfOptLevel_OgPlus;
  8722. }
  8723. bool BfModule::WantsLifetimes()
  8724. {
  8725. if (mBfIRBuilder->mIgnoreWrites)
  8726. return false;
  8727. if ((mIsComptimeModule) && (mBfIRBuilder->HasDebugLocation()))
  8728. return true;
  8729. else if (mProject == NULL)
  8730. return false;
  8731. return GetModuleOptions().mOptLevel == BfOptLevel_OgPlus;
  8732. }
  8733. bool BfModule::HasCompiledOutput()
  8734. {
  8735. return (!mSystem->mIsResolveOnly) && (mGeneratesCode) && (!mIsComptimeModule);
  8736. }
  8737. bool BfModule::HasExecutedOutput()
  8738. {
  8739. return ((!mSystem->mIsResolveOnly) && (mGeneratesCode)) || (mIsComptimeModule);
  8740. }
  8741. // We will skip the object access check for any occurrences of this value
  8742. void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
  8743. {
  8744. if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
  8745. return;
  8746. if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule))
  8747. return;
  8748. if ((typedVal.mValue.mFlags & BfIRValueFlags_Value) == 0)
  8749. return;
  8750. mCurMethodState->mSkipObjectAccessChecks.Add(typedVal.mValue.mId);
  8751. }
  8752. void BfModule::EmitObjectAccessCheck(BfTypedValue typedVal)
  8753. {
  8754. if ((mBfIRBuilder->mIgnoreWrites) || (!typedVal.mType->IsObjectOrInterface()) || (mCurMethodState == NULL) || (mCurMethodState->mIgnoreObjectAccessCheck))
  8755. return;
  8756. if ((!mCompiler->mOptions.mObjectHasDebugFlags) || (mIsComptimeModule))
  8757. return;
  8758. if (typedVal.mValue.IsConst())
  8759. {
  8760. int stringIdx = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
  8761. if (stringIdx != -1)
  8762. return;
  8763. auto constant = mBfIRBuilder->GetConstant(typedVal.mValue);
  8764. if (constant->mTypeCode == BfTypeCode_NullPtr)
  8765. return;
  8766. if (constant->mConstType == BfConstType_BitCastNull)
  8767. return;
  8768. }
  8769. bool emitObjectAccessCheck = mCompiler->mOptions.mEmitObjectAccessCheck;
  8770. auto typeOptions = GetTypeOptions();
  8771. if (typeOptions != NULL)
  8772. emitObjectAccessCheck = typeOptions->Apply(emitObjectAccessCheck, BfOptionFlags_EmitObjectAccessCheck);
  8773. if (!emitObjectAccessCheck)
  8774. return;
  8775. if ((typedVal.mValue.mFlags & BfIRValueFlags_Value) != 0)
  8776. {
  8777. if (mCurMethodState->mSkipObjectAccessChecks.Contains(typedVal.mValue.mId))
  8778. return;
  8779. }
  8780. if (typedVal.IsAddr())
  8781. typedVal = LoadValue(typedVal);
  8782. mBfIRBuilder->CreateObjectAccessCheck(typedVal.mValue, !IsOptimized());
  8783. }
  8784. void BfModule::EmitEnsureInstructionAt()
  8785. {
  8786. if (mBfIRBuilder->mIgnoreWrites)
  8787. return;
  8788. if (mIsComptimeModule)
  8789. {
  8790. // Always add
  8791. }
  8792. else if ((mProject == NULL) || (!mHasFullDebugInfo) || (IsOptimized()) || (mCompiler->mOptions.mOmitDebugHelpers))
  8793. return;
  8794. mBfIRBuilder->CreateEnsureInstructionAt();
  8795. }
  8796. void BfModule::EmitDynamicCastCheck(const BfTypedValue& targetValue, BfType* targetType, BfIRBlock trueBlock, BfIRBlock falseBlock, bool nullSucceeds)
  8797. {
  8798. if (mBfIRBuilder->mIgnoreWrites)
  8799. return; // Nothing needed here
  8800. auto irb = mBfIRBuilder;
  8801. auto checkBB = irb->CreateBlock("as.check");
  8802. auto isNull = irb->CreateIsNull(targetValue.mValue);
  8803. mBfIRBuilder->CreateCondBr(isNull, nullSucceeds ? trueBlock : falseBlock, checkBB);
  8804. if (mIsComptimeModule)
  8805. {
  8806. AddBasicBlock(checkBB);
  8807. auto callResult = mBfIRBuilder->Comptime_DynamicCastCheck(targetValue.mValue, targetType->mTypeId, mBfIRBuilder->MapType(mContext->mBfObjectType));
  8808. auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult, GetDefaultValue(mContext->mBfObjectType));
  8809. irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
  8810. return;
  8811. }
  8812. auto intType = GetPrimitiveType(BfTypeCode_IntPtr);
  8813. auto intPtrType = CreatePointerType(intType);
  8814. auto intPtrPtrType = CreatePointerType(intPtrType);
  8815. auto int32Type = GetPrimitiveType(BfTypeCode_Int32);
  8816. auto int32PtrType = CreatePointerType(int32Type);
  8817. auto typeTypeInstance = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef)->ToTypeInstance();
  8818. if (mCompiler->mOptions.mAllowHotSwapping)
  8819. {
  8820. BfExprEvaluator exprEvaluator(this);
  8821. AddBasicBlock(checkBB);
  8822. auto objectParam = mBfIRBuilder->CreateBitCast(targetValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
  8823. auto moduleMethodInstance = GetMethodByName(mContext->mBfObjectType, targetType->IsInterface() ? "DynamicCastToInterface" : "DynamicCastToTypeId");
  8824. SizedArray<BfIRValue, 4> irArgs;
  8825. irArgs.push_back(objectParam);
  8826. irArgs.push_back(GetConstValue32(targetType->mTypeId));
  8827. auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
  8828. auto cmpResult = mBfIRBuilder->CreateCmpNE(callResult.mValue, GetDefaultValue(callResult.mType));
  8829. irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
  8830. }
  8831. else
  8832. {
  8833. AddBasicBlock(checkBB);
  8834. BfIRValue vDataPtr = irb->CreateBitCast(targetValue.mValue, irb->MapType(intPtrType));
  8835. vDataPtr = irb->CreateLoad(vDataPtr);
  8836. if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsComptimeModule))
  8837. vDataPtr = irb->CreateAnd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, (uint64)~0xFFULL));
  8838. if (targetType->IsInterface())
  8839. {
  8840. auto targetTypeInst = targetType->ToTypeInstance();
  8841. AddDependency(targetType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
  8842. // Skip past mType, but since a 'GetDynCastVDataCount()' data is included in the sSlotOfs, we need to remove that
  8843. //int inheritanceIdOfs = mSystem->mPtrSize - (mCompiler->GetDynCastVDataCount())*4;
  8844. //vDataPtr = irb->CreateAdd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, inheritanceIdOfs));
  8845. vDataPtr = irb->CreateAdd(vDataPtr, irb->GetConfigConst(BfIRConfigConst_DynSlotOfs, BfTypeCode_IntPtr));
  8846. BfIRValue slotOfs = GetInterfaceSlotNum(targetType->ToTypeInstance());
  8847. BfIRValue slotByteOfs = irb->CreateMul(slotOfs, irb->CreateConst(BfTypeCode_Int32, 4));
  8848. slotByteOfs = irb->CreateNumericCast(slotByteOfs, false, BfTypeCode_IntPtr);
  8849. vDataPtr = irb->CreateAdd(vDataPtr, slotByteOfs);
  8850. vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType));
  8851. BfIRValue typeId = irb->CreateLoad(vDataPtr);
  8852. BfIRValue cmpResult = irb->CreateCmpEQ(typeId, irb->CreateConst(BfTypeCode_Int32, targetType->mTypeId));
  8853. irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
  8854. }
  8855. else
  8856. {
  8857. if (!targetType->IsTypeInstance())
  8858. targetType = GetWrappedStructType(targetType);
  8859. AddDependency(targetType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
  8860. int inheritanceIdOfs = mSystem->mPtrSize;
  8861. vDataPtr = irb->CreateAdd(vDataPtr, irb->CreateConst(BfTypeCode_IntPtr, inheritanceIdOfs));
  8862. vDataPtr = irb->CreateIntToPtr(vDataPtr, irb->MapType(int32PtrType));
  8863. BfIRValue objInheritanceId = irb->CreateLoad(vDataPtr);
  8864. BfIRValue typeDataRef = CreateTypeDataRef(targetType);
  8865. BfIRValue typeInstDataRef = irb->CreateBitCast(typeDataRef, irb->MapType(typeTypeInstance, BfIRPopulateType_Full));
  8866. auto fieldInst = &typeTypeInstance->mFieldInstances[9];
  8867. BF_ASSERT(fieldInst->GetFieldDef()->mName == "mInheritanceId");
  8868. BfIRValue gepValue = irb->CreateInBoundsGEP(typeInstDataRef, 0, fieldInst->mDataIdx);
  8869. BfIRValue wantInheritanceId = irb->CreateLoad(gepValue);
  8870. fieldInst = &typeTypeInstance->mFieldInstances[10];
  8871. BF_ASSERT(fieldInst->GetFieldDef()->mName == "mInheritanceCount");
  8872. gepValue = irb->CreateInBoundsGEP(typeInstDataRef, 0, fieldInst->mDataIdx);
  8873. BfIRValue inheritanceCount = irb->CreateLoad(gepValue);
  8874. BfIRValue idDiff = irb->CreateSub(objInheritanceId, wantInheritanceId);
  8875. BfIRValue cmpResult = irb->CreateCmpLTE(idDiff, inheritanceCount, false);
  8876. irb->CreateCondBr(cmpResult, trueBlock, falseBlock);
  8877. }
  8878. }
  8879. }
  8880. void BfModule::EmitDynamicCastCheck(BfTypedValue typedVal, BfType* type, bool allowNull)
  8881. {
  8882. if (mBfIRBuilder->mIgnoreWrites)
  8883. return;
  8884. bool emitDynamicCastCheck = mCompiler->mOptions.mEmitDynamicCastCheck;
  8885. auto typeOptions = GetTypeOptions();
  8886. if (typeOptions != NULL)
  8887. emitDynamicCastCheck = typeOptions->Apply(emitDynamicCastCheck, BfOptionFlags_EmitDynamicCastCheck);
  8888. if (emitDynamicCastCheck)
  8889. {
  8890. int wantTypeId = 0;
  8891. if (!type->IsGenericParam())
  8892. wantTypeId = type->mTypeId;
  8893. BfIRBlock failBlock = mBfIRBuilder->CreateBlock("dynFail");
  8894. BfIRBlock endBlock = mBfIRBuilder->CreateBlock("dynEnd");
  8895. EmitDynamicCastCheck(typedVal, type, endBlock, failBlock, allowNull ? true : false);
  8896. AddBasicBlock(failBlock);
  8897. if (mIsComptimeModule)
  8898. {
  8899. mBfIRBuilder->Comptime_Error(CeErrorKind_ObjectDynCheckFailed);
  8900. }
  8901. else
  8902. {
  8903. SizedArray<BfIRValue, 8> llvmArgs;
  8904. auto bitAddr = mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
  8905. llvmArgs.push_back(bitAddr);
  8906. llvmArgs.push_back(GetConstValue32(wantTypeId));
  8907. auto objDynCheck = GetInternalMethod("ObjectDynCheckFailed");
  8908. BF_ASSERT(objDynCheck);
  8909. if (objDynCheck)
  8910. {
  8911. auto callInst = mBfIRBuilder->CreateCall(objDynCheck.mFunc, llvmArgs);
  8912. }
  8913. }
  8914. mBfIRBuilder->CreateBr(endBlock);
  8915. AddBasicBlock(endBlock);
  8916. }
  8917. }
  8918. BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, const BfAllocTarget& allocTarget, BfCastFlags castFlags)
  8919. {
  8920. bool callDtor = (castFlags & BfCastFlags_NoBoxDtor) == 0;
  8921. bool wantConst = ((castFlags & BfCastFlags_WantsConst) != 0) && (typedVal.mValue.IsConst());
  8922. if ((mBfIRBuilder->mIgnoreWrites) && (!wantConst))
  8923. {
  8924. if (toType == mContext->mBfObjectType)
  8925. return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType);
  8926. if (toType->IsBoxed())
  8927. {
  8928. BfBoxedType* boxedType = (BfBoxedType*)toType;
  8929. if (boxedType->mElementType->IsGenericParam())
  8930. {
  8931. if (typedVal.mType == boxedType->mElementType)
  8932. return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType);
  8933. else
  8934. return BfTypedValue();
  8935. }
  8936. }
  8937. }
  8938. BP_ZONE("BoxValue");
  8939. BfTypeInstance* fromStructTypeInstance = typedVal.mType->ToTypeInstance();
  8940. if (typedVal.mType->IsNullable())
  8941. {
  8942. typedVal = MakeAddressable(typedVal);
  8943. auto innerType = typedVal.mType->GetUnderlyingType();
  8944. if (!innerType->IsValueType())
  8945. {
  8946. if (!mIgnoreErrors)
  8947. Fail("Only value types can be boxed", srcNode);
  8948. return BfTypedValue();
  8949. }
  8950. auto boxedType = CreateBoxedType(innerType);
  8951. auto resultType = toType;
  8952. if (resultType == NULL)
  8953. resultType = boxedType;
  8954. if (mBfIRBuilder->mIgnoreWrites)
  8955. return BfTypedValue(mBfIRBuilder->GetFakeVal(), resultType);
  8956. auto prevBB = mBfIRBuilder->GetInsertBlock();
  8957. auto boxBB = mBfIRBuilder->CreateBlock("boxedN.notNull");
  8958. auto endBB = mBfIRBuilder->CreateBlock("boxedN.end");
  8959. mBfIRBuilder->PopulateType(typedVal.mType);
  8960. auto hasValueAddr = mBfIRBuilder->CreateInBoundsGEP(typedVal.mValue, 0, innerType->IsValuelessType() ? 1 : 2); // has_value
  8961. auto hasValue = mBfIRBuilder->CreateLoad(hasValueAddr);
  8962. mBfIRBuilder->CreateCondBr(hasValue, boxBB, endBB);
  8963. AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
  8964. mBfIRBuilder->AddBlock(boxBB);
  8965. mBfIRBuilder->SetInsertPoint(boxBB);
  8966. BfScopeData newScope;
  8967. newScope.mOuterIsConditional = true;
  8968. mCurMethodState->AddScope(&newScope);
  8969. NewScopeState();
  8970. BfIRValue nullableValueAddr;
  8971. BfIRValue loadedVal;
  8972. if (innerType->IsValuelessType())
  8973. {
  8974. loadedVal = mBfIRBuilder->GetFakeVal();
  8975. }
  8976. else
  8977. {
  8978. nullableValueAddr = mBfIRBuilder->CreateInBoundsGEP(typedVal.mValue, 0, 1); // value
  8979. loadedVal = mBfIRBuilder->CreateLoad(nullableValueAddr);
  8980. }
  8981. auto boxedVal = BoxValue(srcNode, BfTypedValue(loadedVal, fromStructTypeInstance->GetUnderlyingType()), resultType, allocTarget, callDtor ? BfCastFlags_None : BfCastFlags_NoBoxDtor);
  8982. RestoreScopeState();
  8983. if (!boxedVal)
  8984. return BfTypedValue();
  8985. mBfIRBuilder->CreateBr(endBB);
  8986. auto boxBBEnd = mBfIRBuilder->GetInsertBlock();
  8987. mBfIRBuilder->AddBlock(endBB);
  8988. mBfIRBuilder->SetInsertPoint(endBB);
  8989. auto phi = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(resultType), 2);
  8990. mBfIRBuilder->AddPhiIncoming(phi, boxedVal.mValue, boxBBEnd);
  8991. mBfIRBuilder->AddPhiIncoming(phi, GetDefaultValue(resultType), prevBB);
  8992. return BfTypedValue(phi, resultType);
  8993. }
  8994. bool alreadyCheckedCast = false;
  8995. BfTypeInstance* toTypeInstance = NULL;
  8996. if (toType != NULL)
  8997. toTypeInstance = toType->ToTypeInstance();
  8998. bool isStructPtr = typedVal.mType->IsStructPtr();
  8999. if (fromStructTypeInstance == NULL)
  9000. {
  9001. auto primType = (BfPrimitiveType*)typedVal.mType;
  9002. if ((typedVal.mType->IsPointer()) && (toTypeInstance->IsInstanceOf(mCompiler->mIHashableTypeDef)))
  9003. {
  9004. // Can always do IHashable
  9005. alreadyCheckedCast = true;
  9006. }
  9007. if ((!typedVal.mType->IsPointer()) || (toTypeInstance == mContext->mBfObjectType))
  9008. fromStructTypeInstance = GetWrappedStructType(typedVal.mType);
  9009. else
  9010. {
  9011. auto checkStructTypeInstance = GetWrappedStructType(typedVal.mType);
  9012. if (checkStructTypeInstance == toType->GetUnderlyingType())
  9013. fromStructTypeInstance = checkStructTypeInstance;
  9014. }
  9015. if (isStructPtr)
  9016. {
  9017. if ((toTypeInstance != NULL) && (fromStructTypeInstance != NULL) && (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
  9018. alreadyCheckedCast = true;
  9019. fromStructTypeInstance = typedVal.mType->GetUnderlyingType()->ToTypeInstance();
  9020. }
  9021. if ((fromStructTypeInstance == NULL) && (alreadyCheckedCast))
  9022. fromStructTypeInstance = GetWrappedStructType(typedVal.mType);
  9023. }
  9024. if (fromStructTypeInstance == NULL)
  9025. return BfTypedValue();
  9026. // Need to box it
  9027. bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed());
  9028. if ((toType == NULL) || (toType == mContext->mBfObjectType) || (isBoxedType) || (alreadyCheckedCast) || (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
  9029. {
  9030. if ((mBfIRBuilder->mIgnoreWrites) && (!wantConst))
  9031. return BfTypedValue(mBfIRBuilder->GetFakeVal(), (toType != NULL) ? toType : CreateBoxedType(typedVal.mType));
  9032. auto boxedType = CreateBoxedType(typedVal.mType);
  9033. mBfIRBuilder->PopulateType(boxedType);
  9034. if (wantConst)
  9035. return BfTypedValue(mBfIRBuilder->CreateConstBox(typedVal.mValue, mBfIRBuilder->MapType(boxedType)), boxedType);
  9036. AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
  9037. auto allocaInst = AllocFromType(boxedType, allocTarget, BfIRValue(), BfIRValue(), 0, callDtor ? BfAllocFlags_None : BfAllocFlags_NoDtorCall);
  9038. BfTypedValue boxedTypedValue(allocaInst, boxedType);
  9039. mBfIRBuilder->SetName(allocaInst, "boxed." + fromStructTypeInstance->mTypeDef->mName->ToString());
  9040. if (boxedType->IsUnspecializedType())
  9041. {
  9042. BF_ASSERT((srcNode == NULL) || (mCurMethodInstance->mIsUnspecialized));
  9043. }
  9044. else
  9045. {
  9046. PopulateType(fromStructTypeInstance);
  9047. if (!fromStructTypeInstance->IsValuelessType())
  9048. {
  9049. typedVal = LoadValue(typedVal);
  9050. auto valPtr = mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 1);
  9051. if ((typedVal.mType != fromStructTypeInstance) && (!isStructPtr))
  9052. {
  9053. auto ptrType = CreatePointerType(typedVal.mType);
  9054. valPtr = mBfIRBuilder->CreateBitCast(valPtr, mBfIRBuilder->MapType(ptrType));
  9055. }
  9056. if (typedVal.IsSplat())
  9057. {
  9058. AggregateSplatIntoAddr(typedVal, valPtr);
  9059. }
  9060. else
  9061. mBfIRBuilder->CreateStore(typedVal.mValue, valPtr, typedVal.mType->mAlign);
  9062. }
  9063. }
  9064. if (toType == NULL)
  9065. {
  9066. return BfTypedValue(allocaInst, boxedType);
  9067. }
  9068. else
  9069. {
  9070. auto castedValue = mBfIRBuilder->CreateBitCast(allocaInst, mBfIRBuilder->MapType(toType));
  9071. return BfTypedValue(castedValue, toType);
  9072. }
  9073. }
  9074. return BfTypedValue();
  9075. }
  9076. bool BfModule::GetBasePropertyDef(BfPropertyDef*& propDef, BfTypeInstance*& typeInst)
  9077. {
  9078. BfTypeInstance* checkTypeInst = typeInst;
  9079. while (checkTypeInst != NULL)
  9080. {
  9081. for (auto checkProp : checkTypeInst->mTypeDef->mProperties)
  9082. {
  9083. if (checkProp->mName == propDef->mName)
  9084. {
  9085. auto checkPropDeclaration = BfNodeDynCast<BfPropertyDeclaration>(checkProp->mFieldDeclaration);
  9086. if ((checkPropDeclaration == NULL) || (checkPropDeclaration->mVirtualSpecifier == NULL) || (checkPropDeclaration->mVirtualSpecifier->GetToken() == BfToken_Virtual))
  9087. {
  9088. propDef = checkProp;
  9089. typeInst = checkTypeInst;
  9090. return true;
  9091. }
  9092. }
  9093. }
  9094. checkTypeInst = checkTypeInst->mBaseType;
  9095. }
  9096. return false;
  9097. }
  9098. BfMethodInstance* BfModule::GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName)
  9099. {
  9100. if (!typeInstance->mResolvingVarField)
  9101. {
  9102. if (!typeInstance->DefineStateAllowsStaticMethods())
  9103. PopulateType(typeInstance, BfPopulateType_AllowStaticMethods);
  9104. }
  9105. else
  9106. {
  9107. if (methodIdx >= (int)typeInstance->mMethodInstanceGroups.size())
  9108. {
  9109. AssertErrorState();
  9110. return NULL;
  9111. }
  9112. }
  9113. if (assertName != NULL)
  9114. {
  9115. BF_ASSERT(typeInstance->mTypeDef->mMethods[methodIdx]->mName == assertName);
  9116. }
  9117. if (methodIdx >= typeInstance->mMethodInstanceGroups.mSize)
  9118. {
  9119. if (mCompiler->EnsureCeUnpaused(typeInstance))
  9120. {
  9121. BF_FATAL("OOB in GetRawMethodInstanceAtIdx");
  9122. }
  9123. return NULL;
  9124. }
  9125. auto& methodGroup = typeInstance->mMethodInstanceGroups[methodIdx];
  9126. if (methodGroup.mDefault == NULL)
  9127. {
  9128. if (!mCompiler->mIsResolveOnly)
  9129. {
  9130. // Get it from the owning module so we don't create a reference prematurely...
  9131. auto declModule = typeInstance->mModule;
  9132. if ((typeInstance->mGenericTypeInfo != NULL) && (typeInstance->mGenericTypeInfo->mFinishedGenericParams) && (methodGroup.mOnDemandKind == BfMethodOnDemandKind_NotSet))
  9133. {
  9134. methodGroup.mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
  9135. if (!declModule->mIsScratchModule)
  9136. declModule->mOnDemandMethodCount++;
  9137. }
  9138. BF_ASSERT((methodGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
  9139. (typeInstance->mTypeFailed) || (typeInstance->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted));
  9140. if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl))
  9141. methodGroup.mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
  9142. BfGetMethodInstanceFlags useFlags = (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_Unreified);
  9143. return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), useFlags).mMethodInstance;
  9144. }
  9145. else
  9146. {
  9147. auto declModule = typeInstance->mModule;
  9148. BfGetMethodInstanceFlags useFlags = (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_UnspecializedPass);
  9149. return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), useFlags).mMethodInstance;
  9150. }
  9151. }
  9152. auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
  9153. //TODO: Why did we have this adding methods to the work list? This should only happen if we actually attempt to USE the method, which should
  9154. // be from a call to the NON-raw version
  9155. // if (!methodInstance->mMethodInstanceGroup->IsImplemented())
  9156. // {
  9157. // methodInstance->mIsReified = mIsReified;
  9158. // if (methodInstance->mMethodProcessRequest == NULL)
  9159. // typeInstance->mModule->AddMethodToWorkList(methodInstance);
  9160. // }
  9161. return methodInstance;
  9162. }
  9163. BfMethodInstance* BfModule::GetRawMethodInstance(BfTypeInstance* typeInstance, BfMethodDef* methodDef)
  9164. {
  9165. if (methodDef->mIsLocalMethod)
  9166. {
  9167. return GetMethodInstance(typeInstance, methodDef, BfTypeVector()).mMethodInstance;
  9168. }
  9169. return GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx, NULL);
  9170. }
  9171. BfMethodInstance* BfModule::GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase, bool allowMixin)
  9172. {
  9173. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  9174. while (typeInstance != NULL)
  9175. {
  9176. typeInstance->mTypeDef->PopulateMemberSets();
  9177. BfMemberSetEntry* entry = NULL;
  9178. BfMethodDef* methodDef = NULL;
  9179. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(methodName, &entry))
  9180. methodDef = (BfMethodDef*)entry->mMemberDef;
  9181. while (methodDef != NULL)
  9182. {
  9183. if (((allowMixin) || (methodDef->mMethodType != BfMethodType_Mixin)) &&
  9184. (methodDef->mGenericParams.size() == 0) &&
  9185. ((paramCount == -1) || (paramCount == (int)methodDef->mParams.size())))
  9186. return GetRawMethodInstance(typeInstance, methodDef);
  9187. methodDef = methodDef->mNextWithSameName;
  9188. }
  9189. if (!checkBase)
  9190. break;
  9191. typeInstance = typeInstance->mBaseType;
  9192. }
  9193. return NULL;
  9194. }
  9195. BfMethodInstance* BfModule::GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType)
  9196. {
  9197. if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mMethodGenericArguments.size() != 0))
  9198. methodInstance = methodInstance->mMethodInstanceGroup->mDefault;
  9199. auto owner = methodInstance->mMethodInstanceGroup->mOwner;
  9200. if (!useUnspecializedType)
  9201. return methodInstance;
  9202. if (!owner->IsGenericTypeInstance())
  9203. return methodInstance;
  9204. if ((owner->IsDelegateFromTypeRef()) ||
  9205. (owner->IsFunctionFromTypeRef()) ||
  9206. (owner->IsTuple()))
  9207. {
  9208. return methodInstance;
  9209. }
  9210. auto genericType = (BfTypeInstance*)owner;
  9211. if ((genericType->IsUnspecializedType()) && (!genericType->IsUnspecializedTypeVariation()))
  9212. return methodInstance;
  9213. if (methodInstance->mMethodDef->mIsLocalMethod)
  9214. return methodInstance;
  9215. if (methodInstance->mMethodDef->mDeclaringType->IsEmitted())
  9216. return methodInstance;
  9217. auto unspecializedType = ResolveTypeDef(genericType->mTypeDef->GetDefinition());
  9218. if (unspecializedType == NULL)
  9219. {
  9220. AssertErrorState();
  9221. return methodInstance;
  9222. }
  9223. if (unspecializedType == NULL)
  9224. return methodInstance;
  9225. auto unspecializedTypeInst = unspecializedType->ToTypeInstance();
  9226. return GetRawMethodInstanceAtIdx(unspecializedTypeInst, methodInstance->mMethodDef->mIdx);
  9227. }
  9228. int BfModule::GetGenericParamAndReturnCount(BfMethodInstance* methodInstance)
  9229. {
  9230. int genericCount = 0;
  9231. auto unspecializedMethodInstance = GetUnspecializedMethodInstance(methodInstance);
  9232. for (int paramIdx = 0; paramIdx < unspecializedMethodInstance->GetParamCount(); paramIdx++)
  9233. {
  9234. auto param = unspecializedMethodInstance->GetParamType(paramIdx);
  9235. if (param->IsGenericParam())
  9236. genericCount++;
  9237. }
  9238. if (unspecializedMethodInstance->mReturnType->IsGenericParam())
  9239. genericCount++;
  9240. return genericCount;
  9241. }
  9242. BfModule* BfModule::GetSpecializedMethodModule(const SizedArrayImpl<BfProject*>& projectList)
  9243. {
  9244. BF_ASSERT(!mIsScratchModule);
  9245. BF_ASSERT(mIsReified);
  9246. BfModule* mainModule = this;
  9247. if (mParentModule != NULL)
  9248. mainModule = mParentModule;
  9249. BfModule* specModule = NULL;
  9250. BfModule** specModulePtr = NULL;
  9251. if (mainModule->mSpecializedMethodModules.TryGetValueWith(projectList, &specModulePtr))
  9252. {
  9253. return *specModulePtr;
  9254. }
  9255. else
  9256. {
  9257. String specModuleName = mModuleName;
  9258. for (auto bfProject : projectList)
  9259. {
  9260. specModuleName += StrFormat("@%s", bfProject->mSafeName.c_str());
  9261. }
  9262. specModule = new BfModule(mContext, specModuleName);
  9263. specModule->mProject = mainModule->mProject;
  9264. specModule->mParentModule = mainModule;
  9265. specModule->mIsSpecializedMethodModuleRoot = true;
  9266. specModule->Init();
  9267. Array<BfProject*> projList;
  9268. for (auto project : projectList)
  9269. projList.Add(project);
  9270. mainModule->mSpecializedMethodModules[projList] = specModule;
  9271. }
  9272. return specModule;
  9273. }
  9274. BfIRValue BfModule::CreateFunctionFrom(BfMethodInstance* methodInstance, bool tryExisting, bool isInlined)
  9275. {
  9276. if (IsSkippingExtraResolveChecks())
  9277. return BfIRValue();
  9278. if (methodInstance->mMethodInstanceGroup->mOwner->IsInterface())
  9279. {
  9280. //BF_ASSERT(!methodInstance->mIRFunction);
  9281. return BfIRValue();
  9282. }
  9283. auto methodDef = methodInstance->mMethodDef;
  9284. StringT<4096> methodName;
  9285. BfMangler::Mangle(methodName, mCompiler->GetMangleKind(), methodInstance);
  9286. if (isInlined != methodInstance->mAlwaysInline)
  9287. {
  9288. if (isInlined)
  9289. methodName += "__INLINE";
  9290. else
  9291. methodName += "__NOINLINE";
  9292. }
  9293. if (tryExisting)
  9294. {
  9295. auto func = mBfIRBuilder->GetFunction(methodName);
  9296. if (func)
  9297. return func;
  9298. }
  9299. auto intrinsic = GetIntrinsic(methodInstance);
  9300. if (intrinsic)
  9301. return intrinsic;
  9302. if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
  9303. {
  9304. return CreateDllImportGlobalVar(methodInstance, false);
  9305. }
  9306. BfIRType returnType;
  9307. SizedArray<BfIRType, 8> paramTypes;
  9308. methodInstance->GetIRFunctionInfo(this, returnType, paramTypes);
  9309. auto funcType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs());
  9310. auto func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName);
  9311. auto callingConv = GetIRCallingConvention(methodInstance);
  9312. if (callingConv != BfIRCallingConv_CDecl)
  9313. mBfIRBuilder->SetFuncCallingConv(func, callingConv);
  9314. SetupIRMethod(methodInstance, func, isInlined);
  9315. // auto srcModule = methodInstance->GetOwner()->GetModule();
  9316. // if ((srcModule != NULL) && (srcModule->mProject != mProject))
  9317. // {
  9318. // if (srcModule->mProject->mTargetType == BfTargetType_BeefDynLib)
  9319. // {
  9320. // mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllImport);
  9321. // }
  9322. // }
  9323. return func;
  9324. }
  9325. BfModuleMethodInstance BfModule::GetMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName, BfGetMethodInstanceFlags flags)
  9326. {
  9327. if (assertName != NULL)
  9328. {
  9329. BF_ASSERT(typeInstance->mTypeDef->mMethods[methodIdx]->mName == assertName);
  9330. }
  9331. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  9332. auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
  9333. BfMethodDef* methodDef = NULL;
  9334. BfTypeInstance* foreignType = NULL;
  9335. if (methodInstance != NULL)
  9336. {
  9337. methodDef = methodInstance->mMethodDef;
  9338. if (methodInstance->mMethodInfoEx != NULL)
  9339. foreignType = methodInstance->mMethodInfoEx->mForeignType;
  9340. }
  9341. if ((methodInstance != NULL) && (mIsReified) && (!methodInstance->mIsReified))
  9342. {
  9343. // Can't use it, not reified
  9344. methodInstance = NULL;
  9345. }
  9346. if ((methodInstance != NULL) && (mBfIRBuilder != NULL) && (mBfIRBuilder->mIgnoreWrites) &&
  9347. (methodInstance->mMethodInstanceGroup->IsImplemented()))
  9348. {
  9349. BfIRFunction func(mBfIRBuilder->GetFakeVal());
  9350. return BfModuleMethodInstance(methodInstance, func);
  9351. }
  9352. if (foreignType != NULL)
  9353. return GetMethodInstance(typeInstance, methodDef, BfTypeVector(), (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ForeignMethodDef), foreignType);
  9354. return GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), flags);
  9355. }
  9356. BfModuleMethodInstance BfModule::GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase)
  9357. {
  9358. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  9359. while (typeInstance != NULL)
  9360. {
  9361. typeInstance->mTypeDef->PopulateMemberSets();
  9362. BfMemberSetEntry* entry = NULL;
  9363. BfMethodDef* methodDef = NULL;
  9364. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(methodName, &entry))
  9365. methodDef = (BfMethodDef*)entry->mMemberDef;
  9366. while (methodDef != NULL)
  9367. {
  9368. if ((methodDef->mMethodType != BfMethodType_Mixin) &&
  9369. (methodDef->mGenericParams.size() == 0) &&
  9370. ((paramCount == -1) || (paramCount == (int)methodDef->mParams.size())))
  9371. return GetMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
  9372. methodDef = methodDef->mNextWithSameName;
  9373. }
  9374. if (!checkBase)
  9375. break;
  9376. typeInstance = typeInstance->mBaseType;
  9377. }
  9378. return BfModuleMethodInstance();
  9379. }
  9380. BfModuleMethodInstance BfModule::GetMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, const Array<BfType*>& paramTypes, bool checkBase)
  9381. {
  9382. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  9383. while (typeInstance != NULL)
  9384. {
  9385. typeInstance->mTypeDef->PopulateMemberSets();
  9386. BfMemberSetEntry* entry = NULL;
  9387. BfMethodDef* methodDef = NULL;
  9388. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(methodName, &entry))
  9389. methodDef = (BfMethodDef*)entry->mMemberDef;
  9390. while (methodDef != NULL)
  9391. {
  9392. if ((methodDef->mMethodType != BfMethodType_Mixin) &&
  9393. (methodDef->mGenericParams.size() == 0) &&
  9394. (paramTypes.size() == methodDef->mParams.size()))
  9395. {
  9396. auto moduleMethodInstance = GetMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
  9397. if (moduleMethodInstance.mMethodInstance != NULL)
  9398. {
  9399. bool matches = true;
  9400. for (int paramIdx = 0; paramIdx < (int)paramTypes.size(); paramIdx++)
  9401. {
  9402. if (moduleMethodInstance.mMethodInstance->GetParamType(paramIdx) != paramTypes[paramIdx])
  9403. matches = false;
  9404. }
  9405. if (matches)
  9406. return moduleMethodInstance;
  9407. }
  9408. }
  9409. methodDef = methodDef->mNextWithSameName;
  9410. }
  9411. if (!checkBase)
  9412. break;
  9413. typeInstance = typeInstance->mBaseType;
  9414. }
  9415. return BfModuleMethodInstance();
  9416. }
  9417. BfModuleMethodInstance BfModule::GetInternalMethod(const StringImpl& methodName, int paramCount)
  9418. {
  9419. auto internalType = ResolveTypeDef(mCompiler->mInternalTypeDef);
  9420. PopulateType(internalType);
  9421. auto moduleMethodInstance = GetMethodByName(internalType->ToTypeInstance(), methodName, paramCount);
  9422. if (!moduleMethodInstance)
  9423. {
  9424. Fail(StrFormat("Failed to find System.Internal method '%s'", methodName.c_str()));
  9425. }
  9426. return moduleMethodInstance;
  9427. }
  9428. BfOperatorInfo* BfModule::GetOperatorInfo(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef)
  9429. {
  9430. while (operatorDef->mIdx >= typeInstance->mOperatorInfo.size())
  9431. typeInstance->mOperatorInfo.Add(NULL);
  9432. if (typeInstance->mOperatorInfo[operatorDef->mIdx] == NULL)
  9433. {
  9434. SetAndRestoreValue<bool> ignoreErrors(mIgnoreErrors, true);
  9435. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  9436. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
  9437. BfTypeState typeState;
  9438. typeState.mType = typeInstance;
  9439. typeState.mCurTypeDef = operatorDef->mDeclaringType;
  9440. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  9441. BfOperatorInfo* operatorInfo = new BfOperatorInfo();
  9442. if (operatorDef->mReturnTypeRef != NULL)
  9443. operatorInfo->mReturnType = ResolveTypeRef(operatorDef->mReturnTypeRef, BfPopulateType_Identity);
  9444. if (operatorDef->mParams.size() >= 1)
  9445. operatorInfo->mLHSType = ResolveTypeRef(operatorDef->mParams[0]->mTypeRef, BfPopulateType_Identity);
  9446. if (operatorDef->mParams.size() >= 2)
  9447. operatorInfo->mRHSType = ResolveTypeRef(operatorDef->mParams[1]->mTypeRef, BfPopulateType_Identity);
  9448. typeInstance->mOperatorInfo[operatorDef->mIdx] = operatorInfo;
  9449. }
  9450. return typeInstance->mOperatorInfo[operatorDef->mIdx];
  9451. }
  9452. BfType* BfModule::CheckOperator(BfTypeInstance* typeInstance, BfOperatorDef* operatorDef, const BfTypedValue& lhs, const BfTypedValue& rhs)
  9453. {
  9454. auto operatorInfo = GetOperatorInfo(typeInstance, operatorDef);
  9455. if (operatorInfo == NULL)
  9456. return NULL;
  9457. if (operatorInfo->mReturnType == NULL)
  9458. return NULL;
  9459. auto castFlags = BfCastFlags_IsConstraintCheck;
  9460. if (operatorDef->mOperatorDeclaration->mIsConvOperator)
  9461. castFlags = (BfCastFlags)(castFlags | BfCastFlags_NoConversionOperator);
  9462. if (lhs)
  9463. {
  9464. if (operatorInfo->mLHSType == NULL)
  9465. return NULL;
  9466. if (!CanCast(lhs, operatorInfo->mLHSType, castFlags))
  9467. return NULL;
  9468. }
  9469. if (rhs)
  9470. {
  9471. if (operatorInfo->mRHSType == NULL)
  9472. return NULL;
  9473. if (!CanCast(rhs, operatorInfo->mRHSType, castFlags))
  9474. return NULL;
  9475. }
  9476. return operatorInfo->mReturnType;
  9477. }
  9478. bool BfModule::IsMethodImplementedAndReified(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase)
  9479. {
  9480. while (typeInstance != NULL)
  9481. {
  9482. typeInstance->mTypeDef->PopulateMemberSets();
  9483. BfMemberSetEntry* entry = NULL;
  9484. BfMethodDef* methodDef = NULL;
  9485. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(methodName, &entry))
  9486. methodDef = (BfMethodDef*)entry->mMemberDef;
  9487. while (methodDef != NULL)
  9488. {
  9489. if ((methodDef->mMethodType != BfMethodType_Mixin) &&
  9490. (methodDef->mGenericParams.size() == 0) &&
  9491. ((paramCount == -1) || (paramCount == (int)methodDef->mParams.size())))
  9492. {
  9493. auto& methodInstanceGroup = typeInstance->mMethodInstanceGroups[methodDef->mIdx];
  9494. if (!methodInstanceGroup.IsImplemented())
  9495. return false;
  9496. if (methodInstanceGroup.mDefault == NULL)
  9497. return false;
  9498. return methodInstanceGroup.mDefault->mIsReified;
  9499. }
  9500. methodDef = methodDef->mNextWithSameName;
  9501. }
  9502. if (!checkBase)
  9503. break;
  9504. typeInstance = typeInstance->mBaseType;
  9505. }
  9506. return false;
  9507. }
  9508. bool BfModule::HasMixin(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase)
  9509. {
  9510. PopulateType(typeInstance, BfPopulateType_DataAndMethods);
  9511. while (typeInstance != NULL)
  9512. {
  9513. typeInstance->mTypeDef->PopulateMemberSets();
  9514. BfMemberSetEntry* entry = NULL;
  9515. BfMethodDef* methodDef = NULL;
  9516. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(methodName, &entry))
  9517. methodDef = (BfMethodDef*)entry->mMemberDef;
  9518. while (methodDef != NULL)
  9519. {
  9520. if ((methodDef->mMethodType == BfMethodType_Mixin) &&
  9521. ((paramCount == -1) || (paramCount == (int)methodDef->mParams.size())))
  9522. return true;
  9523. methodDef = methodDef->mNextWithSameName;
  9524. }
  9525. if (!checkBase)
  9526. break;
  9527. typeInstance = typeInstance->mBaseType;
  9528. }
  9529. return BfModuleMethodInstance();
  9530. }
  9531. StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags methodNameFlags, BfTypeVector* typeGenericArgs, BfTypeVector* methodGenericArgs)
  9532. {
  9533. auto methodDef = methodInst->mMethodDef;
  9534. bool allowResolveGenericParamNames = ((methodNameFlags & BfMethodNameFlag_ResolveGenericParamNames) != 0);
  9535. BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None;
  9536. bool hasGenericArgs = (typeGenericArgs != NULL) || (methodGenericArgs != NULL);
  9537. BfType* type = methodInst->mMethodInstanceGroup->mOwner;
  9538. if ((hasGenericArgs) && (type->IsUnspecializedType()))
  9539. type = ResolveGenericType(type, typeGenericArgs, methodGenericArgs, mCurTypeInstance);
  9540. if ((type == NULL) || (!type->IsUnspecializedTypeVariation()))
  9541. typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames;
  9542. if (allowResolveGenericParamNames)
  9543. typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames;
  9544. StringT<128> methodName;
  9545. auto _AddTypeName = [&](BfType* type)
  9546. {
  9547. auto typeNameFlags = BfTypeNameFlags_None;
  9548. if (allowResolveGenericParamNames)
  9549. typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames;
  9550. if ((hasGenericArgs) && (type->IsUnspecializedType()))
  9551. type = ResolveGenericType(type, typeGenericArgs, methodGenericArgs, mCurTypeInstance);
  9552. methodName += TypeToString(type, typeNameFlags);
  9553. };
  9554. if ((methodNameFlags & BfMethodNameFlag_IncludeReturnType) != 0)
  9555. {
  9556. _AddTypeName(methodInst->mReturnType);
  9557. methodName += " ";
  9558. }
  9559. if ((methodNameFlags & BfMethodNameFlag_OmitTypeName) == 0)
  9560. {
  9561. methodName += TypeToString(type, typeNameFlags);
  9562. if (methodName == "$")
  9563. methodName = "";
  9564. else if (!methodName.IsEmpty())
  9565. methodName += ".";
  9566. }
  9567. String accessorString;
  9568. StringT<64> methodDefName = methodInst->mMethodDef->mName;
  9569. if (methodInst->mMethodDef->mIsLocalMethod)
  9570. {
  9571. int atPos = (int)methodDefName.IndexOf('$');
  9572. methodDefName.RemoveToEnd(atPos);
  9573. methodDefName.Replace("@", ".");
  9574. }
  9575. else
  9576. {
  9577. int atPos = (int)methodDefName.IndexOf('$');
  9578. if (atPos != -1)
  9579. {
  9580. accessorString = methodDefName.Substring(0, atPos);
  9581. if ((accessorString == "get") || (accessorString == "set"))
  9582. {
  9583. methodDefName = methodDefName.Substring(atPos + 1);
  9584. }
  9585. else
  9586. accessorString = "";
  9587. }
  9588. }
  9589. if ((methodInst->mMethodInfoEx != NULL) && (methodInst->mMethodInfoEx->mForeignType != NULL))
  9590. {
  9591. BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None;
  9592. if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames)
  9593. typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames;
  9594. methodName += TypeToString(methodInst->mMethodInfoEx->mForeignType, typeNameFlags);
  9595. methodName += ".";
  9596. }
  9597. if ((methodInst->mMethodInfoEx != NULL) && (methodInst->mMethodInfoEx->mExplicitInterface != NULL))
  9598. {
  9599. BfTypeNameFlags typeNameFlags = BfTypeNameFlags_None;
  9600. if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames)
  9601. typeNameFlags = BfTypeNameFlag_ResolveGenericParamNames;
  9602. methodName += "[";
  9603. methodName += TypeToString(methodInst->mMethodInfoEx->mExplicitInterface, typeNameFlags);
  9604. methodName += "].";
  9605. }
  9606. if (methodDef->mMethodType == BfMethodType_Operator)
  9607. {
  9608. BfOperatorDef* operatorDef = (BfOperatorDef*)methodDef;
  9609. if (operatorDef->mOperatorDeclaration->mIsConvOperator)
  9610. {
  9611. // Don't add explicit/implicit part, since that's not available in GCC mangling
  9612. /*if (operatorDef->mOperatorDeclaration->mExplicitToken != NULL)
  9613. {
  9614. if (operatorDef->mOperatorDeclaration->mExplicitToken->GetToken() == BfToken_Explicit)
  9615. methodName += "explicit ";
  9616. else if (operatorDef->mOperatorDeclaration->mExplicitToken->GetToken() == BfToken_Explicit)
  9617. methodName += "explicit ";
  9618. }*/
  9619. methodName += "operator ";
  9620. if (methodInst->mReturnType != NULL)
  9621. methodName += TypeToString(methodInst->mReturnType);
  9622. }
  9623. else
  9624. {
  9625. methodName += "operator";
  9626. if (operatorDef->mOperatorDeclaration->mOpTypeToken != NULL)
  9627. methodName += BfTokenToString(operatorDef->mOperatorDeclaration->mOpTypeToken->GetToken());
  9628. }
  9629. }
  9630. else if (methodDef->mMethodType == BfMethodType_Ctor)
  9631. {
  9632. if (methodDef->mIsStatic)
  9633. methodName += "__BfStaticCtor";
  9634. else
  9635. methodName += "this";
  9636. accessorString = "";
  9637. }
  9638. else if (methodDef->mMethodType == BfMethodType_PropertyGetter)
  9639. {
  9640. auto propertyDecl = methodDef->GetPropertyDeclaration();
  9641. if (auto indexerProperty = BfNodeDynCast<BfIndexerDeclaration>(propertyDecl))
  9642. {
  9643. methodName += "get indexer";
  9644. }
  9645. else
  9646. {
  9647. if ((propertyDecl != NULL) && (propertyDecl->mNameNode != NULL))
  9648. propertyDecl->mNameNode->ToString(methodName);
  9649. methodName += " get accessor";
  9650. return methodName;
  9651. }
  9652. }
  9653. else if (methodDef->mMethodType == BfMethodType_PropertySetter)
  9654. {
  9655. auto propertyDecl = methodDef->GetPropertyDeclaration();
  9656. if (auto indexerProperty = BfNodeDynCast<BfIndexerDeclaration>(propertyDecl))
  9657. {
  9658. methodName += "set indexer";
  9659. }
  9660. else
  9661. {
  9662. if ((propertyDecl != NULL) && (propertyDecl->mNameNode != NULL))
  9663. propertyDecl->mNameNode->ToString(methodName);
  9664. methodName += " set accessor";
  9665. return methodName;
  9666. }
  9667. }
  9668. else
  9669. methodName += methodDefName;
  9670. if (methodDef->mMethodType == BfMethodType_Mixin)
  9671. methodName += "!";
  9672. BfTypeVector newMethodGenericArgs;
  9673. if ((methodInst->mMethodInfoEx != NULL) && (methodInst->mMethodInfoEx->mMethodGenericArguments.size() != 0))
  9674. {
  9675. methodName += "<";
  9676. for (int i = 0; i < (int)methodInst->mMethodInfoEx->mMethodGenericArguments.size(); i++)
  9677. {
  9678. if (i > 0)
  9679. methodName += ", ";
  9680. BfTypeNameFlags typeNameFlags = BfTypeNameFlag_ShortConst;
  9681. //Why did we have this methodInst->mIsUnspecializedVariation check? Sometimes we do need to show errors calling methods that refer back to our types
  9682. //if (!methodInst->mIsUnspecializedVariation && allowResolveGenericParamNames)
  9683. if (allowResolveGenericParamNames)
  9684. typeNameFlags = (BfTypeNameFlags)(typeNameFlags | BfTypeNameFlag_ResolveGenericParamNames);
  9685. BfType* type = methodInst->mMethodInfoEx->mMethodGenericArguments[i];
  9686. if ((methodGenericArgs != NULL) && (type->IsUnspecializedType()))
  9687. {
  9688. bool hasEmpty = false;
  9689. for (auto arg : *methodGenericArgs)
  9690. {
  9691. if (arg == NULL)
  9692. hasEmpty = true;
  9693. }
  9694. if (hasEmpty)
  9695. {
  9696. for (int genericIdx = 0; genericIdx < (int)methodGenericArgs->size(); genericIdx++)
  9697. {
  9698. auto arg = (*methodGenericArgs)[genericIdx];
  9699. if (arg != NULL)
  9700. newMethodGenericArgs.push_back(arg);
  9701. else
  9702. {
  9703. auto genericParamInst = methodInst->mMethodInfoEx->mGenericParams[genericIdx];
  9704. if (genericParamInst->mTypeConstraint != NULL)
  9705. newMethodGenericArgs.push_back(genericParamInst->mTypeConstraint);
  9706. else
  9707. newMethodGenericArgs.push_back(mContext->mBfObjectType); // Default
  9708. }
  9709. }
  9710. methodGenericArgs = &newMethodGenericArgs;
  9711. }
  9712. if (type->IsUnspecializedType())
  9713. type = ResolveGenericType(type, NULL, methodGenericArgs, mCurTypeInstance);
  9714. }
  9715. if ((methodGenericArgs == NULL) && (mCurMethodInstance == NULL) && (mCurTypeInstance == NULL))
  9716. {
  9717. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, methodInst->GetOwner());
  9718. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInst);
  9719. methodName += TypeToString(type, typeNameFlags);
  9720. }
  9721. else
  9722. methodName += TypeToString(type, typeNameFlags);
  9723. }
  9724. methodName += ">";
  9725. }
  9726. if (accessorString.length() == 0)
  9727. {
  9728. int dispParamIdx = 0;
  9729. methodName += "(";
  9730. for (int paramIdx = 0; paramIdx < (int)methodInst->GetParamCount(); paramIdx++)
  9731. {
  9732. int paramKind = methodInst->GetParamKind(paramIdx);
  9733. if (paramKind == BfParamKind_ImplicitCapture)
  9734. continue;
  9735. if (dispParamIdx > 0)
  9736. methodName += ", ";
  9737. if (paramKind == BfParamKind_Params)
  9738. methodName += "params ";
  9739. BfType* type = methodInst->GetParamType(paramIdx);
  9740. _AddTypeName(type);
  9741. methodName += " ";
  9742. methodName += methodInst->GetParamName(paramIdx);
  9743. auto paramInitializer = methodInst->GetParamInitializer(paramIdx);
  9744. if ((paramInitializer != NULL) && ((methodNameFlags & BfMethodNameFlag_NoAst) == 0))
  9745. {
  9746. methodName += " = ";
  9747. methodName += paramInitializer->ToString();
  9748. }
  9749. dispParamIdx++;
  9750. }
  9751. methodName += ")";
  9752. }
  9753. if (accessorString.length() != 0)
  9754. {
  9755. methodName += " ";
  9756. methodName += accessorString;
  9757. }
  9758. if ((methodNameFlags & BfMethodNameFlag_IncludeMut) != 0)
  9759. {
  9760. if ((methodDef->mIsMutating) && (methodInst->GetOwner()->IsValueType()))
  9761. methodName += " mut";
  9762. }
  9763. return methodName;
  9764. }
  9765. void BfModule::pt(BfType* type)
  9766. {
  9767. OutputDebugStrF("%s\n", TypeToString(type).c_str());
  9768. }
  9769. void BfModule::pm(BfMethodInstance* type)
  9770. {
  9771. OutputDebugStrF("%s\n", MethodToString(type).c_str());
  9772. }
  9773. static void AddAttributeTargetName(BfAttributeTargets& flagsLeft, BfAttributeTargets checkFlag, String& str, String addString)
  9774. {
  9775. if ((flagsLeft & checkFlag) == 0)
  9776. return;
  9777. if (!str.empty())
  9778. {
  9779. if (flagsLeft == checkFlag)
  9780. {
  9781. if ((int)str.IndexOf(',') != -1)
  9782. str += ", and ";
  9783. else
  9784. str += " and ";
  9785. }
  9786. else
  9787. str += ", ";
  9788. }
  9789. str += addString;
  9790. flagsLeft = (BfAttributeTargets)(flagsLeft & ~checkFlag);
  9791. }
  9792. static String GetAttributesTargetListString(BfAttributeTargets attrTarget)
  9793. {
  9794. String resultStr;
  9795. auto flagsLeft = attrTarget;
  9796. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Assembly, resultStr, "assembly declarations");
  9797. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Module, resultStr, "module declarations");
  9798. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Class, resultStr, "class declarations");
  9799. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Struct, resultStr, "struct declarations");
  9800. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Enum, resultStr, "enum declarations");
  9801. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Constructor, resultStr, "constructor declarations");
  9802. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Method, resultStr, "method declarations");
  9803. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Property, resultStr, "property declarations");
  9804. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Field, resultStr, "field declarations");
  9805. AddAttributeTargetName(flagsLeft, BfAttributeTargets_StaticField, resultStr, "static field declarations");
  9806. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Interface, resultStr, "interface declarations");
  9807. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Parameter, resultStr, "parameter declarations");
  9808. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Delegate, resultStr, "delegate declarations");
  9809. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Function, resultStr, "function declarations");
  9810. AddAttributeTargetName(flagsLeft, BfAttributeTargets_ReturnValue, resultStr, "return value");
  9811. AddAttributeTargetName(flagsLeft, BfAttributeTargets_GenericParameter, resultStr, "generic parameters");
  9812. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Invocation, resultStr, "invocations");
  9813. AddAttributeTargetName(flagsLeft, BfAttributeTargets_MemberAccess, resultStr, "member access");
  9814. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alloc, resultStr, "allocations");
  9815. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Alias, resultStr, "aliases");
  9816. AddAttributeTargetName(flagsLeft, BfAttributeTargets_Block, resultStr, "blocks");
  9817. if (resultStr.IsEmpty())
  9818. return "<nothing>";
  9819. return resultStr;
  9820. }
  9821. void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
  9822. {
  9823. auto constant = mBfIRBuilder->GetConstant(irVal);
  9824. int stringPoolIdx = GetStringPoolIdx(irVal, mBfIRBuilder);
  9825. if (stringPoolIdx != -1)
  9826. {
  9827. irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConst(BfTypeCode_StringId, stringPoolIdx);
  9828. return;
  9829. }
  9830. if (constant->mConstType == BfConstType_Agg)
  9831. {
  9832. auto constArray = (BfConstantAgg*)constant;
  9833. SizedArray<BfIRValue, 8> newVals;
  9834. for (auto val : constArray->mValues)
  9835. {
  9836. auto newVal = val;
  9837. CurrentAddToConstHolder(newVal);
  9838. newVals.push_back(newVal);
  9839. }
  9840. irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstAgg(constArray->mType, newVals);
  9841. return;
  9842. }
  9843. auto origConst = irVal;
  9844. if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
  9845. {
  9846. auto bitcast = (BfConstantBitCast*)constant;
  9847. BfIRValue newVal;
  9848. if (bitcast->mTarget)
  9849. {
  9850. newVal = BfIRValue(BfIRValueFlags_Const, bitcast->mTarget);
  9851. CurrentAddToConstHolder(newVal);
  9852. }
  9853. else
  9854. newVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstNull();
  9855. irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstBitCast(newVal, bitcast->mToType);
  9856. return;
  9857. }
  9858. irVal = mCurTypeInstance->CreateConst(constant, mBfIRBuilder);
  9859. }
  9860. void BfModule::ClearConstData()
  9861. {
  9862. mBfIRBuilder->ClearConstData();
  9863. mStringObjectPool.Clear();
  9864. mStringCharPtrPool.Clear();
  9865. mStringPoolRefs.Clear();
  9866. mUnreifiedStringPoolRefs.Clear();
  9867. }
  9868. BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType)
  9869. {
  9870. switch (constant->mTypeCode)
  9871. {
  9872. case BfTypeCode_StringId:
  9873. case BfTypeCode_Boolean:
  9874. case BfTypeCode_Int8:
  9875. case BfTypeCode_UInt8:
  9876. case BfTypeCode_Int16:
  9877. case BfTypeCode_UInt16:
  9878. case BfTypeCode_Int32:
  9879. case BfTypeCode_UInt32:
  9880. case BfTypeCode_Int64:
  9881. case BfTypeCode_UInt64:
  9882. case BfTypeCode_IntPtr:
  9883. case BfTypeCode_UIntPtr:
  9884. case BfTypeCode_IntUnknown:
  9885. case BfTypeCode_UIntUnknown:
  9886. case BfTypeCode_Char8:
  9887. case BfTypeCode_Char16:
  9888. case BfTypeCode_Char32:
  9889. case BfTypeCode_Float:
  9890. case BfTypeCode_Double:
  9891. {
  9892. auto constVal = mBfIRBuilder->CreateConst(constant, constHolder);
  9893. BfTypedValue typedValue;
  9894. bool allowUnactualized = mBfIRBuilder->mIgnoreWrites;
  9895. if (constant->mTypeCode == BfTypeCode_StringId)
  9896. {
  9897. if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
  9898. ((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
  9899. {
  9900. typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, wantType, allowUnactualized), wantType);
  9901. return typedValue;
  9902. }
  9903. auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef);
  9904. typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, stringType, allowUnactualized), stringType);
  9905. }
  9906. if (!typedValue)
  9907. {
  9908. auto constVal = mBfIRBuilder->CreateConst(constant, constHolder);
  9909. typedValue = BfTypedValue(constVal, GetPrimitiveType(constant->mTypeCode));
  9910. }
  9911. if (typedValue.mType == wantType)
  9912. return typedValue;
  9913. if (wantType->IsTypedPrimitive())
  9914. {
  9915. if (typedValue.mType == wantType->GetUnderlyingType())
  9916. {
  9917. typedValue.mType = wantType;
  9918. return typedValue;
  9919. }
  9920. }
  9921. auto castedTypedValue = Cast(NULL, typedValue, wantType, (BfCastFlags)(BfCastFlags_SilentFail | BfCastFlags_Explicit));
  9922. if (!castedTypedValue)
  9923. return BfTypedValue();
  9924. return castedTypedValue;
  9925. }
  9926. break;
  9927. default: break;
  9928. }
  9929. BfIRValue irValue = ConstantToCurrent(constant, constHolder, wantType);
  9930. BF_ASSERT(irValue);
  9931. if (!irValue)
  9932. return BfTypedValue();
  9933. if (constant->mConstType == BfConstType_GlobalVar)
  9934. {
  9935. mBfIRBuilder->PopulateType(wantType);
  9936. auto result = BfTypedValue(irValue, wantType, true);
  9937. if (!wantType->IsComposite())
  9938. result = LoadValue(result);
  9939. return result;
  9940. }
  9941. return BfTypedValue(irValue, wantType, false);
  9942. }
  9943. bool BfModule::HasUnactializedConstant(BfConstant* constant, BfIRConstHolder* constHolder)
  9944. {
  9945. if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
  9946. return true;
  9947. if (constant->mTypeCode == BfTypeCode_StringId)
  9948. return true;
  9949. if (constant->mConstType == BfConstType_Agg)
  9950. {
  9951. auto constArray = (BfConstantAgg*)constant;
  9952. for (auto val : constArray->mValues)
  9953. {
  9954. if (HasUnactializedConstant(constHolder->GetConstant(val), constHolder))
  9955. return true;
  9956. }
  9957. }
  9958. return false;
  9959. }
  9960. BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowUnactualized)
  9961. {
  9962. if (constant->mTypeCode == BfTypeCode_NullPtr)
  9963. {
  9964. if ((wantType == NULL) && (constant->mIRType.mKind == BfIRTypeData::TypeKind_TypeId))
  9965. wantType = mContext->mTypes[constant->mIRType.mId];
  9966. if (wantType == NULL)
  9967. return mBfIRBuilder->CreateConstNull();
  9968. return GetDefaultValue(wantType);
  9969. }
  9970. if (constant->mTypeCode == BfTypeCode_StringId)
  9971. {
  9972. if (!allowUnactualized)
  9973. {
  9974. if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) ||
  9975. ((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8))))
  9976. {
  9977. const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString;
  9978. BfIRValue stringObjConst = GetStringObjectValue(str, false, true);
  9979. if (wantType->IsPointer())
  9980. return GetStringCharPtr(stringObjConst, true);
  9981. return stringObjConst;
  9982. }
  9983. }
  9984. }
  9985. if (constant->mConstType == Beefy::BfConstType_TypeOf)
  9986. {
  9987. auto constTypeOf = (BfTypeOf_Const*)constant;
  9988. if (mCurTypeInstance != NULL)
  9989. AddDependency(constTypeOf->mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
  9990. return CreateTypeDataRef(constTypeOf->mType);
  9991. }
  9992. if (constant->mConstType == BfConstType_PtrToInt)
  9993. {
  9994. auto fromPtrToInt = (BfConstantPtrToInt*)constant;
  9995. auto fromTarget = constHolder->GetConstantById(fromPtrToInt->mTarget);
  9996. return mBfIRBuilder->CreatePtrToInt(ConstantToCurrent(fromTarget, constHolder, NULL), fromPtrToInt->mToTypeCode);
  9997. }
  9998. if (constant->mConstType == BfConstType_IntToPtr)
  9999. {
  10000. auto fromPtrToInt = (BfConstantIntToPtr*)constant;
  10001. auto fromTarget = constHolder->GetConstantById(fromPtrToInt->mTarget);
  10002. BfIRType toIRType = fromPtrToInt->mToType;
  10003. if (toIRType.mKind == BfIRTypeData::TypeKind_TypeId)
  10004. {
  10005. auto toType = mContext->mTypes[toIRType.mId];
  10006. toIRType = mBfIRBuilder->MapType(toType);
  10007. }
  10008. return mBfIRBuilder->CreateIntToPtr(ConstantToCurrent(fromTarget, constHolder, NULL), toIRType);
  10009. }
  10010. if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
  10011. {
  10012. auto bitcast = (BfConstantBitCast*)constant;
  10013. auto fromTarget = constHolder->GetConstantById(bitcast->mTarget);
  10014. BfIRType toIRType = bitcast->mToType;
  10015. if (toIRType.mKind == BfIRTypeData::TypeKind_TypeId)
  10016. {
  10017. auto toType = mContext->mTypes[toIRType.mId];
  10018. toIRType = mBfIRBuilder->MapType(toType);
  10019. }
  10020. return mBfIRBuilder->CreateBitCast(ConstantToCurrent(fromTarget, constHolder, NULL), toIRType);
  10021. }
  10022. if (constant->mConstType == BfConstType_Agg)
  10023. {
  10024. auto constArray = (BfConstantAgg*)constant;
  10025. if ((wantType == NULL) && (constArray->mType.mKind == BfIRTypeData::TypeKind_TypeId))
  10026. wantType = mContext->mTypes[constArray->mType.mId];
  10027. SizedArray<BfIRValue, 8> newVals;
  10028. if (wantType->IsSizedArray())
  10029. {
  10030. auto elementType = wantType->GetUnderlyingType();
  10031. for (auto val : constArray->mValues)
  10032. {
  10033. newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType));
  10034. }
  10035. }
  10036. else
  10037. {
  10038. auto wantTypeInst = wantType->ToTypeInstance();
  10039. if (wantTypeInst->mBaseType != NULL)
  10040. {
  10041. auto baseVal = ConstantToCurrent(constHolder->GetConstant(constArray->mValues[0]), constHolder, wantTypeInst->mBaseType);
  10042. newVals.Add(baseVal);
  10043. }
  10044. if (wantType->IsUnion())
  10045. {
  10046. auto innerType = wantType->ToTypeInstance()->GetUnionInnerType();
  10047. if (!innerType->IsValuelessType())
  10048. {
  10049. auto val = ConstantToCurrent(constHolder->GetConstant(constArray->mValues[1]), constHolder, innerType);
  10050. newVals.Add(val);
  10051. }
  10052. }
  10053. if ((!wantType->IsUnion()) || (wantType->IsPayloadEnum()))
  10054. {
  10055. for (auto& fieldInstance : wantTypeInst->mFieldInstances)
  10056. {
  10057. if (fieldInstance.mDataIdx < 0)
  10058. continue;
  10059. auto val = constArray->mValues[fieldInstance.mDataIdx];
  10060. BfIRValue memberVal = ConstantToCurrent(constHolder->GetConstant(val), constHolder, fieldInstance.mResolvedType);
  10061. if (fieldInstance.mDataIdx == newVals.mSize)
  10062. newVals.Add(memberVal);
  10063. else
  10064. {
  10065. while (fieldInstance.mDataIdx >= newVals.mSize)
  10066. newVals.Add(BfIRValue());
  10067. newVals[fieldInstance.mDataIdx] = memberVal;
  10068. }
  10069. }
  10070. }
  10071. for (auto& val : newVals)
  10072. {
  10073. if (!val)
  10074. val = mBfIRBuilder->CreateConstArrayZero(0);
  10075. }
  10076. }
  10077. return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(wantType, BfIRPopulateType_Identity), newVals);
  10078. }
  10079. return mBfIRBuilder->CreateConst(constant, constHolder);
  10080. }
  10081. void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget)
  10082. {
  10083. if (attrTarget == BfAttributeTargets_SkipValidate)
  10084. return;
  10085. for (auto& customAttribute : customAttributes->mAttributes)
  10086. {
  10087. if (!customAttribute.mAwaitingValidation)
  10088. continue;
  10089. if ((customAttribute.mType->mAttributeData->mAttributeTargets & attrTarget) == 0)
  10090. {
  10091. Fail(StrFormat("Attribute '%s' is not valid on this declaration type. It is only valid on %s.",
  10092. customAttribute.GetRefNode()->ToString().c_str(), GetAttributesTargetListString(customAttribute.mType->mAttributeData->mAttributeTargets).c_str()), customAttribute.mRef->mAttributeTypeRef); // CS0592
  10093. }
  10094. customAttribute.mAwaitingValidation = false;
  10095. }
  10096. }
  10097. void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget, BfGetCustomAttributesFlags flags, BfCaptureInfo* captureInfo)
  10098. {
  10099. bool allowNonConstArgs = (flags & BfGetCustomAttributesFlags_AllowNonConstArgs) != 0;
  10100. bool keepConstsInModule = (flags & BfGetCustomAttributesFlags_KeepConstsInModule) != 0;
  10101. if (!mCompiler->mHasRequiredTypes)
  10102. return;
  10103. if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))
  10104. {
  10105. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
  10106. sourceClassifier->VisitChild(attributesDirective);
  10107. }
  10108. SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
  10109. if (mCompiler->IsAutocomplete())
  10110. prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
  10111. BfTypeInstance* baseAttrTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
  10112. BfAttributeTargets targetOverride = (BfAttributeTargets)0;
  10113. BfTypeDef* activeTypeDef = GetActiveTypeDef();
  10114. BfAutoComplete* autoComplete = NULL;
  10115. if (mCompiler->mResolvePassData != NULL)
  10116. autoComplete = mCompiler->mResolvePassData->mAutoComplete;
  10117. for (; attributesDirective != NULL; attributesDirective = attributesDirective->mNextAttribute)
  10118. {
  10119. if (auto tokenNode = BfNodeDynCast<BfTokenNode>(attributesDirective->mAttributeTargetSpecifier))
  10120. {
  10121. if (captureInfo == NULL)
  10122. {
  10123. Fail("Capture specifiers can only be used in lambda allocations", tokenNode);
  10124. continue;
  10125. }
  10126. BfCaptureInfo::Entry captureEntry;
  10127. captureEntry.mCaptureType = (tokenNode->mToken == BfToken_Ampersand) ? BfCaptureType_Reference : BfCaptureType_Copy;
  10128. if (!attributesDirective->mArguments.IsEmpty())
  10129. {
  10130. captureEntry.mNameNode = BfNodeDynCast<BfIdentifierNode>(attributesDirective->mArguments[0]);
  10131. if ((captureEntry.mNameNode != NULL) && (autoComplete != NULL))
  10132. autoComplete->CheckIdentifier(captureEntry.mNameNode);
  10133. }
  10134. captureInfo->mCaptures.Add(captureEntry);
  10135. continue;
  10136. }
  10137. BfAutoParentNodeEntry autoParentNodeEntry(this, attributesDirective);
  10138. BfCustomAttribute customAttribute;
  10139. customAttribute.mAwaitingValidation = true;
  10140. customAttribute.mDeclaringType = activeTypeDef;
  10141. customAttribute.mRef = attributesDirective;
  10142. if (attributesDirective->mAttrOpenToken != NULL)
  10143. targetOverride = (BfAttributeTargets)0;
  10144. if (attributesDirective->mAttributeTypeRef == NULL)
  10145. {
  10146. AssertErrorState();
  10147. continue;
  10148. }
  10149. BfType* attrType;
  10150. if (mContext->mCurTypeState != NULL)
  10151. {
  10152. SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurAttributeTypeRef, attributesDirective->mAttributeTypeRef);
  10153. attrType = ResolveTypeRef(attributesDirective->mAttributeTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_Attribute | BfResolveTypeRefFlag_NoReify));
  10154. }
  10155. else
  10156. {
  10157. attrType = ResolveTypeRef(attributesDirective->mAttributeTypeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_Attribute | BfResolveTypeRefFlag_NoReify));
  10158. }
  10159. BfTypeDef* attrTypeDef = NULL;
  10160. if ((attrType != NULL) && (attrType->IsTypeInstance()))
  10161. attrTypeDef = attrType->ToTypeInstance()->mTypeDef;
  10162. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  10163. {
  10164. mCompiler->mResolvePassData->mAutoComplete->CheckAttributeTypeRef(attributesDirective->mAttributeTypeRef);
  10165. if (attrTypeDef != NULL)
  10166. mCompiler->mResolvePassData->HandleTypeReference(attributesDirective->mAttributeTypeRef, attrTypeDef);
  10167. }
  10168. bool isBypassedAttr = false;
  10169. if (attrTypeDef != NULL)
  10170. {
  10171. // 'Object' has some dependencies on some attributes, but those attributes are classes so we have a circular dependency issue
  10172. // We solve it by having a 'bypass' for known attributes that Object depends on
  10173. if ((attributesDirective->mArguments.empty()) && (autoComplete == NULL) && (attrType != NULL) && (attrType->IsTypeInstance()))
  10174. {
  10175. if (attrType->IsInstanceOf(mCompiler->mCReprAttributeTypeDef))
  10176. {
  10177. for (auto methodDef : attrTypeDef->mMethods)
  10178. {
  10179. if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mProtection == BfProtection_Public))
  10180. {
  10181. customAttribute.mType = attrType->ToTypeInstance();
  10182. customAttribute.mCtor = methodDef;
  10183. isBypassedAttr = true;
  10184. break;
  10185. }
  10186. }
  10187. }
  10188. }
  10189. if (isBypassedAttr)
  10190. {
  10191. customAttribute.mAwaitingValidation = false;
  10192. customAttributes->mAttributes.push_back(customAttribute);
  10193. continue;
  10194. }
  10195. SetAndRestoreValue<BfTypeInstance*> prevCurTypeInst(mContext->mUnreifiedModule->mCurTypeInstance, mCurTypeInstance);
  10196. SetAndRestoreValue<BfMethodInstance*> prevCurMethodInst(mContext->mUnreifiedModule->mCurMethodInstance, mCurMethodInstance);
  10197. if (mContext->mCurTypeState != NULL)
  10198. {
  10199. SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurAttributeTypeRef, attributesDirective->mAttributeTypeRef);
  10200. mContext->mUnreifiedModule->ResolveTypeResult(attributesDirective->mAttributeTypeRef, attrType, BfPopulateType_BaseType, (BfResolveTypeRefFlags)0);
  10201. }
  10202. else
  10203. {
  10204. mContext->mUnreifiedModule->ResolveTypeResult(attributesDirective->mAttributeTypeRef, attrType, BfPopulateType_BaseType, (BfResolveTypeRefFlags)0);
  10205. }
  10206. }
  10207. BfTypeInstance* attrTypeInst = NULL;
  10208. if (attrType == NULL)
  10209. continue;
  10210. attrTypeInst = attrType->ToTypeInstance();
  10211. if ((attrTypeInst != NULL) && (attrTypeInst->mDefineState != BfTypeDefineState_DefinedAndMethodsSlotting))
  10212. mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods);
  10213. if ((attrTypeInst == NULL) || (!TypeIsSubTypeOf(attrTypeInst, baseAttrTypeInst)) || (attrTypeInst->mAttributeData == NULL))
  10214. {
  10215. Fail(StrFormat("'%s' is not an attribute class", TypeToString(attrType).c_str()), attributesDirective->mAttributeTypeRef); //CS0616
  10216. continue;
  10217. }
  10218. if ((mIsReified) && (attrTypeInst->mAttributeData != NULL) && ((attrTypeInst->mAttributeData->mFlags & BfAttributeFlag_ReflectAttribute) != 0))
  10219. {
  10220. // Reify attribute
  10221. PopulateType(attrTypeInst);
  10222. }
  10223. if (mCurTypeInstance != NULL)
  10224. AddDependency(attrTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute);
  10225. customAttribute.mType = attrTypeInst;
  10226. bool allocatedMethodState = NULL;
  10227. defer(
  10228. {
  10229. if (allocatedMethodState)
  10230. {
  10231. delete mCurMethodState;
  10232. mCurMethodState = NULL;
  10233. }
  10234. });
  10235. if (mCurMethodState == NULL)
  10236. {
  10237. allocatedMethodState = true;
  10238. mCurMethodState = new BfMethodState();
  10239. mCurMethodState->mTempKind = BfMethodState::TempKind_Static;
  10240. }
  10241. BfConstResolver constResolver(this);
  10242. if (allowNonConstArgs)
  10243. constResolver.mBfEvalExprFlags = (BfEvalExprFlags)(constResolver.mBfEvalExprFlags | BfEvalExprFlags_AllowNonConst);
  10244. bool inPropSet = false;
  10245. SizedArray<BfResolvedArg, 2> argValues;
  10246. for (BfExpression* arg : attributesDirective->mArguments)
  10247. {
  10248. if (arg == NULL)
  10249. {
  10250. continue;
  10251. }
  10252. if (autoComplete != NULL)
  10253. autoComplete->mShowAttributeProperties = attrTypeInst;
  10254. if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(arg))
  10255. {
  10256. inPropSet = true;
  10257. if (autoComplete != NULL)
  10258. autoComplete->CheckNode(assignExpr->mLeft, true);
  10259. String findName = assignExpr->mLeft->ToString();
  10260. BfPropertyDef* bestProp = NULL;
  10261. BfTypeInstance* bestPropTypeInst = NULL;
  10262. BfFieldDef* bestField = NULL;
  10263. BfTypeInstance* bestFieldTypeInst = NULL;
  10264. auto checkTypeInst = attrTypeInst;
  10265. while (checkTypeInst != NULL)
  10266. {
  10267. mContext->mUnreifiedModule->PopulateType(checkTypeInst, BfPopulateType_Data);
  10268. for (auto prop : checkTypeInst->mTypeDef->mProperties)
  10269. {
  10270. if (prop->mName == findName)
  10271. {
  10272. if ((bestProp == NULL) || (bestProp->mProtection != BfProtection_Public))
  10273. {
  10274. bestProp = prop;
  10275. bestPropTypeInst = checkTypeInst;
  10276. }
  10277. }
  10278. }
  10279. for (auto field : checkTypeInst->mTypeDef->mFields)
  10280. {
  10281. if (field->mName == findName)
  10282. {
  10283. if ((bestField == NULL) || (bestField->mProtection != BfProtection_Public))
  10284. {
  10285. bestField = field;
  10286. bestFieldTypeInst = checkTypeInst;
  10287. }
  10288. }
  10289. }
  10290. if ((bestProp != NULL) || (bestField != NULL))
  10291. break;
  10292. checkTypeInst = checkTypeInst->mBaseType;
  10293. }
  10294. bool handledExpr = false;
  10295. if (bestField != NULL)
  10296. {
  10297. handledExpr = true;
  10298. if (mCompiler->mResolvePassData != NULL)
  10299. {
  10300. mCompiler->mResolvePassData->HandleFieldReference(assignExpr->mLeft, attrTypeDef, bestField);
  10301. if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(assignExpr->mLeft)))
  10302. {
  10303. autoComplete->mDefField = bestField;
  10304. autoComplete->mDefType = attrTypeDef;
  10305. }
  10306. }
  10307. if (bestField->mProtection != BfProtection_Public)
  10308. Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", TypeToString(bestFieldTypeInst).c_str(), findName.c_str()), assignExpr->mLeft); // CS0122
  10309. AddDependency(bestFieldTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute);
  10310. BfCustomAttributeSetField setField;
  10311. setField.mFieldRef = BfFieldRef(bestFieldTypeInst, bestField);
  10312. auto& fieldTypeInst = checkTypeInst->mFieldInstances[bestField->mIdx];
  10313. if (assignExpr->mRight != NULL)
  10314. {
  10315. BfTypedValue result = constResolver.Resolve(assignExpr->mRight, fieldTypeInst.mResolvedType, BfConstResolveFlag_NoActualizeValues);
  10316. if (result)
  10317. {
  10318. if (!keepConstsInModule)
  10319. CurrentAddToConstHolder(result.mValue);
  10320. setField.mParam = result;
  10321. customAttribute.mSetField.push_back(setField);
  10322. }
  10323. }
  10324. }
  10325. else if (bestProp == NULL)
  10326. {
  10327. Fail(StrFormat("'%s' does not contain a field or property named '%s'", TypeToString(attrTypeInst).c_str(), findName.c_str()), assignExpr->mLeft);
  10328. }
  10329. else
  10330. {
  10331. BfMethodDef* setMethod = NULL;
  10332. for (auto methodDef : bestProp->mMethods)
  10333. {
  10334. if (methodDef->mMethodType == BfMethodType_PropertySetter)
  10335. {
  10336. setMethod = methodDef;
  10337. break;
  10338. }
  10339. }
  10340. if (setMethod == NULL)
  10341. {
  10342. Fail("Property has no setter", assignExpr->mLeft);
  10343. }
  10344. else
  10345. {
  10346. if (mCompiler->mResolvePassData != NULL)
  10347. {
  10348. mCompiler->mResolvePassData->HandlePropertyReference(assignExpr->mLeft, attrTypeDef, bestProp);
  10349. if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(assignExpr->mLeft)))
  10350. {
  10351. autoComplete->mDefProp = bestProp;
  10352. autoComplete->mDefType = attrTypeDef;
  10353. }
  10354. }
  10355. handledExpr = true;
  10356. if (bestProp->mProtection != BfProtection_Public)
  10357. Fail(StrFormat("'%s.%s' is inaccessible due to its protection level", TypeToString(bestPropTypeInst).c_str(), findName.c_str()), assignExpr->mLeft); // CS0122
  10358. BfResolvedArg resolvedArg;
  10359. AddDependency(bestPropTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute);
  10360. BfCustomAttributeSetProperty setProperty;
  10361. setProperty.mPropertyRef = BfPropertyRef(bestPropTypeInst, bestProp);
  10362. // We don't actually need the mFunc, so get the ModuleMethodInstance from the native module
  10363. auto methodInstance = bestPropTypeInst->mModule->GetMethodInstance(bestPropTypeInst, setMethod, BfTypeVector());
  10364. if (methodInstance.mMethodInstance != NULL)
  10365. {
  10366. auto propType = methodInstance.mMethodInstance->GetParamType(0);
  10367. if (assignExpr->mRight != NULL)
  10368. {
  10369. BfTypedValue result = constResolver.Resolve(assignExpr->mRight, propType, BfConstResolveFlag_NoActualizeValues);
  10370. if ((result) && (!result.mType->IsVar()))
  10371. {
  10372. if (!result.mValue.IsConst())
  10373. result = GetDefaultTypedValue(result.mType);
  10374. BF_ASSERT(result.mType == propType);
  10375. if (!keepConstsInModule)
  10376. CurrentAddToConstHolder(result.mValue);
  10377. setProperty.mParam = result;
  10378. customAttribute.mSetProperties.push_back(setProperty);
  10379. }
  10380. }
  10381. }
  10382. }
  10383. }
  10384. if ((!handledExpr) && (assignExpr->mRight != NULL))
  10385. constResolver.Resolve(assignExpr->mRight, NULL, BfConstResolveFlag_NoActualizeValues);
  10386. }
  10387. else
  10388. {
  10389. if (inPropSet)
  10390. {
  10391. Fail("Named attribute argument expected", arg); // CS1016
  10392. }
  10393. BfDeferEvalChecker deferEvalChecker;
  10394. arg->Accept(&deferEvalChecker);
  10395. bool deferParamEval = deferEvalChecker.mNeedsDeferEval;
  10396. BfResolvedArg resolvedArg;
  10397. resolvedArg.mExpression = arg;
  10398. if (deferParamEval)
  10399. {
  10400. resolvedArg.mArgFlags = BfArgFlag_DeferredEval;
  10401. }
  10402. else
  10403. resolvedArg.mTypedValue = constResolver.Resolve(arg, NULL, BfConstResolveFlag_NoActualizeValues);
  10404. if (!inPropSet)
  10405. {
  10406. argValues.push_back(resolvedArg);
  10407. }
  10408. }
  10409. if (autoComplete != NULL)
  10410. autoComplete->mShowAttributeProperties = NULL;
  10411. }
  10412. auto wasCapturingMethodInfo = false;
  10413. if (autoComplete != NULL)
  10414. {
  10415. wasCapturingMethodInfo = autoComplete->mIsCapturingMethodMatchInfo;
  10416. if (attributesDirective->mCtorOpenParen != NULL)
  10417. autoComplete->CheckInvocation(attributesDirective, attributesDirective->mCtorOpenParen, attributesDirective->mCtorCloseParen, attributesDirective->mCommas);
  10418. }
  10419. BfMethodMatcher methodMatcher(attributesDirective, this, "", argValues, BfMethodGenericArguments());
  10420. methodMatcher.mBfEvalExprFlags = constResolver.mBfEvalExprFlags;
  10421. attrTypeDef = attrTypeInst->mTypeDef;
  10422. bool success = true;
  10423. bool isFailurePass = false;
  10424. for (int pass = 0; pass < 2; pass++)
  10425. {
  10426. bool isFailurePass = pass == 1;
  10427. for (auto checkMethod : attrTypeDef->mMethods)
  10428. {
  10429. if ((isFailurePass) && (checkMethod->mMethodDeclaration == NULL))
  10430. continue; // Don't match private default ctor if there's a user-defined one
  10431. if ((checkMethod->mIsStatic) || (checkMethod->mMethodType != BfMethodType_Ctor))
  10432. continue;
  10433. if ((!isFailurePass) && (!CheckProtection(checkMethod->mProtection, attrTypeInst->mTypeDef, false, false)))
  10434. continue;
  10435. methodMatcher.CheckMethod(NULL, attrTypeInst, checkMethod, isFailurePass);
  10436. }
  10437. if ((methodMatcher.mBestMethodDef != NULL) || (methodMatcher.mBackupMethodDef != NULL))
  10438. break;
  10439. }
  10440. if (autoComplete != NULL)
  10441. {
  10442. if ((wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo))
  10443. {
  10444. autoComplete->mIsCapturingMethodMatchInfo = true;
  10445. BF_ASSERT(autoComplete->mMethodMatchInfo != NULL);
  10446. }
  10447. else
  10448. autoComplete->mIsCapturingMethodMatchInfo = false;
  10449. }
  10450. if (methodMatcher.mBestMethodDef == NULL)
  10451. methodMatcher.mBestMethodDef = methodMatcher.mBackupMethodDef;
  10452. BF_ASSERT(methodMatcher.mBestMethodDef != NULL);
  10453. customAttribute.mCtor = methodMatcher.mBestMethodDef;
  10454. if (methodMatcher.mBestMethodTypeInstance == mCurTypeInstance)
  10455. {
  10456. Fail("Custom attribute circular reference", attributesDirective);
  10457. }
  10458. if (mCurTypeInstance != NULL)
  10459. AddDependency(methodMatcher.mBestMethodTypeInstance, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute);
  10460. if (!constResolver.PrepareMethodArguments(attributesDirective->mAttributeTypeRef, &methodMatcher, customAttribute.mCtorArgs))
  10461. success = false;
  10462. for (auto& arg : argValues)
  10463. {
  10464. if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0)
  10465. {
  10466. if (auto expr = BfNodeDynCast<BfExpression>(arg.mExpression))
  10467. constResolver.Resolve(expr, NULL, BfConstResolveFlag_NoActualizeValues);
  10468. }
  10469. }
  10470. // Move all those to the constHolder
  10471. if (!keepConstsInModule)
  10472. {
  10473. for (auto& ctorArg : customAttribute.mCtorArgs)
  10474. {
  10475. if (ctorArg.IsConst())
  10476. CurrentAddToConstHolder(ctorArg);
  10477. }
  10478. }
  10479. if (attributesDirective->mAttributeTargetSpecifier != NULL)
  10480. {
  10481. targetOverride = BfAttributeTargets_ReturnValue;
  10482. if (attrTarget != BfAttributeTargets_Method)
  10483. {
  10484. Fail(StrFormat("'%s' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '%s'. All attributes in this block will be ignored.",
  10485. GetAttributesTargetListString(targetOverride).c_str(), GetAttributesTargetListString(attrTarget).c_str()), attributesDirective->mAttributeTargetSpecifier); // CS0657
  10486. success = false;
  10487. }
  10488. }
  10489. if ((success) && (targetOverride != (BfAttributeTargets)0))
  10490. {
  10491. if ((mCurMethodInstance != NULL) && (targetOverride == BfAttributeTargets_ReturnValue) && (attrTarget == BfAttributeTargets_Method))
  10492. {
  10493. auto methodInfoEx = mCurMethodInstance->GetMethodInfoEx();
  10494. if (methodInfoEx->mMethodCustomAttributes == NULL)
  10495. methodInfoEx->mMethodCustomAttributes = new BfMethodCustomAttributes();
  10496. if (success)
  10497. {
  10498. if (methodInfoEx->mMethodCustomAttributes->mReturnCustomAttributes == NULL)
  10499. methodInfoEx->mMethodCustomAttributes->mReturnCustomAttributes = new BfCustomAttributes();
  10500. methodInfoEx->mMethodCustomAttributes->mReturnCustomAttributes->mAttributes.push_back(customAttribute);
  10501. }
  10502. }
  10503. // Mark as failed since we don't actually want to add this to the custom attributes set
  10504. success = false;
  10505. }
  10506. if (success)
  10507. {
  10508. if ((attrTypeInst->mAttributeData->mFlags & BfAttributeFlag_DisallowAllowMultiple) != 0)
  10509. {
  10510. for (auto& prevCustomAttribute : customAttributes->mAttributes)
  10511. {
  10512. if (prevCustomAttribute.mType == attrTypeInst)
  10513. {
  10514. Fail(StrFormat("Duplicate '%s' attribute", attributesDirective->mAttributeTypeRef->ToCleanAttributeString().c_str()), attributesDirective->mAttributeTypeRef); // CS0579
  10515. }
  10516. }
  10517. }
  10518. }
  10519. if (success)
  10520. {
  10521. customAttributes->mAttributes.push_back(customAttribute);
  10522. }
  10523. }
  10524. ValidateCustomAttributes(customAttributes, attrTarget);
  10525. }
  10526. BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags, BfCaptureInfo* captureInfo)
  10527. {
  10528. BfCustomAttributes* customAttributes = new BfCustomAttributes();
  10529. GetCustomAttributes(customAttributes, attributesDirective, attrType, flags, captureInfo);
  10530. return customAttributes;
  10531. }
  10532. BfCustomAttributes* BfModule::GetCustomAttributes(BfTypeDef* typeDef)
  10533. {
  10534. BF_ASSERT(mCompiler->IsAutocomplete());
  10535. BfAttributeTargets attrTarget;
  10536. if (typeDef->mIsDelegate)
  10537. attrTarget = BfAttributeTargets_Delegate;
  10538. else if (typeDef->mIsFunction)
  10539. attrTarget = BfAttributeTargets_Function;
  10540. else if (typeDef->mTypeCode == BfTypeCode_Enum)
  10541. attrTarget = BfAttributeTargets_Enum;
  10542. else if (typeDef->mTypeCode == BfTypeCode_Interface)
  10543. attrTarget = BfAttributeTargets_Interface;
  10544. else if (typeDef->mTypeCode == BfTypeCode_Struct)
  10545. attrTarget = BfAttributeTargets_Struct;
  10546. else
  10547. attrTarget = BfAttributeTargets_Class;
  10548. return GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget);
  10549. }
  10550. void BfModule::FinishAttributeState(BfAttributeState* attributeState)
  10551. {
  10552. if ((!attributeState->mUsed) && (attributeState->mSrc != NULL))
  10553. Warn(0, "Unused attributes", attributeState->mSrc);
  10554. }
  10555. void BfModule::ProcessTypeInstCustomAttributes(int& packing, bool& isUnion, bool& isCRepr, bool& isOrdered, int& alignOverride, BfType*& underlyingArrayType, int& underlyingArraySize)
  10556. {
  10557. if (mCurTypeInstance->mTypeDef->mIsAlwaysInclude)
  10558. mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_Type);
  10559. if (mCurTypeInstance->mCustomAttributes != NULL)
  10560. {
  10561. for (auto& customAttribute : mCurTypeInstance->mCustomAttributes->mAttributes)
  10562. {
  10563. String typeName = TypeToString(customAttribute.mType);
  10564. if (typeName == "System.PackedAttribute")
  10565. {
  10566. packing = 1;
  10567. if (customAttribute.mCtorArgs.size() >= 1)
  10568. {
  10569. auto alignConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  10570. int checkPacking = alignConstant->mInt32;
  10571. if (((checkPacking & (checkPacking - 1)) == 0) && (packing > 0) && (packing < 256))
  10572. packing = checkPacking;
  10573. else
  10574. Fail("Packing must be a power of 2", customAttribute.GetRefNode());
  10575. }
  10576. }
  10577. else if (typeName == "System.UnionAttribute")
  10578. {
  10579. isUnion = true;
  10580. }
  10581. else if (typeName == "System.CReprAttribute")
  10582. {
  10583. isCRepr = true;
  10584. isOrdered = true;
  10585. }
  10586. else if (typeName == "System.OrderedAttribute")
  10587. {
  10588. isOrdered = true;
  10589. }
  10590. else if (typeName == "System.AlwaysIncludeAttribute")
  10591. {
  10592. mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_Type);
  10593. for (auto setProp : customAttribute.mSetProperties)
  10594. {
  10595. BfPropertyDef* propertyDef = setProp.mPropertyRef;
  10596. if (propertyDef->mName == "AssumeInstantiated")
  10597. {
  10598. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10599. if ((constant != NULL) && (constant->mBool))
  10600. mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_AssumeInstantiated);
  10601. }
  10602. else if (propertyDef->mName == "IncludeAllMethods")
  10603. {
  10604. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10605. if ((constant != NULL) && (constant->mBool))
  10606. mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_IncludeAllMethods);
  10607. }
  10608. }
  10609. }
  10610. else if (typeName == "System.AlignAttribute")
  10611. {
  10612. if (customAttribute.mCtorArgs.size() >= 1)
  10613. {
  10614. auto alignConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  10615. int checkAlign = alignConstant->mInt32;
  10616. if ((checkAlign & (checkAlign - 1)) == 0)
  10617. alignOverride = checkAlign;
  10618. else
  10619. Fail("Alignment must be a power of 2", customAttribute.GetRefNode());
  10620. }
  10621. }
  10622. else if (typeName == "System.UnderlyingArrayAttribute")
  10623. {
  10624. if (customAttribute.mCtorArgs.size() >= 2)
  10625. {
  10626. auto typeConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  10627. auto sizeConstant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[1]);
  10628. if ((typeConstant != NULL) && (sizeConstant != NULL) && (typeConstant->mConstType == BfConstType_TypeOf))
  10629. {
  10630. underlyingArrayType = (BfType*)(intptr)typeConstant->mInt64;
  10631. underlyingArraySize = sizeConstant->mInt32;
  10632. }
  10633. }
  10634. }
  10635. if (customAttribute.mType->mAttributeData == NULL)
  10636. PopulateType(customAttribute.mType);
  10637. BF_ASSERT(customAttribute.mType->mAttributeData != NULL);
  10638. if ((customAttribute.mType->mAttributeData != NULL) && ((customAttribute.mType->mAttributeData->mAlwaysIncludeUser & BfAlwaysIncludeFlag_AssumeInstantiated) != 0))
  10639. mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | customAttribute.mType->mAttributeData->mAlwaysIncludeUser);
  10640. }
  10641. }
  10642. }
  10643. // Checking to see if we're an attribute or not
  10644. void BfModule::ProcessCustomAttributeData()
  10645. {
  10646. if (mCurTypeInstance->mAttributeData != NULL)
  10647. return;
  10648. bool isAttribute = false;
  10649. auto checkTypeInst = mCurTypeInstance->mBaseType;
  10650. while (checkTypeInst != NULL)
  10651. {
  10652. if (checkTypeInst->IsInstanceOf(mCompiler->mAttributeTypeDef))
  10653. isAttribute = true;
  10654. checkTypeInst = checkTypeInst->mBaseType;
  10655. }
  10656. if (!isAttribute)
  10657. return;
  10658. auto attributeData = new BfAttributeData();
  10659. bool hasCustomAttribute = false;
  10660. if (mCurTypeInstance->mCustomAttributes != NULL)
  10661. {
  10662. for (auto& customAttribute : mCurTypeInstance->mCustomAttributes->mAttributes)
  10663. {
  10664. if (customAttribute.mType->IsInstanceOf(mCompiler->mAttributeUsageAttributeTypeDef))
  10665. {
  10666. if (customAttribute.mCtorArgs.size() > 0)
  10667. {
  10668. auto constant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  10669. if ((constant != NULL) && (mBfIRBuilder->IsInt(constant->mTypeCode)))
  10670. attributeData->mAttributeTargets = (BfAttributeTargets)constant->mInt32;
  10671. }
  10672. if (customAttribute.mCtorArgs.size() == 2)
  10673. {
  10674. auto constant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]);
  10675. if ((constant != NULL) && (mBfIRBuilder->IsInt(constant->mTypeCode)))
  10676. {
  10677. attributeData->mFlags = (BfAttributeFlags)constant->mInt32;
  10678. }
  10679. }
  10680. for (auto& setProp : customAttribute.mSetProperties)
  10681. {
  10682. BfPropertyDef* propDef = setProp.mPropertyRef;
  10683. if (propDef->mName == "AllowMultiple")
  10684. {
  10685. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10686. if ((constant != NULL) && (constant->mBool))
  10687. attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags & ~BfAttributeFlag_DisallowAllowMultiple);
  10688. else
  10689. attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags | BfAttributeFlag_DisallowAllowMultiple);
  10690. }
  10691. else if (propDef->mName == "Inherited")
  10692. {
  10693. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10694. if ((constant != NULL) && (constant->mBool))
  10695. attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags & ~BfAttributeFlag_NotInherited);
  10696. else
  10697. attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags | BfAttributeFlag_NotInherited);
  10698. }
  10699. else if (propDef->mName == "ValidOn")
  10700. {
  10701. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10702. if (constant != NULL)
  10703. attributeData->mAttributeTargets = (BfAttributeTargets)constant->mInt32;
  10704. }
  10705. else if (propDef->mName == "AlwaysIncludeUser")
  10706. {
  10707. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  10708. if (constant != NULL)
  10709. attributeData->mAlwaysIncludeUser = (BfAlwaysIncludeFlags)constant->mInt32;
  10710. }
  10711. }
  10712. hasCustomAttribute = true;
  10713. }
  10714. }
  10715. }
  10716. if ((!hasCustomAttribute) && (mCurTypeInstance->mBaseType->mAttributeData != NULL))
  10717. {
  10718. attributeData->mAttributeTargets = mCurTypeInstance->mBaseType->mAttributeData->mAttributeTargets;
  10719. attributeData->mFlags = mCurTypeInstance->mBaseType->mAttributeData->mFlags;
  10720. attributeData->mAlwaysIncludeUser = mCurTypeInstance->mBaseType->mAttributeData->mAlwaysIncludeUser;
  10721. }
  10722. mCurTypeInstance->mAttributeData = attributeData;
  10723. }
  10724. bool BfModule::TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue, StringImpl& str)
  10725. {
  10726. auto constant = constHolder->GetConstant(irValue);
  10727. if (constant == NULL)
  10728. return false;
  10729. if (constant->mTypeCode != BfTypeCode_StringId)
  10730. return false;
  10731. int stringId = constant->mInt32;
  10732. BfStringPoolEntry* entry = NULL;
  10733. if (mContext->mStringObjectIdMap.TryGetValue(stringId, &entry))
  10734. {
  10735. str += entry->mString;
  10736. }
  10737. else
  10738. {
  10739. BF_DBG_FATAL("Failed to find string by id");
  10740. }
  10741. return true;
  10742. }
  10743. BfVariant BfModule::TypedValueToVariant(BfAstNode* refNode, const BfTypedValue& value, bool allowUndef)
  10744. {
  10745. BfVariant variant;
  10746. variant.mTypeCode = BfTypeCode_None;
  10747. BfType* primType = NULL;
  10748. if (value.mType->IsPrimitiveType())
  10749. primType = (BfPrimitiveType*)value.mType;
  10750. else if (value.mType->IsTypedPrimitive())
  10751. primType = value.mType->GetUnderlyingType();
  10752. else if (value.mType->IsInstanceOf(mCompiler->mStringTypeDef))
  10753. primType = value.mType;
  10754. if (primType)
  10755. {
  10756. auto constant = mBfIRBuilder->GetConstant(value.mValue);
  10757. if (constant != NULL)
  10758. {
  10759. if ((allowUndef) && (constant->mConstType == BfConstType_Undef))
  10760. {
  10761. variant.mUInt64 = 0;
  10762. variant.mTypeCode = BfTypeCode_Let;
  10763. return variant;
  10764. }
  10765. if (constant->mConstType == BfConstType_GlobalVar)
  10766. {
  10767. int stringIdx = GetStringPoolIdx(value.mValue, mBfIRBuilder);
  10768. if (stringIdx != -1)
  10769. {
  10770. variant.mTypeCode = BfTypeCode_StringId;
  10771. variant.mInt64 = stringIdx;
  10772. return variant;
  10773. }
  10774. }
  10775. switch (constant->mTypeCode)
  10776. {
  10777. case BfTypeCode_Boolean:
  10778. case BfTypeCode_Int8:
  10779. case BfTypeCode_UInt8:
  10780. case BfTypeCode_Int16:
  10781. case BfTypeCode_UInt16:
  10782. case BfTypeCode_Int32:
  10783. case BfTypeCode_UInt32:
  10784. case BfTypeCode_Int64:
  10785. case BfTypeCode_UInt64:
  10786. case BfTypeCode_IntPtr:
  10787. case BfTypeCode_UIntPtr:
  10788. case BfTypeCode_IntUnknown:
  10789. case BfTypeCode_UIntUnknown:
  10790. case BfTypeCode_Double:
  10791. case BfTypeCode_Char8:
  10792. case BfTypeCode_Char16:
  10793. case BfTypeCode_Char32:
  10794. case BfTypeCode_StringId:
  10795. variant.mTypeCode = constant->mTypeCode;
  10796. variant.mInt64 = constant->mInt64;
  10797. break;
  10798. case BfTypeCode_Float:
  10799. variant.mTypeCode = constant->mTypeCode;
  10800. variant.mSingle = (float)constant->mDouble;
  10801. break;
  10802. default:
  10803. if (refNode != NULL)
  10804. Fail("Invalid const expression type", refNode);
  10805. break;
  10806. }
  10807. }
  10808. }
  10809. return variant;
  10810. }
  10811. BfTypedValue BfModule::RemoveRef(BfTypedValue typedValue)
  10812. {
  10813. if ((typedValue.mType != NULL) && (typedValue.mType->IsRef()))
  10814. {
  10815. auto refType = (BfRefType*)typedValue.mType;
  10816. auto elementType = typedValue.mType->GetUnderlyingType();
  10817. if (typedValue.IsAddr())
  10818. {
  10819. if (elementType->IsValuelessType())
  10820. {
  10821. BF_ASSERT(!typedValue.mValue);
  10822. typedValue = BfTypedValue(typedValue.mValue, elementType, true);
  10823. }
  10824. else
  10825. typedValue = BfTypedValue(mBfIRBuilder->CreateAlignedLoad(typedValue.mValue, elementType->mAlign), elementType, true);
  10826. }
  10827. else
  10828. typedValue = BfTypedValue(typedValue.mValue, elementType, true);
  10829. if (typedValue.mType->IsValuelessType())
  10830. {
  10831. BF_ASSERT(typedValue.mValue.IsFake());
  10832. }
  10833. if (refType->mRefKind == BfRefType::RefKind_In)
  10834. {
  10835. if (typedValue.mKind == BfTypedValueKind_Addr)
  10836. typedValue.mKind = BfTypedValueKind_ReadOnlyAddr;
  10837. }
  10838. }
  10839. return typedValue;
  10840. }
  10841. BfTypedValue BfModule::ToRef(BfTypedValue typedValue, BfRefType* refType)
  10842. {
  10843. if (refType == NULL)
  10844. refType = CreateRefType(typedValue.mType);
  10845. if ((refType->mRefKind == BfRefType::RefKind_Mut) && (typedValue.mType->IsObjectOrInterface()))
  10846. {
  10847. return LoadValue(typedValue);
  10848. }
  10849. if (refType->mRefKind == BfRefType::RefKind_Mut)
  10850. refType = CreateRefType(typedValue.mType);
  10851. if (!typedValue.mType->IsValuelessType())
  10852. typedValue = MakeAddressable(typedValue, false, true);
  10853. return BfTypedValue(typedValue.mValue, refType);
  10854. }
  10855. BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bool isVolatile)
  10856. {
  10857. if (!typedValue.IsAddr())
  10858. return typedValue;
  10859. PopulateType(typedValue.mType);
  10860. if ((typedValue.mType->IsValuelessType()) || (typedValue.mType->IsVar()))
  10861. return BfTypedValue(mBfIRBuilder->GetFakeVal(), typedValue.mType, false);
  10862. if (typedValue.mValue.IsConst())
  10863. {
  10864. auto constantValue = mBfIRBuilder->GetConstant(typedValue.mValue);
  10865. if (constantValue != NULL)
  10866. {
  10867. if (constantValue->mConstType == BfConstType_GlobalVar)
  10868. {
  10869. auto globalVar = (BfGlobalVar*)constantValue;
  10870. if (globalVar->mName[0] == '#')
  10871. {
  10872. BfTypedValue result = GetCompilerFieldValue(globalVar->mName);
  10873. if (result)
  10874. {
  10875. // We want to avoid 'unreachable code' issues from values that
  10876. // are technically constant but change depending on compilation context
  10877. if (mCurMethodState != NULL)
  10878. {
  10879. auto checkScope = mCurMethodState->mCurScope;
  10880. while (checkScope != NULL)
  10881. {
  10882. checkScope->mSupressNextUnreachable = true;
  10883. checkScope = checkScope->mPrevScope;
  10884. }
  10885. }
  10886. return result;
  10887. }
  10888. return GetDefaultTypedValue(typedValue.mType);
  10889. }
  10890. }
  10891. if ((mIsComptimeModule) && (mCompiler->mCeMachine->mDebugger != NULL) && (mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
  10892. {
  10893. auto ceDebugger = mCompiler->mCeMachine->mDebugger;
  10894. auto ceContext = ceDebugger->mCurDbgState->mCeContext;
  10895. auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
  10896. auto ceTypedValue = ceDebugger->GetAddr(constantValue);
  10897. if (ceTypedValue)
  10898. {
  10899. if ((typedValue.mType->IsObjectOrInterface()) || (typedValue.mType->IsPointer()) || (typedValue.mType->IsRef()))
  10900. {
  10901. void* data = ceContext->GetMemoryPtr((addr_ce)ceTypedValue.mAddr, sizeof(addr_ce));
  10902. if (data == NULL)
  10903. {
  10904. Fail("Invalid address", refNode);
  10905. return GetDefaultTypedValue(typedValue.mType);
  10906. }
  10907. uint64 dataAddr;
  10908. if (mSystem->mPtrSize == 4)
  10909. dataAddr = *(uint32*)data;
  10910. else
  10911. dataAddr = *(uint64*)data;
  10912. return BfTypedValue(mBfIRBuilder->CreateIntToPtr(
  10913. mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, dataAddr), mBfIRBuilder->MapType(typedValue.mType)), typedValue.mType);
  10914. }
  10915. auto constVal = ceContext->CreateConstant(this, ceContext->mMemory.mVals + ceTypedValue.mAddr, typedValue.mType);
  10916. if (!constVal)
  10917. {
  10918. Fail("Failed to create const", refNode);
  10919. return GetDefaultTypedValue(typedValue.mType);
  10920. }
  10921. return BfTypedValue(constVal, typedValue.mType);
  10922. }
  10923. }
  10924. }
  10925. }
  10926. BfIRValue loadedVal = typedValue.mValue;
  10927. if (loadedVal)
  10928. {
  10929. if (typedValue.mType->IsVar())
  10930. {
  10931. return BfTypedValue(loadedVal, typedValue.mType, false);
  10932. }
  10933. /*if (isVolatile)
  10934. mBfIRBuilder->CreateFence(BfIRFenceType_AcquireRelease);*/
  10935. PopulateType(typedValue.mType, BfPopulateType_Data);
  10936. loadedVal = mBfIRBuilder->CreateAlignedLoad(loadedVal, std::max(1, (int)typedValue.mType->mAlign), isVolatile);
  10937. }
  10938. return BfTypedValue(loadedVal, typedValue.mType, false);
  10939. }
  10940. BfTypedValue BfModule::PrepareConst(BfTypedValue& typedValue)
  10941. {
  10942. if (!typedValue.mValue.IsConst())
  10943. return typedValue;
  10944. auto constant = mBfIRBuilder->GetConstant(typedValue.mValue);
  10945. if (constant->mTypeCode == BfTypeCode_StringId)
  10946. return GetTypedValueFromConstant(constant, mBfIRBuilder, typedValue.mType);
  10947. return typedValue;
  10948. }
  10949. BfTypedValue BfModule::LoadOrAggregateValue(BfTypedValue typedValue)
  10950. {
  10951. if (typedValue.IsSplat())
  10952. return AggregateSplat(typedValue);
  10953. if (typedValue.IsAddr())
  10954. return LoadValue(typedValue);
  10955. return typedValue;
  10956. }
  10957. BfTypedValue BfModule::AggregateSplat(BfTypedValue typedValue, BfIRValue* valueArrPtr)
  10958. {
  10959. if (!typedValue.IsSplat())
  10960. return typedValue;
  10961. BF_ASSERT(!mIsComptimeModule);
  10962. if (typedValue.mType->IsValuelessType())
  10963. return typedValue;
  10964. int elementIdx = 0;
  10965. auto _ExtractValue = [&](BfType* checkType)
  10966. {
  10967. if (valueArrPtr != NULL)
  10968. return valueArrPtr[elementIdx++];
  10969. return ExtractSplatValue(typedValue, elementIdx++, checkType);
  10970. };
  10971. std::function<BfIRValue(BfType*)> checkTypeLambda = [&](BfType* checkType)
  10972. {
  10973. if (checkType->IsStruct())
  10974. {
  10975. BfIRValue curValue = mBfIRBuilder->CreateUndefValue(mBfIRBuilder->MapType(checkType, BfIRPopulateType_Full));
  10976. auto checkTypeInstance = checkType->ToTypeInstance();
  10977. if (checkTypeInstance->mBaseType != NULL)
  10978. {
  10979. mBfIRBuilder->PopulateType(checkTypeInstance->mBaseType, BfIRPopulateType_Full);
  10980. BfIRValue baseValue = checkTypeLambda(checkTypeInstance->mBaseType);
  10981. curValue = mBfIRBuilder->CreateInsertValue(curValue, baseValue, 0);
  10982. }
  10983. if (checkTypeInstance->mIsUnion)
  10984. {
  10985. auto unionInnerType = checkTypeInstance->GetUnionInnerType();
  10986. if (!unionInnerType->IsValuelessType())
  10987. {
  10988. BfIRValue fieldValue = checkTypeLambda(unionInnerType);
  10989. curValue = mBfIRBuilder->CreateInsertValue(curValue, fieldValue, 1);
  10990. }
  10991. if (checkTypeInstance->IsEnum())
  10992. {
  10993. auto dscrType = checkTypeInstance->GetDiscriminatorType();
  10994. BfIRValue fieldValue = checkTypeLambda(dscrType);
  10995. curValue = mBfIRBuilder->CreateInsertValue(curValue, fieldValue, 2);
  10996. }
  10997. }
  10998. else
  10999. {
  11000. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  11001. {
  11002. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  11003. if (fieldInstance->mDataIdx >= 0)
  11004. {
  11005. BfIRValue fieldValue = checkTypeLambda(fieldInstance->GetResolvedType());
  11006. curValue = mBfIRBuilder->CreateInsertValue(curValue, fieldValue, fieldInstance->mDataIdx);
  11007. }
  11008. }
  11009. }
  11010. return curValue;
  11011. }
  11012. else if (checkType->IsMethodRef())
  11013. {
  11014. BfMethodRefType* methodRefType = (BfMethodRefType*)checkType;
  11015. BfIRValue curValue = mBfIRBuilder->CreateUndefValue(mBfIRBuilder->MapType(checkType, BfIRPopulateType_Full));
  11016. for (int dataIdx = 0; dataIdx < methodRefType->GetCaptureDataCount(); dataIdx++)
  11017. {
  11018. BfIRValue fieldValue;
  11019. auto checkType = methodRefType->GetCaptureType(dataIdx);
  11020. if (methodRefType->WantsDataPassedAsSplat(dataIdx))
  11021. {
  11022. fieldValue = checkTypeLambda(checkType);
  11023. }
  11024. else
  11025. {
  11026. fieldValue = _ExtractValue(checkType);
  11027. }
  11028. curValue = mBfIRBuilder->CreateInsertValue(curValue, fieldValue, dataIdx);
  11029. }
  11030. return curValue;
  11031. }
  11032. else if (!checkType->IsValuelessType())
  11033. {
  11034. return _ExtractValue(checkType);
  11035. }
  11036. return BfIRValue();
  11037. };
  11038. BfIRValue value = checkTypeLambda(typedValue.mType);
  11039. return BfTypedValue(value, typedValue.mType, typedValue.IsThis() ? BfTypedValueKind_ThisValue : BfTypedValueKind_Value);
  11040. }
  11041. void BfModule::AggregateSplatIntoAddr(BfTypedValue typedValue, BfIRValue addrVal)
  11042. {
  11043. if (!typedValue.IsSplat())
  11044. return;
  11045. if (typedValue.mType->IsValuelessType())
  11046. return;
  11047. BF_ASSERT(!mIsComptimeModule);
  11048. /*static int sCallIdx = 0;
  11049. if (!mCompiler->mIsResolveOnly)
  11050. sCallIdx++;
  11051. int callIdx = sCallIdx;*/
  11052. int elementIdx = 0;
  11053. std::function<void(BfType*, BfIRValue)> checkTypeLambda = [&](BfType* checkType, BfIRValue curAddrVal)
  11054. {
  11055. if (checkType->IsStruct())
  11056. {
  11057. auto checkTypeInstance = checkType->ToTypeInstance();
  11058. if (checkTypeInstance->mBaseType != NULL)
  11059. {
  11060. mBfIRBuilder->PopulateType(checkTypeInstance->mBaseType);
  11061. auto baseAddrVal = mBfIRBuilder->CreateInBoundsGEP(curAddrVal, 0, 0);
  11062. checkTypeLambda(checkTypeInstance->mBaseType, baseAddrVal);
  11063. }
  11064. if (checkTypeInstance->mIsUnion)
  11065. {
  11066. auto unionInnerType = checkTypeInstance->GetUnionInnerType();
  11067. if (!unionInnerType->IsValuelessType())
  11068. {
  11069. auto fieldAddrVal = mBfIRBuilder->CreateInBoundsGEP(curAddrVal, 0, 1);
  11070. checkTypeLambda(unionInnerType, fieldAddrVal);
  11071. }
  11072. if (checkTypeInstance->IsEnum())
  11073. {
  11074. auto dscrType = checkTypeInstance->GetDiscriminatorType();
  11075. auto fieldAddrVal = mBfIRBuilder->CreateInBoundsGEP(curAddrVal, 0, 2);
  11076. checkTypeLambda(dscrType, fieldAddrVal);
  11077. }
  11078. }
  11079. else
  11080. {
  11081. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  11082. {
  11083. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  11084. if (fieldInstance->mDataIdx >= 0)
  11085. {
  11086. auto fieldAddrVal = mBfIRBuilder->CreateInBoundsGEP(curAddrVal, 0, fieldInstance->mDataIdx);
  11087. checkTypeLambda(fieldInstance->mResolvedType, fieldAddrVal);
  11088. }
  11089. }
  11090. }
  11091. }
  11092. else if (checkType->IsMethodRef())
  11093. {
  11094. BfMethodRefType* methodRefType = (BfMethodRefType*)checkType;
  11095. for (int dataIdx = 0; dataIdx < methodRefType->GetCaptureDataCount(); dataIdx++)
  11096. {
  11097. auto dataType = methodRefType->GetCaptureType(dataIdx);
  11098. auto fieldAddrVal = mBfIRBuilder->CreateInBoundsGEP(curAddrVal, 0, dataIdx);
  11099. if (methodRefType->WantsDataPassedAsSplat(dataIdx))
  11100. {
  11101. checkTypeLambda(methodRefType->GetCaptureType(dataIdx), fieldAddrVal);
  11102. }
  11103. else
  11104. {
  11105. // static int sItrCount = 0;
  11106. // sItrCount++;
  11107. // int curItr = sItrCount;
  11108. // if (curItr == 1)
  11109. // {
  11110. // NOP;
  11111. // }
  11112. auto val = ExtractSplatValue(typedValue, elementIdx++, dataType);
  11113. mBfIRBuilder->CreateStore(val, fieldAddrVal);
  11114. }
  11115. }
  11116. }
  11117. else if (!checkType->IsValuelessType())
  11118. {
  11119. auto val = ExtractSplatValue(typedValue, elementIdx++, checkType);
  11120. mBfIRBuilder->CreateStore(val, curAddrVal);
  11121. }
  11122. };
  11123. checkTypeLambda(typedValue.mType, addrVal);
  11124. }
  11125. BfTypedValue BfModule::MakeAddressable(BfTypedValue typedVal, bool forceMutable, bool forceAddressable)
  11126. {
  11127. bool wasReadOnly = typedVal.IsReadOnly();
  11128. if ((forceAddressable) ||
  11129. ((typedVal.mType->IsValueType()) &&
  11130. (!typedVal.mType->IsValuelessType())))
  11131. {
  11132. wasReadOnly = true; // Any non-addr is implicitly read-only
  11133. //static int gCallIdx = 0;
  11134. FixValueActualization(typedVal);
  11135. if (typedVal.IsAddr())
  11136. return typedVal;
  11137. BfType* type = typedVal.mType;
  11138. PopulateType(type);
  11139. BfIRValue tempVar;
  11140. if (typedVal.mValue.IsFake())
  11141. tempVar = mBfIRBuilder->GetFakeVal();
  11142. else
  11143. {
  11144. tempVar = CreateAlloca(type);
  11145. if (typedVal.IsSplat())
  11146. AggregateSplatIntoAddr(typedVal, tempVar);
  11147. else
  11148. mBfIRBuilder->CreateAlignedStore(typedVal.mValue, tempVar, type->mAlign);
  11149. }
  11150. if (forceMutable)
  11151. wasReadOnly = false;
  11152. return BfTypedValue(tempVar, type,
  11153. typedVal.IsThis() ?
  11154. (wasReadOnly ? BfTypedValueKind_ReadOnlyThisAddr : BfTypedValueKind_ThisAddr) :
  11155. (wasReadOnly ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr));
  11156. }
  11157. return LoadValue(typedVal);
  11158. }
  11159. BfTypedValue BfModule::RemoveReadOnly(BfTypedValue typedValue)
  11160. {
  11161. if (typedValue.mKind == BfTypedValueKind_ReadOnlyAddr)
  11162. typedValue.mKind = BfTypedValueKind_Addr;
  11163. return typedValue;
  11164. }
  11165. BfTypedValue BfModule::CopyValue(const BfTypedValue& typedValue)
  11166. {
  11167. return MakeAddressable(LoadValue(typedValue), true);
  11168. }
  11169. BfIRValue BfModule::ExtractSplatValue(BfTypedValue typedValue, int componentIdx, BfType* wantType, bool* isAddr)
  11170. {
  11171. BF_ASSERT(!mIsComptimeModule);
  11172. BfIRValue val;
  11173. if (typedValue.mValue.IsArg())
  11174. {
  11175. val = mBfIRBuilder->GetArgument(typedValue.mValue.mId + componentIdx);
  11176. if (isAddr != NULL)
  11177. {
  11178. if (wantType != NULL)
  11179. *isAddr = wantType->IsComposite();
  11180. else
  11181. *isAddr = false;
  11182. }
  11183. else if (wantType->IsComposite())
  11184. val = mBfIRBuilder->CreateLoad(val);
  11185. }
  11186. if (!val)
  11187. {
  11188. auto checkMethodState = mCurMethodState;
  11189. while (checkMethodState != NULL)
  11190. {
  11191. for (int idx = 0; idx < (int)checkMethodState->mSplatDecompAddrs.size(); idx++)
  11192. {
  11193. auto decompAddr = checkMethodState->mSplatDecompAddrs[idx];
  11194. if (decompAddr == typedValue.mValue)
  11195. {
  11196. val = checkMethodState->mSplatDecompAddrs[idx + componentIdx];
  11197. if ((wantType->IsComposite()) && (typedValue.mType->IsMethodRef()))
  11198. {
  11199. // This is really backing for a POINTER to a composite inside a methodRef
  11200. val = mBfIRBuilder->CreateLoad(val);
  11201. }
  11202. if ((isAddr != NULL) && (typedValue.mKind != BfTypedValueKind_SplatHead_NeedsCasting))
  11203. {
  11204. *isAddr = true;
  11205. return val;
  11206. }
  11207. else
  11208. {
  11209. val = mBfIRBuilder->CreateAlignedLoad(val, wantType->mAlign);
  11210. break;
  11211. }
  11212. }
  11213. }
  11214. if (val)
  11215. break;
  11216. if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mCapturing))
  11217. {
  11218. BF_ASSERT(mBfIRBuilder->mIgnoreWrites);
  11219. return mBfIRBuilder->GetFakeVal();
  11220. }
  11221. checkMethodState = checkMethodState->mPrevMethodState;
  11222. }
  11223. }
  11224. if (val)
  11225. {
  11226. if (typedValue.mKind == BfTypedValueKind_SplatHead_NeedsCasting)
  11227. {
  11228. BF_ASSERT(wantType != NULL);
  11229. if (wantType != NULL)
  11230. return mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(wantType));
  11231. }
  11232. return val;
  11233. }
  11234. BFMODULE_FATAL(this, "Splat not found");
  11235. return BfIRValue();
  11236. }
  11237. BfTypedValue BfModule::ExtractValue(BfTypedValue typedValue, BfFieldInstance* fieldInstance, int fieldIdx)
  11238. {
  11239. int useFieldIdx = fieldIdx;
  11240. BfType* fieldType = NULL;
  11241. if (fieldInstance != NULL)
  11242. {
  11243. fieldType = fieldInstance->mResolvedType;
  11244. if (typedValue.mType->IsUnion())
  11245. {
  11246. if (fieldIdx == 1)
  11247. {
  11248. if (typedValue.IsSplat())
  11249. {
  11250. BfTypedValue innerVal = typedValue;
  11251. innerVal.mType = fieldType;
  11252. return innerVal;
  11253. }
  11254. }
  11255. }
  11256. }
  11257. else
  11258. {
  11259. if (typedValue.mType->IsPayloadEnum())
  11260. {
  11261. auto typeInst = typedValue.mType->ToTypeInstance();
  11262. if (fieldIdx == 1)
  11263. fieldType = typeInst->GetUnionInnerType();
  11264. else if (fieldIdx == 2)
  11265. {
  11266. fieldType = typeInst->GetDiscriminatorType(&useFieldIdx);
  11267. }
  11268. }
  11269. else if (typedValue.mType->IsUnion())
  11270. {
  11271. if (fieldIdx == 1)
  11272. {
  11273. fieldType = typedValue.mType->ToTypeInstance()->GetUnionInnerType();
  11274. if (typedValue.IsSplat())
  11275. {
  11276. BfTypedValue innerVal = typedValue;
  11277. innerVal.mType = fieldType;
  11278. return innerVal;
  11279. }
  11280. }
  11281. }
  11282. }
  11283. BF_ASSERT(typedValue.mType->IsStruct());
  11284. if (typedValue.IsSplat())
  11285. {
  11286. if (typedValue.mType->IsPayloadEnum())
  11287. {
  11288. if (fieldIdx == 1)
  11289. {
  11290. // Payload
  11291. auto typeInst = typedValue.mType->ToTypeInstance();
  11292. auto unionInnerType = typeInst->GetUnionInnerType();
  11293. bool isAddr = false;
  11294. BfIRValue irVal = ExtractSplatValue(typedValue, 0, unionInnerType, &isAddr);
  11295. return BfTypedValue(irVal, unionInnerType, BfTypedValueKind_SplatHead);
  11296. }
  11297. if (fieldIdx == 2)
  11298. {
  11299. // Discriminator
  11300. auto typeInst = typedValue.mType->ToTypeInstance();
  11301. auto unionInnerType = typeInst->GetUnionInnerType();
  11302. auto dscrType = typeInst->GetDiscriminatorType();
  11303. int argIdx = typedValue.mValue.mId;
  11304. int componentIdx = 0;
  11305. BfTypeUtils::SplatIterate([&](BfType* checkType) { componentIdx++; }, unionInnerType);
  11306. bool isAddr;
  11307. BfIRValue irVal = ExtractSplatValue(typedValue, componentIdx, dscrType, &isAddr);
  11308. return BfTypedValue(irVal, dscrType, isAddr);
  11309. }
  11310. }
  11311. int componentIdx = 0;
  11312. BfTypedValue retVal;
  11313. BfFieldInstance* wantFieldInstance = fieldInstance;
  11314. std::function<void(BfType*)> checkTypeLambda = [&](BfType* checkType)
  11315. {
  11316. if (checkType->IsStruct())
  11317. {
  11318. auto checkTypeInstance = checkType->ToTypeInstance();
  11319. if ((checkType->IsUnion()) || (checkType->IsEnum()))
  11320. {
  11321. //TODO: Why did we have this removed? It messed up an extraction from a nullable splattable
  11322. fieldType = checkTypeInstance->GetUnionInnerType();
  11323. checkTypeLambda(fieldType);
  11324. if (checkType->IsEnum())
  11325. {
  11326. // Past discriminator...
  11327. componentIdx++;
  11328. }
  11329. return;
  11330. }
  11331. if (checkTypeInstance->mBaseType != NULL)
  11332. checkTypeLambda(checkTypeInstance->mBaseType);
  11333. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  11334. {
  11335. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  11336. if (fieldInstance == wantFieldInstance)
  11337. {
  11338. if (fieldInstance->mResolvedType->IsValuelessType())
  11339. {
  11340. retVal = GetDefaultTypedValue(fieldInstance->mResolvedType);
  11341. break;
  11342. }
  11343. bool isAddr = false;
  11344. BfIRValue val = ExtractSplatValue(typedValue, componentIdx, fieldInstance->mResolvedType, &isAddr);
  11345. retVal = BfTypedValue(val, fieldInstance->mResolvedType,
  11346. fieldInstance->mResolvedType->IsComposite() ? BfTypedValueKind_SplatHead :
  11347. isAddr ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Value);
  11348. if ((retVal.IsAddr()) && (!fieldInstance->mResolvedType->IsValueType()))
  11349. {
  11350. retVal = LoadValue(retVal);
  11351. }
  11352. break;
  11353. }
  11354. if (fieldInstance->mDataIdx >= 0)
  11355. checkTypeLambda(fieldInstance->GetResolvedType());
  11356. }
  11357. }
  11358. else if (!checkType->IsValuelessType())
  11359. {
  11360. componentIdx++;
  11361. //argIdx++;
  11362. }
  11363. };
  11364. checkTypeLambda(typedValue.mType);
  11365. BF_ASSERT(retVal);
  11366. return retVal;
  11367. }
  11368. if (typedValue.IsAddr())
  11369. {
  11370. BF_ASSERT(fieldType != NULL);
  11371. auto valRef = mBfIRBuilder->CreateInBoundsGEP(typedValue.mValue, 0, useFieldIdx);
  11372. return BfTypedValue(valRef, fieldType, BfTypedValueKind_ReadOnlyAddr);
  11373. }
  11374. else
  11375. {
  11376. BF_ASSERT(fieldType != NULL);
  11377. return BfTypedValue(mBfIRBuilder->CreateExtractValue(typedValue.mValue, useFieldIdx), fieldType, BfTypedValueKind_Value);
  11378. }
  11379. }
  11380. BfIRValue BfModule::ExtractValue(BfTypedValue typedValue, int dataIdx)
  11381. {
  11382. if (typedValue.IsAddr())
  11383. {
  11384. auto addrVal = mBfIRBuilder->CreateInBoundsGEP(typedValue.mValue, 0, dataIdx);
  11385. return mBfIRBuilder->CreateAlignedLoad(addrVal, typedValue.mType->mAlign);
  11386. }
  11387. return mBfIRBuilder->CreateExtractValue(typedValue.mValue, dataIdx);
  11388. }
  11389. BfIRValue BfModule::CreateIndexedValue(BfType* elementType, BfIRValue value, BfIRValue indexValue, bool isElementIndex)
  11390. {
  11391. if (isElementIndex)
  11392. return mBfIRBuilder->CreateInBoundsGEP(value, GetConstValue(0), indexValue);
  11393. else
  11394. return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
  11395. // if (elementType->IsSizeAligned())
  11396. // {
  11397. // if (isElementIndex)
  11398. // return mBfIRBuilder->CreateInBoundsGEP(value, GetConstValue(0), indexValue);
  11399. // else
  11400. // return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
  11401. // }
  11402. //
  11403. // auto ptrType = CreatePointerType(elementType);
  11404. // auto ofsVal = mBfIRBuilder->CreateNumericCast(indexValue, true, BfTypeCode_IntPtr);
  11405. // auto ofsScaledVal = mBfIRBuilder->CreateMul(ofsVal, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, elementType->GetStride()));
  11406. // auto i8PtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8));
  11407. // BfIRValue origPtrValue = mBfIRBuilder->CreateBitCast(value, i8PtrType);
  11408. // BfIRValue newPtrValue = mBfIRBuilder->CreateInBoundsGEP(origPtrValue, ofsScaledVal);
  11409. // return mBfIRBuilder->CreateBitCast(newPtrValue, mBfIRBuilder->MapType(ptrType));
  11410. }
  11411. BfIRValue BfModule::CreateIndexedValue(BfType* elementType, BfIRValue value, int indexValue, bool isElementIndex)
  11412. {
  11413. if (elementType->IsSizeAligned())
  11414. {
  11415. if (isElementIndex)
  11416. return mBfIRBuilder->CreateInBoundsGEP(value, 0, indexValue);
  11417. else
  11418. return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
  11419. }
  11420. return CreateIndexedValue(elementType, value, GetConstValue(indexValue), isElementIndex);
  11421. }
  11422. bool BfModule::CheckModifyValue(BfTypedValue& typedValue, BfAstNode* refNode, const char* modifyType)
  11423. {
  11424. if (modifyType == NULL)
  11425. modifyType = "modify";
  11426. if (typedValue.mType->IsVar())
  11427. return true;
  11428. if (typedValue.IsReadOnly())
  11429. {
  11430. Fail(StrFormat("Cannot %s read-only variable", modifyType), refNode);
  11431. return false;
  11432. }
  11433. if ((!typedValue.IsAddr()) && (!typedValue.mType->IsValuelessType()))
  11434. {
  11435. Fail(StrFormat("Cannot %s value", modifyType), refNode);
  11436. return false;
  11437. }
  11438. if (typedValue.mKind == BfTypedValueKind_RestrictedTempAddr)
  11439. {
  11440. Fail(StrFormat("Cannot %s temporary value", modifyType), refNode);
  11441. return false;
  11442. }
  11443. return true;
  11444. }
  11445. bool BfModule::CompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB)
  11446. {
  11447. // If one is an interface and the other is an impl, B is the impl
  11448. auto implOwner = methodB->GetOwner();
  11449. if (methodA->mMethodDef->mIsLocalMethod)
  11450. {
  11451. int sepPosA = (int)BF_MIN(methodA->mMethodDef->mName.IndexOf('@'), methodA->mMethodDef->mName.length());
  11452. int sepPosB = (int)BF_MIN(methodB->mMethodDef->mName.IndexOf('@'), methodB->mMethodDef->mName.length());
  11453. if (sepPosA != sepPosB)
  11454. return false;
  11455. if (strncmp(methodA->mMethodDef->mName.c_str(), methodB->mMethodDef->mName.c_str(), sepPosA) != 0)
  11456. return false;
  11457. }
  11458. else if (methodA->mMethodDef->mName != methodB->mMethodDef->mName)
  11459. return false;
  11460. if (methodA->mMethodDef->mCheckedKind != methodB->mMethodDef->mCheckedKind)
  11461. return false;
  11462. if (methodA->mMethodDef->mHasComptime != methodB->mMethodDef->mHasComptime)
  11463. return false;
  11464. if ((methodA->mMethodDef->mMethodType == BfMethodType_Mixin) != (methodB->mMethodDef->mMethodType == BfMethodType_Mixin))
  11465. return false;
  11466. if (methodA->mMethodDef->mMethodType == BfMethodType_Ctor)
  11467. {
  11468. if (methodA->mMethodDef->mIsStatic != methodB->mMethodDef->mIsStatic)
  11469. return false;
  11470. }
  11471. if (methodA->mMethodDef->mMethodType == BfMethodType_Operator)
  11472. {
  11473. if (methodB->mMethodDef->mMethodType != BfMethodType_Operator)
  11474. return false;
  11475. auto operatorA = (BfOperatorDef*)methodA->mMethodDef;
  11476. auto operatorB = (BfOperatorDef*)methodB->mMethodDef;
  11477. if (operatorA->mOperatorDeclaration->mUnaryOp != operatorB->mOperatorDeclaration->mUnaryOp)
  11478. return false;
  11479. if (operatorA->mOperatorDeclaration->mBinOp != operatorB->mOperatorDeclaration->mBinOp)
  11480. return false;
  11481. if (operatorA->mOperatorDeclaration->mAssignOp != operatorB->mOperatorDeclaration->mAssignOp)
  11482. return false;
  11483. if (operatorA->mOperatorDeclaration->mIsConvOperator)
  11484. {
  11485. if (!BfTypeUtils::TypeEquals(methodA->mReturnType, methodB->mReturnType, implOwner))
  11486. return false;
  11487. }
  11488. }
  11489. int implicitParamCountA = methodA->GetImplicitParamCount();
  11490. int implicitParamCountB = methodB->GetImplicitParamCount();
  11491. if (methodA->GetParamCount() - implicitParamCountA != methodB->GetParamCount() - implicitParamCountB)
  11492. return false;
  11493. if (methodA->mHadGenericDelegateParams != methodB->mHadGenericDelegateParams)
  11494. return false;
  11495. for (int paramIdx = 0; paramIdx < (int)methodA->GetParamCount() - implicitParamCountA; paramIdx++)
  11496. {
  11497. if ((!BfTypeUtils::TypeEquals(methodA->GetParamType(paramIdx + implicitParamCountA), methodB->GetParamType(paramIdx + implicitParamCountB), implOwner)) ||
  11498. (methodA->GetParamKind(paramIdx + implicitParamCountA) != methodB->GetParamKind(paramIdx + implicitParamCountB)))
  11499. return false;
  11500. }
  11501. // Compare generic params. Generic params are part of the method signature here
  11502. if (methodA->GetNumGenericParams() != methodB->GetNumGenericParams())
  11503. return false;
  11504. for (int genericParamIdx = 0; genericParamIdx < (int)methodA->GetNumGenericParams(); genericParamIdx++)
  11505. {
  11506. auto genericParamA = methodA->mMethodInfoEx->mGenericParams[genericParamIdx];
  11507. auto genericParamB = methodB->mMethodInfoEx->mGenericParams[genericParamIdx];
  11508. if (genericParamA->mGenericParamFlags != genericParamB->mGenericParamFlags)
  11509. return false;
  11510. if (genericParamA->mTypeConstraint != genericParamB->mTypeConstraint)
  11511. return false;
  11512. if (genericParamA->mInterfaceConstraints.size() != genericParamB->mInterfaceConstraints.size())
  11513. return false;
  11514. for (int interfaceIdx = 0; interfaceIdx < (int)genericParamA->mInterfaceConstraints.size(); interfaceIdx++)
  11515. if (genericParamA->mInterfaceConstraints[interfaceIdx] != genericParamB->mInterfaceConstraints[interfaceIdx])
  11516. return false;
  11517. }
  11518. return true;
  11519. }
  11520. bool BfModule::StrictCompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB)
  11521. {
  11522. if (!CompareMethodSignatures(methodA, methodB))
  11523. return false;
  11524. if (methodA->mReturnType != methodB->mReturnType)
  11525. return false;
  11526. if (methodA->mMethodDef->mIsStatic != methodB->mMethodDef->mIsStatic)
  11527. return false;
  11528. return true;
  11529. }
  11530. bool BfModule::IsCompatibleInterfaceMethod(BfMethodInstance* iMethodInst, BfMethodInstance* methodInstance)
  11531. {
  11532. if ((iMethodInst->GetNumGenericParams() != 0) || (methodInstance->GetNumGenericParams() != 0))
  11533. return false;
  11534. if (iMethodInst->mMethodDef->mName != methodInstance->mMethodDef->mName)
  11535. return false;
  11536. if (iMethodInst->mMethodDef->mIsOperator != methodInstance->mMethodDef->mIsOperator)
  11537. return false;
  11538. if (iMethodInst->mMethodDef->mIsOperator)
  11539. {
  11540. auto iOperatorDef = (BfOperatorDef*)iMethodInst->mMethodDef;
  11541. auto operatorDef = (BfOperatorDef*)methodInstance->mMethodDef;
  11542. if (iOperatorDef->mOperatorDeclaration->mUnaryOp != operatorDef->mOperatorDeclaration->mUnaryOp)
  11543. return false;
  11544. if (iOperatorDef->mOperatorDeclaration->mBinOp != operatorDef->mOperatorDeclaration->mBinOp)
  11545. return false;
  11546. }
  11547. if (iMethodInst->GetParamCount() != methodInstance->GetParamCount())
  11548. return false;
  11549. auto selfType = methodInstance->GetOwner();
  11550. for (int paramIdx = 0; paramIdx < (int)iMethodInst->GetParamCount(); paramIdx++)
  11551. {
  11552. if (iMethodInst->GetParamKind(paramIdx) != methodInstance->GetParamKind(paramIdx))
  11553. return false;
  11554. BfType* iParamType = iMethodInst->GetParamType(paramIdx);
  11555. BfType* methodParamType = methodInstance->GetParamType(paramIdx);
  11556. iParamType = ResolveSelfType(iParamType, selfType);
  11557. methodParamType = ResolveSelfType(methodParamType, selfType);
  11558. if (!iParamType->IsGenericParam())
  11559. {
  11560. if (methodParamType != iParamType)
  11561. return false;
  11562. }
  11563. else
  11564. {
  11565. if (!methodParamType->IsGenericParam())
  11566. return false;
  11567. auto genericParamType = (BfGenericParamType*)methodParamType;
  11568. if (genericParamType->mGenericParamKind == BfGenericParamKind_Type)
  11569. return false;
  11570. auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
  11571. bool hadInterface = false;
  11572. for (auto interfaceConstraint : genericParam->mInterfaceConstraints)
  11573. if (interfaceConstraint == iParamType)
  11574. hadInterface = true;
  11575. if (!hadInterface)
  11576. return false;
  11577. }
  11578. }
  11579. return true;
  11580. }
  11581. void BfModule::AddMethodReference(const BfMethodRef& methodRef, BfGetMethodInstanceFlags flags)
  11582. {
  11583. BfMethodInstance* methodInstance = methodRef;
  11584. if ((mCurTypeInstance != NULL) && (!mCompiler->IsAutocomplete()))
  11585. {
  11586. auto methodInstanceGroup = methodInstance->mMethodInstanceGroup;
  11587. if ((methodInstance->IsSpecializedGenericMethod()) || (methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude))
  11588. {
  11589. BF_ASSERT(!methodRef.mTypeInstance->IsFunction());
  11590. // This ensures we rebuild - there are some cases where we get a method reference but never call it, so this is required here
  11591. AddDependency(methodInstance->GetOwner(), mCurTypeInstance, BfDependencyMap::DependencyFlag_Calls);
  11592. BfMethodRef methodRef = methodInstance;
  11593. BfSpecializedMethodRefInfo* specializedMethodRefInfo = NULL;
  11594. bool isNew = mCurTypeInstance->mSpecializedMethodReferences.TryAdd(methodRef, NULL, &specializedMethodRefInfo);
  11595. if (((flags & BfGetMethodInstanceFlag_Unreified) == 0) &&
  11596. ((flags & BfGetMethodInstanceFlag_NoForceReification) == 0) &&
  11597. (mIsReified))
  11598. {
  11599. specializedMethodRefInfo->mHasReifiedRef = true;
  11600. }
  11601. }
  11602. }
  11603. }
  11604. BfModuleMethodInstance BfModule::ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags)
  11605. {
  11606. if ((flags & BfGetMethodInstanceFlag_ResultNotUsed) != 0)
  11607. return BfModuleMethodInstance(methodInstance, BfIRValue());
  11608. if (mBfIRBuilder == NULL)
  11609. return BfModuleMethodInstance(methodInstance, BfIRValue());
  11610. if (methodInstance->GetOwner()->IsFunction())
  11611. {
  11612. // No actual ref needed- not an actual generated function
  11613. return BfModuleMethodInstance(methodInstance, BfIRValue());
  11614. }
  11615. bool isGenFunction = methodInstance->mMethodInstanceGroup->mMethodIdx < 0;
  11616. if (!isGenFunction)
  11617. AddMethodReference(methodInstance, flags);
  11618. if ((mBfIRBuilder->mIgnoreWrites) || ((flags & BfGetMethodInstanceFlag_Unreified) != 0))
  11619. return BfModuleMethodInstance(methodInstance, mBfIRBuilder->GetFakeVal());
  11620. if (IsSkippingExtraResolveChecks())
  11621. return BfModuleMethodInstance(methodInstance, BfIRFunction());
  11622. if (methodInstance->mMethodDef->mMethodType == BfMethodType_Mixin)
  11623. {
  11624. return BfModuleMethodInstance(methodInstance, BfIRFunction());
  11625. }
  11626. bool isInlined = (methodInstance->mAlwaysInline) || ((flags & BfGetMethodInstanceFlag_ForceInline) != 0);
  11627. if ((methodInstance->mIsIntrinsic) || (methodInstance->mMethodDef->mIsExtern))
  11628. isInlined = false;
  11629. BfMethodRef methodRef = methodInstance;
  11630. if (isInlined)
  11631. methodRef.mMethodRefFlags = (BfMethodRefFlags)(methodRef.mMethodRefFlags | BfMethodRefFlag_AlwaysInclude);
  11632. else
  11633. methodRef.mMethodRefFlags = BfMethodRefFlag_None;
  11634. if (!isGenFunction)
  11635. {
  11636. BfIRValue* irFuncPtr = NULL;
  11637. if (mFuncReferences.TryGetValue(methodRef, &irFuncPtr))
  11638. return BfModuleMethodInstance(methodInstance, *irFuncPtr);
  11639. }
  11640. if (mAwaitingInitFinish)
  11641. FinishInit();
  11642. BfIRValue func = CreateFunctionFrom(methodInstance, isGenFunction, isInlined);
  11643. if (!isGenFunction)
  11644. {
  11645. BF_ASSERT(func || methodInstance->mMethodInstanceGroup->mOwner->IsInterface());
  11646. mFuncReferences[methodRef] = func;
  11647. }
  11648. BfLogSysM("Adding func reference. Module:%p MethodInst:%p NewLLVMFunc:%d OldLLVMFunc:%d\n", this, methodInstance, func.mId, methodInstance->mIRFunction.mId);
  11649. if ((isInlined) && (!mIsScratchModule) && ((flags & BfGetMethodInstanceFlag_NoInline) == 0))
  11650. {
  11651. // We can't just add a dependency to mCurTypeInstance because we may have nested inlined functions, and
  11652. // mCurTypeInstance will just reflect the owner of the method currently being inlined, not the top-level
  11653. // type instance
  11654. // Be smarter about this if we ever insert a lot of type instances into a single module - track in a field
  11655. BF_ASSERT(mOwnedTypeInstances.size() <= 1);
  11656. for (auto ownedTypeInst : mOwnedTypeInstances)
  11657. AddDependency(methodInstance->GetOwner(), ownedTypeInst, BfDependencyMap::DependencyFlag_InlinedCall);
  11658. if ((!mCompiler->mIsResolveOnly) && (mIsReified) && (!methodInstance->mIsUnspecialized))
  11659. {
  11660. mIncompleteMethodCount++;
  11661. BfInlineMethodRequest* inlineMethodRequest = mContext->mInlineMethodWorkList.Alloc();
  11662. inlineMethodRequest->mType = methodInstance->GetOwner();
  11663. inlineMethodRequest->mFromModule = this;
  11664. inlineMethodRequest->mFunc = func;
  11665. inlineMethodRequest->mFromModuleRevision = mRevision;
  11666. inlineMethodRequest->mMethodInstance = methodInstance;
  11667. BF_ASSERT(mIsModuleMutable);
  11668. BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in ReferenceExternalMethodInstance\n", inlineMethodRequest, methodInstance, this);
  11669. }
  11670. }
  11671. return BfModuleMethodInstance(methodInstance, func);
  11672. }
  11673. BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
  11674. {
  11675. BfTypeInstance* typeInst = methodInstance->mMethodInstanceGroup->mOwner;
  11676. if (mBfIRBuilder == NULL)
  11677. {
  11678. // To allow for custom attribute data
  11679. PrepareForIRWriting(typeInst);
  11680. }
  11681. BfModule* declareModule = this;
  11682. // Get to the optionless branch head -- but this could still be a specialized method module, not the true root
  11683. while ((declareModule->mParentModule != NULL) && (!declareModule->mIsSpecializedMethodModuleRoot))
  11684. declareModule = declareModule->mParentModule;
  11685. // Check for attributes
  11686. if (typeInst == mContext->mBfObjectType)
  11687. {
  11688. auto methodDecl = methodInstance->mMethodDef->GetMethodDeclaration();
  11689. if (methodDecl != NULL)
  11690. {
  11691. auto attributesDirective = methodDecl->mAttributes;
  11692. if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))
  11693. {
  11694. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
  11695. sourceClassifier->VisitChild(attributesDirective);
  11696. }
  11697. }
  11698. }
  11699. else
  11700. {
  11701. // Only allow attributes on System.Object methods that can be handled inside the DefBuilder
  11702. GetMethodCustomAttributes(methodInstance);
  11703. }
  11704. BF_ASSERT(mModuleOptions == NULL);
  11705. if (methodInstance->GetCustomAttributes() != NULL)
  11706. {
  11707. auto project = typeInst->mTypeDef->mProject;
  11708. BfModuleOptions moduleOptions = declareModule->GetModuleOptions();
  11709. BfModuleOptions wantOptions = moduleOptions;
  11710. auto typeOptions = mSystem->GetTypeOptions(typeInst->mTypeOptionsIdx);
  11711. if (typeOptions != NULL)
  11712. {
  11713. wantOptions.mOptLevel = (BfOptLevel)BfTypeOptions::Apply((int)wantOptions.mOptLevel, (int)typeOptions->mOptimizationLevel);
  11714. wantOptions.mSIMDSetting = (BfSIMDSetting)BfTypeOptions::Apply((int)wantOptions.mSIMDSetting, typeOptions->mSIMDSetting);
  11715. wantOptions.mEmitDebugInfo = (BfSIMDSetting)BfTypeOptions::Apply((int)wantOptions.mEmitDebugInfo, typeOptions->mEmitDebugInfo);
  11716. }
  11717. if (!mCompiler->mAttributeTypeOptionMap.IsEmpty())
  11718. {
  11719. StringT<128> attrName;
  11720. for (auto& customAttrs : methodInstance->GetCustomAttributes()->mAttributes)
  11721. {
  11722. attrName.Clear();
  11723. customAttrs.mType->mTypeDef->mFullName.ToString(attrName);
  11724. Array<int>* arrPtr;
  11725. if (mCompiler->mAttributeTypeOptionMap.TryGetValue(attrName, &arrPtr))
  11726. {
  11727. for (auto optionsIdx : *arrPtr)
  11728. {
  11729. auto& typeOptions = mCompiler->mSystem->mTypeOptions[optionsIdx];
  11730. wantOptions.mOptLevel = (BfOptLevel)BfTypeOptions::Apply((int)wantOptions.mOptLevel, (int)typeOptions.mOptimizationLevel);
  11731. wantOptions.mSIMDSetting = (BfSIMDSetting)BfTypeOptions::Apply((int)wantOptions.mSIMDSetting, typeOptions.mSIMDSetting);
  11732. wantOptions.mEmitDebugInfo = (BfSIMDSetting)BfTypeOptions::Apply((int)wantOptions.mEmitDebugInfo, typeOptions.mEmitDebugInfo);
  11733. }
  11734. }
  11735. }
  11736. }
  11737. if ((HasCompiledOutput()) && (wantOptions != moduleOptions) && (!mIsScratchModule))
  11738. {
  11739. auto lastCheckModule = this;
  11740. auto checkModule = this->mNextAltModule;
  11741. while (checkModule != NULL)
  11742. {
  11743. if (*checkModule->mModuleOptions == wantOptions)
  11744. {
  11745. declareModule = checkModule;
  11746. break;
  11747. }
  11748. lastCheckModule = checkModule;
  11749. checkModule = checkModule->mNextAltModule;
  11750. }
  11751. // Not found?
  11752. if (declareModule == this)
  11753. {
  11754. String specModuleName = mModuleName + "@@";
  11755. if (wantOptions.mOptLevel != moduleOptions.mOptLevel)
  11756. specModuleName += StrFormat("O%d", wantOptions.mOptLevel);
  11757. if (wantOptions.mSIMDSetting != moduleOptions.mSIMDSetting)
  11758. specModuleName += StrFormat("SIMD%d", wantOptions.mSIMDSetting);
  11759. declareModule = new BfModule(mContext, specModuleName);
  11760. declareModule->mProject = project;
  11761. declareModule->mModuleOptions = new BfModuleOptions();
  11762. *declareModule->mModuleOptions = wantOptions;
  11763. declareModule->mParentModule = lastCheckModule;
  11764. declareModule->Init();
  11765. lastCheckModule->mNextAltModule = declareModule;
  11766. }
  11767. }
  11768. }
  11769. declareModule->PrepareForIRWriting(typeInst);
  11770. return declareModule;
  11771. }
  11772. BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
  11773. {
  11774. if (methodDef->mMethodType == BfMethodType_Init)
  11775. return BfModuleMethodInstance();
  11776. if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (mCompiler->mIsResolveOnly))
  11777. {
  11778. // Don't bother inlining for resolve-only
  11779. flags = (BfGetMethodInstanceFlags)(flags & ~BfGetMethodInstanceFlag_ForceInline);
  11780. }
  11781. if (methodDef->mIsExtern)
  11782. flags = (BfGetMethodInstanceFlags)(flags & ~BfGetMethodInstanceFlag_ForceInline);
  11783. bool processNow = false;
  11784. bool keepInCurrentModule = false;
  11785. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized))
  11786. flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_NoForceReification);
  11787. if (!typeInst->IsTypeMemberIncluded(methodDef->mDeclaringType))
  11788. {
  11789. return BfModuleMethodInstance();
  11790. }
  11791. if (methodDef->mIsLocalMethod)
  11792. {
  11793. auto rootMethodState = mCurMethodState->GetRootMethodState();
  11794. BfLocalMethod* localMethod;
  11795. if (rootMethodState->mLocalMethodCache.TryGetValue(methodDef->mName, &localMethod))
  11796. {
  11797. // Handle the def in the correct method state
  11798. return GetLocalMethodInstance(localMethod, methodGenericArguments);
  11799. }
  11800. BFMODULE_FATAL(this, "Cannot find local method");
  11801. return BfModuleMethodInstance();
  11802. }
  11803. #ifdef _DEBUG
  11804. for (auto arg : methodGenericArguments)
  11805. BF_ASSERT(!arg->IsVar());
  11806. #endif
  11807. BF_ASSERT(methodDef->mMethodType != BfMethodType_Ignore);
  11808. // We need to do the 'mNeedsMethodProcessing' check because we want to do a proper initial "awaiting reference" population
  11809. // on the methods before we handle an on-demand situation. This also ensures that our type options are set before doing
  11810. // a FinishInit
  11811. if ((typeInst->IsIncomplete()) &&
  11812. (!typeInst->mResolvingVarField) && (!typeInst->mTypeFailed))
  11813. {
  11814. // For autocomplete, we still may not actually generate methods. This shouldn't matter, and on-demand works differently
  11815. // for resolve-only because we don't differentiate between reified/unreified there
  11816. if ((methodDef->mIsStatic) /*&& (mIsComptimeModule)*/)
  11817. {
  11818. if (!typeInst->DefineStateAllowsStaticMethods())
  11819. PopulateType(typeInst, BfPopulateType_AllowStaticMethods);
  11820. }
  11821. else
  11822. PopulateType(typeInst, BfPopulateType_Full);
  11823. if (typeInst->mDefineState < BfTypeDefineState_Defined)
  11824. {
  11825. if (!mCompiler->EnsureCeUnpaused(typeInst))
  11826. {
  11827. BfLogSysM("GetMethodInstance (DefineState < BfTypeDefineState_Defined)) bailing due to IsCePaused\n");
  11828. return BfModuleMethodInstance();
  11829. }
  11830. }
  11831. }
  11832. bool tryModuleMethodLookup = false;
  11833. BfModuleMethodInstance moduleMethodInst;
  11834. BfModule* instModule = typeInst->mModule;
  11835. if (keepInCurrentModule)
  11836. {
  11837. // Stay here
  11838. instModule = this;
  11839. }
  11840. if (this == mContext->mUnreifiedModule)
  11841. {
  11842. // Stay in this 'resolve only' module here
  11843. }
  11844. else if (flags & BfGetMethodInstanceFlag_ExplicitResolveOnlyPass)
  11845. {
  11846. BF_ASSERT(this == mContext->mUnreifiedModule);
  11847. }
  11848. else if (flags & BfGetMethodInstanceFlag_ExplicitSpecializedModule)
  11849. {
  11850. BF_ASSERT(instModule == mParentModule);
  11851. }
  11852. else if (instModule != this)
  11853. {
  11854. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth >= 32))
  11855. flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_DepthExceeded);
  11856. if ((!mIsComptimeModule) && (!mIsReified) && (instModule->mIsReified))
  11857. {
  11858. BF_ASSERT(!mCompiler->mIsResolveOnly);
  11859. // A resolve-only module is specializing a method from a type in a reified module,
  11860. // we need to take care that this doesn't cause anything new to become reified
  11861. BfModuleMethodInstance moduleMethodInstance = mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass), foreignType);
  11862. if (!moduleMethodInstance)
  11863. return moduleMethodInstance;
  11864. SetMethodDependency(moduleMethodInstance.mMethodInstance);
  11865. return moduleMethodInstance;
  11866. }
  11867. else
  11868. {
  11869. if ((!mIsComptimeModule) && (mIsReified) && (!instModule->mIsReified))
  11870. {
  11871. if (!typeInst->IsUnspecializedType())
  11872. {
  11873. if (!instModule->mReifyQueued)
  11874. {
  11875. BF_ASSERT((instModule != mContext->mUnreifiedModule) && (instModule != mContext->mScratchModule));
  11876. BF_ASSERT((mCompiler->mCompileState != BfCompiler::CompileState_Unreified) && (mCompiler->mCompileState != BfCompiler::CompileState_VData));
  11877. BfLogSysM("Queueing ReifyModule: %p\n", instModule);
  11878. mContext->mReifyModuleWorkList.Add(instModule);
  11879. instModule->mReifyQueued = true;
  11880. }
  11881. // This ensures that the method will actually be created when it gets reified
  11882. BfMethodSpecializationRequest* specializationRequest = mContext->mMethodSpecializationWorkList.Alloc();
  11883. specializationRequest->mFromModule = typeInst->mModule;
  11884. specializationRequest->mFromModuleRevision = typeInst->mModule->mRevision;
  11885. specializationRequest->Init(typeInst, foreignType, methodDef);
  11886. //specializationRequest->mMethodDef = methodDef;
  11887. specializationRequest->mMethodGenericArguments = methodGenericArguments;
  11888. specializationRequest->mType = typeInst;
  11889. specializationRequest->mFlags = flags;
  11890. }
  11891. }
  11892. auto defFlags = (BfGetMethodInstanceFlags)(flags & ~BfGetMethodInstanceFlag_ForceInline);
  11893. defFlags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_NoReference);
  11894. if (mIsComptimeModule)
  11895. {
  11896. defFlags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_MethodInstanceOnly);
  11897. if (!mCompiler->mIsResolveOnly)
  11898. defFlags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_NoForceReification | BfGetMethodInstanceFlag_Unreified | BfGetMethodInstanceFlag_MethodInstanceOnly);
  11899. }
  11900. // Not extern
  11901. // Create the instance in the proper module and then create a reference in this one
  11902. moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType);
  11903. if (!moduleMethodInst)
  11904. return moduleMethodInst;
  11905. tryModuleMethodLookup = true;
  11906. if ((mIsReified) && (!moduleMethodInst.mMethodInstance->mIsReified))
  11907. {
  11908. CheckHotMethod(moduleMethodInst.mMethodInstance, "");
  11909. }
  11910. }
  11911. }
  11912. if (tryModuleMethodLookup)
  11913. {
  11914. SetMethodDependency(moduleMethodInst.mMethodInstance);
  11915. return ReferenceExternalMethodInstance(moduleMethodInst.mMethodInstance, flags);
  11916. }
  11917. if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (!methodDef->mAlwaysInline))
  11918. {
  11919. auto moduleMethodInstance = GetMethodInstance(typeInst, methodDef, methodGenericArguments, (BfGetMethodInstanceFlags)(flags & ~BfGetMethodInstanceFlag_ForceInline), foreignType);
  11920. if (moduleMethodInstance)
  11921. return ReferenceExternalMethodInstance(moduleMethodInstance.mMethodInstance, flags);
  11922. return moduleMethodInst;
  11923. }
  11924. bool isReified = mIsReified /* || ((flags & BfGetMethodInstanceFlag_ExplicitResolveOnlyPass) != 0)*/;
  11925. bool hadConcreteInterfaceGenericArgument = false;
  11926. if ((flags & BfGetMethodInstanceFlag_Unreified) != 0)
  11927. isReified = false;
  11928. if ((flags & BfGetMethodInstanceFlag_ExplicitResolveOnlyPass) != 0)
  11929. {
  11930. isReified = false;
  11931. }
  11932. BfTypeVector sanitizedMethodGenericArguments;
  11933. SizedArray<BfProject*, 4> projectList;
  11934. bool isUnspecializedPass = (flags & BfGetMethodInstanceFlag_UnspecializedPass) != 0;
  11935. if ((isUnspecializedPass) && (methodDef->mGenericParams.size() == 0))
  11936. isUnspecializedPass = false;
  11937. // Check for whether we are an extension method from a project that does not hold the root type, AND that isn't already the project for this type
  11938. bool isExternalExtensionMethod = false;
  11939. if ((!typeInst->IsUnspecializedType()) && (!isUnspecializedPass))
  11940. {
  11941. if (((flags & BfGetMethodInstanceFlag_ForeignMethodDef) == 0) &&
  11942. (methodDef->mDeclaringType != NULL) &&
  11943. (methodDef->mDeclaringType->mProject != typeInst->mTypeDef->mProject))
  11944. {
  11945. auto specProject = methodDef->mDeclaringType->mProject;
  11946. isExternalExtensionMethod = true;
  11947. if (typeInst->IsGenericTypeInstance())
  11948. {
  11949. auto genericTypeInst = (BfTypeInstance*)typeInst;
  11950. if (genericTypeInst->mGenericTypeInfo->mProjectsReferenced.empty())
  11951. genericTypeInst->GenerateProjectsReferenced();
  11952. if (genericTypeInst->mGenericTypeInfo->mProjectsReferenced.Contains(specProject))
  11953. {
  11954. // This is a generic type where a generic param is already confined to the project in question
  11955. isExternalExtensionMethod = false;
  11956. }
  11957. }
  11958. if (isExternalExtensionMethod)
  11959. {
  11960. BF_ASSERT(typeInst->mTypeDef->mIsCombinedPartial);
  11961. projectList.push_back(methodDef->mDeclaringType->mProject);
  11962. }
  11963. }
  11964. }
  11965. if ((!isUnspecializedPass) && (methodGenericArguments.size() != 0))
  11966. {
  11967. int typeProjectsCounts = 0;
  11968. if (typeInst->IsGenericTypeInstance())
  11969. {
  11970. auto genericTypeInst = (BfTypeInstance*)typeInst;
  11971. if (genericTypeInst->mGenericTypeInfo->mProjectsReferenced.empty())
  11972. genericTypeInst->GenerateProjectsReferenced();
  11973. typeProjectsCounts = (int)genericTypeInst->mGenericTypeInfo->mProjectsReferenced.size();
  11974. projectList.Insert(0, &genericTypeInst->mGenericTypeInfo->mProjectsReferenced[0], genericTypeInst->mGenericTypeInfo->mProjectsReferenced.size());
  11975. }
  11976. else
  11977. {
  11978. typeProjectsCounts = 1;
  11979. projectList.Insert(0, typeInst->mTypeDef->mProject);
  11980. }
  11981. isUnspecializedPass = true;
  11982. for (int genericArgIdx = 0; genericArgIdx < (int) methodGenericArguments.size(); genericArgIdx++)
  11983. {
  11984. auto genericArgType = methodGenericArguments[genericArgIdx];
  11985. //BF_ASSERT(!genericArgType->IsRef());
  11986. if (genericArgType->IsConcreteInterfaceType())
  11987. {
  11988. hadConcreteInterfaceGenericArgument = true;
  11989. auto concreteInterfaceType = (BfConcreteInterfaceType*)genericArgType;
  11990. genericArgType = concreteInterfaceType->mInterface;
  11991. }
  11992. if (genericArgType->IsGenericParam())
  11993. {
  11994. auto genericParam = (BfGenericParamType*) genericArgType;
  11995. if ((genericParam->mGenericParamKind != BfGenericParamKind_Method) || (genericParam->mGenericParamIdx != genericArgIdx))
  11996. isUnspecializedPass = false;
  11997. }
  11998. else
  11999. {
  12000. BfTypeUtils::GetProjectList(genericArgType, &projectList, typeProjectsCounts);
  12001. isUnspecializedPass = false;
  12002. }
  12003. sanitizedMethodGenericArguments.push_back(genericArgType);
  12004. }
  12005. if ((int)projectList.size() > typeProjectsCounts)
  12006. {
  12007. // Just leave the new items
  12008. projectList.RemoveRange(0, typeProjectsCounts);
  12009. std::sort(projectList.begin(), projectList.end(), [](BfProject* lhs, BfProject*rhs)
  12010. {
  12011. return lhs->mName < rhs->mName;
  12012. });
  12013. }
  12014. else
  12015. {
  12016. projectList.Clear();
  12017. }
  12018. }
  12019. const BfTypeVector& lookupMethodGenericArguments = isUnspecializedPass ? BfTypeVector() : sanitizedMethodGenericArguments;
  12020. BfMethodInstanceGroup* methodInstGroup = NULL;
  12021. if ((flags & BfGetMethodInstanceFlag_ForeignMethodDef) != 0)
  12022. {
  12023. BF_ASSERT(!typeInst->IsInterface());
  12024. //for (auto& checkGroup : typeInst->mMethodInstanceGroups)
  12025. for (int methodIdx = (int)typeInst->mTypeDef->mMethods.size(); methodIdx < (int)typeInst->mMethodInstanceGroups.size(); methodIdx++)
  12026. {
  12027. auto& checkGroup = typeInst->mMethodInstanceGroups[methodIdx];
  12028. // if (checkGroup.mDefault == NULL)
  12029. // {
  12030. // // This should only be for when we explicitly add a spot so we can set mOnDemandKind
  12031. // BF_ASSERT(methodIdx == typeInst->mMethodInstanceGroups.size() - 1);
  12032. // methodInstGroup = &checkGroup;
  12033. // break;
  12034. // }
  12035. if ((checkGroup.mDefault != NULL) && (checkGroup.mDefault->mMethodDef == methodDef))
  12036. {
  12037. methodInstGroup = &checkGroup;
  12038. break;
  12039. }
  12040. }
  12041. if (methodInstGroup == NULL)
  12042. {
  12043. if (lookupMethodGenericArguments.size() != 0)
  12044. {
  12045. BF_ASSERT((flags & BfGetMethodInstanceFlag_ForeignMethodDef) != 0);
  12046. auto defaultMethodInstance = GetMethodInstance(typeInst, methodDef, BfTypeVector(),
  12047. (BfGetMethodInstanceFlags)((flags & (BfGetMethodInstanceFlag_ForeignMethodDef)) | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_MethodInstanceOnly), foreignType);
  12048. methodInstGroup = defaultMethodInstance.mMethodInstance->mMethodInstanceGroup;
  12049. }
  12050. else
  12051. {
  12052. // Allocate a new entry
  12053. typeInst->mMethodInstanceGroups.Resize(typeInst->mMethodInstanceGroups.size() + 1);
  12054. methodInstGroup = &typeInst->mMethodInstanceGroups.back();
  12055. methodInstGroup->mMethodIdx = (int)typeInst->mMethodInstanceGroups.size() - 1;
  12056. methodInstGroup->mOwner = typeInst;
  12057. // if (methodInstGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
  12058. // methodInstGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  12059. if (mCompiler->mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
  12060. methodInstGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  12061. else
  12062. {
  12063. methodInstGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
  12064. if (!mIsScratchModule)
  12065. mOnDemandMethodCount++;
  12066. }
  12067. }
  12068. }
  12069. }
  12070. else
  12071. {
  12072. methodInstGroup = &typeInst->mMethodInstanceGroups[methodDef->mIdx];
  12073. }
  12074. if (methodInstGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
  12075. {
  12076. if (typeInst->mDefineState > BfTypeDefineState_DefinedAndMethodsSlotted)
  12077. {
  12078. BfLogSysM("Forcing BfMethodOnDemandKind_NotSet to BfMethodOnDemandKind_AlwaysInclude for Method:%s in Type:%p\n", methodDef->mName.c_str(), typeInst);
  12079. methodInstGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  12080. }
  12081. }
  12082. BfIRFunction prevIRFunc;
  12083. bool doingRedeclare = false;
  12084. BfMethodInstance* methodInstance = NULL;
  12085. auto _SetReified = [&]()
  12086. {
  12087. if (!mCompiler->mIsResolveOnly)
  12088. BF_ASSERT(mCompiler->mCompileState <= BfCompiler::CompileState_Normal);
  12089. methodInstance->mIsReified = true;
  12090. };
  12091. if (lookupMethodGenericArguments.size() == 0)
  12092. {
  12093. methodInstance = methodInstGroup->mDefault;
  12094. if ((methodInstance != NULL) && ((flags & BfGetMethodInstanceFlag_MethodInstanceOnly) != 0))
  12095. return methodInstance;
  12096. if ((methodInstance != NULL) && (isReified) && (!methodInstance->mIsReified))
  12097. {
  12098. MarkDerivedDirty(typeInst);
  12099. if (!HasCompiledOutput())
  12100. {
  12101. BfLogSysM("Marking non-compiled-output module method instance as reified: %p\n", methodInstance);
  12102. _SetReified();
  12103. CheckHotMethod(methodInstance, "");
  12104. }
  12105. else if ((flags & BfGetMethodInstanceFlag_NoForceReification) != 0)
  12106. {
  12107. // We don't need to force reification if we're in an unspecialized generic- we can wait for
  12108. // the specializations to handle that for us
  12109. return BfModuleMethodInstance(methodInstance);
  12110. }
  12111. else if (methodInstGroup->mOnDemandKind == BfMethodOnDemandKind_Referenced)
  12112. {
  12113. if (methodDef->mIsAbstract)
  12114. {
  12115. BfLogSysM("Reifying abstract unreified method instance: %p IRFunction:%d\n", methodInstance, methodInstance->mIRFunction.mId);
  12116. _SetReified();
  12117. }
  12118. else
  12119. {
  12120. BfLogSysM("Re-declaring processed but unreified method instance: %p IRFunction:%d\n", methodInstance, methodInstance->mIRFunction.mId);
  12121. methodInstGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
  12122. methodInstance->UndoDeclaration(!methodInstance->mIRFunction.IsFake());
  12123. doingRedeclare = true;
  12124. mOnDemandMethodCount++;
  12125. VerifyOnDemandMethods();
  12126. }
  12127. }
  12128. else
  12129. {
  12130. BfLogSysM("Marking unprocessed method instance as reified: %p\n", methodInstance);
  12131. // We haven't processed it yet
  12132. _SetReified();
  12133. CheckHotMethod(methodInstance, "");
  12134. if (methodInstance->mDeclModule == this)
  12135. {
  12136. if (methodInstance->mMethodProcessRequest != NULL)
  12137. {
  12138. // Disconnect method process request
  12139. BF_ASSERT(methodInstance->mMethodProcessRequest->mFromModule == this);
  12140. }
  12141. }
  12142. else
  12143. {
  12144. if (methodInstance->mMethodProcessRequest != NULL)
  12145. {
  12146. // Disconnect method process request
  12147. methodInstance->mMethodProcessRequest->mMethodInstance = NULL;
  12148. methodInstance->mMethodProcessRequest = NULL;
  12149. }
  12150. if (methodInstance->mDeclModule == mContext->mUnreifiedModule)
  12151. {
  12152. // Add new request in proper module
  12153. methodInstance->mDeclModule = this;
  12154. }
  12155. else
  12156. {
  12157. if (methodInstance->mDeclModule == NULL)
  12158. {
  12159. //
  12160. }
  12161. else if (methodInstance->mDeclModule != this)
  12162. {
  12163. // Is from specialized module?
  12164. BF_ASSERT(methodInstance->mDeclModule->mParentModule == this);
  12165. }
  12166. }
  12167. if ((!methodInstance->mIRFunction) || (methodInstance->mIRFunction.IsFake()))
  12168. {
  12169. methodInstance->mIRFunction = BfIRFunction();
  12170. if (!mIsModuleMutable)
  12171. StartExtension();
  12172. if ((!mBfIRBuilder->mIgnoreWrites) && (methodInstance->mDeclModule != NULL))
  12173. {
  12174. StringT<512> mangledName;
  12175. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
  12176. bool isIntrinsic = false;
  12177. SetupIRFunction(methodInstance, mangledName, false, &isIntrinsic);
  12178. BfLogSysM("Creating new IRFunction %d\n", methodInstance->mIRFunction.mId);
  12179. }
  12180. }
  12181. AddMethodToWorkList(methodInstance);
  12182. }
  12183. }
  12184. }
  12185. }
  12186. else
  12187. {
  12188. if (methodInstGroup->mDefault == NULL)
  12189. {
  12190. auto defaultMethodInstance = GetMethodInstance(typeInst, methodDef, BfTypeVector(),
  12191. (BfGetMethodInstanceFlags)((flags & (BfGetMethodInstanceFlag_ForeignMethodDef)) | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_MethodInstanceOnly), foreignType);
  12192. methodInstGroup = defaultMethodInstance.mMethodInstance->mMethodInstanceGroup;
  12193. }
  12194. BF_ASSERT(lookupMethodGenericArguments.size() != 0);
  12195. if (methodInstGroup->mMethodSpecializationMap == NULL)
  12196. methodInstGroup->mMethodSpecializationMap = new BfMethodInstanceGroup::MapType();
  12197. BfMethodInstance** methodInstancePtr = NULL;
  12198. if (methodInstGroup->mMethodSpecializationMap->TryGetValue(lookupMethodGenericArguments, &methodInstancePtr))
  12199. {
  12200. methodInstance = *methodInstancePtr;
  12201. if ((flags & BfGetMethodInstanceFlag_MethodInstanceOnly) != 0)
  12202. return methodInstance;
  12203. if ((methodInstance->mRequestedByAutocomplete) && (!mCompiler->IsAutocomplete()))
  12204. {
  12205. BfLogSysM("Setting mRequestedByAutocomplete=false for method instance %p\n", methodInstance);
  12206. // We didn't want to process this message yet if it was autocomplete-specific, but now we will
  12207. if (methodInstance->mMethodProcessRequest == NULL)
  12208. AddMethodToWorkList(methodInstance);
  12209. methodInstance->mRequestedByAutocomplete = false;
  12210. }
  12211. if ((isReified) && (!methodInstance->mIsReified))
  12212. {
  12213. MarkDerivedDirty(typeInst);
  12214. if (methodInstance->mHasBeenProcessed)
  12215. {
  12216. BfLogSysM("Deleting processed but unreified specialized method instance %p\n", methodInstance);
  12217. delete methodInstance;
  12218. methodInstGroup->mMethodSpecializationMap->Remove(lookupMethodGenericArguments);
  12219. methodInstance = NULL;
  12220. }
  12221. else if ((!methodInstance->mIRFunction) || (methodInstance->mIRFunction.IsFake()))
  12222. {
  12223. BfLogSysM("Deleting declared but uncreated specialized method instance %p\n", methodInstance);
  12224. delete methodInstance;
  12225. methodInstGroup->mMethodSpecializationMap->Remove(lookupMethodGenericArguments);
  12226. methodInstance = NULL;
  12227. }
  12228. else
  12229. {
  12230. BfLogSysM("Reifying declared but unreified method instance %p\n", methodInstance);
  12231. // We haven't processed it yet
  12232. _SetReified();
  12233. CheckHotMethod(methodInstance, "");
  12234. if (methodInstance->mMethodProcessRequest == NULL)
  12235. AddMethodToWorkList(methodInstance);
  12236. }
  12237. }
  12238. }
  12239. }
  12240. if ((methodInstance != NULL) && (!doingRedeclare))
  12241. {
  12242. SetMethodDependency(methodInstance);
  12243. if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
  12244. {
  12245. /*if ((!mCompiler->mIsResolveOnly) && (!isReified))
  12246. BF_ASSERT(!methodInstance->mIsReified);*/
  12247. if (methodInstance->mIsReified != isReified)
  12248. BfLogSysM("GetMethodInstance %p Decl_AwaitingReference setting reified to %d\n", methodInstance, isReified);
  12249. if ((!isReified) &&
  12250. ((methodInstance->mDeclModule == NULL) || (!methodInstance->mDeclModule->mIsModuleMutable)))
  12251. {
  12252. methodInstance->mDeclModule = mContext->mUnreifiedModule;
  12253. methodInstance->mIRFunction = BfIRFunction();
  12254. }
  12255. methodInstance->mIsReified = isReified;
  12256. if ((methodInstance->mHotMethod != NULL) && (!mCompiler->IsHotCompile()) && (isReified))
  12257. {
  12258. methodInstance->mHotMethod->mFlags = (BfHotDepDataFlags)(methodInstance->mHotMethod->mFlags | BfHotDepDataFlag_IsOriginalBuild);
  12259. }
  12260. if (!methodInstance->mMethodDef->mIsAbstract)
  12261. {
  12262. if ((methodInstance->mMethodDef->mMethodType == BfMethodType_Mixin) && (!methodInstance->mDeclModule->mIsModuleMutable))
  12263. {
  12264. // Wait until unreified
  12265. }
  12266. else
  12267. AddMethodToWorkList(methodInstance);
  12268. }
  12269. else
  12270. {
  12271. methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Referenced;
  12272. auto owningModule = methodInstance->GetOwner()->mModule;
  12273. if (!owningModule->mIsScratchModule)
  12274. {
  12275. owningModule->mOnDemandMethodCount--;
  12276. owningModule->VerifyOnDemandMethods();
  12277. }
  12278. }
  12279. }
  12280. if (mExtensionCount > 0)
  12281. {
  12282. if ((mIsModuleMutable) && (!methodInstance->mIRFunction) &&
  12283. ((projectList.IsEmpty() || ((flags & BfGetMethodInstanceFlag_ExplicitSpecializedModule) != 0))))
  12284. {
  12285. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, false);
  12286. if (mAwaitingInitFinish)
  12287. FinishInit();
  12288. // We need to refer to a function that was defined in a prior module
  12289. bool isInlined = (methodInstance->mAlwaysInline) || ((flags & BfGetMethodInstanceFlag_ForceInline) != 0);
  12290. if (methodInstance->mIsIntrinsic)
  12291. isInlined = false;
  12292. methodInstance->mIRFunction = CreateFunctionFrom(methodInstance, false, isInlined);
  12293. BF_ASSERT((methodInstance->mDeclModule == this) || (methodInstance->mDeclModule == mContext->mUnreifiedModule) || (methodInstance->mDeclModule == NULL));
  12294. methodInstance->mDeclModule = this;
  12295. // Add this inlined def to ourselves
  12296. if ((methodInstance->mAlwaysInline) && (HasCompiledOutput()) && (!methodInstance->mIsUnspecialized) && ((flags & BfGetMethodInstanceFlag_NoInline) == 0))
  12297. {
  12298. mIncompleteMethodCount++;
  12299. BfInlineMethodRequest* inlineMethodRequest = mContext->mInlineMethodWorkList.Alloc();
  12300. inlineMethodRequest->mType = typeInst;
  12301. inlineMethodRequest->mFromModule = this;
  12302. inlineMethodRequest->mFunc = methodInstance->mIRFunction;
  12303. inlineMethodRequest->mFromModuleRevision = mRevision;
  12304. inlineMethodRequest->mMethodInstance = methodInstance;
  12305. BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this);
  12306. BF_ASSERT(mIsModuleMutable);
  12307. }
  12308. }
  12309. }
  12310. if (IsSkippingExtraResolveChecks())
  12311. return BfModuleMethodInstance(methodInstance, BfIRFunction());
  12312. else
  12313. {
  12314. if ((flags & (BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_NoReference)) != 0)
  12315. return methodInstance;
  12316. if (methodInstance->mDeclModule != this)
  12317. return ReferenceExternalMethodInstance(methodInstance, flags);
  12318. if ((!methodInstance->mIRFunction) && (mIsModuleMutable) && (!mBfIRBuilder->mIgnoreWrites))
  12319. {
  12320. auto importKind = methodInstance->GetImportCallKind();
  12321. if (importKind != BfImportCallKind_None)
  12322. {
  12323. BfLogSysM("DllImportGlobalVar creating %p\n", methodInstance);
  12324. methodInstance->mIRFunction = mBfIRBuilder->GetFakeVal();
  12325. auto func = CreateDllImportGlobalVar(methodInstance, true);
  12326. BF_ASSERT(func);
  12327. mFuncReferences[methodInstance] = func;
  12328. }
  12329. }
  12330. return BfModuleMethodInstance(methodInstance);
  12331. }
  12332. }
  12333. if (!doingRedeclare)
  12334. {
  12335. BfModule* specModule = NULL;
  12336. if ((!keepInCurrentModule) && (projectList.size() > 0) && (!isUnspecializedPass) && (HasCompiledOutput()) && (!mIsScratchModule))
  12337. {
  12338. specModule = GetSpecializedMethodModule(projectList);
  12339. }
  12340. if ((specModule != NULL) && (specModule != this))
  12341. {
  12342. auto specMethodInstance = specModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ExplicitSpecializedModule));
  12343. if (mAwaitingInitFinish)
  12344. return BfModuleMethodInstance(specMethodInstance.mMethodInstance, BfIRFunction());
  12345. if ((flags & (BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_NoReference)) != 0)
  12346. return specMethodInstance.mMethodInstance;
  12347. return ReferenceExternalMethodInstance(specMethodInstance.mMethodInstance, flags);
  12348. }
  12349. if ((!isUnspecializedPass) && (methodGenericArguments.size() != 0) && (methodInstGroup->mDefault == NULL))
  12350. {
  12351. // We are attempting to specialize but we don't have the unspecialized method yet. Generate that first.
  12352. GetMethodInstance(typeInst, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_UnspecializedPass);
  12353. }
  12354. }
  12355. if (methodInstance == NULL)
  12356. {
  12357. if (!mCompiler->EnsureCeUnpaused(typeInst))
  12358. {
  12359. BfLogSysM("GetMethodInstance (methodInstance == NULL) bailing due to IsCePaused\n");
  12360. return BfModuleMethodInstance();
  12361. }
  12362. if (lookupMethodGenericArguments.size() == 0)
  12363. {
  12364. BF_ASSERT(methodInstGroup->mDefault == NULL);
  12365. methodInstance = new BfMethodInstance();
  12366. methodInstGroup->mDefault = methodInstance;
  12367. BF_ASSERT(typeInst->mDefineState > BfTypeDefineState_Declared);
  12368. BfLogSysM("Created Default MethodInst: %p TypeInst: %p Group: %p\n", methodInstance, typeInst, methodInstGroup);
  12369. }
  12370. else
  12371. {
  12372. bool depthExceeded = ((flags & BfGetMethodInstanceFlag_DepthExceeded) != 0);
  12373. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth >= 32))
  12374. depthExceeded = true;
  12375. if (depthExceeded)
  12376. {
  12377. Fail("Generic method dependency depth exceeded", methodDef->GetRefNode());
  12378. return BfModuleMethodInstance();
  12379. }
  12380. BfMethodInstance** methodInstancePtr = NULL;
  12381. bool added = methodInstGroup->mMethodSpecializationMap->TryAdd(lookupMethodGenericArguments, NULL, &methodInstancePtr);
  12382. BF_ASSERT(added);
  12383. methodInstance = new BfMethodInstance();
  12384. *methodInstancePtr = methodInstance;
  12385. if (mCompiler->IsAutocomplete())
  12386. methodInstance->mRequestedByAutocomplete = true;
  12387. BfLogSysM("Created Specialized MethodInst: %p TypeInst: %p\n", methodInstance, typeInst);
  12388. }
  12389. if ((prevIRFunc) && (!prevIRFunc.IsFake()))
  12390. methodInstance->mIRFunction = prevIRFunc; // Take it over
  12391. }
  12392. methodInstance->mMethodDef = methodDef;
  12393. methodInstance->mAlwaysInline = methodDef->mAlwaysInline;
  12394. methodInstance->mMethodInstanceGroup = methodInstGroup;
  12395. methodInstance->mIsReified = isReified;
  12396. SetupMethodIdHash(methodInstance);
  12397. if (hadConcreteInterfaceGenericArgument)
  12398. methodInstance->mIgnoreBody = true;
  12399. if ((flags & BfGetMethodInstanceFlag_ForeignMethodDef) != 0)
  12400. {
  12401. methodInstance->mIsForeignMethodDef = true;
  12402. BF_ASSERT(foreignType != NULL);
  12403. methodInstance->GetMethodInfoEx()->mForeignType = foreignType;
  12404. }
  12405. if ((typeInst->IsInstanceOf(mCompiler->mValueTypeTypeDef)) && (methodDef->mName == BF_METHODNAME_EQUALS))
  12406. {
  12407. if (!lookupMethodGenericArguments.empty())
  12408. {
  12409. auto compareType = lookupMethodGenericArguments[0];
  12410. PopulateType(compareType, BfPopulateType_Data);
  12411. if (compareType->IsSplattable())
  12412. methodInstance->mAlwaysInline = true;
  12413. }
  12414. }
  12415. if (methodDef->mMethodType == BfMethodType_Init)
  12416. {
  12417. methodInstance->mMangleWithIdx = true;
  12418. }
  12419. BF_ASSERT(typeInst == methodInstance->GetOwner());
  12420. auto methodDeclaration = methodDef->GetMethodDeclaration();
  12421. if (isUnspecializedPass)
  12422. {
  12423. for (int genericParamIdx = 0; genericParamIdx < (int) methodDef->mGenericParams.size(); genericParamIdx++)
  12424. {
  12425. auto genericParamType = GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
  12426. methodInstance->GetMethodInfoEx()->mMethodGenericArguments.Add(genericParamType);
  12427. }
  12428. }
  12429. else if ((methodDeclaration != NULL) && (methodDeclaration->mGenericParams != NULL))
  12430. {
  12431. if (!sanitizedMethodGenericArguments.IsEmpty())
  12432. methodInstance->GetMethodInfoEx()->mMethodGenericArguments = sanitizedMethodGenericArguments;
  12433. if (methodDef->mGenericParams.size() != sanitizedMethodGenericArguments.size())
  12434. {
  12435. Fail("Internal error");
  12436. BFMODULE_FATAL(this, "Generic method argument counts mismatch");
  12437. return NULL;
  12438. }
  12439. for (auto genericArg : sanitizedMethodGenericArguments)
  12440. {
  12441. if (genericArg->IsPrimitiveType())
  12442. genericArg = GetWrappedStructType(genericArg);
  12443. if (genericArg != NULL)
  12444. AddDependency(genericArg, typeInst, BfDependencyMap::DependencyFlag_MethodGenericArg);
  12445. }
  12446. }
  12447. // Generic constraints
  12448. if (!methodDef->mGenericParams.IsEmpty())
  12449. {
  12450. BF_ASSERT(methodInstance->GetMethodInfoEx()->mGenericParams.IsEmpty());
  12451. for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
  12452. {
  12453. auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
  12454. methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
  12455. }
  12456. }
  12457. for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++)
  12458. {
  12459. auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
  12460. methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
  12461. }
  12462. bool addToWorkList = !processNow;
  12463. if (mCompiler->GetAutoComplete() != NULL)
  12464. {
  12465. if (typeInst->IsSpecializedByAutoCompleteMethod())
  12466. addToWorkList = false;
  12467. if (methodInstance->mRequestedByAutocomplete)
  12468. addToWorkList = false;
  12469. }
  12470. BfModule* declareModule;
  12471. //
  12472. {
  12473. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
  12474. declareModule = GetOrCreateMethodModule(methodInstance);
  12475. }
  12476. if ((doingRedeclare) && (methodInstance->mDeclModule != mContext->mUnreifiedModule))
  12477. declareModule = methodInstance->mDeclModule;
  12478. BF_ASSERT(declareModule != NULL);
  12479. methodInstance->mDeclModule = declareModule;
  12480. if ((!methodInstance->mIsReified) && (mCompiler->mCompileState != BfCompiler::CompileState_Normal))
  12481. {
  12482. // We can be sure this method won't become reified later. Normally we can "go either way" with an unreified method
  12483. // of a reified module -
  12484. // If we declare it in the reified module then we can switch it to "reified" before actual processing without any extra work,
  12485. // BUT if we don't reify it then we have to remove the body after processing.
  12486. // But if we declare it in the unreified module module and then end up needing to reify it then we need to re-declare it in
  12487. // the proper reified module.
  12488. declareModule = mContext->mUnreifiedModule;
  12489. }
  12490. else if ((!declareModule->mIsModuleMutable) && (!mCompiler->mIsResolveOnly))
  12491. {
  12492. if (!methodInstance->mIsReified)
  12493. {
  12494. declareModule = mContext->mUnreifiedModule;
  12495. }
  12496. else
  12497. {
  12498. declareModule->PrepareForIRWriting(methodInstance->GetOwner());
  12499. }
  12500. }
  12501. SetMethodDependency(methodInstance);
  12502. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(declareModule->mCurMethodInstance, methodInstance);
  12503. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(declareModule->mCurTypeInstance, typeInst);
  12504. SetAndRestoreValue<BfFilePosition> prevFilePos(declareModule->mCurFilePosition);
  12505. if ((methodDef->mMethodType == BfMethodType_Mixin) && (methodDef->mGenericParams.size() != 0) && (!isUnspecializedPass))
  12506. {
  12507. // For mixins we only process the unspecialized version
  12508. addToWorkList = false;
  12509. }
  12510. if ((flags & BfGetMethodInstanceFlag_MethodInstanceOnly) != 0)
  12511. {
  12512. addToWorkList = false;
  12513. }
  12514. // if ((flags & BfGetMethodInstanceFlag_NoReference) != 0)
  12515. // addToWorkList = false;
  12516. declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList);
  12517. if (processNow)
  12518. {
  12519. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
  12520. ProcessMethod(methodInstance);
  12521. }
  12522. if (IsSkippingExtraResolveChecks())
  12523. return BfModuleMethodInstance(methodInstance, BfIRFunction());
  12524. if (methodInstance->mDeclModule != this)
  12525. return ReferenceExternalMethodInstance(methodInstance, flags);
  12526. return BfModuleMethodInstance(methodInstance);
  12527. }
  12528. BfModuleMethodInstance BfModule::GetMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags)
  12529. {
  12530. BF_ASSERT((methodInstance->mMethodInfoEx == NULL) || (methodInstance->mMethodInfoEx->mGenericParams.IsEmpty()));
  12531. if (methodInstance->mIsForeignMethodDef)
  12532. flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ForeignMethodDef);
  12533. return GetMethodInstance(methodInstance->GetOwner(), methodInstance->mMethodDef, BfTypeVector(), flags);
  12534. }
  12535. BfMethodInstance* BfModule::GetOuterMethodInstance(BfMethodInstance* methodInstance)
  12536. {
  12537. if (!methodInstance->mMethodDef->mIsLocalMethod)
  12538. return NULL;
  12539. auto outerLocal = methodInstance->mMethodInfoEx->mClosureInstanceInfo->mLocalMethod->mOuterLocalMethod;
  12540. if (outerLocal == NULL)
  12541. return NULL;
  12542. BfTypeVector genericArgs;
  12543. for (int i = 0; i < (int)outerLocal->mMethodDef->mGenericParams.size(); i++)
  12544. genericArgs.Add(methodInstance->mMethodInfoEx->mMethodGenericArguments[i]);
  12545. return GetLocalMethodInstance(outerLocal, genericArgs).mMethodInstance;
  12546. }
  12547. void BfModule::SetupMethodIdHash(BfMethodInstance* methodInstance)
  12548. {
  12549. HashContext hashCtx;
  12550. std::function<void(BfMethodInstance*)> _MixinMethodInstance = [&](BfMethodInstance* methodInstance)
  12551. {
  12552. hashCtx.Mixin(methodInstance->GetOwner()->mTypeId);
  12553. hashCtx.Mixin(methodInstance->mMethodDef->mIdx);
  12554. if (methodInstance->GetNumGenericArguments() != 0)
  12555. {
  12556. hashCtx.Mixin((int32)methodInstance->mMethodInfoEx->mMethodGenericArguments.size());
  12557. for (auto methodGenericArg : methodInstance->mMethodInfoEx->mMethodGenericArguments)
  12558. hashCtx.Mixin(methodGenericArg->mTypeId);
  12559. }
  12560. };
  12561. _MixinMethodInstance(methodInstance);
  12562. if (methodInstance->mMethodDef->mIsLocalMethod)
  12563. {
  12564. auto outmostMethodInstance = mCurMethodState->GetRootMethodState()->mMethodInstance;
  12565. if (outmostMethodInstance != NULL)
  12566. {
  12567. BF_ASSERT((outmostMethodInstance->mIdHash != 0) || (outmostMethodInstance->mIsAutocompleteMethod));
  12568. hashCtx.Mixin(outmostMethodInstance->mIdHash);
  12569. }
  12570. }
  12571. methodInstance->mIdHash = (int64)hashCtx.Finish64();
  12572. }
  12573. bool BfModule::CheckUseMethodInstance(BfMethodInstance* methodInstance, BfAstNode* refNode)
  12574. {
  12575. if (methodInstance->mHasBeenDeclared)
  12576. return true;
  12577. Fail(StrFormat("Circular reference in method instance '%s'", MethodToString(methodInstance).c_str()), refNode);
  12578. return false;
  12579. }
  12580. BfIRValue BfModule::GetInterfaceSlotNum(BfTypeInstance* ifaceType)
  12581. {
  12582. BfIRValue globalValue;
  12583. BfIRValue* globalValuePtr = NULL;
  12584. if (mInterfaceSlotRefs.TryGetValue(ifaceType, &globalValuePtr))
  12585. {
  12586. globalValue = *globalValuePtr;
  12587. }
  12588. if (!globalValue)
  12589. {
  12590. // This is necessary to reify the interface type
  12591. PopulateType(ifaceType);
  12592. StringT<512> slotVarName;
  12593. BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), ifaceType, "sBfSlotOfs");
  12594. BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
  12595. BfIRValue value;
  12596. if ((mCompiler->mHotState != NULL) && (ifaceType->mSlotNum >= 0))
  12597. {
  12598. /*// If this interface already existed before this hot compile but we never indirectly called any of its methods
  12599. // then the sBfSlotOfs could have gotten its symbol stripped, so actually define it here.
  12600. int virtSlotIdx = ifaceType->mSlotNum + 1;
  12601. value = GetConstValue32(virtSlotIdx);*/
  12602. mCompiler->mHotState->mSlotDefineTypeIds.Add(ifaceType->mTypeId);
  12603. ifaceType->mDirty = true; // Makes sure we create interface in vdata
  12604. }
  12605. globalValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External, value, slotVarName);
  12606. mInterfaceSlotRefs[ifaceType] = globalValue;
  12607. }
  12608. return mBfIRBuilder->CreateAlignedLoad(globalValue/*, "slotOfs"*/, 4);
  12609. }
  12610. void BfModule::HadSlotCountDependency()
  12611. {
  12612. if (mCompiler->mIsResolveOnly)
  12613. return;
  12614. BF_ASSERT(!mBfIRBuilder->mIgnoreWrites);
  12615. BF_ASSERT((mUsedSlotCount == BF_MAX(mCompiler->mMaxInterfaceSlots, 0)) || (mUsedSlotCount == -1));
  12616. mUsedSlotCount = BF_MAX(mCompiler->mMaxInterfaceSlots, 0);
  12617. }
  12618. BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str)
  12619. {
  12620. if (str == "#IsComptime")
  12621. {
  12622. return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, mIsComptimeModule ? 1 : 0), GetPrimitiveType(BfTypeCode_Boolean));
  12623. }
  12624. if (str == "#IsBuilding")
  12625. {
  12626. return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, (!mCompiler->mIsResolveOnly) ? 1 : 0), GetPrimitiveType(BfTypeCode_Boolean));
  12627. }
  12628. if (str == "#IsReified")
  12629. {
  12630. return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Boolean, mIsReified ? 1 : 0), GetPrimitiveType(BfTypeCode_Boolean));
  12631. }
  12632. if (str == "#CompileRev")
  12633. {
  12634. return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mRevision), GetPrimitiveType(BfTypeCode_Int32));
  12635. }
  12636. if (str == "#ModuleName")
  12637. {
  12638. return BfTypedValue(GetStringObjectValue(mModuleName), ResolveTypeDef(mCompiler->mStringTypeDef));
  12639. }
  12640. if (str == "#ProjectName")
  12641. {
  12642. if (mProject != NULL)
  12643. return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
  12644. }
  12645. if (str == "#AllocStackCount")
  12646. {
  12647. return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mAllocStackCount), GetPrimitiveType(BfTypeCode_Int32));
  12648. }
  12649. if (mCurMethodState->mMixinState != NULL)
  12650. {
  12651. if (str == "#CallerLineNum")
  12652. {
  12653. return BfTypedValue(GetConstValue(mCurMethodState->mMixinState->mInjectFilePosition.mCurLine + 1), GetPrimitiveType(BfTypeCode_Int32));
  12654. }
  12655. else if (str == "#CallerFilePath")
  12656. {
  12657. String filePath = "";
  12658. if (mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance != NULL)
  12659. filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
  12660. return BfTypedValue(GetStringObjectValue(filePath), ResolveTypeDef(mCompiler->mStringTypeDef));
  12661. }
  12662. else if (str == "#CallerFileName")
  12663. {
  12664. String filePath = "";
  12665. if (mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance != NULL)
  12666. filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
  12667. return BfTypedValue(GetStringObjectValue(GetFileName(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
  12668. }
  12669. else if (str == "#CallerFileDir")
  12670. {
  12671. String filePath = "";
  12672. if (mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance != NULL)
  12673. filePath = mCurMethodState->mMixinState->mInjectFilePosition.mFileInstance->mParser->mFileName;
  12674. return BfTypedValue(GetStringObjectValue(GetFileDir(filePath)), ResolveTypeDef(mCompiler->mStringTypeDef));
  12675. }
  12676. else if (str == "#CallerMemberName")
  12677. {
  12678. String memberName = "";
  12679. if (mCurMethodState->mMixinState->mMixinMethodInstance)
  12680. memberName = MethodToString(mCurMethodState->mMixinState->mMixinMethodInstance);
  12681. return BfTypedValue(GetStringObjectValue(memberName), ResolveTypeDef(mCompiler->mStringTypeDef));
  12682. }
  12683. else if (str == "#CallerProject")
  12684. {
  12685. BfProject* project = NULL;
  12686. project = mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mProject;
  12687. if (project != NULL)
  12688. return BfTypedValue(GetStringObjectValue(mProject->mName), ResolveTypeDef(mCompiler->mStringTypeDef));
  12689. }
  12690. }
  12691. if (str == "#TimeLocal")
  12692. {
  12693. time_t rawtime;
  12694. time(&rawtime);
  12695. tm* timeinfo = localtime(&rawtime);
  12696. char result[32];
  12697. sprintf(result, "%d/%.2d/%.2d %.2d:%.2d:%.2d",
  12698. 1900 + timeinfo->tm_year,
  12699. timeinfo->tm_mon,
  12700. timeinfo->tm_mday,
  12701. timeinfo->tm_hour,
  12702. timeinfo->tm_min,
  12703. timeinfo->tm_sec);
  12704. return BfTypedValue(GetStringObjectValue(result), ResolveTypeDef(mCompiler->mStringTypeDef));
  12705. }
  12706. return BfTypedValue();
  12707. }
  12708. BfTypedValue BfModule::GetCompilerFieldValue(BfTypedValue typedValue)
  12709. {
  12710. if (!typedValue.IsAddr())
  12711. return BfTypedValue();
  12712. if (typedValue.mValue.IsConst())
  12713. {
  12714. auto constantValue = mBfIRBuilder->GetConstant(typedValue.mValue);
  12715. if (constantValue != NULL)
  12716. {
  12717. if (constantValue->mConstType == BfConstType_GlobalVar)
  12718. {
  12719. auto globalVar = (BfGlobalVar*)constantValue;
  12720. if (globalVar->mName[0] == '#')
  12721. {
  12722. BfTypedValue result = GetCompilerFieldValue(globalVar->mName);
  12723. return result;
  12724. }
  12725. }
  12726. }
  12727. }
  12728. return BfTypedValue();
  12729. }
  12730. BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
  12731. {
  12732. BfIRValue globalValue;
  12733. auto fieldDef = fieldInstance->GetFieldDef();
  12734. if ((fieldDef->mIsConst) && (!fieldDef->mIsExtern))
  12735. {
  12736. if (fieldInstance->mConstIdx != -1)
  12737. {
  12738. auto constant = fieldInstance->mOwner->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
  12739. return BfTypedValue(ConstantToCurrent(constant, fieldInstance->mOwner->mConstHolder, fieldInstance->GetResolvedType()), fieldInstance->GetResolvedType());
  12740. }
  12741. else
  12742. {
  12743. return GetDefaultTypedValue(fieldInstance->GetResolvedType());
  12744. }
  12745. }
  12746. if ((mIsScratchModule) && (mCompiler->mIsResolveOnly))
  12747. {
  12748. // Just fake it for the extern and unspecialized modules
  12749. // We can't do this for compilation because unreified methods with default params need to get acutal global variable refs
  12750. return BfTypedValue(mBfIRBuilder->CreateConstNull(), fieldInstance->GetResolvedType(), true);
  12751. }
  12752. BfIRValue* globalValuePtr = NULL;
  12753. if (mStaticFieldRefs.TryGetValue(fieldInstance, &globalValuePtr))
  12754. {
  12755. globalValue = *globalValuePtr;
  12756. BF_ASSERT(globalValue);
  12757. auto globalVar = (BfGlobalVar*)mBfIRBuilder->GetConstant(globalValue);
  12758. if ((globalVar->mStreamId == -1) && (!mBfIRBuilder->mIgnoreWrites))
  12759. {
  12760. mBfIRBuilder->MapType(fieldInstance->mResolvedType);
  12761. mBfIRBuilder->CreateGlobalVariable(globalValue);
  12762. }
  12763. }
  12764. else
  12765. {
  12766. StringT<512> staticVarName;
  12767. BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), fieldInstance);
  12768. auto typeType = fieldInstance->GetResolvedType();
  12769. if ((fieldDef->mIsExtern) && (fieldDef->mIsConst) && (typeType->IsPointer()))
  12770. {
  12771. typeType = typeType->GetUnderlyingType();
  12772. }
  12773. if (mIsComptimeModule)
  12774. {
  12775. mCompiler->mCeMachine->QueueStaticField(fieldInstance, staticVarName);
  12776. }
  12777. PopulateType(typeType);
  12778. if ((typeType != NULL) && (!typeType->IsValuelessType()))
  12779. {
  12780. BfIRType irType = mBfIRBuilder->MapType(typeType);
  12781. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || staticVarName.StartsWith('#'));
  12782. globalValue = mBfIRBuilder->CreateGlobalVariable(
  12783. irType,
  12784. false,
  12785. BfIRLinkageType_External,
  12786. BfIRValue(),
  12787. staticVarName,
  12788. IsThreadLocal(fieldInstance));
  12789. BF_ASSERT(globalValue);
  12790. mStaticFieldRefs[fieldInstance] = globalValue;
  12791. BfLogSysM("Mod:%p Type:%p ReferenceStaticField %p -> %p\n", this, fieldInstance->mOwner, fieldInstance, globalValue);
  12792. }
  12793. }
  12794. auto type = fieldInstance->GetResolvedType();
  12795. if (type->IsValuelessType())
  12796. return BfTypedValue(globalValue, type);
  12797. return BfTypedValue(globalValue, type, !fieldDef->mIsConst);
  12798. }
  12799. BfFieldInstance* BfModule::GetFieldInstance(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName)
  12800. {
  12801. if (typeInst->IsDataIncomplete())
  12802. PopulateType(typeInst);
  12803. if (fieldIdx >= typeInst->mFieldInstances.mSize)
  12804. {
  12805. Fail(StrFormat("Invalid field data in type '%s'", TypeToString(typeInst).c_str()));
  12806. return 0;
  12807. }
  12808. return &typeInst->mFieldInstances[fieldIdx];
  12809. }
  12810. void BfModule::MarkUsingThis()
  12811. {
  12812. auto useMethodState = mCurMethodState;
  12813. while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
  12814. {
  12815. useMethodState = useMethodState->mPrevMethodState;
  12816. }
  12817. if ((useMethodState != NULL) && (!useMethodState->mLocals.IsEmpty()))
  12818. {
  12819. auto localVar = useMethodState->mLocals[0];
  12820. if (localVar->mIsThis)
  12821. localVar->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++;
  12822. }
  12823. }
  12824. BfTypedValue BfModule::GetThis(bool markUsing)
  12825. {
  12826. if ((mIsComptimeModule) && (mCompiler->mCeMachine->mDebugger != NULL) && (mCompiler->mCeMachine->mDebugger->mCurDbgState != NULL))
  12827. {
  12828. if (mCompiler->mCeMachine->mDebugger->mCurDbgState->mExplicitThis)
  12829. return mCompiler->mCeMachine->mDebugger->mCurDbgState->mExplicitThis;
  12830. auto ceDebugger = mCompiler->mCeMachine->mDebugger;
  12831. auto activeFrame = ceDebugger->mCurDbgState->mActiveFrame;
  12832. if ((activeFrame != NULL) && (activeFrame->mFunction->mDbgInfo != NULL))
  12833. {
  12834. for (auto& dbgVar : activeFrame->mFunction->mDbgInfo->mVariables)
  12835. {
  12836. if (dbgVar.mName == "this")
  12837. return BfTypedValue(mBfIRBuilder->CreateConstAggCE(mBfIRBuilder->MapType(dbgVar.mType), activeFrame->mFrameAddr + dbgVar.mValue.mFrameOfs), dbgVar.mType,
  12838. dbgVar.mIsConst ? BfTypedValueKind_ReadOnlyAddr : BfTypedValueKind_Addr);
  12839. }
  12840. }
  12841. return BfTypedValue();
  12842. }
  12843. auto useMethodState = mCurMethodState;
  12844. while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
  12845. {
  12846. useMethodState = useMethodState->mPrevMethodState;
  12847. }
  12848. if (useMethodState != NULL)
  12849. {
  12850. // Fake a 'this' for var field resolution
  12851. if (useMethodState->mTempKind == BfMethodState::TempKind_NonStatic)
  12852. {
  12853. auto thisType = mCurTypeInstance;
  12854. if (thisType->IsValueType())
  12855. return BfTypedValue(mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapTypeInstPtr(thisType)), thisType, BfTypedValueKind_ThisAddr);
  12856. else
  12857. return BfTypedValue(mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapTypeInst(thisType)), thisType, BfTypedValueKind_ThisValue);
  12858. }
  12859. else if (useMethodState->mTempKind == BfMethodState::TempKind_Static)
  12860. {
  12861. return BfTypedValue();
  12862. }
  12863. }
  12864. else
  12865. {
  12866. //TODO: Do we allow useMethodState to be NULL anymore?
  12867. return BfTypedValue();
  12868. }
  12869. // Check mixin state for 'this'
  12870. {
  12871. auto checkMethodState = mCurMethodState;
  12872. while (checkMethodState != NULL)
  12873. {
  12874. if (checkMethodState->mMixinState != NULL)
  12875. {
  12876. BfTypedValue thisValue = checkMethodState->mMixinState->mTarget;
  12877. if (thisValue.HasType())
  12878. {
  12879. checkMethodState->mMixinState->mLastTargetAccessId = useMethodState->GetRootMethodState()->mCurAccessId++;
  12880. if (!thisValue.mType->IsValueType())
  12881. thisValue = LoadValue(thisValue);
  12882. return thisValue;
  12883. }
  12884. }
  12885. checkMethodState = checkMethodState->mPrevMethodState;
  12886. }
  12887. }
  12888. auto curMethodInstance = mCurMethodInstance;
  12889. if (useMethodState->mMethodInstance != NULL)
  12890. curMethodInstance = useMethodState->mMethodInstance;
  12891. if ((curMethodInstance == NULL) /*|| (!mCurMethodInstance->mIRFunction)*/ || (curMethodInstance->mMethodDef->mIsStatic))
  12892. {
  12893. if ((useMethodState->mClosureState != NULL) && (!useMethodState->mClosureState->mConstLocals.empty()))
  12894. {
  12895. auto& constLocal = useMethodState->mClosureState->mConstLocals[0];
  12896. if (constLocal.mIsThis)
  12897. {
  12898. BF_ASSERT(constLocal.mResolvedType->IsValuelessType());
  12899. return BfTypedValue(mBfIRBuilder->GetFakeVal(), constLocal.mResolvedType);
  12900. }
  12901. }
  12902. return BfTypedValue();
  12903. }
  12904. if (useMethodState->mLocals.IsEmpty())
  12905. {
  12906. // This can happen in rare non-capture cases, such as when we need to do a const expression resolve for a sized-array return type on a local method
  12907. BF_ASSERT(useMethodState->mPrevMethodState != NULL);
  12908. return BfTypedValue();
  12909. }
  12910. auto thisLocal = useMethodState->mLocals[0];
  12911. BF_ASSERT(thisLocal->mIsThis);
  12912. bool preferValue = !IsTargetingBeefBackend();
  12913. if (!thisLocal->mAddr)
  12914. preferValue = true;
  12915. bool usedVal = false;
  12916. BfIRValue thisValue;
  12917. if ((preferValue) && (!thisLocal->mIsLowered))
  12918. {
  12919. thisValue = thisLocal->mValue;
  12920. usedVal = true;
  12921. }
  12922. else if ((thisLocal->mIsSplat) || (thisLocal->mIsLowered))
  12923. thisValue = thisLocal->mAddr;
  12924. else
  12925. thisValue = mBfIRBuilder->CreateAlignedLoad(thisLocal->mAddr, thisLocal->mResolvedType->mAlign);
  12926. if (markUsing)
  12927. useMethodState->mLocals[0]->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++;
  12928. if (useMethodState->mClosureState != NULL)
  12929. {
  12930. auto closureTypeInst = useMethodState->mClosureState->mClosureType;
  12931. if (closureTypeInst != NULL)
  12932. {
  12933. if (closureTypeInst->mFieldInstances.size() > 0)
  12934. {
  12935. auto& field = closureTypeInst->mFieldInstances[0];
  12936. auto fieldDef = field.GetFieldDef();
  12937. if (fieldDef->mName == "__this")
  12938. {
  12939. if (mCurMethodState->mClosureState->mCapturing)
  12940. mCurMethodState->mClosureState->mReferencedOuterClosureMembers.Add(&field);
  12941. // This is a captured 'this'
  12942. BfTypedValue result = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(thisValue, 0, field.mDataIdx), field.mResolvedType, true);
  12943. if (field.mResolvedType->IsRef())
  12944. {
  12945. auto refType = (BfRefType*)field.mResolvedType;
  12946. auto underlyingType = refType->GetUnderlyingType();
  12947. result = BfTypedValue(mBfIRBuilder->CreateLoad(result.mValue), underlyingType, true);
  12948. }
  12949. if (field.mResolvedType->IsObject())
  12950. {
  12951. result = LoadValue(result);
  12952. result.mKind = BfTypedValueKind_ThisValue;
  12953. }
  12954. else
  12955. {
  12956. if (fieldDef->mIsReadOnly)
  12957. result.mKind = BfTypedValueKind_ReadOnlyThisAddr;
  12958. else
  12959. result.mKind = BfTypedValueKind_ThisAddr;
  12960. }
  12961. return result;
  12962. }
  12963. }
  12964. return BfTypedValue();
  12965. }
  12966. if (useMethodState->mClosureState->mCapturing)
  12967. {
  12968. auto thisType = useMethodState->mLocals[0]->mResolvedType;
  12969. if (thisType->IsValueType())
  12970. return BfTypedValue(CreateAlloca(thisType), thisType, BfTypedValueKind_ThisAddr);
  12971. else
  12972. return BfTypedValue(GetDefaultValue(thisType), thisType, BfTypedValueKind_ThisValue);
  12973. }
  12974. }
  12975. if (mCurMethodInstance == NULL)
  12976. return BfTypedValue();
  12977. auto localDef = useMethodState->mLocals[0];
  12978. auto curMethodOwner = mCurMethodInstance->mMethodInstanceGroup->mOwner;
  12979. if ((curMethodOwner->IsStruct()) || (curMethodOwner->IsTypedPrimitive()))
  12980. {
  12981. if ((localDef->mResolvedType->IsTypedPrimitive()) && (!mCurMethodInstance->mMethodDef->mIsMutating))
  12982. {
  12983. return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, BfTypedValueKind_ReadOnlyThisValue);
  12984. }
  12985. if (localDef->mIsSplat)
  12986. {
  12987. return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, BfTypedValueKind_ThisSplatHead);
  12988. }
  12989. return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, localDef->mIsReadOnly ? BfTypedValueKind_ReadOnlyThisAddr : BfTypedValueKind_ThisAddr);
  12990. }
  12991. return BfTypedValue(thisValue, mCurMethodInstance->mMethodInstanceGroup->mOwner, BfTypedValueKind_ThisValue);
  12992. }
  12993. BfLocalVariable* BfModule::GetThisVariable()
  12994. {
  12995. if (mCurMethodState == NULL)
  12996. return NULL;
  12997. auto methodState = mCurMethodState->GetNonCaptureState();
  12998. if ((methodState->mLocals.size() > 0) && (methodState->mLocals[0]->mIsThis))
  12999. return methodState->mLocals[0];
  13000. return NULL;
  13001. }
  13002. bool BfModule::IsInGeneric()
  13003. {
  13004. return ((mCurMethodInstance != NULL) && (mCurMethodInstance->GetNumGenericArguments() != 0)) || (mCurTypeInstance->IsGenericTypeInstance());
  13005. }
  13006. bool BfModule::InDefinitionSection()
  13007. {
  13008. if (mCurTypeInstance != NULL)
  13009. {
  13010. if (mCurTypeInstance->IsUnspecializedTypeVariation())
  13011. return false;
  13012. }
  13013. return !IsInSpecializedSection();
  13014. }
  13015. bool BfModule::IsInSpecializedGeneric()
  13016. {
  13017. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsSpecializedType()))
  13018. return true;
  13019. if ((mCurMethodInstance == NULL) || (mCurMethodInstance->mIsUnspecialized))
  13020. return false;
  13021. return (mCurMethodInstance->GetNumGenericArguments() != 0);
  13022. }
  13023. bool BfModule::IsInSpecializedSection()
  13024. {
  13025. return IsInSpecializedGeneric() ||
  13026. ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL));
  13027. }
  13028. bool BfModule::IsInUnspecializedGeneric()
  13029. {
  13030. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized))
  13031. return true;
  13032. if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsUnspecializedType()))
  13033. return true;
  13034. return false;
  13035. }
  13036. //////////////////////////////////////////////////////////////////////////
  13037. BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd)
  13038. {
  13039. //if ((type->IsValuelessType()) || (type->IsMethodRef()))
  13040. if (type->IsValuelessType())
  13041. return mBfIRBuilder->GetFakeVal();
  13042. auto allocaInst = CreateAlloca(type, doLifetimeEnd, name.c_str());
  13043. if ((!doLifetimeEnd) && (WantsLifetimes()))
  13044. {
  13045. auto lifetimeStart = mBfIRBuilder->CreateLifetimeStart(allocaInst);
  13046. mBfIRBuilder->ClearDebugLocation(lifetimeStart);
  13047. }
  13048. bool initLocalVariables = mCompiler->mOptions.mInitLocalVariables;
  13049. auto typeOptions = GetTypeOptions();
  13050. if (typeOptions != NULL)
  13051. initLocalVariables = typeOptions->Apply(initLocalVariables, BfOptionFlags_InitLocalVariables);
  13052. // Local variable inits are implicitly handled in the Beef Backend
  13053. if ((initLocalVariables) && (!IsTargetingBeefBackend()))
  13054. {
  13055. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  13056. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  13057. auto storeInst = mBfIRBuilder->CreateAlignedStore(GetDefaultValue(type), allocaInst, type->mAlign);
  13058. mBfIRBuilder->ClearDebugLocation(storeInst);
  13059. mBfIRBuilder->SetInsertPoint(prevBlock);
  13060. }
  13061. return allocaInst;
  13062. }
  13063. void BfModule::DoAddLocalVariable(BfLocalVariable* localVar)
  13064. {
  13065. while (localVar->mName.StartsWith('@'))
  13066. {
  13067. localVar->mNamePrefixCount++;
  13068. localVar->mName.Remove(0);
  13069. }
  13070. if (mCurMethodState->mLocals.mAllocSize == 0)
  13071. {
  13072. mCurMethodState->mLocals.Reserve(16);
  13073. mCurMethodState->mLocalVarSet.Reserve(16);
  13074. }
  13075. localVar->mLocalVarIdx = (int)mCurMethodState->mLocals.size();
  13076. mCurMethodState->mLocals.push_back(localVar);
  13077. BfLocalVarEntry* localVarEntryPtr;
  13078. if (!mCurMethodState->mLocalVarSet.TryAdd(BfLocalVarEntry(localVar), &localVarEntryPtr))
  13079. {
  13080. localVar->mShadowedLocal = localVarEntryPtr->mLocalVar;
  13081. localVarEntryPtr->mLocalVar = localVar;
  13082. }
  13083. }
  13084. void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAliasValue, BfIRValue declareBefore, BfIRInitType initType)
  13085. {
  13086. if (localVarDef->mResolvedType->IsVar())
  13087. return;
  13088. if ((mBfIRBuilder->DbgHasInfo()) &&
  13089. ((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecialized)) &&
  13090. (mHasFullDebugInfo) &&
  13091. ((mCurMethodState->mClosureState == NULL) || (!mCurMethodState->mClosureState->mCapturing)))
  13092. {
  13093. auto varType = localVarDef->mResolvedType;
  13094. if (localVarDef->mResolvedType->IsValuelessType())
  13095. {
  13096. }
  13097. else
  13098. {
  13099. bool isByAddr = false;
  13100. auto diValue = localVarDef->mValue;
  13101. if (localVarDef->mConstValue)
  13102. diValue = localVarDef->mConstValue;
  13103. else if (localVarDef->mAddr)
  13104. {
  13105. diValue = localVarDef->mAddr;
  13106. isByAddr = true;
  13107. }
  13108. if (diValue.IsConst())
  13109. {
  13110. auto constant = mBfIRBuilder->GetConstant(diValue);
  13111. if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData))
  13112. {
  13113. // Ignore for now
  13114. return;
  13115. }
  13116. }
  13117. auto diType = mBfIRBuilder->DbgGetType(localVarDef->mResolvedType);
  13118. bool didConstToMem = false;
  13119. bool isConstant = false;
  13120. if ((localVarDef->mIsReadOnly) && (localVarDef->mAddr))
  13121. diType = mBfIRBuilder->DbgCreateConstType(diType);
  13122. else if (localVarDef->mConstValue)
  13123. {
  13124. auto constant = mBfIRBuilder->GetConstant(localVarDef->mConstValue);
  13125. isConstant =
  13126. (constant->mConstType < BfConstType_GlobalVar) ||
  13127. (constant->mConstType == BfConstType_AggZero) ||
  13128. (constant->mConstType == BfConstType_Agg);
  13129. if (isConstant)
  13130. {
  13131. if (localVarDef->mResolvedType->IsComposite())
  13132. {
  13133. mBfIRBuilder->PopulateType(localVarDef->mResolvedType);
  13134. auto constMem = mBfIRBuilder->ConstToMemory(localVarDef->mConstValue);
  13135. // if (IsTargetingBeefBackend())
  13136. // {
  13137. // diValue = mBfIRBuilder->CreateAliasValue(constMem);
  13138. // didConstToMem = true;
  13139. //
  13140. // diType = mBfIRBuilder->DbgCreateReferenceType(diType);
  13141. // }
  13142. //else
  13143. {
  13144. isByAddr = true;
  13145. mBfIRBuilder->SaveDebugLocation();
  13146. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  13147. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRInitBlock);
  13148. mBfIRBuilder->ClearDebugLocation();
  13149. auto ptrType = CreatePointerType(localVarDef->mResolvedType);
  13150. auto addrVal = CreateAlloca(ptrType);
  13151. mBfIRBuilder->CreateStore(constMem, addrVal);
  13152. diType = mBfIRBuilder->DbgCreateReferenceType(diType);
  13153. diValue = addrVal;
  13154. didConstToMem = true;
  13155. mBfIRBuilder->SetInsertPoint(prevBlock);
  13156. mBfIRBuilder->RestoreDebugLocation();
  13157. }
  13158. }
  13159. if (mCompiler->mOptions.IsCodeView())
  13160. diType = mBfIRBuilder->DbgCreateConstType(diType);
  13161. }
  13162. }
  13163. if (!mBfIRBuilder->mIgnoreWrites)
  13164. {
  13165. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  13166. localVarDef->mName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType, initType);
  13167. localVarDef->mDbgVarInst = diVariable;
  13168. if (mBfIRBuilder->HasDebugLocation())
  13169. {
  13170. if ((isConstant) && (!didConstToMem))
  13171. {
  13172. BfTypedValue result(localVarDef->mConstValue, localVarDef->mResolvedType);
  13173. FixValueActualization(result);
  13174. localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(result.mValue, diVariable);
  13175. }
  13176. else
  13177. {
  13178. if ((IsTargetingBeefBackend()) && (doAliasValue) && (!mIsComptimeModule))
  13179. {
  13180. diValue = mBfIRBuilder->CreateAliasValue(diValue);
  13181. mCurMethodState->mCurScope->mDeferredLifetimeEnds.Add(diValue);
  13182. }
  13183. if (isByAddr)
  13184. localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertDeclare(diValue, diVariable, declareBefore);
  13185. else if (diValue)
  13186. {
  13187. localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(diValue, diVariable);
  13188. }
  13189. else if (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU) // DWARF chokes on this:
  13190. localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(BfIRValue(), diVariable);
  13191. }
  13192. }
  13193. }
  13194. }
  13195. }
  13196. }
  13197. BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, bool addDebugInfo, bool doAliasValue, BfIRValue declareBefore, BfIRInitType initType)
  13198. {
  13199. if ((localVarDef->mValue) && (!localVarDef->mAddr) && (IsTargetingBeefBackend()) && (!localVarDef->mResolvedType->IsValuelessType()))
  13200. {
  13201. if ((!localVarDef->mValue.IsConst()) &&
  13202. (!localVarDef->mValue.IsArg()) && (!localVarDef->mValue.IsFake()))
  13203. {
  13204. mBfIRBuilder->CreateValueScopeRetain(localVarDef->mValue);
  13205. mCurMethodState->mCurScope->mHadScopeValueRetain = true;
  13206. }
  13207. }
  13208. if (addDebugInfo)
  13209. DoLocalVariableDebugInfo(localVarDef, doAliasValue, declareBefore, initType);
  13210. localVarDef->mDeclBlock = mBfIRBuilder->GetInsertBlock();
  13211. DoAddLocalVariable(localVarDef);
  13212. auto rootMethodState = mCurMethodState->GetRootMethodState();
  13213. if (localVarDef->mLocalVarId == -1)
  13214. {
  13215. BF_ASSERT(rootMethodState->mCurLocalVarId >= 0);
  13216. localVarDef->mLocalVarId = rootMethodState->mCurLocalVarId++;
  13217. }
  13218. bool checkLocal = true;
  13219. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Ctor))
  13220. {
  13221. if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(mCurMethodInstance->mMethodDef->mMethodDeclaration))
  13222. checkLocal = false;
  13223. }
  13224. if ((localVarDef->mNameNode != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (!mIsComptimeModule) && (checkLocal))
  13225. mCompiler->mResolvePassData->mAutoComplete->CheckLocalDef(localVarDef->mNameNode, localVarDef);
  13226. if (((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL)) && (checkLocal))
  13227. {
  13228. bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing);
  13229. if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (rootMethodState->mMethodInstance != NULL) && (!mIsComptimeModule))
  13230. mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
  13231. }
  13232. return localVarDef;
  13233. }
  13234. void BfModule::CreateDIRetVal()
  13235. {
  13236. if (!WantsDebugInfo())
  13237. return;
  13238. /*if (!mCurMethodState->mRetVal)
  13239. {
  13240. if (mCurMethodInstance->mMethodDef->mName != "Ziggle")
  13241. return;
  13242. }*/
  13243. if ((mCurMethodState->mRetVal) || (mCurMethodState->mRetValAddr))
  13244. {
  13245. BfType* dbgType = mCurMethodInstance->mReturnType;
  13246. BfIRValue dbgValue = mCurMethodState->mRetVal.mValue;
  13247. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  13248. {
  13249. BF_ASSERT(mCurMethodState->mRetValAddr);
  13250. dbgType = CreatePointerType(dbgType);
  13251. dbgValue = mCurMethodState->mRetValAddr;
  13252. }
  13253. else
  13254. {
  13255. BF_ASSERT(!mCurMethodState->mRetValAddr);
  13256. }
  13257. mCurMethodState->mDIRetVal = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  13258. "@return", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(dbgType));
  13259. auto declareCall = mBfIRBuilder->DbgInsertDeclare(dbgValue, mCurMethodState->mDIRetVal);
  13260. }
  13261. }
  13262. BfTypedValue BfModule::CreateTuple(const Array<BfTypedValue>& values, const Array<String>& fieldNames)
  13263. {
  13264. BfTypeVector fieldTypes;
  13265. for (auto arg : values)
  13266. fieldTypes.Add(arg.mType);
  13267. auto tupleType = CreateTupleType(fieldTypes, fieldNames);
  13268. auto tupleTypedValue = BfTypedValue(CreateAlloca(tupleType), tupleType, true);
  13269. for (int fieldIdx = 0; fieldIdx < tupleType->mFieldInstances.size(); fieldIdx++)
  13270. {
  13271. auto& fieldInstance = tupleType->mFieldInstances[fieldIdx];
  13272. if (fieldInstance.mDataIdx <= 0)
  13273. continue;
  13274. auto typedVal = values[fieldIdx];
  13275. typedVal = LoadOrAggregateValue(typedVal);
  13276. mBfIRBuilder->CreateAlignedStore(typedVal.mValue, mBfIRBuilder->CreateInBoundsGEP(tupleTypedValue.mValue, 0, fieldInstance.mDataIdx), typedVal.mType->mAlign);
  13277. }
  13278. return tupleTypedValue;
  13279. }
  13280. void BfModule::CheckVariableDef(BfLocalVariable* variableDef)
  13281. {
  13282. if (variableDef->mName.IsEmpty())
  13283. return;
  13284. BfLocalVarEntry* localVarEntryPtr = NULL;
  13285. if ((mCurMethodState != NULL) && (mCurMethodState->mLocalVarSet.TryGet(BfLocalVarEntry(variableDef), &localVarEntryPtr)))
  13286. {
  13287. auto checkLocal = localVarEntryPtr->mLocalVar;
  13288. if ((checkLocal->mLocalVarIdx >= mCurMethodState->GetLocalStartIdx()) && (!checkLocal->mIsShadow))
  13289. {
  13290. BfError* error;
  13291. if (checkLocal->mIsImplicitParam)
  13292. return; // Ignore 'redefinition'
  13293. if (checkLocal->IsParam())
  13294. {
  13295. if (variableDef->IsParam())
  13296. error = Fail(StrFormat("A parameter named '%s' has already been declared", variableDef->mName.c_str()), variableDef->mNameNode);
  13297. else
  13298. error = Fail(StrFormat("The name '%s' is already used by a parameter. Consider declaring 'var %s;' if you wish to make a mutable copy of that parameter.", variableDef->mName.c_str(), variableDef->mName.c_str()), variableDef->mNameNode);
  13299. }
  13300. else if (checkLocal->mLocalVarIdx < mCurMethodState->mCurScope->mLocalVarStart)
  13301. error = Fail(StrFormat("A variable named '%s' has already been declared in this parent's scope", variableDef->mName.c_str()), variableDef->mNameNode);
  13302. else
  13303. error = Fail(StrFormat("A variable named '%s' has already been declared in this scope", variableDef->mName.c_str()), variableDef->mNameNode);
  13304. if ((checkLocal->mNameNode != NULL) && (error != NULL))
  13305. mCompiler->mPassInstance->MoreInfo("Previous declaration", checkLocal->mNameNode);
  13306. return;
  13307. }
  13308. }
  13309. }
  13310. BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinState, bool allowAcrossDeferredBlock)
  13311. {
  13312. bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin());
  13313. if (auto tokenNode = BfNodeDynCast<BfTokenNode>(scopeName))
  13314. {
  13315. if (tokenNode->GetToken() == BfToken_Colon)
  13316. {
  13317. if ((!allowAcrossDeferredBlock) && (mCurMethodState->mInDeferredBlock))
  13318. {
  13319. Fail("Cannot access method scope across deferred block boundary", scopeName);
  13320. return NULL;
  13321. }
  13322. return &mCurMethodState->mHeadScope;
  13323. }
  13324. else if (tokenNode->GetToken() == BfToken_Mixin)
  13325. {
  13326. if (fromMixinState == NULL)
  13327. {
  13328. if (mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Mixin)
  13329. Fail("'mixin' scope specifier can only be used within a mixin declaration", scopeName);
  13330. return mCurMethodState->mCurScope;
  13331. }
  13332. fromMixinState->mUsedInvocationScope = true;
  13333. return fromMixinState->mTargetScope;
  13334. }
  13335. else if (tokenNode->GetToken() == BfToken_New)
  13336. return NULL;
  13337. }
  13338. if (auto identifier = BfNodeDynCast<BfIdentifierNode>(scopeName))
  13339. {
  13340. auto findLabel = scopeName->ToString();
  13341. bool crossedDeferredBlock = false;
  13342. auto checkScope = mCurMethodState->mCurScope;
  13343. while (checkScope != NULL)
  13344. {
  13345. if (checkScope->mIsDeferredBlock)
  13346. crossedDeferredBlock = true;
  13347. if (checkScope->mLabel == findLabel)
  13348. {
  13349. if ((crossedDeferredBlock) && (!allowAcrossDeferredBlock))
  13350. {
  13351. Fail(StrFormat("Cannot access scope '%s' across deferred block boundary", findLabel.c_str()), scopeName);
  13352. return NULL;
  13353. }
  13354. return checkScope;
  13355. }
  13356. checkScope = checkScope->mPrevScope;
  13357. }
  13358. if (!inMixinDecl)
  13359. Fail(StrFormat("Unable to locate label '%s'", findLabel.c_str()), scopeName);
  13360. }
  13361. if (auto scopeNode = BfNodeDynCast<BfScopeNode>(scopeName))
  13362. {
  13363. return FindScope(scopeNode->mTargetNode, allowAcrossDeferredBlock);
  13364. }
  13365. return mCurMethodState->mCurScope;
  13366. }
  13367. BfScopeData* BfModule::FindScope(BfAstNode* scopeName, bool allowAcrossDeferredBlock)
  13368. {
  13369. return FindScope(scopeName, mCurMethodState->mMixinState, allowAcrossDeferredBlock);
  13370. }
  13371. BfBreakData* BfModule::FindBreakData(BfAstNode* scopeName)
  13372. {
  13373. auto scopeData = FindScope(scopeName, false);
  13374. if (scopeData == NULL)
  13375. return NULL;
  13376. int scopeDepth = scopeData->GetDepth();
  13377. // Find the first break data that is at or below the depth of our requested scope
  13378. auto breakData = mCurMethodState->mBreakData;
  13379. while ((breakData != NULL) && (scopeDepth < breakData->mScope->GetDepth()))
  13380. {
  13381. if (breakData->mScope->mIsConditional)
  13382. return NULL;
  13383. breakData = breakData->mPrevBreakData;
  13384. }
  13385. return breakData;
  13386. }
  13387. void BfModule::EmitLifetimeEnds(BfScopeData* scopeData)
  13388. {
  13389. // LLVM is stricter about the placement of these (ie: they can't occur after a 'ret')
  13390. if (!IsTargetingBeefBackend())
  13391. return;
  13392. for (auto lifetimeEnd : scopeData->mDeferredLifetimeEnds)
  13393. {
  13394. mBfIRBuilder->CreateLifetimeEnd(lifetimeEnd);
  13395. }
  13396. }
  13397. void BfModule::ClearLifetimeEnds()
  13398. {
  13399. auto scopeData = mCurMethodState->mCurScope;
  13400. while (scopeData != NULL)
  13401. {
  13402. scopeData->mDeferredLifetimeEnds.Clear();
  13403. scopeData = scopeData->mPrevScope;
  13404. }
  13405. }
  13406. bool BfModule::WantsDebugInfo()
  13407. {
  13408. if ((mCurMethodInstance != NULL) &&
  13409. ((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mMethodType == BfMethodType_Mixin)))
  13410. return false;
  13411. return (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo) &&
  13412. ((mCurMethodState == NULL) || (mCurMethodState->mClosureState == NULL) || (!mCurMethodState->mClosureState->mCapturing));
  13413. }
  13414. BfTypeOptions* BfModule::GetTypeOptions()
  13415. {
  13416. if ((mCurMethodState != NULL) && (mCurMethodState->mMethodTypeOptions != NULL))
  13417. return mCurMethodState->mMethodTypeOptions;
  13418. if (mCurMethodInstance == NULL)
  13419. return NULL;
  13420. return mSystem->GetTypeOptions(mCurTypeInstance->mTypeOptionsIdx);
  13421. }
  13422. BfReflectKind BfModule::GetUserReflectKind(BfTypeInstance* attrType)
  13423. {
  13424. BfReflectKind reflectKind = BfReflectKind_None;
  13425. if (attrType->mCustomAttributes != NULL)
  13426. {
  13427. for (auto& customAttr : attrType->mCustomAttributes->mAttributes)
  13428. {
  13429. if (customAttr.mType->mTypeDef->mName->ToString() == "AttributeUsageAttribute")
  13430. {
  13431. for (auto& prop : customAttr.mSetProperties)
  13432. {
  13433. auto propDef = prop.mPropertyRef.mTypeInstance->mTypeDef->mProperties[prop.mPropertyRef.mPropIdx];
  13434. if (propDef->mName == "ReflectUser")
  13435. {
  13436. if (prop.mParam.mValue.IsConst())
  13437. {
  13438. auto constant = attrType->mConstHolder->GetConstant(prop.mParam.mValue);
  13439. reflectKind = (BfReflectKind)(reflectKind | (BfReflectKind)constant->mInt32);
  13440. }
  13441. }
  13442. }
  13443. // Check for Flags arg
  13444. if (customAttr.mCtorArgs.size() < 2)
  13445. continue;
  13446. auto constant = attrType->mConstHolder->GetConstant(customAttr.mCtorArgs[1]);
  13447. if (constant == NULL)
  13448. continue;
  13449. if (constant->mTypeCode == BfTypeCode_Boolean)
  13450. continue;
  13451. if ((constant->mInt8 & BfCustomAttributeFlags_ReflectAttribute) != 0)
  13452. reflectKind = (BfReflectKind)(reflectKind | BfReflectKind_User);
  13453. }
  13454. }
  13455. }
  13456. return reflectKind;
  13457. }
  13458. BfReflectKind BfModule::GetReflectKind(BfReflectKind reflectKind, BfTypeInstance* typeInstance)
  13459. {
  13460. auto checkTypeInstance = typeInstance;
  13461. while (checkTypeInstance != NULL)
  13462. {
  13463. if (checkTypeInstance->mCustomAttributes != NULL)
  13464. {
  13465. auto checkReflectKind = BfReflectKind_None;
  13466. for (auto& customAttr : checkTypeInstance->mCustomAttributes->mAttributes)
  13467. {
  13468. if (customAttr.mType->mTypeDef->mName->ToString() == "ReflectAttribute")
  13469. {
  13470. if (customAttr.mCtorArgs.size() > 0)
  13471. {
  13472. auto constant = checkTypeInstance->mConstHolder->GetConstant(customAttr.mCtorArgs[0]);
  13473. checkReflectKind = (BfReflectKind)((int)checkReflectKind | constant->mInt32);
  13474. }
  13475. else
  13476. {
  13477. checkReflectKind = BfReflectKind_All;
  13478. }
  13479. }
  13480. else
  13481. {
  13482. auto userReflectKind = GetUserReflectKind(customAttr.mType);
  13483. checkReflectKind = (BfReflectKind)(checkReflectKind | userReflectKind);
  13484. }
  13485. }
  13486. if ((checkTypeInstance == typeInstance) ||
  13487. ((checkReflectKind & BfReflectKind_ApplyToInnerTypes) != 0))
  13488. {
  13489. reflectKind = (BfReflectKind)(reflectKind | checkReflectKind);
  13490. }
  13491. }
  13492. for (auto ifaceEntry : typeInstance->mInterfaces)
  13493. {
  13494. if (ifaceEntry.mInterfaceType->mCustomAttributes != NULL)
  13495. {
  13496. auto iface = ifaceEntry.mInterfaceType;
  13497. auto customAttr = iface->mCustomAttributes->Get(mCompiler->mReflectAttributeTypeDef);
  13498. if (customAttr != NULL)
  13499. {
  13500. for (auto& prop : customAttr->mSetProperties)
  13501. {
  13502. auto propDef = prop.mPropertyRef.mTypeInstance->mTypeDef->mProperties[prop.mPropertyRef.mPropIdx];
  13503. if (propDef->mName == "ReflectImplementer")
  13504. {
  13505. if (prop.mParam.mValue.IsConst())
  13506. {
  13507. auto constant = iface->mConstHolder->GetConstant(prop.mParam.mValue);
  13508. reflectKind = (BfReflectKind)(reflectKind | (BfReflectKind)constant->mInt32);
  13509. }
  13510. }
  13511. }
  13512. }
  13513. }
  13514. }
  13515. checkTypeInstance = mContext->mUnreifiedModule->GetOuterType(checkTypeInstance);
  13516. }
  13517. return reflectKind;
  13518. }
  13519. bool BfModule::HasDeferredScopeCalls(BfScopeData* scope)
  13520. {
  13521. BfScopeData* checkScope = mCurMethodState->mCurScope;
  13522. while (checkScope != NULL)
  13523. {
  13524. if ((!checkScope->mDeferredCallEntries.IsEmpty()) || (!checkScope->mDeferredLifetimeEnds.empty()))
  13525. return true;
  13526. if (checkScope == scope)
  13527. break;
  13528. checkScope = checkScope->mPrevScope;
  13529. }
  13530. return false;
  13531. }
  13532. void BfModule::EmitDeferredScopeCalls(bool useSrcPositions, BfScopeData* scopeData, BfIRBlock doneBlock)
  13533. {
  13534. // Is there anything we need to do here?
  13535. if (mBfIRBuilder->mIgnoreWrites)
  13536. {
  13537. // Just visit deferred blocks
  13538. BfScopeData* checkScope = mCurMethodState->mCurScope;
  13539. while (checkScope != NULL)
  13540. {
  13541. BfDeferredCallEntry* deferredCallEntry = checkScope->mDeferredCallEntries.mHead;
  13542. while (deferredCallEntry != NULL)
  13543. {
  13544. if (deferredCallEntry->mDeferredBlock != NULL)
  13545. {
  13546. SetAndRestoreValue<BfMixinState*> prevMixinState(mCurMethodState->mMixinState, checkScope->mMixinState);
  13547. if (checkScope == &mCurMethodState->mHeadScope)
  13548. CreateRetValLocal();
  13549. SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, deferredCallEntry->mEmitRefNode);
  13550. VisitEmbeddedStatement(deferredCallEntry->mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
  13551. }
  13552. deferredCallEntry = deferredCallEntry->mNext;
  13553. }
  13554. if (checkScope == scopeData)
  13555. break;
  13556. checkScope = checkScope->mPrevScope;
  13557. }
  13558. return;
  13559. }
  13560. // Why did we want to do SetIllegalSrcPos here?
  13561. // Don't we always want to step onto these instances?
  13562. // Find a case where we don't and perhaps only do it there.
  13563. // The downside was that 'EmitEnsureInstructionAt' on the end of block statements causes
  13564. // a (seemingly) unneeded NOP when we do SetIllegalSrcPos
  13565. //SetIllegalSrcPos();
  13566. bool setSrcPos = false;
  13567. bool wantsNop = true;
  13568. BfAstNode* deferCloseNode = NULL;
  13569. if (mCurMethodState->mInPostReturn)
  13570. {
  13571. // These won't get used, they are post-return
  13572. return;
  13573. }
  13574. SizedArray<BfIRValue, 8> deferredLifetimeEnds;
  13575. BfScopeData* scopeJumpBlock = NULL;
  13576. bool hadExtraDeferredLifetimeEnds = false;
  13577. auto _FlushLifetimeEnds = [&]()
  13578. {
  13579. for (auto lifetimeEnd : deferredLifetimeEnds)
  13580. {
  13581. mBfIRBuilder->CreateLifetimeEnd(lifetimeEnd);
  13582. mBfIRBuilder->ClearDebugLocation_Last();
  13583. }
  13584. deferredLifetimeEnds.clear();
  13585. };
  13586. BfScopeData* checkScope = mCurMethodState->mCurScope;
  13587. while (checkScope != NULL)
  13588. {
  13589. if (checkScope->mCloseNode != NULL)
  13590. deferCloseNode = checkScope->mCloseNode;
  13591. if (doneBlock)
  13592. {
  13593. // Try to find a match where we've already emitted these calls and then jumped to the correct block
  13594. for (auto& checkHandler : checkScope->mDeferredHandlers)
  13595. {
  13596. if (checkHandler.mDoneBlock == doneBlock)
  13597. {
  13598. scopeJumpBlock = checkScope;
  13599. mBfIRBuilder->CreateBr(checkHandler.mHandlerBlock);
  13600. mBfIRBuilder->ClearDebugLocation_Last();
  13601. _FlushLifetimeEnds();
  13602. break;
  13603. }
  13604. }
  13605. if (scopeJumpBlock != NULL)
  13606. break;
  13607. }
  13608. bool hasWork = (checkScope->mSavedStack) || (checkScope->mDeferredCallEntries.mHead != NULL);
  13609. if (checkScope != scopeData) // Only emit a block for deferred lifetimes if we're going back beyond this entry
  13610. hasWork |= (!deferredLifetimeEnds.IsEmpty());
  13611. if (hasWork)
  13612. {
  13613. SetAndRestoreValue<BfScopeData*> prevScope(mCurMethodState->mCurScope, checkScope);
  13614. if (deferCloseNode != NULL)
  13615. {
  13616. UpdateSrcPos(deferCloseNode);
  13617. }
  13618. if (checkScope == &mCurMethodState->mHeadScope)
  13619. CreateRetValLocal();
  13620. if (doneBlock)
  13621. {
  13622. bool crossingMixin = mCurMethodState->mCurScope->mMixinDepth != checkScope->mMixinDepth;
  13623. String blockName = "deferredCalls";
  13624. //blockName += StrFormat("_%d", mBfIRBuilder->mBlockCount);
  13625. BfDeferredHandler deferredHandler;
  13626. if ((!crossingMixin) && (deferredLifetimeEnds.IsEmpty()))
  13627. {
  13628. mBfIRBuilder->SaveDebugLocation();
  13629. mBfIRBuilder->ClearDebugLocation();
  13630. deferredHandler.mHandlerBlock = mBfIRBuilder->MaybeChainNewBlock(blockName);
  13631. mBfIRBuilder->RestoreDebugLocation();
  13632. }
  13633. else
  13634. {
  13635. // Definitely chain
  13636. deferredHandler.mHandlerBlock = mBfIRBuilder->CreateBlock(blockName);
  13637. mBfIRBuilder->CreateBr(deferredHandler.mHandlerBlock);
  13638. mBfIRBuilder->ClearDebugLocation_Last();
  13639. _FlushLifetimeEnds();
  13640. mBfIRBuilder->AddBlock(deferredHandler.mHandlerBlock);
  13641. mBfIRBuilder->SetInsertPoint(deferredHandler.mHandlerBlock);
  13642. }
  13643. deferredHandler.mDoneBlock = doneBlock;
  13644. if (!mBfIRBuilder->mIgnoreWrites)
  13645. checkScope->mDeferredHandlers.push_back(deferredHandler);
  13646. if (checkScope == &mCurMethodState->mHeadScope)
  13647. {
  13648. if (!mCurMethodState->mDIRetVal)
  13649. {
  13650. // Weird case- if we have a return from a mixin, we need the DbgLoc to be for the mixin but we need the DIRetVal to
  13651. // be scoped to the physical method
  13652. /*if (deferCloseNode != NULL)
  13653. {
  13654. UpdateSrcPos(deferCloseNode);
  13655. }*/
  13656. CreateDIRetVal();
  13657. }
  13658. }
  13659. if (checkScope != mCurMethodState->mTailScope)
  13660. {
  13661. if (deferredHandler.mHandlerBlock.IsFake())
  13662. {
  13663. BF_ASSERT(mBfIRBuilder->mIgnoreWrites);
  13664. }
  13665. if (!mBfIRBuilder->mIgnoreWrites)
  13666. checkScope->mAtEndBlocks.push_back(deferredHandler.mHandlerBlock);
  13667. }
  13668. }
  13669. HashSet<BfDeferredCallEntry*> handledSet;
  13670. BfDeferredCallEntry* deferredCallEntry = checkScope->mDeferredCallEntries.mHead;
  13671. while (deferredCallEntry != NULL)
  13672. {
  13673. BfDeferredCallEmitState deferredCallEmitState;
  13674. deferredCallEmitState.mCloseNode = deferCloseNode;
  13675. SetAndRestoreValue<BfDeferredCallEmitState*> prevDeferredCallEmitState(mCurMethodState->mDeferredCallEmitState, &deferredCallEmitState);
  13676. SetAndRestoreValue<bool> prevIgnoredWrites(mBfIRBuilder->mIgnoreWrites, deferredCallEntry->mIgnored);
  13677. SetAndRestoreValue<BfMixinState*> prevMixinState(mCurMethodState->mMixinState, checkScope->mMixinState);
  13678. if (deferCloseNode != NULL)
  13679. {
  13680. UpdateSrcPos(deferCloseNode);
  13681. }
  13682. if (wantsNop)
  13683. EmitEnsureInstructionAt();
  13684. wantsNop = false;
  13685. if (deferredCallEntry->mDeferredBlock != NULL)
  13686. {
  13687. BfDeferredCallEntry** entryPtr = NULL;
  13688. if (!handledSet.TryAdd(deferredCallEntry, &entryPtr))
  13689. {
  13690. // Already handled, can happen if we defer again within the block
  13691. deferredCallEntry = deferredCallEntry->mNext;
  13692. continue;
  13693. }
  13694. auto prevHead = checkScope->mDeferredCallEntries.mHead;
  13695. EmitDeferredCall(*deferredCallEntry, true);
  13696. if (prevHead != checkScope->mDeferredCallEntries.mHead)
  13697. {
  13698. // The list changed, start over and ignore anything we've already handled
  13699. deferredCallEntry = checkScope->mDeferredCallEntries.mHead;
  13700. }
  13701. else
  13702. deferredCallEntry = deferredCallEntry->mNext;
  13703. }
  13704. else
  13705. {
  13706. EmitDeferredCall(*deferredCallEntry, true);
  13707. deferredCallEntry = deferredCallEntry->mNext;
  13708. }
  13709. }
  13710. if (checkScope->mSavedStack)
  13711. {
  13712. checkScope->mSavedStackUses.Add(mBfIRBuilder->CreateStackRestore(checkScope->mSavedStack));
  13713. if (mCurMethodState->mDynStackRevIdx)
  13714. {
  13715. auto curValue = mBfIRBuilder->CreateLoad(mCurMethodState->mDynStackRevIdx);
  13716. auto newValue = mBfIRBuilder->CreateAdd(curValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1));
  13717. mBfIRBuilder->CreateStore(newValue, mCurMethodState->mDynStackRevIdx);
  13718. }
  13719. }
  13720. }
  13721. if (!checkScope->mIsScopeHead)
  13722. {
  13723. // We manually emit function-level lifetime ends after the 'ret' in ProcessMethod
  13724. if (!IsTargetingBeefBackend())
  13725. {
  13726. for (auto lifetimeEnd : checkScope->mDeferredLifetimeEnds)
  13727. {
  13728. mBfIRBuilder->CreateLifetimeEnd(lifetimeEnd);
  13729. }
  13730. }
  13731. else
  13732. {
  13733. for (auto lifetimeEnd : checkScope->mDeferredLifetimeEnds)
  13734. {
  13735. deferredLifetimeEnds.Add(lifetimeEnd);
  13736. }
  13737. }
  13738. }
  13739. if (checkScope == scopeData)
  13740. break;
  13741. checkScope = checkScope->mPrevScope;
  13742. }
  13743. if ((doneBlock) && (scopeJumpBlock == NULL))
  13744. {
  13745. mBfIRBuilder->CreateBr(doneBlock);
  13746. mBfIRBuilder->ClearDebugLocation_Last();
  13747. }
  13748. // Keeping CreateLifetimeEnds until the end messes up when we chain to old mDeferredHandlers that
  13749. // may have been created when other scope lifetimes were available
  13750. _FlushLifetimeEnds();
  13751. // Emit lifetimeEnds after the branch for Beef
  13752. /*if (IsTargetingBeefBackend())
  13753. {
  13754. bool needsEnsureInst = (!doneBlock) && (scopeJumpBlock == NULL);
  13755. BfScopeData* checkScope = mCurMethodState->mCurScope;
  13756. while (checkScope != NULL)
  13757. {
  13758. if (checkScope == scopeJumpBlock)
  13759. break;
  13760. if (!checkScope->mIsScopeHead)
  13761. {
  13762. for (auto lifetimeEnd : checkScope->mDeferredLifetimeEnds)
  13763. {
  13764. if (needsEnsureInst)
  13765. {
  13766. needsEnsureInst = false;
  13767. }
  13768. mBfIRBuilder->CreateLifetimeEnd(lifetimeEnd);
  13769. }
  13770. }
  13771. if (checkScope == scopeData)
  13772. break;
  13773. checkScope = checkScope->mPrevScope;
  13774. }
  13775. }*/
  13776. }
  13777. void BfModule::MarkScopeLeft(BfScopeData* scopeData, bool isNoReturn)
  13778. {
  13779. if ((mCurMethodState->mDeferredLocalAssignData != NULL) && (!isNoReturn))
  13780. {
  13781. auto deferredLocalAssignData = mCurMethodState->mDeferredLocalAssignData;
  13782. while (deferredLocalAssignData != NULL)
  13783. {
  13784. if ((deferredLocalAssignData->mScopeData == NULL) || (deferredLocalAssignData->mScopeData->mScopeDepth < scopeData->mScopeDepth))
  13785. break;
  13786. if ((deferredLocalAssignData->mScopeData != NULL) && (deferredLocalAssignData->mScopeData->mScopeDepth == scopeData->mScopeDepth))
  13787. deferredLocalAssignData->mIsUnconditional = false;
  13788. deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
  13789. }
  13790. }
  13791. // When we leave a scope, mark those as assigned for deferred assignment purposes
  13792. for (int localIdx = scopeData->mLocalVarStart; localIdx < (int)mCurMethodState->mLocals.size(); localIdx++)
  13793. {
  13794. auto localDef = mCurMethodState->mLocals[localIdx];
  13795. if (localDef->mAssignedKind == BfLocalVarAssignKind_None)
  13796. {
  13797. bool hadAssignment = false;
  13798. if (mCurMethodState->mDeferredLocalAssignData != NULL)
  13799. {
  13800. for (auto& entry : mCurMethodState->mDeferredLocalAssignData->mAssignedLocals)
  13801. if (entry.mLocalVar == localDef)
  13802. hadAssignment = true;
  13803. }
  13804. if (!hadAssignment)
  13805. {
  13806. if (!isNoReturn)
  13807. localDef->mHadExitBeforeAssign = true;
  13808. mCurMethodState->LocalDefined(localDef);
  13809. }
  13810. }
  13811. }
  13812. }
  13813. void BfModule::CreateReturn(BfIRValue val)
  13814. {
  13815. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  13816. {
  13817. // Store to sret
  13818. BF_ASSERT(val);
  13819. mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
  13820. mBfIRBuilder->CreateRetVoid();
  13821. return;
  13822. }
  13823. if (mCurMethodInstance->mReturnType->IsVar())
  13824. return;
  13825. if (mCurMethodInstance->mReturnType->IsValuelessType())
  13826. {
  13827. mBfIRBuilder->CreateRetVoid();
  13828. return;
  13829. }
  13830. if (mCurMethodInstance->mReturnType->IsStruct())
  13831. {
  13832. BfTypeCode loweredReturnType = BfTypeCode_None;
  13833. BfTypeCode loweredReturnType2 = BfTypeCode_None;
  13834. if (!mIsComptimeModule)
  13835. mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
  13836. if (loweredReturnType != BfTypeCode_None)
  13837. {
  13838. auto retVal = CreateAlloca(mCurMethodInstance->mReturnType);
  13839. mBfIRBuilder->CreateStore(val, retVal);
  13840. auto irRetType = GetIRLoweredType(loweredReturnType, loweredReturnType2);
  13841. irRetType = mBfIRBuilder->GetPointerTo(irRetType);
  13842. auto ptrReturnValue = mBfIRBuilder->CreateBitCast(retVal, irRetType);
  13843. auto loadedReturnValue = mBfIRBuilder->CreateLoad(ptrReturnValue);
  13844. mBfIRBuilder->CreateRet(loadedReturnValue);
  13845. return;
  13846. }
  13847. }
  13848. BF_ASSERT(val);
  13849. mBfIRBuilder->CreateRet(val);
  13850. }
  13851. void BfModule::EmitReturn(const BfTypedValue& val)
  13852. {
  13853. if (mCurMethodState->mIRExitBlock)
  13854. {
  13855. if (!mCurMethodInstance->mReturnType->IsValuelessType())
  13856. {
  13857. if (val) // We allow for val to be empty if we know we've already written the value to mRetVal
  13858. {
  13859. if ((mCurMethodState->mRetValAddr) || (mCurMethodState->mRetVal))
  13860. {
  13861. BfIRValue retVal = mCurMethodState->mRetVal.mValue;
  13862. if (!mCurMethodState->mRetVal)
  13863. retVal = mBfIRBuilder->CreateAlignedLoad(mCurMethodState->mRetValAddr, mCurMethodInstance->mReturnType->mAlign);
  13864. mBfIRBuilder->CreateAlignedStore(val.mValue, retVal, mCurMethodInstance->mReturnType->mAlign);
  13865. }
  13866. else if (mIsComptimeModule)
  13867. {
  13868. if (!val.mType->IsValuelessType())
  13869. mBfIRBuilder->CreateSetRet(val.mValue, val.mType->mTypeId);
  13870. else
  13871. mBfIRBuilder->CreateSetRet(BfIRValue(), val.mType->mTypeId);
  13872. }
  13873. else
  13874. {
  13875. // Just ignore
  13876. BF_ASSERT(mCurMethodInstance->mReturnType->IsVar());
  13877. }
  13878. }
  13879. }
  13880. EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
  13881. }
  13882. else
  13883. {
  13884. EmitDeferredScopeCalls(false, NULL);
  13885. if (val)
  13886. {
  13887. BF_ASSERT(mBfIRBuilder->mIgnoreWrites);
  13888. }
  13889. }
  13890. mCurMethodState->SetHadReturn(true);
  13891. mCurMethodState->mLeftBlockUncond = true;
  13892. }
  13893. void BfModule::EmitDefaultReturn()
  13894. {
  13895. if (mCurMethodState->mInDeferredBlock)
  13896. return;
  13897. if (mCurMethodState->mIRExitBlock)
  13898. {
  13899. EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
  13900. }
  13901. else
  13902. {
  13903. if ((mCurMethodInstance == NULL) || (mCurMethodInstance->mReturnType->IsVar()))
  13904. {
  13905. // Ignore
  13906. }
  13907. else if (mCurMethodInstance->mReturnType->IsVoid())
  13908. mBfIRBuilder->CreateRetVoid();
  13909. else if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == -1))
  13910. mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType));
  13911. }
  13912. mCurMethodState->SetHadReturn(true);
  13913. mCurMethodState->mLeftBlockUncond = true;
  13914. }
  13915. void BfModule::AssertErrorState()
  13916. {
  13917. if (mIgnoreErrors)
  13918. return;
  13919. if (mHadBuildError)
  13920. return;
  13921. if (mCurTypeInstance != NULL)
  13922. {
  13923. if (mCurTypeInstance->IsUnspecializedTypeVariation())
  13924. return;
  13925. }
  13926. if (mCurMethodInstance != NULL)
  13927. {
  13928. if (mCurMethodInstance->IsOrInUnspecializedVariation())
  13929. return;
  13930. if (mCurMethodInstance->mHasFailed)
  13931. return;
  13932. }
  13933. // We want the module to be marked as failed even if it's just an error in the parser
  13934. if (mCurMethodInstance != NULL)
  13935. mCurMethodInstance->mHasFailed = true;
  13936. mHadBuildError = true;
  13937. // We check for either the parsing to have failed (possibly on a previous run), or for the current instance to have failed
  13938. if (mCurTypeInstance != NULL)
  13939. {
  13940. if (mCurTypeInstance->mTypeFailed)
  13941. return;
  13942. if ((mCurTypeInstance->mTypeDef->GetDefinition()->mSource != NULL) && (mCurTypeInstance->mTypeDef->GetDefinition()->mSource->mParsingFailed))
  13943. return;
  13944. }
  13945. if (mCurMethodInstance != NULL)
  13946. {
  13947. if ((mCurMethodInstance->mMethodDef->mDeclaringType != NULL) &&
  13948. (mCurMethodInstance->mMethodDef->mDeclaringType->mSource != NULL) &&
  13949. (mCurMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
  13950. return;
  13951. if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL) &&
  13952. (mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource != NULL) &&
  13953. (mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
  13954. return;
  13955. }
  13956. if (mCompiler->IsAutocomplete())
  13957. return;
  13958. BF_ASSERT(mCompiler->mPassInstance->HasFailed());
  13959. }
  13960. void BfModule::AssertParseErrorState()
  13961. {
  13962. if (mCompiler->mRevision == 1)
  13963. AssertErrorState();
  13964. }
  13965. BfType* BfModule::GetDelegateReturnType(BfType* delegateType)
  13966. {
  13967. BF_ASSERT(delegateType->IsDelegate());
  13968. auto typeInst = delegateType->ToTypeInstance();
  13969. PopulateType(typeInst, BfPopulateType_DataAndMethods);
  13970. BfMethodInstance* invokeMethodInstance = GetRawMethodInstanceAtIdx(typeInst->ToTypeInstance(), 0, "Invoke");
  13971. if (invokeMethodInstance == NULL)
  13972. return GetPrimitiveType(BfTypeCode_Var);
  13973. return invokeMethodInstance->mReturnType;
  13974. }
  13975. BfMethodInstance* BfModule::GetDelegateInvokeMethod(BfTypeInstance* typeInstance)
  13976. {
  13977. return GetRawMethodInstanceAtIdx(typeInstance, 0, "Invoke");
  13978. }
  13979. void BfModule::CreateDelegateInvokeMethod()
  13980. {
  13981. // Clear out debug loc - otherwise we'll single step onto the delegate type declaration
  13982. //mBfIRBuilder->ClearDebugLocation();
  13983. SetIllegalSrcPos();
  13984. auto typeInstance = mCurTypeInstance;
  13985. auto memberFuncType = mBfIRBuilder->MapMethod(mCurMethodInstance);
  13986. SizedArray<BfIRType, 4> staticParamTypes;
  13987. SizedArray<BfIRValue, 4> staticFuncArgs;
  13988. SizedArray<BfIRValue, 4> memberFuncArgs;
  13989. auto multicastDelegateType = typeInstance->mBaseType;
  13990. if (multicastDelegateType->mFieldInstances.size() != 2)
  13991. {
  13992. AssertErrorState();
  13993. return;
  13994. }
  13995. auto multicastDelegate = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapType(multicastDelegateType));
  13996. auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 2); // Load 'delegate.mTarget'
  13997. auto fieldVal = mBfIRBuilder->CreateAlignedLoad(fieldPtr, mSystem->mPtrSize);
  13998. BfExprEvaluator exprEvaluator(this);
  13999. SizedArray<BfIRType, 8> origParamTypes;
  14000. BfIRType origReturnType;
  14001. BfIRType staticReturnType;
  14002. mCurMethodInstance->GetIRFunctionInfo(this, origReturnType, origParamTypes);
  14003. if (mCurMethodInstance->mReturnType->IsValueType())
  14004. mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType, BfIRPopulateType_Full);
  14005. if ((mIsComptimeModule) || (mCurMethodInstance->GetStructRetIdx() != 0))
  14006. memberFuncArgs.push_back(BfIRValue()); // Push 'target'
  14007. int thisIdx = 0;
  14008. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  14009. {
  14010. thisIdx = mCurMethodInstance->GetStructRetIdx() ^ 1;
  14011. memberFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
  14012. }
  14013. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx(true) != -1))
  14014. staticFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
  14015. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == 0))
  14016. memberFuncArgs.push_back(BfIRValue()); // Push 'target'
  14017. mCurMethodInstance->GetIRFunctionInfo(this, staticReturnType, staticParamTypes, true);
  14018. for (int i = 1; i < (int)mCurMethodState->mLocals.size(); i++)
  14019. {
  14020. BfTypedValue localVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[i], true);
  14021. exprEvaluator.PushArg(localVal, staticFuncArgs);
  14022. exprEvaluator.PushArg(localVal, memberFuncArgs);
  14023. }
  14024. auto staticFunc = mBfIRBuilder->CreateFunctionType(staticReturnType, staticParamTypes, false);
  14025. auto staticFuncPtr = mBfIRBuilder->GetPointerTo(staticFunc);
  14026. auto staticFuncPtrPtr = mBfIRBuilder->GetPointerTo(staticFuncPtr);
  14027. auto trueBB = mBfIRBuilder->CreateBlock("if.then", true);
  14028. auto falseBB = mBfIRBuilder->CreateBlock("if.else");
  14029. auto doneBB = mBfIRBuilder->CreateBlock("done");
  14030. auto checkTargetNull = mBfIRBuilder->CreateIsNotNull(fieldVal);
  14031. mBfIRBuilder->CreateCondBr(checkTargetNull, trueBB, falseBB);
  14032. BfIRValue nonStaticResult;
  14033. BfIRValue staticResult;
  14034. auto callingConv = GetIRCallingConvention(mCurMethodInstance);
  14035. /// Non-static invocation
  14036. {
  14037. auto memberFuncPtr = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapMethod(mCurMethodInstance));
  14038. auto memberFuncPtrPtr = mBfIRBuilder->GetPointerTo(memberFuncPtr);
  14039. mBfIRBuilder->SetInsertPoint(trueBB);
  14040. memberFuncArgs[thisIdx] = mBfIRBuilder->CreateBitCast(fieldVal, mBfIRBuilder->MapType(mCurTypeInstance));
  14041. auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 1); // Load 'delegate.mFuncPtr'
  14042. auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
  14043. auto funcPtr = mBfIRBuilder->CreateAlignedLoad(funcPtrPtr, mSystem->mPtrSize);
  14044. nonStaticResult = mBfIRBuilder->CreateCall(funcPtr, memberFuncArgs);
  14045. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  14046. mBfIRBuilder->Call_AddAttribute(nonStaticResult, mCurMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
  14047. if (callingConv != BfIRCallingConv_CDecl)
  14048. mBfIRBuilder->SetCallCallingConv(nonStaticResult, callingConv);
  14049. mCurMethodState->SetHadReturn(false);
  14050. mCurMethodState->mLeftBlockUncond = false;
  14051. mCurMethodState->mLeftBlockCond = false;
  14052. mBfIRBuilder->CreateBr(doneBB);
  14053. }
  14054. // Static invocation
  14055. {
  14056. mBfIRBuilder->AddBlock(falseBB);
  14057. mBfIRBuilder->SetInsertPoint(falseBB);
  14058. auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(multicastDelegate, 0, 1); // Load 'delegate.mFuncPtr'
  14059. auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, staticFuncPtrPtr);
  14060. auto funcPtr = mBfIRBuilder->CreateAlignedLoad(funcPtrPtr, mSystem->mPtrSize);
  14061. staticResult = mBfIRBuilder->CreateCall(funcPtr, staticFuncArgs);
  14062. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx(true) != -1))
  14063. {
  14064. // Note: since this is a forced static invocation, we know the sret will be the first parameter
  14065. mBfIRBuilder->Call_AddAttribute(staticResult, 0 + 1, BfIRAttribute_StructRet);
  14066. }
  14067. // We had a sret for the non-static but no sret for the static (because we have a lowered return type there)
  14068. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1) && (mCurMethodInstance->GetStructRetIdx(true) == -1))
  14069. {
  14070. auto sretToType = mBfIRBuilder->GetPointerTo(staticReturnType);
  14071. auto sretCastedPtr = mBfIRBuilder->CreateBitCast(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()), sretToType);
  14072. mBfIRBuilder->CreateStore(staticResult, sretCastedPtr);
  14073. }
  14074. if (callingConv == BfIRCallingConv_ThisCall)
  14075. callingConv = BfIRCallingConv_CDecl;
  14076. if (callingConv != BfIRCallingConv_CDecl)
  14077. mBfIRBuilder->SetCallCallingConv(staticResult, callingConv);
  14078. mCurMethodState->SetHadReturn(false);
  14079. mCurMethodState->mLeftBlockUncond = false;
  14080. mCurMethodState->mLeftBlockCond = false;
  14081. mBfIRBuilder->CreateBr(doneBB);
  14082. }
  14083. mBfIRBuilder->AddBlock(doneBB);
  14084. mBfIRBuilder->SetInsertPoint(doneBB);
  14085. if (mCurMethodInstance->mReturnType->IsVar())
  14086. {
  14087. // Do nothing
  14088. }
  14089. else if ((mCurMethodInstance->mReturnType->IsValuelessType()) ||
  14090. ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)))
  14091. {
  14092. mBfIRBuilder->CreateRetVoid();
  14093. }
  14094. else
  14095. {
  14096. BfIRType loweredIRReturnType;
  14097. BfTypeCode loweredTypeCode = BfTypeCode_None;
  14098. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  14099. if ((!mIsComptimeModule) && (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2)))
  14100. loweredIRReturnType = GetIRLoweredType(loweredTypeCode, loweredTypeCode2);
  14101. else
  14102. loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
  14103. auto phi = mBfIRBuilder->CreatePhi(loweredIRReturnType, 2);
  14104. mBfIRBuilder->AddPhiIncoming(phi, nonStaticResult, trueBB);
  14105. mBfIRBuilder->AddPhiIncoming(phi, staticResult, falseBB);
  14106. mBfIRBuilder->CreateRet(phi);
  14107. }
  14108. }
  14109. // "Interested" here means every method for a normal compile, and just the method the cursor is on for autocompletion
  14110. bool BfModule::IsInterestedInMethod(BfTypeInstance* typeInstance, BfMethodDef* methodDef)
  14111. {
  14112. auto typeDef = typeInstance->mTypeDef;
  14113. auto methodDeclaration = methodDef->mMethodDeclaration;
  14114. if (!mCompiler->mIsResolveOnly)
  14115. return true;
  14116. if (typeInstance->IsGenericTypeInstance())
  14117. {
  14118. // We only really want to process the unspecialized type for autocompletion
  14119. if ((!typeInstance->IsUnspecializedType()) || (typeInstance->IsUnspecializedTypeVariation()))
  14120. return false;
  14121. }
  14122. BfAstNode* checkNode = methodDeclaration;
  14123. if (methodDeclaration == NULL)
  14124. checkNode = methodDef->mBody;
  14125. if ((!mCompiler->mResolvePassData->mParsers.IsEmpty()) && (typeDef->mTypeDeclaration->IsFromParser(mCompiler->mResolvePassData->mParsers[0])))
  14126. {
  14127. if (mCompiler->mResolvePassData->mAutoComplete == NULL)
  14128. return true;
  14129. }
  14130. return false;
  14131. }
  14132. void BfModule::CalcAppendAlign(BfMethodInstance* methodInst)
  14133. {
  14134. methodInst->mAppendAllocAlign = 1;
  14135. }
  14136. BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArrayImpl<BfIRValue>& args)
  14137. {
  14138. BP_ZONE("BfModule::TryConstCalcAppend");
  14139. BF_ASSERT(methodInst->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend);
  14140. if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule))
  14141. return BfTypedValue();
  14142. // We want to regenerate all ctor calls when the method internals change
  14143. {
  14144. auto checkTypeInst = methodInst->GetOwner();
  14145. while (checkTypeInst->mTypeDef->mHasAppendCtor)
  14146. {
  14147. AddDependency(checkTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_InlinedCall);
  14148. checkTypeInst = GetBaseType(checkTypeInst);
  14149. }
  14150. }
  14151. if (!methodInst->mMayBeConst)
  14152. return BfTypedValue();
  14153. // Do we need to iterate in order to resolve mAppendAllocAlign?
  14154. bool isFirstRun = methodInst->mEndingAppendAllocAlign < 0;
  14155. bool wasAllConst = true;
  14156. int argIdx = 0;
  14157. int paramIdx = 0;
  14158. while (true)
  14159. {
  14160. if (argIdx >= (int)args.size())
  14161. break;
  14162. auto paramType = methodInst->GetParamType(paramIdx);
  14163. PopulateType(paramType);
  14164. int argCount = 0;
  14165. if (!paramType->IsValuelessType())
  14166. {
  14167. if ((!mIsComptimeModule) && (methodInst->GetParamIsSplat(paramIdx)))
  14168. argCount = paramType->GetSplatCount();
  14169. else
  14170. argCount = 1;
  14171. for (int argOfs = 0; argOfs < argCount; argOfs++)
  14172. {
  14173. auto arg = args[argIdx + argOfs];
  14174. if (!arg.IsConst())
  14175. {
  14176. wasAllConst = false;
  14177. if (!isFirstRun)
  14178. {
  14179. auto& param = methodInst->mParams[argIdx];
  14180. if (param.mReferencedInConstPass)
  14181. {
  14182. // If this param is required as part of the const calculation then
  14183. // we require that it be const...
  14184. return BfTypedValue();
  14185. }
  14186. }
  14187. }
  14188. }
  14189. }
  14190. paramIdx++;
  14191. argIdx += argCount;
  14192. }
  14193. auto methodDef = methodInst->mMethodDef;
  14194. auto methodDecl = methodDef->GetMethodDeclaration();
  14195. auto methodDeclBlock = BfNodeDynCast<BfBlock>(methodDecl->mBody);
  14196. if (methodDeclBlock == NULL)
  14197. return GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_IntPtr)); // Must not have an append alloc at all!
  14198. BfTypedValue constValue;
  14199. auto prevBlock = mBfIRBuilder->GetInsertBlock();
  14200. auto checkState = mCurMethodState->mConstResolveState;
  14201. while (checkState != NULL)
  14202. {
  14203. if (checkState->mMethodInstance == methodInst)
  14204. {
  14205. return BfTypedValue();
  14206. }
  14207. checkState = checkState->mPrevConstResolveState;
  14208. }
  14209. //auto accumValue = GetConstValue(0);
  14210. bool failed = false;
  14211. //
  14212. {
  14213. BfConstResolveState constResolveState;
  14214. constResolveState.mMethodInstance = methodInst;
  14215. constResolveState.mPrevConstResolveState = mCurMethodState->mConstResolveState;
  14216. SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  14217. BfMethodState methodState;
  14218. SetAndRestoreValue<BfTypeInstance*> prevTypeInst(mCurTypeInstance, methodInst->GetOwner());
  14219. SetAndRestoreValue<BfMethodInstance*> prevMethodInst(mCurMethodInstance, methodInst);
  14220. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  14221. methodState.mTempKind = BfMethodState::TempKind_NonStatic;
  14222. methodState.mConstResolveState = &constResolveState;
  14223. int argIdx = 0;
  14224. for (int paramIdx = 0; paramIdx < methodInst->GetParamCount(); paramIdx++)
  14225. {
  14226. if (methodInst->GetParamKind(paramIdx) == BfParamKind_AppendIdx)
  14227. continue;
  14228. auto paramType = methodInst->GetParamType(paramIdx);
  14229. // Fix this after we allow structs to be consts
  14230. //BF_ASSERT(!paramType->IsSplattable());
  14231. BfLocalVariable* localVar = new BfLocalVariable();
  14232. localVar->mName = methodInst->GetParamName(paramIdx);
  14233. localVar->mResolvedType = paramType;
  14234. localVar->mConstValue = args[argIdx];
  14235. localVar->mParamIdx = paramIdx;
  14236. AddLocalVariableDef(localVar);
  14237. argIdx++;
  14238. }
  14239. AppendAllocVisitor appendAllocVisitor;
  14240. appendAllocVisitor.mConstAccum = GetDefaultTypedValue(GetPrimitiveType(BfTypeCode_IntPtr));
  14241. appendAllocVisitor.mIsFirstConstPass = isFirstRun;
  14242. BfTypedValue baseCtorAppendValue = CallBaseCtorCalc(true);
  14243. if (baseCtorAppendValue)
  14244. {
  14245. if (baseCtorAppendValue.mValue.IsFake())
  14246. appendAllocVisitor.mFailed = true;
  14247. else
  14248. appendAllocVisitor.mConstAccum = baseCtorAppendValue;
  14249. }
  14250. appendAllocVisitor.mModule = this;
  14251. appendAllocVisitor.VisitChild(methodDecl->mBody);
  14252. if (!appendAllocVisitor.mFailed)
  14253. constValue = appendAllocVisitor.mConstAccum;
  14254. if (isFirstRun)
  14255. {
  14256. mCurMethodInstance->mEndingAppendAllocAlign = appendAllocVisitor.mCurAppendAlign;
  14257. if (mCurMethodInstance->mAppendAllocAlign <= 0)
  14258. mCurMethodInstance->mAppendAllocAlign = 1;
  14259. }
  14260. if (isFirstRun)
  14261. {
  14262. for (int paramIdx = 0; paramIdx < methodInst->GetParamCount(); paramIdx++)
  14263. {
  14264. auto localVar = mCurMethodState->mLocals[paramIdx];
  14265. if (localVar->mReadFromId != -1)
  14266. {
  14267. auto& param = methodInst->mParams[paramIdx];
  14268. param.mReferencedInConstPass = true;
  14269. }
  14270. }
  14271. }
  14272. }
  14273. mBfIRBuilder->SetInsertPoint(prevBlock);
  14274. if (!constValue)
  14275. {
  14276. // If we did a 'force' then some params may not have been const -- only clear mMayBeConst if we had
  14277. // all-const args
  14278. if (wasAllConst)
  14279. {
  14280. methodInst->mMayBeConst = false;
  14281. }
  14282. }
  14283. return constValue;
  14284. }
  14285. BfTypedValue BfModule::CallBaseCtorCalc(bool constOnly)
  14286. {
  14287. // Any errors should only be shown in the actual CTOR call
  14288. SetAndRestoreValue<bool> prevIgnoreWrites(mIgnoreErrors, true);
  14289. auto methodDef = mCurMethodInstance->mMethodDef;
  14290. BF_ASSERT((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend));
  14291. auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration;
  14292. BfCustomAttributes* customAttributes = NULL;
  14293. defer(delete customAttributes);
  14294. BfInvocationExpression* ctorInvocation = NULL;
  14295. if (ctorDeclaration != NULL)
  14296. {
  14297. ctorInvocation = BfNodeDynCast<BfInvocationExpression>(ctorDeclaration->mInitializer);
  14298. if (auto attributedExpr = BfNodeDynCast<BfAttributedExpression>(ctorDeclaration->mInitializer))
  14299. {
  14300. ctorInvocation = BfNodeDynCast<BfInvocationExpression>(attributedExpr->mExpression);
  14301. customAttributes = GetCustomAttributes(attributedExpr->mAttributes, BfAttributeTargets_MemberAccess);
  14302. }
  14303. }
  14304. BfTypeInstance* targetType = NULL;
  14305. if (ctorInvocation != NULL)
  14306. {
  14307. auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
  14308. targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
  14309. }
  14310. else
  14311. targetType = mCurTypeInstance->mBaseType;
  14312. if ((targetType == NULL) || (targetType == mContext->mBfObjectType))
  14313. return NULL;
  14314. auto targetRefNode = methodDef->GetRefNode();
  14315. BfType* targetThisType = targetType;
  14316. BfTypedValue target(mBfIRBuilder->GetFakeVal(), targetThisType);
  14317. BfExprEvaluator exprEvaluator(this);
  14318. BfResolvedArgs argValues;
  14319. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
  14320. {
  14321. argValues.Init(&ctorInvocation->mArguments);
  14322. }
  14323. //
  14324. {
  14325. }
  14326. BfFunctionBindResult bindResult;
  14327. bindResult.mSkipThis = true;
  14328. bindResult.mWantsArgs = true;
  14329. {
  14330. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  14331. exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
  14332. SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
  14333. exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, true);
  14334. }
  14335. if (bindResult.mMethodInstance == NULL)
  14336. {
  14337. AssertErrorState();
  14338. return BfTypedValue();
  14339. }
  14340. if (!bindResult.mMethodInstance->mMethodDef->mHasAppend)
  14341. {
  14342. return BfTypedValue();
  14343. }
  14344. BF_ASSERT(bindResult.mIRArgs[0].IsFake());
  14345. bindResult.mIRArgs.RemoveAt(0);
  14346. auto calcAppendMethodModule = GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
  14347. BfTypedValue appendSizeTypedValue = TryConstCalcAppend(calcAppendMethodModule.mMethodInstance, bindResult.mIRArgs);
  14348. BF_ASSERT(calcAppendMethodModule.mMethodInstance->mAppendAllocAlign >= 0);
  14349. mCurMethodInstance->mAppendAllocAlign = BF_MAX((int)mCurMethodInstance->mAppendAllocAlign, calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
  14350. BF_ASSERT(calcAppendMethodModule.mMethodInstance->mEndingAppendAllocAlign > -1);
  14351. mCurMethodState->mCurAppendAlign = BF_MAX(calcAppendMethodModule.mMethodInstance->mEndingAppendAllocAlign, 0);
  14352. if (appendSizeTypedValue)
  14353. return appendSizeTypedValue;
  14354. if (constOnly)
  14355. return BfTypedValue(mBfIRBuilder->GetFakeVal(), GetPrimitiveType(BfTypeCode_IntPtr));
  14356. bool needsRecalc = false;
  14357. for (auto irArg : bindResult.mIRArgs)
  14358. {
  14359. if (irArg.IsFake())
  14360. needsRecalc = true;
  14361. }
  14362. auto calcAppendArgs = bindResult.mIRArgs;
  14363. if (needsRecalc)
  14364. {
  14365. // Do it again, but without mIgnoreWrites set
  14366. BfResolvedArgs argValues;
  14367. argValues.Init(&ctorInvocation->mArguments);
  14368. exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
  14369. BfFunctionBindResult bindResult;
  14370. bindResult.mSkipThis = true;
  14371. bindResult.mWantsArgs = true;
  14372. SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
  14373. exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, true);
  14374. BF_ASSERT(bindResult.mIRArgs[0].IsFake());
  14375. bindResult.mIRArgs.RemoveAt(0);
  14376. calcAppendArgs = bindResult.mIRArgs;
  14377. }
  14378. BF_ASSERT(calcAppendMethodModule.mFunc);
  14379. appendSizeTypedValue = exprEvaluator.CreateCall(NULL, calcAppendMethodModule.mMethodInstance, calcAppendMethodModule.mFunc, false, calcAppendArgs);
  14380. BF_ASSERT(appendSizeTypedValue.mType == GetPrimitiveType(BfTypeCode_IntPtr));
  14381. return appendSizeTypedValue;
  14382. }
  14383. // This method never throws errors - it relies on the proper ctor actually throwing the errors
  14384. void BfModule::EmitCtorCalcAppend()
  14385. {
  14386. if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule))
  14387. return;
  14388. auto methodDef = mCurMethodInstance->mMethodDef;
  14389. auto methodDecl = methodDef->GetMethodDeclaration();
  14390. Array<BfAstNode*> deferredNodeList;
  14391. auto methodDeclBlock = BfNodeDynCast<BfBlock>(methodDecl->mBody);
  14392. if (methodDeclBlock == NULL)
  14393. return;
  14394. AppendAllocVisitor appendAllocVisitor;
  14395. auto baseCalcAppend = CallBaseCtorCalc(false);
  14396. if (baseCalcAppend)
  14397. {
  14398. mBfIRBuilder->CreateStore(baseCalcAppend.mValue, mCurMethodState->mRetVal.mValue);
  14399. }
  14400. appendAllocVisitor.mModule = this;
  14401. appendAllocVisitor.VisitChild(methodDecl->mBody);
  14402. }
  14403. void BfModule::CreateStaticCtor()
  14404. {
  14405. auto typeDef = mCurTypeInstance->mTypeDef;
  14406. auto methodDef = mCurMethodInstance->mMethodDef;
  14407. BfIRBlock exitBB;
  14408. if ((HasCompiledOutput()) && (!mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
  14409. {
  14410. auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
  14411. auto didStaticInitVarAddr = mBfIRBuilder->CreateGlobalVariable(
  14412. mBfIRBuilder->MapType(boolType),
  14413. false,
  14414. BfIRLinkageType_Internal,
  14415. GetDefaultValue(boolType),
  14416. "didStaticInit");
  14417. auto initBB = mBfIRBuilder->CreateBlock("init", true);
  14418. mCurMethodState->mIRExitBlock = mBfIRBuilder->CreateBlock("exit", true);
  14419. auto didStaticInitVar = mBfIRBuilder->CreateLoad(didStaticInitVarAddr);
  14420. mBfIRBuilder->CreateCondBr(didStaticInitVar, mCurMethodState->mIRExitBlock, initBB);
  14421. mBfIRBuilder->SetInsertPoint(initBB);
  14422. mBfIRBuilder->CreateStore(GetConstValue(1, boolType), didStaticInitVarAddr);
  14423. }
  14424. // Do DLL imports
  14425. if (!mDllImportEntries.empty())
  14426. {
  14427. auto internalType = ResolveTypeDef(mCompiler->mInternalTypeDef);
  14428. PopulateType(internalType);
  14429. auto getSharedProcAddressInstance = GetMethodByName(internalType->ToTypeInstance(), "GetSharedProcAddress");
  14430. if (!getSharedProcAddressInstance)
  14431. {
  14432. if (!mCompiler->mPassInstance->HasFailed())
  14433. Fail("Internal error: System.Internal doesn't contain LoadSharedLibrary method");
  14434. }
  14435. }
  14436. // Fill in initializer values
  14437. if ((!mCompiler->mIsResolveOnly) || (mCompiler->mResolvePassData->mAutoComplete == NULL))
  14438. {
  14439. for (auto fieldDef : typeDef->mFields)
  14440. {
  14441. if ((!fieldDef->mIsConst) && (fieldDef->mIsStatic) && (fieldDef->GetInitializer() != NULL))
  14442. {
  14443. // For extensions, only handle these fields in the appropriate extension
  14444. if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
  14445. continue;
  14446. UpdateSrcPos(fieldDef->GetInitializer());
  14447. auto fieldInst = &mCurTypeInstance->mFieldInstances[fieldDef->mIdx];
  14448. if (!fieldInst->mFieldIncluded)
  14449. continue;
  14450. if (fieldInst->mResolvedType->IsVar())
  14451. {
  14452. continue;
  14453. }
  14454. GetFieldInitializerValue(fieldInst, NULL, NULL, NULL, true);
  14455. }
  14456. }
  14457. auto _CheckInitBlock = [&](BfAstNode* node)
  14458. {
  14459. };
  14460. EmitInitBlocks(_CheckInitBlock);
  14461. }
  14462. else
  14463. {
  14464. for (auto tempTypeDef : mCompiler->mResolvePassData->mAutoCompleteTempTypes)
  14465. {
  14466. if (tempTypeDef->mFullName == typeDef->mFullName)
  14467. {
  14468. for (auto fieldDef : tempTypeDef->mFields)
  14469. {
  14470. if ((fieldDef->mIsStatic) && (!fieldDef->mIsConst))
  14471. {
  14472. if (fieldDef->GetInitializer() != NULL)
  14473. {
  14474. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDef->GetInitializer()))
  14475. {
  14476. sourceClassifier->SetElementType(fieldDef->GetInitializer(), BfSourceElementType_Normal);
  14477. sourceClassifier->VisitChildNoRef(fieldDef->GetInitializer());
  14478. }
  14479. BfType* wantType = NULL;
  14480. if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) && (!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
  14481. {
  14482. wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowInferredSizedArray);
  14483. }
  14484. CreateValueFromExpression(fieldDef->GetInitializer(), wantType, BfEvalExprFlags_FieldInitializer);
  14485. }
  14486. }
  14487. }
  14488. }
  14489. }
  14490. }
  14491. if (mCurMethodInstance->mChainType == BfMethodChainType_ChainHead)
  14492. CallChainedMethods(mCurMethodInstance, false);
  14493. }
  14494. void BfModule::EmitDtorBody()
  14495. {
  14496. if (!mCurMethodState->mIRExitBlock)
  14497. mCurMethodState->mIRExitBlock = mBfIRBuilder->CreateBlock("exit", true);
  14498. if (mCurTypeInstance->IsClosure())
  14499. {
  14500. BfFieldInstance* fieldInstance = &mCurTypeInstance->mFieldInstances.back();
  14501. BF_ASSERT(fieldInstance->GetFieldDef()->mName == "__dtorThunk");
  14502. auto thisVal = GetThis();
  14503. auto dtorThunkPtr = mBfIRBuilder->CreateInBoundsGEP(thisVal.mValue, 0, fieldInstance->mDataIdx);
  14504. auto dtorThunk = mBfIRBuilder->CreateLoad(dtorThunkPtr);
  14505. auto funcPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapMethod(mCurMethodInstance));
  14506. auto dtorPtr = mBfIRBuilder->CreateBitCast(dtorThunk, funcPtrType);
  14507. SizedArray<BfIRValue, 1> args;
  14508. args.push_back(thisVal.mValue);
  14509. auto result = mBfIRBuilder->CreateCall(dtorPtr, args);
  14510. mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_CDecl);
  14511. // Fall through to Object::~this call
  14512. auto dtorFunc = GetMethodByName(mContext->mBfObjectType, "~this");
  14513. if (mIsComptimeModule)
  14514. mCompiler->mCeMachine->QueueMethod(dtorFunc.mMethodInstance, dtorFunc.mFunc);
  14515. auto basePtr = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapTypeInstPtr(mContext->mBfObjectType));
  14516. SizedArray<BfIRValue, 1> vals = { basePtr };
  14517. result = mBfIRBuilder->CreateCall(dtorFunc.mFunc, vals);
  14518. mBfIRBuilder->SetCallCallingConv(result, GetIRCallingConvention(dtorFunc.mMethodInstance));
  14519. mBfIRBuilder->SetTailCall(result);
  14520. return;
  14521. }
  14522. auto typeDef = mCurTypeInstance->mTypeDef;
  14523. auto methodDef = mCurMethodInstance->mMethodDef;
  14524. auto methodDeclaration = methodDef->GetMethodDeclaration();
  14525. if (mCurMethodInstance->mChainType == BfMethodChainType_ChainHead)
  14526. CallChainedMethods(mCurMethodInstance, true);
  14527. if (auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody))
  14528. {
  14529. VisitEmbeddedStatement(bodyBlock);
  14530. if (bodyBlock->mCloseBrace != NULL)
  14531. {
  14532. UpdateSrcPos(bodyBlock->mCloseBrace);
  14533. }
  14534. }
  14535. else
  14536. {
  14537. if (methodDeclaration != NULL)
  14538. UpdateSrcPos(methodDeclaration);
  14539. else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
  14540. UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
  14541. else if (typeDef->mTypeDeclaration != NULL)
  14542. UpdateSrcPos(typeDef->mTypeDeclaration);
  14543. if ((methodDeclaration != NULL) && (methodDeclaration->mFatArrowToken != NULL))
  14544. {
  14545. Fail("Destructors cannot have expression bodies", methodDeclaration->mFatArrowToken, true);
  14546. }
  14547. }
  14548. if ((!mCompiler->mIsResolveOnly) || (mCompiler->mResolvePassData->mAutoComplete == NULL))
  14549. {
  14550. for (int fieldIdx = (int)mCurTypeInstance->mFieldInstances.size() - 1; fieldIdx >= 0; fieldIdx--)
  14551. {
  14552. auto fieldInst = &mCurTypeInstance->mFieldInstances[fieldIdx];
  14553. auto fieldDef = fieldInst->GetFieldDef();
  14554. BfFieldDeclaration* fieldDecl = NULL;
  14555. if (fieldDef != NULL)
  14556. fieldDecl = fieldDef->GetFieldDeclaration();
  14557. if ((fieldDef != NULL) && (fieldDef->mIsStatic == methodDef->mIsStatic) && (fieldDecl != NULL) && (fieldDecl->mFieldDtor != NULL))
  14558. {
  14559. if (fieldDef->mDeclaringType != mCurMethodInstance->mMethodDef->mDeclaringType)
  14560. {
  14561. BF_ASSERT(mCurTypeInstance->mTypeDef->mIsCombinedPartial);
  14562. continue;
  14563. }
  14564. if ((!methodDef->mIsStatic) && (mCurTypeInstance->IsValueType()))
  14565. {
  14566. Fail("Structs cannot have field destructors", fieldDecl->mFieldDtor->mTildeToken, true);
  14567. }
  14568. SetAndRestoreValue<BfFilePosition> prevFilePos(mCurFilePosition);
  14569. auto fieldDtor = fieldDecl->mFieldDtor;
  14570. if ((fieldDef->mIsStatic) != (methodDef->mIsStatic))
  14571. continue;
  14572. UpdateSrcPos(fieldDtor);
  14573. BfScopeData scopeData;
  14574. mCurMethodState->AddScope(&scopeData);
  14575. NewScopeState();
  14576. UpdateSrcPos(fieldDtor);
  14577. bool hasDbgInfo = (!fieldDef->mIsConst);
  14578. if (hasDbgInfo)
  14579. {
  14580. mBfIRBuilder->SaveDebugLocation();
  14581. mBfIRBuilder->ClearDebugLocation();
  14582. }
  14583. BfIRValue value;
  14584. if (fieldDef->mIsStatic)
  14585. {
  14586. value = ReferenceStaticField(fieldInst).mValue;
  14587. }
  14588. else
  14589. {
  14590. PopulateType(fieldInst->mResolvedType);
  14591. if (fieldInst->mResolvedType->IsValuelessType())
  14592. {
  14593. value = mBfIRBuilder->GetFakeVal();
  14594. }
  14595. else if (!mCurTypeInstance->IsValueType())
  14596. {
  14597. auto thisValue = GetThis();
  14598. value = mBfIRBuilder->CreateInBoundsGEP(thisValue.mValue, 0, fieldInst->mDataIdx);
  14599. }
  14600. else
  14601. {
  14602. AssertErrorState();
  14603. value = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(fieldInst->mResolvedType));
  14604. }
  14605. }
  14606. BfIRValue staticVal;
  14607. if (hasDbgInfo)
  14608. {
  14609. BfIRValue dbgShowValue = value;
  14610. BfLocalVariable* localDef = new BfLocalVariable();
  14611. localDef->mName = "_";
  14612. localDef->mResolvedType = fieldInst->mResolvedType;
  14613. localDef->mAddr = value;
  14614. if ((mBfIRBuilder->DbgHasInfo()) && (!IsTargetingBeefBackend()))
  14615. {
  14616. // Create another pointer indirection, a ref to the gep
  14617. auto refFieldType = CreateRefType(fieldInst->mResolvedType);
  14618. auto allocaInst = CreateAlloca(refFieldType);
  14619. auto storeResult = mBfIRBuilder->CreateStore(value, allocaInst);
  14620. localDef->mResolvedType = refFieldType;
  14621. localDef->mAddr = allocaInst;
  14622. }
  14623. mBfIRBuilder->RestoreDebugLocation();
  14624. auto defLocalVar = AddLocalVariableDef(localDef, true);
  14625. // Put back so we actually modify the correct value*/
  14626. defLocalVar->mResolvedType = fieldInst->mResolvedType;
  14627. defLocalVar->mAddr = value;
  14628. }
  14629. while (fieldDtor != NULL)
  14630. {
  14631. if (mCompiler->mResolvePassData != NULL)
  14632. {
  14633. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
  14634. {
  14635. sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
  14636. sourceClassifier->VisitChild(fieldDtor);
  14637. }
  14638. }
  14639. UpdateSrcPos(fieldDtor);
  14640. VisitEmbeddedStatement(fieldDtor->mBody);
  14641. fieldDtor = fieldDtor->mNextFieldDtor;
  14642. }
  14643. RestoreScopeState();
  14644. }
  14645. }
  14646. if ((!methodDef->mIsStatic) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
  14647. {
  14648. auto checkBaseType = mCurTypeInstance->mBaseType;
  14649. while (checkBaseType != NULL)
  14650. {
  14651. if (auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody))
  14652. {
  14653. if (bodyBlock->mCloseBrace != NULL)
  14654. UpdateSrcPos(bodyBlock->mCloseBrace);
  14655. }
  14656. else
  14657. {
  14658. UpdateSrcPos(typeDef->mTypeDeclaration->mNameNode);
  14659. }
  14660. BfMethodDef* dtorMethodDef = checkBaseType->mTypeDef->GetMethodByName("~this");
  14661. if (dtorMethodDef != NULL)
  14662. {
  14663. auto dtorMethodInstance = GetMethodInstance(checkBaseType, dtorMethodDef, BfTypeVector());
  14664. if (IsSkippingExtraResolveChecks())
  14665. {
  14666. // Nothing
  14667. }
  14668. else if (dtorMethodInstance.mMethodInstance->GetParamCount() == 0)
  14669. {
  14670. if ((!IsSkippingExtraResolveChecks()) && (!checkBaseType->IsUnspecializedType()))
  14671. {
  14672. auto basePtr = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapTypeInstPtr(checkBaseType));
  14673. SizedArray<BfIRValue, 1> vals = { basePtr };
  14674. auto callInst = mBfIRBuilder->CreateCall(dtorMethodInstance.mFunc, vals);
  14675. if (mIsComptimeModule)
  14676. mCompiler->mCeMachine->QueueMethod(dtorMethodInstance.mMethodInstance, dtorMethodInstance.mFunc);
  14677. mBfIRBuilder->SetCallCallingConv(callInst, GetIRCallingConvention(dtorMethodInstance.mMethodInstance));
  14678. }
  14679. }
  14680. else
  14681. {
  14682. // Invalid base dtor declaration
  14683. AssertErrorState();
  14684. }
  14685. break;
  14686. }
  14687. checkBaseType = checkBaseType->mBaseType;
  14688. }
  14689. }
  14690. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  14691. }
  14692. else
  14693. {
  14694. // The reason we can't just do the 'normal' path for this is that the BfTypeInstance here is NOT the
  14695. // autocomplete type instance, so FieldInstance initializer values contain expressions from the full
  14696. // resolve pass, NOT the autocomplete expression
  14697. for (auto tempTypeDef : mCompiler->mResolvePassData->mAutoCompleteTempTypes)
  14698. {
  14699. if (tempTypeDef->mFullName == typeDef->mFullName)
  14700. {
  14701. for (auto fieldDef : tempTypeDef->mFields)
  14702. {
  14703. auto fieldDecl = fieldDef->GetFieldDeclaration();
  14704. if ((fieldDef->mIsStatic == methodDef->mIsStatic) && (fieldDef->mFieldDeclaration != NULL) &&
  14705. (fieldDecl->mFieldDtor != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
  14706. {
  14707. BfType* fieldType = NULL;
  14708. for (int curFieldIdx = 0; curFieldIdx < (int)mCurTypeInstance->mFieldInstances.size(); curFieldIdx++)
  14709. {
  14710. auto curFieldInstance = &mCurTypeInstance->mFieldInstances[curFieldIdx];
  14711. auto curFieldDef = curFieldInstance->GetFieldDef();
  14712. if ((curFieldDef != NULL) && (fieldDef->mName == curFieldDef->mName))
  14713. fieldType = curFieldInstance->GetResolvedType();
  14714. }
  14715. if (fieldType == NULL)
  14716. fieldType = GetPrimitiveType(BfTypeCode_Var);
  14717. auto fieldDtor = fieldDecl->mFieldDtor;
  14718. BfScopeData scopeData;
  14719. mCurMethodState->AddScope(&scopeData);
  14720. NewScopeState();
  14721. // This is just for autocomplete, it doesn't matter that mAddr is incorrect
  14722. if (fieldType != NULL)
  14723. {
  14724. BfLocalVariable* localDef = new BfLocalVariable();
  14725. localDef->mName = "_";
  14726. localDef->mResolvedType = fieldType;
  14727. localDef->mAddr = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(fieldType));
  14728. localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  14729. AddLocalVariableDef(localDef);
  14730. }
  14731. while (fieldDtor != NULL)
  14732. {
  14733. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
  14734. {
  14735. sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
  14736. sourceClassifier->VisitChild(fieldDtor);
  14737. }
  14738. UpdateSrcPos(fieldDtor);
  14739. VisitEmbeddedStatement(fieldDtor->mBody);
  14740. fieldDtor = fieldDtor->mNextFieldDtor;
  14741. }
  14742. RestoreScopeState();
  14743. }
  14744. }
  14745. }
  14746. }
  14747. }
  14748. }
  14749. BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define)
  14750. {
  14751. BF_ASSERT(methodInstance->mIsReified);
  14752. auto typeInstance = methodInstance->GetOwner();
  14753. bool foundDllImportAttr = false;
  14754. BfCallingConvention callingConvention = methodInstance->mCallingConvention;
  14755. for (auto customAttr : methodInstance->GetCustomAttributes()->mAttributes)
  14756. {
  14757. if (customAttr.mType->mTypeDef->mFullName.ToString() == "System.ImportAttribute")
  14758. {
  14759. foundDllImportAttr = true;
  14760. }
  14761. }
  14762. if (!foundDllImportAttr)
  14763. {
  14764. AssertErrorState();
  14765. return BfIRValue();
  14766. }
  14767. StringT<512> name = "bf_hs_preserve@";
  14768. BfMangler::Mangle(name, mCompiler->GetMangleKind(), methodInstance);
  14769. name += "__imp";
  14770. BfIRType returnType;
  14771. SizedArray<BfIRType, 8> paramTypes;
  14772. methodInstance->GetIRFunctionInfo(this, returnType, paramTypes);
  14773. BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, methodInstance->IsVarArgs());
  14774. auto ptrType = mBfIRBuilder->GetPointerTo(externFunctionType);
  14775. BfIRValue initVal;
  14776. if (define)
  14777. {
  14778. if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
  14779. initVal = mBfIRBuilder->CreateConstNull(ptrType);
  14780. }
  14781. auto globalVar = mBfIRBuilder->CreateGlobalVariable(ptrType, false, BfIRLinkageType_External, initVal, name);
  14782. if ((define) && (mBfIRBuilder->DbgHasInfo()))
  14783. {
  14784. auto voidType = GetPrimitiveType(BfTypeCode_None);
  14785. auto ptrType = CreatePointerType(voidType);
  14786. mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, name, name, BfIRMDNode(), 0, mBfIRBuilder->DbgGetType(ptrType), false, globalVar);
  14787. }
  14788. return globalVar;
  14789. }
  14790. void BfModule::CreateDllImportMethod()
  14791. {
  14792. if (mBfIRBuilder->mIgnoreWrites)
  14793. return;
  14794. auto globalVar = mFuncReferences[mCurMethodInstance];
  14795. if (!globalVar)
  14796. return;
  14797. bool allowTailCall = true;
  14798. mBfIRBuilder->ClearDebugLocation();
  14799. bool isHotCompile = mCompiler->IsHotCompile();
  14800. // If we are hot swapping, we need to have this stub because we may need to call the LoadSharedLibraries on demand
  14801. if (isHotCompile)
  14802. {
  14803. auto loadSharedLibsFunc = GetBuiltInFunc(BfBuiltInFuncType_LoadSharedLibraries);
  14804. mBfIRBuilder->CreateCall(loadSharedLibsFunc, SizedArray<BfIRValue, 0>());
  14805. }
  14806. auto callingConvention = GetIRCallingConvention(mCurMethodInstance);
  14807. BfIRType returnType;
  14808. SizedArray<BfIRType, 8> paramTypes;
  14809. mCurMethodInstance->GetIRFunctionInfo(this, returnType, paramTypes, mCurMethodInstance->IsVarArgs());
  14810. SizedArray<BfIRValue, 8> args;
  14811. for (int i = 0; i < (int)paramTypes.size(); i++)
  14812. args.push_back(mBfIRBuilder->GetArgument(i));
  14813. BfIRFunctionType externFunctionType = mBfIRBuilder->CreateFunctionType(returnType, paramTypes, mCurMethodInstance->IsVarArgs());
  14814. if (isHotCompile)
  14815. {
  14816. BfIRValue funcVal = mBfIRBuilder->CreateLoad(globalVar);
  14817. auto result = mBfIRBuilder->CreateCall(funcVal, args);
  14818. if (callingConvention == BfIRCallingConv_StdCall)
  14819. mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_StdCall);
  14820. else if (callingConvention == BfIRCallingConv_FastCall)
  14821. mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_FastCall);
  14822. else
  14823. mBfIRBuilder->SetCallCallingConv(result, BfIRCallingConv_CDecl);
  14824. if (allowTailCall)
  14825. mBfIRBuilder->SetTailCall(result);
  14826. CreateReturn(result);
  14827. mCurMethodState->mHadReturn = true;
  14828. }
  14829. if (HasCompiledOutput())
  14830. {
  14831. BfDllImportEntry dllImportEntry;
  14832. dllImportEntry.mFuncVar = globalVar;
  14833. dllImportEntry.mMethodInstance = mCurMethodInstance;
  14834. mDllImportEntries.push_back(dllImportEntry);
  14835. }
  14836. }
  14837. BfIRCallingConv BfModule::GetIRCallingConvention(BfMethodInstance* methodInstance)
  14838. {
  14839. auto methodDef = methodInstance->mMethodDef;
  14840. BfTypeInstance* owner = NULL;
  14841. if (!methodDef->mIsStatic)
  14842. owner = methodInstance->GetThisType()->ToTypeInstance();
  14843. if (owner == NULL)
  14844. owner = methodInstance->GetOwner();
  14845. if ((mCompiler->mOptions.mMachineType != BfMachineType_x86) || (mCompiler->mOptions.mPlatformType != BfPlatformType_Windows))
  14846. return BfIRCallingConv_CDecl;
  14847. if (methodInstance->mCallingConvention == BfCallingConvention_Stdcall)
  14848. return BfIRCallingConv_StdCall;
  14849. if (methodInstance->mCallingConvention == BfCallingConvention_Fastcall)
  14850. return BfIRCallingConv_FastCall;
  14851. if (!methodDef->mIsStatic)
  14852. {
  14853. if (owner->mIsCRepr)
  14854. return BfIRCallingConv_ThisCall;
  14855. if ((!owner->IsValuelessType()) &&
  14856. ((!owner->IsSplattable()) || (methodDef->HasNoThisSplat())))
  14857. return BfIRCallingConv_ThisCall;
  14858. }
  14859. return BfIRCallingConv_CDecl;
  14860. //return GetIRCallingConvention(owner, methodInstance->mMethodDef);
  14861. }
  14862. void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func, bool isInlined)
  14863. {
  14864. BfMethodDef* methodDef = NULL;
  14865. if (methodInstance != NULL)
  14866. methodDef = methodInstance->mMethodDef;
  14867. if (!func)
  14868. return;
  14869. if (mCompiler->mOptions.mNoFramePointerElim)
  14870. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_NoFramePointerElim);
  14871. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_NoUnwind);
  14872. if (mSystem->mPtrSize == 8) // We need unwind info for debugging
  14873. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_UWTable);
  14874. if (methodInstance == NULL)
  14875. return;
  14876. if (methodInstance->mReturnType->IsVar())
  14877. mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_VarRet);
  14878. if (methodDef->mImportKind == BfImportKind_Export)
  14879. {
  14880. if (methodDef->mDeclaringType->mProject->mTargetType != BfTargetType_BeefLib_StaticLib)
  14881. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_DllExport);
  14882. }
  14883. if (methodDef->mIsNoReturn)
  14884. mBfIRBuilder->Func_AddAttribute(func, -1, BfIRAttribute_NoReturn);
  14885. auto callingConv = GetIRCallingConvention(methodInstance);
  14886. if (callingConv != BfIRCallingConv_CDecl)
  14887. mBfIRBuilder->SetFuncCallingConv(func, callingConv);
  14888. if (isInlined)
  14889. {
  14890. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_AlwaysInline);
  14891. }
  14892. int argIdx = 0;
  14893. int paramIdx = 0;
  14894. if ((methodInstance->HasThis()) && (!methodDef->mHasExplicitThis))
  14895. paramIdx = -1;
  14896. int argCount = methodInstance->GetIRFunctionParamCount(this);
  14897. while (argIdx < argCount)
  14898. {
  14899. if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx()))
  14900. {
  14901. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoAlias);
  14902. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_StructRet);
  14903. argIdx++;
  14904. continue;
  14905. }
  14906. bool isThis = (paramIdx == -1) || ((methodDef->mHasExplicitThis) && (paramIdx == 0));
  14907. while ((!isThis) && (methodInstance->IsParamSkipped(paramIdx)))
  14908. paramIdx++;
  14909. BfType* resolvedTypeRef = NULL;
  14910. BfType* resolvedTypeRef2 = NULL;
  14911. String paramName;
  14912. bool isSplattable = false;
  14913. bool tryLowering = !mIsComptimeModule;
  14914. if (isThis)
  14915. {
  14916. paramName = "this";
  14917. if (methodInstance->mIsClosure)
  14918. resolvedTypeRef = mCurMethodState->mClosureState->mClosureType;
  14919. else
  14920. resolvedTypeRef = methodInstance->GetThisType();
  14921. isSplattable = (!mIsComptimeModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(-1));
  14922. tryLowering = (!mIsComptimeModule) && (methodInstance->AllowsSplatting(-1));
  14923. }
  14924. else
  14925. {
  14926. paramName = methodInstance->GetParamName(paramIdx);
  14927. resolvedTypeRef = methodInstance->GetParamType(paramIdx);
  14928. if (resolvedTypeRef->IsMethodRef())
  14929. isSplattable = true;
  14930. else if ((!mIsComptimeModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting(paramIdx)))
  14931. {
  14932. auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance();
  14933. if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr))
  14934. {
  14935. // crepr splat is always splattable
  14936. isSplattable = true;
  14937. }
  14938. else
  14939. {
  14940. auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance();
  14941. if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr))
  14942. isSplattable = true;
  14943. else if (resolvedTypeRef->GetSplatCount() + argIdx <= mCompiler->mOptions.mMaxSplatRegs)
  14944. isSplattable = true;
  14945. }
  14946. }
  14947. }
  14948. if (tryLowering)
  14949. {
  14950. BfTypeCode loweredTypeCode = BfTypeCode_None;
  14951. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  14952. if (resolvedTypeRef->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
  14953. {
  14954. mBfIRBuilder->Func_SetParamName(func, argIdx + 1, paramName + "__1");
  14955. argIdx++;
  14956. if (loweredTypeCode2 != BfTypeCode_None)
  14957. {
  14958. mBfIRBuilder->Func_SetParamName(func, argIdx + 1, paramName + "__2");
  14959. argIdx++;
  14960. }
  14961. paramIdx++;
  14962. continue;
  14963. }
  14964. }
  14965. auto _SetupParam = [&](const StringImpl& paramName, BfType* resolvedTypeRef)
  14966. {
  14967. mBfIRBuilder->Func_SetParamName(func, argIdx + 1, paramName);
  14968. int addDeref = -1;
  14969. if (resolvedTypeRef->IsRef())
  14970. {
  14971. auto refType = (BfRefType*)resolvedTypeRef;
  14972. auto elementType = refType->mElementType;
  14973. PopulateType(elementType, BfPopulateType_Data);
  14974. addDeref = elementType->mSize;
  14975. if ((addDeref <= 0) && (!elementType->IsValuelessType()) && (!elementType->IsOpaque()))
  14976. AssertErrorState();
  14977. }
  14978. if ((resolvedTypeRef->IsComposite()) && (!resolvedTypeRef->IsTypedPrimitive()))
  14979. {
  14980. if (isThis)
  14981. {
  14982. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoCapture);
  14983. PopulateType(resolvedTypeRef, BfPopulateType_Data);
  14984. addDeref = resolvedTypeRef->mSize;
  14985. }
  14986. else if (methodInstance->WantsStructsAttribByVal(resolvedTypeRef))
  14987. {
  14988. mBfIRBuilder->PopulateType(resolvedTypeRef, BfIRPopulateType_Full);
  14989. BF_ASSERT(resolvedTypeRef->mAlign > 0);
  14990. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ByVal, mSystem->mPtrSize);
  14991. }
  14992. }
  14993. else if (resolvedTypeRef->IsPrimitiveType())
  14994. {
  14995. auto primType = (BfPrimitiveType*)resolvedTypeRef;
  14996. if (primType->mTypeDef->mTypeCode == BfTypeCode_Boolean)
  14997. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_ZExt);
  14998. }
  14999. if (addDeref >= 0)
  15000. mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_Dereferencable, addDeref);
  15001. argIdx++;
  15002. };
  15003. if (isSplattable)
  15004. {
  15005. std::function<void(BfType*, const StringImpl&)> checkTypeLambda = [&](BfType* checkType, const StringImpl& curName)
  15006. {
  15007. if (checkType->IsStruct())
  15008. {
  15009. auto checkTypeInstance = checkType->ToTypeInstance();
  15010. if (checkTypeInstance->mBaseType != NULL)
  15011. checkTypeLambda(checkTypeInstance->mBaseType, curName);
  15012. if (checkTypeInstance->mIsUnion)
  15013. {
  15014. BfType* unionInnerType = checkTypeInstance->GetUnionInnerType();
  15015. checkTypeLambda(unionInnerType, curName + "_data");
  15016. }
  15017. else
  15018. {
  15019. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  15020. {
  15021. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  15022. auto fieldDef = fieldInstance->GetFieldDef();
  15023. if (fieldInstance->mDataIdx >= 0)
  15024. {
  15025. checkTypeLambda(fieldInstance->GetResolvedType(), curName + "_" + fieldInstance->GetFieldDef()->mName);
  15026. }
  15027. }
  15028. }
  15029. if (checkTypeInstance->IsEnum())
  15030. {
  15031. mBfIRBuilder->Func_SetParamName(func, argIdx + 1, curName + "_dscr");
  15032. argIdx++;
  15033. }
  15034. }
  15035. else if (checkType->IsMethodRef())
  15036. {
  15037. auto methodRefType = (BfMethodRefType*)checkType;
  15038. BfMethodInstance* methodRefMethodInst = methodRefType->mMethodRef;
  15039. for (int dataIdx = 0; dataIdx < (int)methodRefType->GetCaptureDataCount(); dataIdx++)
  15040. {
  15041. int methodRefParamIdx = methodRefType->GetParamIdxFromDataIdx(dataIdx);
  15042. if (methodRefType->WantsDataPassedAsSplat(dataIdx))
  15043. {
  15044. checkTypeLambda(methodRefType->GetCaptureType(dataIdx), curName + "_" + methodRefMethodInst->GetParamName(methodRefParamIdx));
  15045. }
  15046. else
  15047. {
  15048. _SetupParam(curName + "_" + methodRefMethodInst->GetParamName(methodRefParamIdx), methodRefType->GetCaptureType(dataIdx));
  15049. }
  15050. }
  15051. }
  15052. else if (!checkType->IsValuelessType())
  15053. {
  15054. _SetupParam(curName, checkType);
  15055. }
  15056. };
  15057. checkTypeLambda(resolvedTypeRef, paramName);
  15058. paramIdx++;
  15059. continue;
  15060. }
  15061. _SetupParam(paramName, resolvedTypeRef);
  15062. if (resolvedTypeRef2 != NULL)
  15063. _SetupParam(paramName, resolvedTypeRef2);
  15064. paramIdx++;
  15065. }
  15066. }
  15067. void BfModule::EmitInitBlocks(const std::function<void(BfAstNode*)>& initBlockCallback)
  15068. {
  15069. auto methodDef = mCurMethodInstance->mMethodDef;
  15070. mCurTypeInstance->mTypeDef->PopulateMemberSets();
  15071. BfMemberSetEntry* entry = NULL;
  15072. BfMethodDef* initMethodDef = NULL;
  15073. mCurTypeInstance->mTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry);
  15074. if (entry != NULL)
  15075. initMethodDef = (BfMethodDef*)entry->mMemberDef;
  15076. SizedArray<BfAstNode*, 8> initBodies;
  15077. for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName)
  15078. {
  15079. if (initMethodDef->mDeclaringType->GetDefinition() != methodDef->mDeclaringType->GetDefinition())
  15080. continue;
  15081. if (initMethodDef->mMethodType != BfMethodType_Init)
  15082. continue;
  15083. if (initMethodDef->mIsStatic != methodDef->mIsStatic)
  15084. continue;
  15085. initBodies.Insert(0, initMethodDef->mBody);
  15086. }
  15087. for (auto body : initBodies)
  15088. {
  15089. initBlockCallback(body);
  15090. VisitEmbeddedStatement(body);
  15091. }
  15092. }
  15093. void BfModule::EmitCtorBody(bool& skipBody)
  15094. {
  15095. auto methodInstance = mCurMethodInstance;
  15096. auto methodDef = methodInstance->mMethodDef;
  15097. auto methodDeclaration = methodDef->mMethodDeclaration;
  15098. auto ctorDeclaration = (BfConstructorDeclaration*)methodDef->mMethodDeclaration;
  15099. auto typeDef = mCurTypeInstance->mTypeDef;
  15100. BfCustomAttributes* customAttributes = NULL;
  15101. defer(delete customAttributes);
  15102. BfInvocationExpression* ctorInvocation = NULL;
  15103. BfAttributeState attributeState;
  15104. attributeState.mTarget = BfAttributeTargets_MemberAccess;
  15105. if (ctorDeclaration != NULL)
  15106. {
  15107. ctorInvocation = BfNodeDynCast<BfInvocationExpression>(ctorDeclaration->mInitializer);
  15108. if (auto attributedExpr = BfNodeDynCast<BfAttributedExpression>(ctorDeclaration->mInitializer))
  15109. {
  15110. ctorInvocation = BfNodeDynCast<BfInvocationExpression>(attributedExpr->mExpression);
  15111. attributeState.mCustomAttributes = GetCustomAttributes(attributedExpr->mAttributes, attributeState.mTarget);
  15112. }
  15113. }
  15114. SetAndRestoreValue<BfAttributeState*> prevAttributeState(mAttributeState, &attributeState);
  15115. // Prologue
  15116. mBfIRBuilder->ClearDebugLocation();
  15117. bool hadThisInitializer = false;
  15118. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
  15119. {
  15120. auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
  15121. auto targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
  15122. if (targetToken->GetToken() == BfToken_This)
  15123. {
  15124. hadThisInitializer = true;
  15125. // Since we call a 'this', it's that other ctor's responsibility to fully assign the fields
  15126. mCurMethodState->LocalDefined(GetThisVariable());
  15127. }
  15128. }
  15129. // Zero out memory for default ctor
  15130. if ((methodDeclaration == NULL) && (mCurTypeInstance->IsStruct()) && (methodInstance->mChainType != BfMethodChainType_ChainMember))
  15131. {
  15132. if (mCurTypeInstance->IsTypedPrimitive())
  15133. {
  15134. auto thisRef = mCurMethodState->mLocals[0]->mValue;
  15135. mBfIRBuilder->CreateStore(GetDefaultValue(mCurTypeInstance), thisRef);
  15136. }
  15137. else if (mCurTypeInstance->mInstSize > 0)
  15138. {
  15139. BfIRValue fillValue = GetConstValue8(0);
  15140. BfIRValue sizeValue = GetConstValue(mCurTypeInstance->mInstSize);
  15141. auto thisRef = mCurMethodState->mLocals[0]->mValue;
  15142. BfIRValue destBits = mBfIRBuilder->CreateBitCast(thisRef, mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
  15143. mBfIRBuilder->CreateMemSet(destBits, fillValue, sizeValue, mCurTypeInstance->mAlign);
  15144. }
  15145. }
  15146. BfAstNode* baseCtorNode = NULL;
  15147. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL) && (ctorInvocation->mTarget != NULL))
  15148. baseCtorNode = ctorInvocation->mTarget;
  15149. else if (methodDef->mBody != NULL)
  15150. baseCtorNode = methodDef->mBody;
  15151. else if (ctorDeclaration != NULL)
  15152. baseCtorNode = ctorDeclaration;
  15153. else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
  15154. baseCtorNode = methodDef->mDeclaringType->GetRefNode();
  15155. else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
  15156. baseCtorNode = mCurTypeInstance->mTypeDef->mTypeDeclaration->mNameNode;
  15157. else if ((mCurTypeInstance->mBaseType != NULL) && (mCurTypeInstance->mBaseType->mTypeDef->mTypeDeclaration != NULL))
  15158. baseCtorNode = mCurTypeInstance->mBaseType->mTypeDef->mTypeDeclaration;
  15159. else
  15160. baseCtorNode = mContext->mBfObjectType->mTypeDef->mTypeDeclaration;
  15161. bool calledCtorNoBody = false;
  15162. if ((mCurTypeInstance->IsTypedPrimitive()) && (!mCurTypeInstance->IsValuelessType()))
  15163. {
  15164. // Zero out typed primitives in ctor
  15165. mBfIRBuilder->CreateAlignedStore(GetDefaultValue(mCurTypeInstance->GetUnderlyingType()), mBfIRBuilder->GetArgument(0), mCurTypeInstance->mAlign);
  15166. }
  15167. if ((!mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType == BfMethodType_Ctor) && (!hadThisInitializer))
  15168. {
  15169. // Call the root type's default ctor (with no body) to initialize its fields and call the chained ctors
  15170. if (mCurTypeInstance->mTypeDef->mHasCtorNoBody)
  15171. {
  15172. BfMethodDef* defaultCtor = NULL;
  15173. for (auto methodDef : mCurTypeInstance->mTypeDef->mMethods)
  15174. {
  15175. if ((methodDef->mMethodType == BfMethodType_CtorNoBody) && (methodDef->mDeclaringType->mTypeCode != BfTypeCode_Extension))
  15176. {
  15177. defaultCtor = methodDef;
  15178. }
  15179. }
  15180. if (defaultCtor != NULL)
  15181. {
  15182. UpdateSrcPos(mCurTypeInstance->mTypeDef->GetRefNode());
  15183. SetIllegalSrcPos();
  15184. auto moduleMethodInstance = GetMethodInstance(mCurTypeInstance, defaultCtor, BfTypeVector());
  15185. BfExprEvaluator exprEvaluator(this);
  15186. SizedArray<BfIRValue, 1> irArgs;
  15187. exprEvaluator.PushThis(NULL, GetThis(), moduleMethodInstance.mMethodInstance, irArgs);
  15188. exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs);
  15189. if (mIsComptimeModule)
  15190. mCompiler->mCeMachine->QueueMethod(moduleMethodInstance);
  15191. calledCtorNoBody = true;
  15192. }
  15193. }
  15194. }
  15195. // Initialize fields (if applicable)
  15196. if (mCurTypeInstance->IsBoxed())
  15197. {
  15198. skipBody = true;
  15199. }
  15200. else if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mDeclaringType->mTypeCode == BfTypeCode_Extension))
  15201. {
  15202. // Field initializers occur in CtorNoBody methods for extensions
  15203. }
  15204. else if (!hadThisInitializer)
  15205. {
  15206. // If we had a 'this' initializer, that other ctor will have initialized our fields
  15207. //auto
  15208. if ((!mCompiler->mIsResolveOnly) ||
  15209. (mCompiler->mResolvePassData->mAutoComplete == NULL) ||
  15210. (mCompiler->mResolvePassData->mAutoComplete->mResolveType == BfResolveType_ShowFileSymbolReferences))
  15211. {
  15212. // If we calledCtorNoBody then we did the field initializer code, but we still need to run though it here
  15213. // to properly set the assigned flags
  15214. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || calledCtorNoBody);
  15215. bool hadInlineInitBlock = false;
  15216. BfScopeData scopeData;
  15217. scopeData.mInInitBlock = true;
  15218. auto _CheckInitBlock = [&](BfAstNode* node)
  15219. {
  15220. if (!hadInlineInitBlock)
  15221. {
  15222. if ((mBfIRBuilder->DbgHasInfo()) && (!mCurTypeInstance->IsUnspecializedType()) && (mHasFullDebugInfo))
  15223. {
  15224. UpdateSrcPos(baseCtorNode);
  15225. if (methodDef->mBody == NULL)
  15226. SetIllegalSrcPos();
  15227. // NOP so we step onto the open paren of the method so we can choose to set into the field initializers or step over them
  15228. EmitEnsureInstructionAt();
  15229. BfType* thisType = mCurTypeInstance;
  15230. if (thisType->IsValueType())
  15231. thisType = CreateRefType(thisType);
  15232. SizedArray<BfIRMDNode, 1> diParamTypes;
  15233. BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes);
  15234. mCurMethodState->AddScope(&scopeData);
  15235. NewScopeState();
  15236. int flags = 0;
  15237. mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation();
  15238. BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt);
  15239. // mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor
  15240. String linkageName;
  15241. if ((mIsComptimeModule) && (mCompiler->mCeMachine->mCurBuilder != NULL))
  15242. linkageName = StrFormat("%d", mCompiler->mCeMachine->mCurBuilder->DbgCreateMethodRef(mCurMethodInstance, "$initFields"));
  15243. mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", linkageName, mCurFilePosition.mFileInstance->mDIFile,
  15244. mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
  15245. UpdateSrcPos(node);
  15246. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  15247. "this", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(thisType));
  15248. //
  15249. {
  15250. auto loadedThis = GetThis();
  15251. // LLVM can't handle two variables pointing to the same value
  15252. BfIRValue copiedThisPtr;
  15253. copiedThisPtr = CreateAlloca(thisType);
  15254. auto storeInst = mBfIRBuilder->CreateStore(loadedThis.mValue, copiedThisPtr);
  15255. mBfIRBuilder->ClearDebugLocation(storeInst);
  15256. mBfIRBuilder->DbgInsertDeclare(copiedThisPtr, diVariable);
  15257. }
  15258. hadInlineInitBlock = true;
  15259. }
  15260. else
  15261. {
  15262. // Just do a simple one
  15263. mCurMethodState->AddScope(&scopeData);
  15264. NewScopeState();
  15265. hadInlineInitBlock = true;
  15266. }
  15267. }
  15268. UpdateSrcPos(node);
  15269. };
  15270. for (auto fieldDef : typeDef->mFields)
  15271. {
  15272. // For extensions, only handle these fields in the appropriate extension
  15273. if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
  15274. continue;
  15275. if ((!fieldDef->mIsConst) && (!fieldDef->mIsStatic))
  15276. {
  15277. auto fieldInst = &mCurTypeInstance->mFieldInstances[fieldDef->mIdx];
  15278. if (!fieldInst->mFieldIncluded)
  15279. continue;
  15280. if (fieldInst->mDataIdx < 0)
  15281. continue;
  15282. auto initializer = fieldDef->GetInitializer();
  15283. if (initializer == NULL)
  15284. {
  15285. continue;
  15286. // if (fieldDef->mProtection != BfProtection_Hidden)
  15287. // continue;
  15288. // if (mCurTypeInstance->IsObject()) // Already zeroed out
  15289. // continue;
  15290. }
  15291. if (fieldInst->mResolvedType == NULL)
  15292. {
  15293. BF_ASSERT(mHadBuildError);
  15294. continue;
  15295. }
  15296. if (initializer != NULL)
  15297. {
  15298. _CheckInitBlock(initializer);
  15299. }
  15300. BfIRValue fieldAddr;
  15301. if ((!mCurTypeInstance->IsTypedPrimitive()) && (!fieldInst->mResolvedType->IsVar()))
  15302. {
  15303. fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx /*, fieldDef->mName*/);
  15304. }
  15305. else
  15306. {
  15307. // Failed
  15308. }
  15309. auto assignValue = GetFieldInitializerValue(fieldInst);
  15310. if (mCurTypeInstance->IsUnion())
  15311. {
  15312. auto fieldPtrType = CreatePointerType(fieldInst->mResolvedType);
  15313. fieldAddr = mBfIRBuilder->CreateBitCast(fieldAddr, mBfIRBuilder->MapType(fieldPtrType));
  15314. }
  15315. if ((fieldAddr) && (assignValue))
  15316. mBfIRBuilder->CreateAlignedStore(assignValue.mValue, fieldAddr, fieldInst->mResolvedType->mAlign);
  15317. }
  15318. }
  15319. EmitInitBlocks(_CheckInitBlock);
  15320. if (hadInlineInitBlock)
  15321. {
  15322. RestoreScopeState();
  15323. // This gets set to false because of AddScope but we actually are still in the head block
  15324. mCurMethodState->mInHeadScope = true;
  15325. // Make sure we emit a return even if we had a NoReturn call or return inside ourselves
  15326. mCurMethodState->mHadReturn = false;
  15327. mCurMethodState->mLeftBlockUncond = false;
  15328. }
  15329. }
  15330. else // Autocomplete case
  15331. {
  15332. BfScopeData scopeData;
  15333. scopeData.mInInitBlock = true;
  15334. mCurMethodState->AddScope(&scopeData);
  15335. NewScopeState();
  15336. // The reason we can't just do the 'normal' path for this is that the BfTypeInstance here is NOT the
  15337. // autocomplete type instance, so FieldInstance initializer values contain expressions from the full
  15338. // resolve pass, NOT the autocomplete expression
  15339. for (auto tempTypeDef : mCompiler->mResolvePassData->mAutoCompleteTempTypes)
  15340. {
  15341. if (tempTypeDef->mFullName == typeDef->mFullName)
  15342. {
  15343. for (auto fieldDef : tempTypeDef->mFields)
  15344. {
  15345. auto initializer = fieldDef->GetInitializer();
  15346. if ((!fieldDef->mIsStatic) && (initializer != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
  15347. {
  15348. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(initializer))
  15349. {
  15350. sourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
  15351. sourceClassifier->VisitChild(initializer);
  15352. }
  15353. BfType* wantType = NULL;
  15354. if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) &&
  15355. (!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
  15356. wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowInferredSizedArray);
  15357. if ((wantType != NULL) &&
  15358. ((wantType->IsVar()) || (wantType->IsLet()) || (wantType->IsRef())))
  15359. wantType = NULL;
  15360. CreateValueFromExpression(initializer, wantType, BfEvalExprFlags_FieldInitializer);
  15361. }
  15362. }
  15363. tempTypeDef->PopulateMemberSets();
  15364. BfMemberSetEntry* entry = NULL;
  15365. BfMethodDef* initMethodDef = NULL;
  15366. tempTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry);
  15367. if (entry != NULL)
  15368. initMethodDef = (BfMethodDef*)entry->mMemberDef;
  15369. SizedArray<BfAstNode*, 8> initBodies;
  15370. for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName)
  15371. {
  15372. if (initMethodDef->mMethodType != BfMethodType_Init)
  15373. continue;
  15374. initBodies.Insert(0, initMethodDef->mBody);
  15375. }
  15376. for (auto body : initBodies)
  15377. VisitEmbeddedStatement(body);
  15378. }
  15379. }
  15380. // Mark fields from full type with initializers as initialized, to give proper initialization errors within ctor
  15381. for (auto fieldDef : typeDef->mFields)
  15382. {
  15383. if ((!fieldDef->mIsConst) && (!fieldDef->mIsStatic) && (fieldDef->GetInitializer() != NULL))
  15384. {
  15385. auto fieldInst = &mCurTypeInstance->mFieldInstances[fieldDef->mIdx];
  15386. if (fieldDef->GetInitializer() != NULL)
  15387. MarkFieldInitialized(fieldInst);
  15388. }
  15389. }
  15390. RestoreScopeState();
  15391. }
  15392. }
  15393. if (!methodInstance->mIsAutocompleteMethod)
  15394. {
  15395. if (auto autoDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
  15396. {
  15397. BfExprEvaluator exprEvaluator(this);
  15398. for (int paramIdx = 0; paramIdx < methodDef->mParams.mSize; paramIdx++)
  15399. {
  15400. auto paramDef = methodDef->mParams[paramIdx];
  15401. auto& fieldInstance = mCurTypeInstance->mFieldInstances[paramIdx];
  15402. BF_ASSERT(paramDef->mName == fieldInstance.GetFieldDef()->mName);
  15403. if (fieldInstance.mDataIdx < 0)
  15404. continue;
  15405. if (paramDef->mParamKind != BfParamKind_Normal)
  15406. continue;
  15407. auto localVar = mCurMethodState->mLocals[paramIdx + 1];
  15408. BF_ASSERT(localVar->mName == paramDef->mName);
  15409. auto localVal = exprEvaluator.LoadLocal(localVar);
  15410. localVal = LoadOrAggregateValue(localVal);
  15411. if (!localVal.mType->IsVar())
  15412. {
  15413. auto thisVal = GetThis();
  15414. auto fieldPtr = mBfIRBuilder->CreateInBoundsGEP(thisVal.mValue, 0, fieldInstance.mDataIdx);
  15415. mBfIRBuilder->CreateAlignedStore(localVal.mValue, fieldPtr, localVar->mResolvedType->mAlign);
  15416. }
  15417. MarkFieldInitialized(&fieldInstance);
  15418. }
  15419. }
  15420. }
  15421. // Call base ctor (if applicable)
  15422. BfTypeInstance* targetType = NULL;
  15423. BfAstNode* targetRefNode = NULL;
  15424. if (ctorDeclaration != NULL)
  15425. targetRefNode = ctorDeclaration->mInitializer;
  15426. if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(targetRefNode))
  15427. targetRefNode = invocationExpr->mTarget;
  15428. if (baseCtorNode != NULL)
  15429. {
  15430. UpdateSrcPos(baseCtorNode);
  15431. if (methodDef->mBody == NULL)
  15432. SetIllegalSrcPos();
  15433. }
  15434. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
  15435. {
  15436. auto targetToken = BfNodeDynCast<BfTokenNode>(ctorInvocation->mTarget);
  15437. targetType = (targetToken->GetToken() == BfToken_This) ? mCurTypeInstance : mCurTypeInstance->mBaseType;
  15438. }
  15439. else if ((mCurTypeInstance->mBaseType != NULL) && (!mCurTypeInstance->IsUnspecializedType()) && (methodDef->mMethodType != BfMethodType_CtorNoBody))
  15440. {
  15441. auto baseType = mCurTypeInstance->mBaseType;
  15442. if ((!mCurTypeInstance->IsTypedPrimitive()) &&
  15443. ((baseType->mTypeDef != mCompiler->mValueTypeTypeDef) || (!mContext->mCanSkipValueTypeCtor)) &&
  15444. ((baseType->mTypeDef != mCompiler->mBfObjectTypeDef) || (!mContext->mCanSkipObjectCtor)))
  15445. {
  15446. // Try to find a ctor without any params first
  15447. BfMethodDef* matchedMethod = NULL;
  15448. bool hadCtorWithAllDefaults = false;
  15449. bool isHiddenGenerated = (methodDeclaration == NULL) && (methodDef->mProtection == BfProtection_Hidden);
  15450. for (int pass = 0; pass < 2; pass++)
  15451. {
  15452. baseType->mTypeDef->PopulateMemberSets();
  15453. BfMemberSetEntry* entry = NULL;
  15454. BfMethodDef* checkMethodDef = NULL;
  15455. baseType->mTypeDef->mMethodSet.TryGetWith(String("__BfCtor"), &entry);
  15456. if (entry != NULL)
  15457. checkMethodDef = (BfMethodDef*)entry->mMemberDef;
  15458. while (checkMethodDef != NULL)
  15459. {
  15460. bool allowMethod = checkMethodDef->mProtection > BfProtection_Private;
  15461. if (isHiddenGenerated)
  15462. {
  15463. // Allow calling of the default base ctor if it is implicitly defined
  15464. if ((checkMethodDef->mMethodDeclaration == NULL) && (pass == 1) && (!hadCtorWithAllDefaults))
  15465. allowMethod = true;
  15466. }
  15467. if ((checkMethodDef->mMethodType == BfMethodType_Ctor) && (!checkMethodDef->mIsStatic) && (allowMethod))
  15468. {
  15469. if (checkMethodDef->mParams.size() == 0)
  15470. {
  15471. if (matchedMethod != NULL)
  15472. {
  15473. // Has multiple matched methods - can happen from extensions
  15474. matchedMethod = NULL;
  15475. break;
  15476. }
  15477. matchedMethod = checkMethodDef;
  15478. }
  15479. else if (isHiddenGenerated)
  15480. {
  15481. if ((checkMethodDef->mParams[0]->mParamDeclaration != NULL) && (checkMethodDef->mParams[0]->mParamDeclaration->mInitializer != NULL))
  15482. hadCtorWithAllDefaults = true;
  15483. }
  15484. }
  15485. checkMethodDef = checkMethodDef->mNextWithSameName;
  15486. }
  15487. if (matchedMethod != NULL)
  15488. break;
  15489. }
  15490. if ((HasExecutedOutput()) && (matchedMethod != NULL))
  15491. {
  15492. SizedArray<BfIRValue, 1> args;
  15493. auto ctorBodyMethodInstance = GetMethodInstance(mCurTypeInstance->mBaseType, matchedMethod, BfTypeVector());
  15494. if (!mCurTypeInstance->mBaseType->IsValuelessType())
  15495. {
  15496. auto basePtr = mBfIRBuilder->CreateBitCast(mCurMethodState->mLocals[0]->mValue, mBfIRBuilder->MapTypeInstPtr(mCurTypeInstance->mBaseType));
  15497. args.push_back(basePtr);
  15498. }
  15499. AddCallDependency(ctorBodyMethodInstance.mMethodInstance, true);
  15500. auto callInst = mBfIRBuilder->CreateCall(ctorBodyMethodInstance.mFunc, args);
  15501. auto callingConv = GetIRCallingConvention(ctorBodyMethodInstance.mMethodInstance);
  15502. if (callingConv != BfIRCallingConv_CDecl)
  15503. mBfIRBuilder->SetCallCallingConv(callInst, callingConv);
  15504. if (mIsComptimeModule)
  15505. mCompiler->mCeMachine->QueueMethod(ctorBodyMethodInstance);
  15506. }
  15507. if (matchedMethod == NULL)
  15508. {
  15509. targetType = mCurTypeInstance->mBaseType;
  15510. if (ctorDeclaration != NULL)
  15511. targetRefNode = ctorDeclaration->mThisToken;
  15512. else if (typeDef->mTypeDeclaration != NULL)
  15513. targetRefNode = typeDef->mTypeDeclaration->mNameNode;
  15514. }
  15515. }
  15516. }
  15517. if (methodDef->mHasAppend)
  15518. {
  15519. mCurMethodState->mCurAppendAlign = methodInstance->mAppendAllocAlign;
  15520. }
  15521. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL) && (ctorInvocation->mArguments.size() == 1) && (targetType != NULL))
  15522. {
  15523. if (auto tokenNode = BfNodeDynCast<BfUninitializedExpression>(ctorInvocation->mArguments[0]))
  15524. {
  15525. if (targetType == mCurTypeInstance)
  15526. {
  15527. auto thisVariable = GetThisVariable();
  15528. if (thisVariable != NULL)
  15529. {
  15530. thisVariable->mUnassignedFieldFlags = 0;
  15531. thisVariable->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  15532. }
  15533. }
  15534. targetType = NULL;
  15535. }
  15536. }
  15537. if (targetType != NULL)
  15538. {
  15539. BfAstNode* refNode = methodDeclaration;
  15540. if (refNode == NULL)
  15541. refNode = typeDef->mTypeDeclaration;
  15542. BfAutoParentNodeEntry autoParentNodeEntry(this, refNode);
  15543. auto autoComplete = mCompiler->GetAutoComplete();
  15544. auto wasCapturingMethodInfo = (autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo);
  15545. if ((autoComplete != NULL) && (ctorDeclaration != NULL) && (ctorInvocation != NULL))
  15546. {
  15547. auto invocationExpr = ctorInvocation;
  15548. autoComplete->CheckInvocation(invocationExpr, invocationExpr->mOpenParen, invocationExpr->mCloseParen, invocationExpr->mCommas);
  15549. }
  15550. BfType* targetThisType = targetType;
  15551. auto target = Cast(targetRefNode, GetThis(), targetThisType);
  15552. BfExprEvaluator exprEvaluator(this);
  15553. BfResolvedArgs argValues;
  15554. if ((ctorDeclaration != NULL) && (ctorInvocation != NULL))
  15555. {
  15556. argValues.Init(&ctorInvocation->mArguments);
  15557. if (gDebugStuff)
  15558. {
  15559. OutputDebugStrF("Expr: %@ %d\n", argValues.mArguments->mVals, argValues.mArguments->mSize);
  15560. }
  15561. }
  15562. exprEvaluator.ResolveArgValues(argValues, BfResolveArgsFlag_DeferParamEval);
  15563. BfTypedValue appendIdxVal;
  15564. if (methodDef->mHasAppend)
  15565. {
  15566. auto localVar = mCurMethodState->GetRootMethodState()->mLocals[1];
  15567. BF_ASSERT(localVar->mName == "appendIdx");
  15568. auto intRefType = localVar->mResolvedType;
  15569. appendIdxVal = BfTypedValue(localVar->mValue, intRefType);
  15570. mCurMethodState->mCurAppendAlign = 1; // Don't make any assumptions about how the base leaves the alignment
  15571. }
  15572. exprEvaluator.MatchConstructor(targetRefNode, NULL, target, targetType, argValues, true, methodDef->mHasAppend, &appendIdxVal);
  15573. if (autoComplete != NULL)
  15574. {
  15575. if ((wasCapturingMethodInfo) && (!autoComplete->mIsCapturingMethodMatchInfo))
  15576. {
  15577. if (autoComplete->mMethodMatchInfo != NULL)
  15578. autoComplete->mIsCapturingMethodMatchInfo = true;
  15579. else
  15580. autoComplete->mIsCapturingMethodMatchInfo = false;
  15581. }
  15582. else
  15583. autoComplete->mIsCapturingMethodMatchInfo = false;
  15584. }
  15585. }
  15586. }
  15587. void BfModule::EmitEnumToStringBody()
  15588. {
  15589. auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef);
  15590. auto strVal = CreateAlloca(stringType);
  15591. auto int64StructType = GetPrimitiveStructType(BfTypeCode_Int64);
  15592. BfExprEvaluator exprEvaluator(this);
  15593. auto stringDestAddr = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  15594. BfIRBlock appendBlock = mBfIRBuilder->CreateBlock("append");
  15595. BfIRBlock noMatchBlock = mBfIRBuilder->CreateBlock("noMatch");
  15596. BfIRBlock endBlock = mBfIRBuilder->CreateBlock("end");
  15597. BfType* discriminatorType = NULL;
  15598. BfTypedValue rawPayload;
  15599. BfIRValue enumVal;
  15600. if (mCurTypeInstance->IsPayloadEnum())
  15601. {
  15602. discriminatorType = mCurTypeInstance->GetDiscriminatorType();
  15603. auto enumTypedValue = ExtractValue(GetThis(), NULL, 2);
  15604. enumTypedValue = LoadValue(enumTypedValue);
  15605. enumVal = enumTypedValue.mValue;
  15606. rawPayload = ExtractValue(GetThis(), NULL, 1);
  15607. }
  15608. else
  15609. enumVal = mBfIRBuilder->GetArgument(0);
  15610. Array<BfType*> paramTypes;
  15611. paramTypes.Add(stringType);
  15612. auto appendModuleMethodInstance = GetMethodByName(stringType->ToTypeInstance(), "Append", paramTypes);
  15613. auto switchVal = mBfIRBuilder->CreateSwitch(enumVal, noMatchBlock, (int)mCurTypeInstance->mFieldInstances.size());
  15614. HashSet<int64> handledCases;
  15615. for (auto& fieldInstance : mCurTypeInstance->mFieldInstances)
  15616. {
  15617. if (fieldInstance.mIsEnumPayloadCase)
  15618. {
  15619. int tagId = -fieldInstance.mDataIdx - 1;
  15620. BfIRBlock caseBlock = mBfIRBuilder->CreateBlock("case");
  15621. mBfIRBuilder->AddBlock(caseBlock);
  15622. mBfIRBuilder->SetInsertPoint(caseBlock);
  15623. BF_ASSERT(discriminatorType->IsPrimitiveType());
  15624. auto constVal = mBfIRBuilder->CreateConst(((BfPrimitiveType*)discriminatorType)->mTypeDef->mTypeCode, tagId);
  15625. mBfIRBuilder->AddSwitchCase(switchVal, constVal, caseBlock);
  15626. auto caseStr = GetStringObjectValue(fieldInstance.GetFieldDef()->mName);
  15627. auto stringDestVal = LoadValue(stringDestAddr);
  15628. SizedArray<BfIRValue, 2> args;
  15629. args.Add(stringDestVal.mValue);
  15630. args.Add(caseStr);
  15631. exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
  15632. auto payloadType = fieldInstance.mResolvedType->ToTypeInstance();
  15633. BF_ASSERT(payloadType->IsTuple());
  15634. if (payloadType->mFieldInstances.size() != 0)
  15635. {
  15636. auto payload = rawPayload;
  15637. if (payload.mType != payloadType)
  15638. {
  15639. payload = Cast(NULL, payload, payloadType, BfCastFlags_Force);
  15640. }
  15641. auto toStringMethod = GetMethodByName(payloadType->ToTypeInstance(), "ToString");
  15642. SizedArray<BfIRValue, 2> irArgs;
  15643. exprEvaluator.PushThis(NULL, payload, toStringMethod.mMethodInstance, irArgs);
  15644. stringDestVal = LoadValue(stringDestAddr);
  15645. irArgs.Add(stringDestVal.mValue);
  15646. exprEvaluator.CreateCall(NULL, toStringMethod.mMethodInstance, toStringMethod.mFunc, true, irArgs);
  15647. }
  15648. mBfIRBuilder->CreateBr(endBlock);
  15649. continue;
  15650. }
  15651. if (fieldInstance.mConstIdx == -1)
  15652. continue;
  15653. // Only allow compact 'ValA, ValB' enum declaration fields through
  15654. auto fieldDef = fieldInstance.GetFieldDef();
  15655. auto fieldDecl = fieldDef->mFieldDeclaration;
  15656. if ((fieldDecl == NULL) || (fieldDef->mTypeRef != NULL))
  15657. continue;
  15658. auto constant = mCurTypeInstance->mConstHolder->GetConstantById(fieldInstance.mConstIdx);
  15659. if (!handledCases.TryAdd(constant->mInt64, NULL))
  15660. {
  15661. // Duplicate
  15662. continue;
  15663. }
  15664. BfIRBlock caseBlock = mBfIRBuilder->CreateBlock("case");
  15665. mBfIRBuilder->AddBlock(caseBlock);
  15666. mBfIRBuilder->SetInsertPoint(caseBlock);
  15667. BfIRValue constVal = ConstantToCurrent(constant, mCurTypeInstance->mConstHolder, mCurTypeInstance);
  15668. mBfIRBuilder->AddSwitchCase(switchVal, constVal, caseBlock);
  15669. auto caseStr = GetStringObjectValue(fieldInstance.GetFieldDef()->mName);
  15670. mBfIRBuilder->CreateStore(caseStr, strVal);
  15671. mBfIRBuilder->CreateBr(appendBlock);
  15672. }
  15673. mBfIRBuilder->AddBlock(appendBlock);
  15674. mBfIRBuilder->SetInsertPoint(appendBlock);
  15675. SizedArray<BfIRValue, 2> args;
  15676. auto stringDestVal = LoadValue(stringDestAddr);
  15677. args.Add(stringDestVal.mValue);
  15678. args.Add(mBfIRBuilder->CreateLoad(strVal));
  15679. exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
  15680. mBfIRBuilder->CreateBr(endBlock);
  15681. mBfIRBuilder->AddBlock(noMatchBlock);
  15682. mBfIRBuilder->SetInsertPoint(noMatchBlock);
  15683. auto int64Val = mBfIRBuilder->CreateNumericCast(enumVal, false, BfTypeCode_Int64);
  15684. auto toStringModuleMethodInstance = GetMethodByName(int64StructType, "ToString", 1);
  15685. args.clear();
  15686. args.Add(int64Val);
  15687. stringDestVal = LoadValue(stringDestAddr);
  15688. args.Add(stringDestVal.mValue);
  15689. exprEvaluator.CreateCall(NULL, toStringModuleMethodInstance.mMethodInstance, toStringModuleMethodInstance.mFunc, false, args);
  15690. mBfIRBuilder->CreateBr(endBlock);
  15691. mBfIRBuilder->AddBlock(endBlock);
  15692. mBfIRBuilder->SetInsertPoint(endBlock);
  15693. }
  15694. void BfModule::EmitTupleToStringBody()
  15695. {
  15696. auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef);
  15697. BfExprEvaluator exprEvaluator(this);
  15698. auto stringDestRef = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  15699. Array<BfType*> paramTypes;
  15700. paramTypes.Add(GetPrimitiveType(BfTypeCode_Char8));
  15701. auto appendCharModuleMethodInstance = GetMethodByName(stringType->ToTypeInstance(), "Append", paramTypes);
  15702. paramTypes.Clear();
  15703. paramTypes.Add(stringType);
  15704. auto appendModuleMethodInstance = GetMethodByName(stringType->ToTypeInstance(), "Append", paramTypes);
  15705. auto _AppendChar = [&](char c)
  15706. {
  15707. SizedArray<BfIRValue, 2> args;
  15708. auto stringDestVal = LoadValue(stringDestRef);
  15709. args.Add(stringDestVal.mValue);
  15710. args.Add(mBfIRBuilder->CreateConst(BfTypeCode_Char8, (int)c));
  15711. exprEvaluator.CreateCall(NULL, appendCharModuleMethodInstance.mMethodInstance, appendCharModuleMethodInstance.mFunc, false, args);
  15712. };
  15713. int fieldIdx = 0;
  15714. auto thisValue = GetThis();
  15715. auto toStringModuleMethodInstance = GetMethodByName(mContext->mBfObjectType, "ToString", 1);
  15716. auto toStringSafeModuleMethodInstance = GetMethodByName(mContext->mBfObjectType, "ToString", 2);
  15717. BfIRValue commaStr;
  15718. auto iPrintableType = ResolveTypeDef(mCompiler->mIPrintableTypeDef)->ToTypeInstance();
  15719. auto printModuleMethodInstance = GetMethodByName(iPrintableType, "Print");
  15720. _AppendChar('(');
  15721. for (auto& fieldInstance : mCurTypeInstance->mFieldInstances)
  15722. {
  15723. if (fieldInstance.mDataIdx == -1)
  15724. continue;
  15725. if (fieldIdx > 0)
  15726. {
  15727. if (!commaStr)
  15728. commaStr = GetStringObjectValue(", ");
  15729. SizedArray<BfIRValue, 2> args;
  15730. auto stringDestVal = LoadValue(stringDestRef);
  15731. args.Add(stringDestVal.mValue);
  15732. args.Add(commaStr);
  15733. exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
  15734. }
  15735. fieldIdx++;
  15736. if (fieldInstance.mResolvedType->IsValuelessType())
  15737. continue;
  15738. BfTypedValue fieldValue = ExtractValue(thisValue, &fieldInstance, fieldInstance.mDataIdx);
  15739. if (fieldValue.mType->IsPrimitiveType())
  15740. {
  15741. fieldValue.mType = GetPrimitiveStructType(((BfPrimitiveType*)fieldValue.mType)->mTypeDef->mTypeCode);
  15742. }
  15743. auto typeInstance = fieldValue.mType->ToTypeInstance();
  15744. if ((typeInstance != NULL) && (TypeIsSubTypeOf(typeInstance, iPrintableType, false)))
  15745. {
  15746. BfExprEvaluator exprEvaluator(this);
  15747. SizedArray<BfResolvedArg, 0> resolvedArgs;
  15748. BfMethodMatcher methodMatcher(NULL, this, printModuleMethodInstance.mMethodInstance, resolvedArgs, BfMethodGenericArguments());
  15749. methodMatcher.mBestMethodDef = printModuleMethodInstance.mMethodInstance->mMethodDef;
  15750. methodMatcher.mBestMethodTypeInstance = iPrintableType;
  15751. methodMatcher.TryDevirtualizeCall(fieldValue);
  15752. BfTypedValue callVal = Cast(NULL, fieldValue, methodMatcher.mBestMethodTypeInstance);
  15753. BfResolvedArg resolvedArg;
  15754. auto stringDestVal = LoadValue(stringDestRef);
  15755. resolvedArg.mTypedValue = stringDestVal;
  15756. resolvedArg.mResolvedType = stringDestVal.mType;
  15757. resolvedArgs.Add(resolvedArg);
  15758. exprEvaluator.CreateCall(&methodMatcher, callVal);
  15759. continue;
  15760. }
  15761. if (fieldValue.mType->IsObjectOrInterface())
  15762. {
  15763. fieldValue = LoadValue(fieldValue);
  15764. BF_ASSERT(!fieldValue.IsAddr());
  15765. SizedArray<BfIRValue, 2> args;
  15766. args.Add(mBfIRBuilder->CreateBitCast(fieldValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType)));
  15767. auto stringDestVal = exprEvaluator.LoadLocal(mCurMethodState->mLocals[1]);
  15768. stringDestVal = LoadValue(stringDestVal);
  15769. args.Add(stringDestVal.mValue);
  15770. exprEvaluator.CreateCall(NULL, toStringSafeModuleMethodInstance.mMethodInstance, toStringSafeModuleMethodInstance.mFunc, false, args);
  15771. continue;
  15772. }
  15773. BfExprEvaluator exprEvaluator(this);
  15774. SizedArray<BfResolvedArg, 0> resolvedArgs;
  15775. BfMethodMatcher methodMatcher(NULL, this, toStringModuleMethodInstance.mMethodInstance, resolvedArgs, BfMethodGenericArguments());
  15776. methodMatcher.mBestMethodDef = toStringModuleMethodInstance.mMethodInstance->mMethodDef;
  15777. methodMatcher.mBestMethodTypeInstance = mContext->mBfObjectType;
  15778. methodMatcher.TryDevirtualizeCall(fieldValue);
  15779. if (methodMatcher.mBestMethodTypeInstance == mContext->mBfObjectType)
  15780. {
  15781. AddCallDependency(appendModuleMethodInstance.mMethodInstance);
  15782. AddDependency(fieldValue.mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_Calls);
  15783. // Just append the type name
  15784. String typeName = TypeToString(fieldInstance.mResolvedType);
  15785. auto strVal = GetStringObjectValue(typeName);
  15786. SizedArray<BfIRValue, 2> args;
  15787. auto stringDestVal = LoadValue(stringDestRef);
  15788. args.Add(stringDestVal.mValue);
  15789. args.Add(strVal);
  15790. exprEvaluator.CreateCall(NULL, appendModuleMethodInstance.mMethodInstance, appendModuleMethodInstance.mFunc, false, args);
  15791. continue;
  15792. }
  15793. BfTypedValue callVal = Cast(NULL, fieldValue, methodMatcher.mBestMethodTypeInstance);
  15794. BfResolvedArg resolvedArg;
  15795. auto stringDestVal = LoadValue(stringDestRef);
  15796. resolvedArg.mTypedValue = stringDestVal;
  15797. resolvedArg.mResolvedType = stringDestVal.mType;
  15798. resolvedArgs.Add(resolvedArg);
  15799. exprEvaluator.CreateCall(&methodMatcher, callVal);
  15800. }
  15801. _AppendChar(')');
  15802. }
  15803. void BfModule::EmitIteratorBlock(bool& skipBody)
  15804. {
  15805. auto methodInstance = mCurMethodInstance;
  15806. auto methodDef = methodInstance->mMethodDef;
  15807. auto methodDeclaration = methodDef->GetMethodDeclaration();
  15808. auto typeDef = mCurTypeInstance->mTypeDef;
  15809. BfType* innerRetType = NULL;
  15810. BfTypeInstance* usingInterface = NULL;
  15811. auto retTypeInst = mCurMethodInstance->mReturnType->ToGenericTypeInstance();
  15812. if (retTypeInst != NULL)
  15813. {
  15814. if ((retTypeInst->IsInstanceOf(mCompiler->mGenericIEnumerableTypeDef)) ||
  15815. (retTypeInst->IsInstanceOf(mCompiler->mGenericIEnumeratorTypeDef)))
  15816. {
  15817. innerRetType = retTypeInst->mGenericTypeInfo->mTypeGenericArguments[0];
  15818. }
  15819. }
  15820. if (innerRetType == NULL)
  15821. {
  15822. Fail("Methods with yields must return either System.IEnumerable<T> or System.IEnumerator<T>", methodDeclaration->mReturnType);
  15823. return;
  15824. }
  15825. auto blockBody = BfNodeDynCast<BfBlock>(methodDeclaration->mBody);
  15826. if (blockBody == NULL)
  15827. return;
  15828. }
  15829. void BfModule::EmitGCMarkValue(BfTypedValue markVal, BfModuleMethodInstance markFromGCThreadMethodInstance)
  15830. {
  15831. auto fieldType = markVal.mType;
  15832. auto fieldTypeInst = fieldType->ToTypeInstance();
  15833. if (fieldType == NULL)
  15834. return;
  15835. if (!markVal.mType->IsComposite())
  15836. markVal = LoadValue(markVal);
  15837. BfExprEvaluator exprEvaluator(this);
  15838. PopulateType(markVal.mType, BfPopulateType_Data);
  15839. if (markVal.mType->IsObjectOrInterface())
  15840. {
  15841. BfIRValue val = markVal.mValue;
  15842. val = mBfIRBuilder->CreateBitCast(val, mBfIRBuilder->MapType(mContext->mBfObjectType));
  15843. SizedArray<BfIRValue, 1> args;
  15844. args.push_back(val);
  15845. exprEvaluator.CreateCall(NULL, markFromGCThreadMethodInstance.mMethodInstance, markFromGCThreadMethodInstance.mFunc, false, args);
  15846. }
  15847. else if (fieldType->IsSizedArray())
  15848. {
  15849. BfSizedArrayType* sizedArrayType = (BfSizedArrayType*)fieldType;
  15850. if (sizedArrayType->mElementType->WantsGCMarking())
  15851. {
  15852. BfTypedValue arrayValue = markVal;
  15853. auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  15854. auto itr = CreateAlloca(intPtrType);
  15855. mBfIRBuilder->CreateStore(GetDefaultValue(intPtrType), itr);
  15856. auto loopBB = mBfIRBuilder->CreateBlock("loop", true);
  15857. auto bodyBB = mBfIRBuilder->CreateBlock("body", true);
  15858. auto doneBB = mBfIRBuilder->CreateBlock("done", true);
  15859. mBfIRBuilder->CreateBr(loopBB);
  15860. mBfIRBuilder->SetInsertPoint(loopBB);
  15861. auto loadedItr = mBfIRBuilder->CreateLoad(itr);
  15862. auto cmpRes = mBfIRBuilder->CreateCmpGTE(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)sizedArrayType->mElementCount), true);
  15863. mBfIRBuilder->CreateCondBr(cmpRes, doneBB, bodyBB);
  15864. mBfIRBuilder->SetInsertPoint(bodyBB);
  15865. auto ptrType = CreatePointerType(sizedArrayType->mElementType);
  15866. auto ptrValue = mBfIRBuilder->CreateBitCast(arrayValue.mValue, mBfIRBuilder->MapType(ptrType));
  15867. auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, loadedItr);
  15868. auto value = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
  15869. EmitGCMarkValue(value, markFromGCThreadMethodInstance);
  15870. auto incValue = mBfIRBuilder->CreateAdd(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1));
  15871. mBfIRBuilder->CreateStore(incValue, itr);
  15872. mBfIRBuilder->CreateBr(loopBB);
  15873. mBfIRBuilder->SetInsertPoint(doneBB);
  15874. }
  15875. }
  15876. else if ((fieldType->IsComposite()) && (!fieldType->IsTypedPrimitive()) && (fieldTypeInst != NULL))
  15877. {
  15878. auto markMemberMethodInstance = GetMethodByName(fieldTypeInst, BF_METHODNAME_MARKMEMBERS, 0, true);
  15879. if (markMemberMethodInstance)
  15880. {
  15881. SizedArray<BfIRValue, 1> args;
  15882. auto methodOwner = markMemberMethodInstance.mMethodInstance->GetOwner();
  15883. if (markVal.mType != methodOwner)
  15884. markVal = Cast(NULL, markVal, methodOwner);
  15885. exprEvaluator.PushThis(NULL, markVal, markMemberMethodInstance.mMethodInstance, args);
  15886. exprEvaluator.CreateCall(NULL, markMemberMethodInstance.mMethodInstance, markMemberMethodInstance.mFunc, false, args);
  15887. }
  15888. }
  15889. }
  15890. void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse)
  15891. {
  15892. Array<BfMethodInstance*> methodInstances;
  15893. for (int methodIdx = 0; methodIdx < (int)mCurTypeInstance->mMethodInstanceGroups.size(); methodIdx++)
  15894. {
  15895. auto& methodInstGroup = mCurTypeInstance->mMethodInstanceGroups[methodIdx];
  15896. auto chainedMethodInst = methodInstGroup.mDefault;
  15897. if ((chainedMethodInst != NULL) && (chainedMethodInst->mChainType == BfMethodChainType_ChainMember))
  15898. {
  15899. if ((chainedMethodInst->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic) &&
  15900. (CompareMethodSignatures(methodInstance, chainedMethodInst)))
  15901. {
  15902. methodInstances.push_back(chainedMethodInst);
  15903. }
  15904. }
  15905. }
  15906. std::stable_sort(methodInstances.begin(), methodInstances.end(),
  15907. [&](BfMethodInstance* lhs, BfMethodInstance* rhs)
  15908. {
  15909. bool isBetter;
  15910. bool isWorse;
  15911. CompareDeclTypes(lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse);
  15912. if (isBetter == isWorse)
  15913. {
  15914. return false;
  15915. }
  15916. return isWorse;
  15917. });
  15918. if (reverse)
  15919. std::reverse(methodInstances.begin(), methodInstances.end());
  15920. for (auto chainedMethodInst : methodInstances)
  15921. {
  15922. auto declModule = this;
  15923. BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None;
  15924. auto moduleMethodInst = declModule->GetMethodInstance(mCurTypeInstance, chainedMethodInst->mMethodDef, BfTypeVector(), flags);
  15925. BfExprEvaluator exprEvaluator(this);
  15926. SizedArray<BfIRValue, 1> args;
  15927. exprEvaluator.PushThis(chainedMethodInst->mMethodDef->GetRefNode(), GetThis(), chainedMethodInst, args);
  15928. exprEvaluator.CreateCall(NULL, moduleMethodInst.mMethodInstance, moduleMethodInst.mFunc, true, args);
  15929. }
  15930. }
  15931. void BfModule::AddHotDataReferences(BfHotDataReferenceBuilder* builder)
  15932. {
  15933. BF_ASSERT(mCurMethodInstance->mIsReified);
  15934. if (mCurTypeInstance->mHotTypeData == NULL)
  15935. {
  15936. mCurTypeInstance->mHotTypeData = new BfHotTypeData();
  15937. BfLogSysM("Created HotTypeData %p created for type %p in AddHotDataReferences\n", mCurTypeInstance->mHotTypeData, mCurTypeInstance);
  15938. }
  15939. auto hotMethod = mCurMethodInstance->mHotMethod;
  15940. for (auto depData : hotMethod->mReferences)
  15941. {
  15942. // Only virtual decls are allowed to already be there
  15943. BF_ASSERT((depData->mDataKind == BfHotDepDataKind_VirtualDecl) || (depData->mDataKind == BfHotDepDataKind_DupMethod));
  15944. }
  15945. BF_ASSERT(hotMethod->mSrcTypeVersion != NULL);
  15946. int prevSize = (int)hotMethod->mReferences.size();
  15947. int refCount = (int)(prevSize + builder->mUsedData.size() + builder->mCalledMethods.size() + builder->mDevirtualizedCalledMethods.size());
  15948. if (!mCurMethodInstance->mMethodDef->mIsStatic)
  15949. refCount++;
  15950. hotMethod->mReferences.Reserve(refCount);
  15951. if (!mCurMethodInstance->mMethodDef->mIsStatic)
  15952. {
  15953. auto hotThis = mCompiler->mHotData->GetThisType(mCurMethodInstance->GetOwner()->mHotTypeData->GetLatestVersion());
  15954. hotThis->mRefCount++;
  15955. hotMethod->mReferences.Insert(0, hotThis);
  15956. prevSize++;
  15957. }
  15958. for (auto val : builder->mAllocatedData)
  15959. {
  15960. auto hotAllocation = mCompiler->mHotData->GetAllocation(val);
  15961. hotMethod->mReferences.Add(hotAllocation);
  15962. }
  15963. for (auto val : builder->mUsedData)
  15964. hotMethod->mReferences.Add(val);
  15965. for (auto val : builder->mCalledMethods)
  15966. hotMethod->mReferences.Add(val);
  15967. for (auto val : builder->mDevirtualizedCalledMethods)
  15968. {
  15969. auto devirtualizedMethod = mCompiler->mHotData->GetDevirtualizedMethod(val);
  15970. hotMethod->mReferences.Add(devirtualizedMethod);
  15971. }
  15972. for (auto val : builder->mFunctionPtrs)
  15973. {
  15974. auto funcRef = mCompiler->mHotData->GetFunctionReference(val);
  15975. hotMethod->mReferences.Add(funcRef);
  15976. }
  15977. for (auto val : builder->mInnerMethods)
  15978. {
  15979. auto innerMethod = mCompiler->mHotData->GetInnerMethod(val);
  15980. hotMethod->mReferences.Add(innerMethod);
  15981. }
  15982. for (int refIdx = prevSize; refIdx < (int)hotMethod->mReferences.size(); refIdx++)
  15983. {
  15984. auto depData = hotMethod->mReferences[refIdx];
  15985. BF_ASSERT(depData != NULL);
  15986. depData->mRefCount++;
  15987. }
  15988. }
  15989. void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfType* thisType, bool wantsDIData, SizedArrayImpl<BfIRMDNode>* diParams)
  15990. {
  15991. auto methodDef = methodInstance->mMethodDef;
  15992. auto methodDeclaration = methodDef->mMethodDeclaration;
  15993. bool isThisStruct = false;
  15994. if (thisType != NULL)
  15995. isThisStruct = thisType->IsStruct() && !thisType->IsTypedPrimitive();
  15996. int argIdx = 0;
  15997. if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx()))
  15998. argIdx++;
  15999. auto rootMethodState = mCurMethodState->GetRootMethodState();
  16000. if (!methodDef->mIsStatic)
  16001. {
  16002. BfTypeCode loweredTypeCode = BfTypeCode_None;
  16003. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  16004. BfLocalVariable* paramVar = rootMethodState->mBumpAlloc.Alloc<BfLocalVariable>();
  16005. paramVar->mIsBumpAlloc = true;
  16006. paramVar->mResolvedType = thisType;
  16007. paramVar->mName.Reference("this");
  16008. if (!thisType->IsValuelessType())
  16009. paramVar->mValue = mBfIRBuilder->GetArgument(argIdx);
  16010. else
  16011. paramVar->mValue = mBfIRBuilder->GetFakeVal();
  16012. if ((!mIsComptimeModule) && (thisType->IsSplattable()) && (methodInstance->AllowsSplatting(-1)))
  16013. {
  16014. if (!thisType->IsTypedPrimitive())
  16015. paramVar->mIsSplat = true;
  16016. }
  16017. else if ((!mIsComptimeModule) && (!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified))
  16018. paramVar->mIsLowered = thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
  16019. auto thisTypeInst = thisType->ToTypeInstance();
  16020. paramVar->mIsStruct = isThisStruct;
  16021. paramVar->mAddr = BfIRValue();
  16022. paramVar->mIsThis = true;
  16023. paramVar->mParamIdx = -1;
  16024. if ((methodDef->mMethodType == BfMethodType_Ctor) && (mCurTypeInstance->IsStruct()))
  16025. {
  16026. paramVar->mAssignedKind = BfLocalVarAssignKind_None;
  16027. }
  16028. else
  16029. {
  16030. paramVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  16031. }
  16032. paramVar->mReadFromId = -1;
  16033. paramVar->Init();
  16034. if (methodDeclaration == NULL)
  16035. UseDefaultSrcPos();
  16036. AddLocalVariableDef(paramVar);
  16037. if (!thisType->IsValuelessType())
  16038. {
  16039. if (wantsDIData)
  16040. {
  16041. BfType* thisPtrType = thisType;
  16042. auto diType = mBfIRBuilder->DbgGetType(thisPtrType);
  16043. if (!thisType->IsValueType())
  16044. diType = mBfIRBuilder->DbgCreateArtificialType(diType);
  16045. else if (!paramVar->mIsSplat)
  16046. diType = mBfIRBuilder->DbgCreatePointerType(diType);
  16047. diParams->push_back(diType);
  16048. }
  16049. if (paramVar->mIsSplat)
  16050. {
  16051. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
  16052. }
  16053. else
  16054. {
  16055. argIdx++;
  16056. if (loweredTypeCode2 != BfTypeCode_None)
  16057. argIdx++;
  16058. }
  16059. }
  16060. }
  16061. if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx()))
  16062. argIdx++;
  16063. bool hadParams = false;
  16064. bool hasDefault = false;
  16065. int compositeVariableIdx = -1;
  16066. int paramIdx = 0;
  16067. for (paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
  16068. {
  16069. // We already issues a type error for this param if we had one in declaration processing
  16070. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  16071. BfLocalVariable* paramVar = rootMethodState->mBumpAlloc.Alloc<BfLocalVariable>();
  16072. paramVar->mIsBumpAlloc = true;
  16073. BfTypeCode loweredTypeCode = BfTypeCode_None;
  16074. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  16075. bool isParamSkipped = methodInstance->IsParamSkipped(paramIdx);
  16076. auto resolvedType = methodInstance->GetParamType(paramIdx);
  16077. if (resolvedType == NULL)
  16078. {
  16079. AssertErrorState();
  16080. paramVar->mParamFailed = true;
  16081. }
  16082. prevIgnoreErrors.Restore();
  16083. PopulateType(resolvedType, BfPopulateType_Declaration);
  16084. paramVar->mResolvedType = resolvedType;
  16085. int namePrefixCount = 0;
  16086. methodInstance->GetParamName(paramIdx, paramVar->mName, namePrefixCount);
  16087. paramVar->mNamePrefixCount = (uint8)namePrefixCount;
  16088. paramVar->mNameNode = methodInstance->GetParamNameNode(paramIdx);
  16089. if (!isParamSkipped)
  16090. {
  16091. paramVar->mValue = mBfIRBuilder->GetArgument(argIdx);
  16092. if (resolvedType->IsMethodRef())
  16093. {
  16094. paramVar->mIsSplat = true;
  16095. }
  16096. else if ((!mIsComptimeModule) && (resolvedType->IsComposite()) && (resolvedType->IsSplattable()))
  16097. {
  16098. if (methodInstance->AllowsSplatting(paramIdx))
  16099. {
  16100. auto resolveTypeInst = resolvedType->ToTypeInstance();
  16101. if ((resolveTypeInst != NULL) && (resolveTypeInst->mIsCRepr))
  16102. paramVar->mIsSplat = true;
  16103. else
  16104. {
  16105. int splatCount = resolvedType->GetSplatCount();
  16106. if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
  16107. paramVar->mIsSplat = true;
  16108. }
  16109. }
  16110. }
  16111. }
  16112. else
  16113. {
  16114. paramVar->mIsSplat = true; // Treat skipped (valueless) as a splat
  16115. paramVar->mValue = mBfIRBuilder->GetFakeVal();
  16116. }
  16117. paramVar->mIsLowered = (!mIsComptimeModule) && resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
  16118. paramVar->mIsStruct = resolvedType->IsComposite() && !resolvedType->IsTypedPrimitive();
  16119. paramVar->mParamIdx = paramIdx;
  16120. paramVar->mIsImplicitParam = methodInstance->IsImplicitCapture(paramIdx);
  16121. paramVar->mReadFromId = 0;
  16122. if (resolvedType->IsRef())
  16123. {
  16124. auto refType = (BfRefType*)resolvedType;
  16125. paramVar->mAssignedKind = (refType->mRefKind != BfRefType::RefKind_Out) ? BfLocalVarAssignKind_Unconditional : BfLocalVarAssignKind_None;
  16126. if (refType->mRefKind == BfRefType::RefKind_In)
  16127. {
  16128. paramVar->mIsReadOnly = true;
  16129. }
  16130. }
  16131. else
  16132. {
  16133. paramVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
  16134. if (methodDef->mMethodType != BfMethodType_Mixin)
  16135. paramVar->mIsReadOnly = true;
  16136. }
  16137. if (paramVar->mResolvedType->IsGenericParam())
  16138. {
  16139. auto genericParamInst = GetGenericParamInstance((BfGenericParamType*)paramVar->mResolvedType);
  16140. if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
  16141. {
  16142. auto typedVal = GetDefaultTypedValue(genericParamInst->mTypeConstraint, false, BfDefaultValueKind_Undef);
  16143. paramVar->mResolvedType = typedVal.mType;
  16144. paramVar->mConstValue = typedVal.mValue;
  16145. }
  16146. }
  16147. if (paramVar->mResolvedType->IsConstExprValue())
  16148. {
  16149. BfConstExprValueType* constExprValueType = (BfConstExprValueType*)paramVar->mResolvedType;
  16150. auto unspecializedMethodInstance = GetUnspecializedMethodInstance(methodInstance);
  16151. auto unspecParamType = unspecializedMethodInstance->GetParamType(paramIdx);
  16152. BF_ASSERT(unspecParamType->IsGenericParam());
  16153. if (unspecParamType->IsGenericParam())
  16154. {
  16155. BfGenericParamType* genericParamType = (BfGenericParamType*)unspecParamType;
  16156. if (genericParamType->mGenericParamKind == BfGenericParamKind_Method)
  16157. {
  16158. auto genericParamInst = unspecializedMethodInstance->mMethodInfoEx->mGenericParams[genericParamType->mGenericParamIdx];
  16159. if (genericParamInst->mTypeConstraint != NULL)
  16160. {
  16161. BfExprEvaluator exprEvaluator(this);
  16162. exprEvaluator.mExpectingType = genericParamInst->mTypeConstraint;
  16163. exprEvaluator.GetLiteral(NULL, constExprValueType->mValue);
  16164. auto checkType = genericParamInst->mTypeConstraint;
  16165. if (checkType->IsTypedPrimitive())
  16166. checkType = checkType->GetUnderlyingType();
  16167. auto typedVal = exprEvaluator.mResult;
  16168. if ((typedVal) && (typedVal.mType != checkType))
  16169. typedVal = Cast(NULL, typedVal, checkType, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail));
  16170. if ((typedVal.mType == checkType) && (typedVal.mValue.IsConst()))
  16171. {
  16172. paramVar->mResolvedType = genericParamInst->mTypeConstraint;
  16173. paramVar->mConstValue = typedVal.mValue;
  16174. BF_ASSERT(paramVar->mConstValue.IsConst());
  16175. paramVar->mIsConst = true;
  16176. }
  16177. else
  16178. {
  16179. AssertErrorState();
  16180. paramVar->mResolvedType = genericParamInst->mTypeConstraint;
  16181. paramVar->mConstValue = GetDefaultValue(genericParamInst->mTypeConstraint);
  16182. paramVar->mIsConst = true;
  16183. }
  16184. if (paramVar->mResolvedType->IsObject())
  16185. {
  16186. BfTypedValue typedVal(paramVar->mConstValue, paramVar->mResolvedType);
  16187. FixValueActualization(typedVal);
  16188. if (typedVal.mValue.IsConst())
  16189. paramVar->mConstValue = typedVal.mValue;
  16190. }
  16191. }
  16192. }
  16193. }
  16194. //BF_ASSERT(!paramVar->mResolvedType->IsConstExprValue());
  16195. if (paramVar->mResolvedType->IsConstExprValue())
  16196. {
  16197. Fail("Invalid use of constant expression", methodInstance->GetParamTypeRef(paramIdx));
  16198. //AssertErrorState();
  16199. paramVar->mResolvedType = GetPrimitiveType(BfTypeCode_IntPtr);
  16200. paramVar->mConstValue = GetDefaultValue(paramVar->mResolvedType);
  16201. paramVar->mIsConst = true;
  16202. }
  16203. }
  16204. if (methodInstance->GetParamKind(paramIdx) == BfParamKind_DelegateParam)
  16205. {
  16206. if (compositeVariableIdx == -1)
  16207. {
  16208. compositeVariableIdx = (int)mCurMethodState->mLocals.size();
  16209. BfLocalVariable* localVar = new BfLocalVariable();
  16210. auto paramInst = &methodInstance->mParams[paramIdx];
  16211. auto paramDef = methodDef->mParams[paramInst->mParamDefIdx];
  16212. localVar->mName = paramDef->mName;
  16213. localVar->mNamePrefixCount = paramDef->mNamePrefixCount;
  16214. localVar->mResolvedType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam);
  16215. localVar->mCompositeCount = 0;
  16216. DoAddLocalVariable(localVar);
  16217. }
  16218. mCurMethodState->mLocals[compositeVariableIdx]->mCompositeCount++;
  16219. }
  16220. if (!mCurTypeInstance->IsDelegateOrFunction())
  16221. CheckVariableDef(paramVar);
  16222. paramVar->Init();
  16223. AddLocalVariableDef(paramVar);
  16224. if (!isParamSkipped)
  16225. {
  16226. if (wantsDIData)
  16227. diParams->push_back(mBfIRBuilder->DbgGetType(resolvedType));
  16228. if (paramVar->mIsSplat)
  16229. {
  16230. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
  16231. }
  16232. else
  16233. {
  16234. argIdx++;
  16235. }
  16236. if (loweredTypeCode2 != BfTypeCode_None)
  16237. argIdx++;
  16238. }
  16239. }
  16240. // Try to find an ending delegate params composite
  16241. if ((compositeVariableIdx == -1) && (methodDef->mParams.size() > 0))
  16242. {
  16243. auto paramDef = methodDef->mParams.back();
  16244. if (paramDef->mParamKind == BfParamKind_Params)
  16245. {
  16246. auto paramsType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_NoResolveGenericParam);
  16247. if (paramsType == NULL)
  16248. {
  16249. // Had error or 'var'
  16250. }
  16251. else if (paramsType->IsGenericParam())
  16252. {
  16253. auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)paramsType);
  16254. if (genericParamInstance->mTypeConstraint != NULL)
  16255. {
  16256. auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance();
  16257. if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) ||
  16258. ((typeInstConstraint != NULL) &&
  16259. ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)))))
  16260. {
  16261. BfLocalVariable* localVar = new BfLocalVariable();
  16262. localVar->mName = paramDef->mName;
  16263. localVar->mResolvedType = paramsType;
  16264. localVar->mCompositeCount = 0;
  16265. DoAddLocalVariable(localVar);
  16266. }
  16267. }
  16268. }
  16269. else if (paramsType->IsDelegate())
  16270. {
  16271. BfMethodInstance* invokeMethodInstance = GetRawMethodInstanceAtIdx(paramsType->ToTypeInstance(), 0, "Invoke");
  16272. if (invokeMethodInstance != NULL)
  16273. {
  16274. // This is only for the case where the delegate didn't actually have any params so the composite is zero-sized
  16275. // and wasn't cleared by the preceding loop
  16276. BF_ASSERT(invokeMethodInstance->GetParamCount() == 0);
  16277. BfLocalVariable* localVar = new BfLocalVariable();
  16278. localVar->mName = paramDef->mName;
  16279. localVar->mResolvedType = paramsType;
  16280. localVar->mCompositeCount = 0;
  16281. DoAddLocalVariable(localVar);
  16282. }
  16283. }
  16284. }
  16285. }
  16286. }
  16287. void BfModule::ProcessMethod_ProcessDeferredLocals(int startIdx)
  16288. {
  16289. // if (mCurMethodState->mPrevMethodState != NULL) // Re-entry
  16290. // return;
  16291. auto startMethodState = mCurMethodState;
  16292. auto _ClearState = [&]()
  16293. {
  16294. mCurMethodState->mLocalMethods.Clear();
  16295. for (auto& local : mCurMethodState->mLocals)
  16296. {
  16297. if (local->mIsBumpAlloc)
  16298. local->~BfLocalVariable();
  16299. else
  16300. delete local;
  16301. }
  16302. mCurMethodState->mLocals.Clear();
  16303. mCurMethodState->mLocalVarSet.Clear();
  16304. };
  16305. while (true)
  16306. {
  16307. bool didWork = false;
  16308. // Don't process local methods if we had a build error - this isn't just an optimization, it keeps us from showing the same error twice since
  16309. // we show errors in the capture phase. If we somehow pass the capture phase without error then this method WILL show any errors here,
  16310. // however (compiler bug), so this is the safest way
  16311. if (!mCurMethodState->mDeferredLocalMethods.IsEmpty())
  16312. {
  16313. for (int deferredLocalMethodIdx = 0; deferredLocalMethodIdx < (int)mCurMethodState->mDeferredLocalMethods.size(); deferredLocalMethodIdx++)
  16314. {
  16315. auto deferredLocalMethod = mCurMethodState->mDeferredLocalMethods[deferredLocalMethodIdx];
  16316. BfLogSysM("Processing deferred local method %p\n", deferredLocalMethod);
  16317. if (!mHadBuildError)
  16318. {
  16319. // Process as a closure - that allows us to look back and see the const locals and stuff
  16320. BfClosureState closureState;
  16321. mCurMethodState->mClosureState = &closureState;
  16322. closureState.mConstLocals = deferredLocalMethod->mConstLocals;
  16323. closureState.mReturnType = deferredLocalMethod->mMethodInstance->mReturnType;
  16324. closureState.mActiveDeferredLocalMethod = deferredLocalMethod;
  16325. closureState.mLocalMethod = deferredLocalMethod->mLocalMethod;
  16326. if (deferredLocalMethod->mMethodInstance->mMethodInfoEx != NULL)
  16327. closureState.mClosureInstanceInfo = deferredLocalMethod->mMethodInstance->mMethodInfoEx->mClosureInstanceInfo;
  16328. mCurMethodState->mMixinState = deferredLocalMethod->mLocalMethod->mDeclMixinState;
  16329. _ClearState();
  16330. for (auto& constLocal : deferredLocalMethod->mConstLocals)
  16331. {
  16332. auto localVar = new BfLocalVariable();
  16333. *localVar = constLocal;
  16334. DoAddLocalVariable(localVar);
  16335. }
  16336. mCurMethodState->mLocalMethods = deferredLocalMethod->mLocalMethods;
  16337. bool doProcess = !mCompiler->mCanceling;
  16338. if (doProcess)
  16339. {
  16340. BP_ZONE_F("ProcessMethod local %s", deferredLocalMethod->mMethodInstance->mMethodDef->mName.c_str());
  16341. ProcessMethod(deferredLocalMethod->mMethodInstance);
  16342. }
  16343. }
  16344. delete deferredLocalMethod;
  16345. mContext->CheckLockYield();
  16346. didWork = true;
  16347. }
  16348. mCurMethodState->mDeferredLocalMethods.Clear();
  16349. }
  16350. for (auto& kv : mCurMethodState->mLocalMethodCache)
  16351. {
  16352. BF_ASSERT((kv.mValue->mMethodDef == NULL) || (kv.mKey == kv.mValue->mMethodDef->mName));
  16353. }
  16354. if ((!mCurMethodState->mDeferredLambdaInstances.IsEmpty()) && (!mHadBuildError))
  16355. {
  16356. for (int deferredLambdaIdx = 0; deferredLambdaIdx < (int)mCurMethodState->mDeferredLambdaInstances.size(); deferredLambdaIdx++)
  16357. {
  16358. auto lambdaInstance = mCurMethodState->mDeferredLambdaInstances[deferredLambdaIdx];
  16359. BfLogSysM("Processing deferred lambdaInstance %p\n", lambdaInstance);
  16360. BfClosureState closureState;
  16361. mCurMethodState->mClosureState = &closureState;
  16362. //closureState.mConstLocals = deferredLocalMethod->mConstLocals;
  16363. closureState.mReturnType = lambdaInstance->mMethodInstance->mReturnType;
  16364. if (lambdaInstance->mClosureTypeInstance != NULL)
  16365. closureState.mClosureType = lambdaInstance->mClosureTypeInstance;
  16366. else
  16367. closureState.mClosureType = lambdaInstance->mDelegateTypeInstance;
  16368. closureState.mClosureInstanceInfo = lambdaInstance->mMethodInstance->mMethodInfoEx->mClosureInstanceInfo;
  16369. closureState.mDeclaringMethodIsMutating = lambdaInstance->mDeclaringMethodIsMutating;
  16370. mCurMethodState->mMixinState = lambdaInstance->mDeclMixinState;
  16371. _ClearState();
  16372. for (auto& constLocal : lambdaInstance->mConstLocals)
  16373. {
  16374. //if (constLocal.mIsThis)
  16375. {
  16376. // Valueless 'this'
  16377. closureState.mConstLocals.Add(constLocal);
  16378. }
  16379. /*else
  16380. {
  16381. auto localVar = new BfLocalVariable();
  16382. *localVar = constLocal;
  16383. DoAddLocalVariable(localVar);
  16384. }*/
  16385. }
  16386. BfMethodInstanceGroup methodInstanceGroup;
  16387. methodInstanceGroup.mOwner = mCurTypeInstance;
  16388. methodInstanceGroup.mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  16389. bool doProcess = !mCompiler->mCanceling;
  16390. if (doProcess)
  16391. {
  16392. BP_ZONE_F("ProcessMethod lambdaInstance %s", lambdaInstance->mMethodInstance->mMethodDef->mName.c_str());
  16393. lambdaInstance->mMethodInstance->mMethodInstanceGroup = &methodInstanceGroup;
  16394. ProcessMethod(lambdaInstance->mMethodInstance);
  16395. lambdaInstance->mMethodInstance->mMethodInstanceGroup = NULL;
  16396. if (lambdaInstance->mDtorMethodInstance != NULL)
  16397. {
  16398. lambdaInstance->mDtorMethodInstance->mMethodInstanceGroup = &methodInstanceGroup;
  16399. auto startMethodState2 = mCurMethodState;
  16400. ProcessMethod(lambdaInstance->mDtorMethodInstance);
  16401. lambdaInstance->mDtorMethodInstance->mMethodInstanceGroup = NULL;
  16402. }
  16403. }
  16404. didWork = true;
  16405. }
  16406. mContext->CheckLockYield();
  16407. mCurMethodState->mDeferredLambdaInstances.Clear();
  16408. }
  16409. if (!didWork)
  16410. break;
  16411. }
  16412. }
  16413. void BfModule::EmitGCMarkValue(BfTypedValue& thisValue, BfType* checkType, int memberDepth, int curOffset, HashSet<int>& objectOffsets, BfModuleMethodInstance markFromGCThreadMethodInstance)
  16414. {
  16415. if (checkType->IsComposite())
  16416. PopulateType(checkType, BfPopulateType_Data);
  16417. if (!checkType->WantsGCMarking())
  16418. return;
  16419. auto typeInstance = checkType->ToTypeInstance();
  16420. bool callMarkMethod = false;
  16421. // Call the actual marking method
  16422. if (memberDepth == 0)
  16423. {
  16424. // Don't call marking method on self
  16425. }
  16426. else if (checkType->IsObjectOrInterface())
  16427. {
  16428. if (!objectOffsets.Add(curOffset))
  16429. {
  16430. return;
  16431. }
  16432. callMarkMethod = true;
  16433. }
  16434. else if (checkType->IsSizedArray())
  16435. {
  16436. BfSizedArrayType* sizedArrayType = (BfSizedArrayType*)checkType;
  16437. if (sizedArrayType->mElementType->WantsGCMarking())
  16438. {
  16439. BfTypedValue arrayValue = thisValue;
  16440. if (thisValue.mType != checkType)
  16441. {
  16442. BfIRValue srcValue = thisValue.mValue;
  16443. if (curOffset != 0)
  16444. {
  16445. if (!thisValue.mType->IsPointer())
  16446. {
  16447. auto int8Type = GetPrimitiveType(BfTypeCode_UInt8);
  16448. auto int8PtrType = CreatePointerType(int8Type);
  16449. srcValue = mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(int8PtrType));
  16450. }
  16451. srcValue = mBfIRBuilder->CreateInBoundsGEP(srcValue, curOffset);
  16452. }
  16453. arrayValue = BfTypedValue(mBfIRBuilder->CreateBitCast(srcValue, mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(checkType))), checkType, BfTypedValueKind_Addr);
  16454. }
  16455. if (sizedArrayType->mElementCount > 6)
  16456. {
  16457. auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
  16458. auto itr = CreateAlloca(intPtrType);
  16459. mBfIRBuilder->CreateStore(GetDefaultValue(intPtrType), itr);
  16460. auto loopBB = mBfIRBuilder->CreateBlock("loop", true);
  16461. auto bodyBB = mBfIRBuilder->CreateBlock("body", true);
  16462. auto doneBB = mBfIRBuilder->CreateBlock("done", true);
  16463. mBfIRBuilder->CreateBr(loopBB);
  16464. mBfIRBuilder->SetInsertPoint(loopBB);
  16465. auto loadedItr = mBfIRBuilder->CreateLoad(itr);
  16466. auto cmpRes = mBfIRBuilder->CreateCmpGTE(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, (uint64)sizedArrayType->mElementCount), true);
  16467. mBfIRBuilder->CreateCondBr(cmpRes, doneBB, bodyBB);
  16468. mBfIRBuilder->SetInsertPoint(bodyBB);
  16469. auto ptrType = CreatePointerType(sizedArrayType->mElementType);
  16470. auto ptrValue = mBfIRBuilder->CreateBitCast(arrayValue.mValue, mBfIRBuilder->MapType(ptrType));
  16471. auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, loadedItr);
  16472. auto value = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
  16473. EmitGCMarkValue(value, markFromGCThreadMethodInstance);
  16474. auto incValue = mBfIRBuilder->CreateAdd(loadedItr, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, 1));
  16475. mBfIRBuilder->CreateStore(incValue, itr);
  16476. mBfIRBuilder->CreateBr(loopBB);
  16477. mBfIRBuilder->SetInsertPoint(doneBB);
  16478. }
  16479. else
  16480. {
  16481. for (int dataIdx = 0; dataIdx < sizedArrayType->mElementCount; dataIdx++)
  16482. {
  16483. auto ptrType = CreatePointerType(sizedArrayType->mElementType);
  16484. auto ptrValue = mBfIRBuilder->CreateBitCast(arrayValue.mValue, mBfIRBuilder->MapType(ptrType));
  16485. auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, dataIdx));
  16486. auto value = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
  16487. HashSet<int> objectOffsets;
  16488. EmitGCMarkValue(value, markFromGCThreadMethodInstance);
  16489. }
  16490. }
  16491. }
  16492. }
  16493. else if (typeInstance != NULL)
  16494. {
  16495. typeInstance->mTypeDef->PopulateMemberSets();
  16496. BfMemberSetEntry* entry = NULL;
  16497. BfMethodDef* methodDef = NULL;
  16498. if (typeInstance->mTypeDef->mMethodSet.TryGetWith(String(BF_METHODNAME_MARKMEMBERS), &entry))
  16499. {
  16500. methodDef = (BfMethodDef*)entry->mMemberDef;
  16501. if (methodDef->HasBody())
  16502. {
  16503. callMarkMethod = true;
  16504. }
  16505. }
  16506. }
  16507. if (callMarkMethod)
  16508. {
  16509. BfTypedValue markValue;
  16510. auto memberType = checkType;
  16511. if (memberType->IsObjectOrInterface())
  16512. memberType = mContext->mBfObjectType; // Just to avoid that extra cast for the call itself
  16513. auto memberPtrType = CreatePointerType(memberType);
  16514. if (curOffset == 0)
  16515. {
  16516. markValue = BfTypedValue(mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(memberPtrType)), memberType, true);
  16517. }
  16518. else
  16519. {
  16520. if (!thisValue.mType->IsPointer())
  16521. {
  16522. auto int8Type = GetPrimitiveType(BfTypeCode_UInt8);
  16523. auto int8PtrType = CreatePointerType(int8Type);
  16524. thisValue = BfTypedValue(mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(int8PtrType)), int8PtrType);
  16525. }
  16526. auto offsetValue = mBfIRBuilder->CreateInBoundsGEP(thisValue.mValue, curOffset);
  16527. markValue = BfTypedValue(mBfIRBuilder->CreateBitCast(offsetValue, mBfIRBuilder->MapType(memberPtrType)), memberType, true);
  16528. }
  16529. EmitGCMarkValue(markValue, markFromGCThreadMethodInstance);
  16530. return;
  16531. }
  16532. auto methodDef = mCurMethodInstance->mMethodDef;
  16533. if (checkType->IsPayloadEnum())
  16534. {
  16535. for (auto& fieldInst : typeInstance->mFieldInstances)
  16536. {
  16537. if (!fieldInst.mIsEnumPayloadCase)
  16538. continue;
  16539. auto fieldDef = fieldInst.GetFieldDef();
  16540. EmitGCMarkValue(thisValue, fieldInst.mResolvedType, memberDepth + 1, curOffset, objectOffsets, markFromGCThreadMethodInstance);
  16541. }
  16542. return;
  16543. }
  16544. if (typeInstance == NULL)
  16545. return;
  16546. for (auto& fieldInst : typeInstance->mFieldInstances)
  16547. {
  16548. auto fieldDef = fieldInst.GetFieldDef();
  16549. if (fieldDef == NULL)
  16550. continue;
  16551. if (fieldDef->mIsStatic)
  16552. continue;
  16553. if (typeInstance == mCurTypeInstance)
  16554. {
  16555. // Note: we don't do method chaining when we are marking members of members. Theoretically this means
  16556. // we may be marking member values that can never contain a value anyway, but this is benign
  16557. if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
  16558. continue;
  16559. }
  16560. EmitGCMarkValue(thisValue, fieldInst.mResolvedType, memberDepth + 1, curOffset + fieldInst.mDataOffset, objectOffsets, markFromGCThreadMethodInstance);
  16561. }
  16562. if ((typeInstance->mBaseType != NULL) && (typeInstance->mBaseType != mContext->mBfObjectType))
  16563. {
  16564. EmitGCMarkValue(thisValue, typeInstance->mBaseType, memberDepth, curOffset, objectOffsets, markFromGCThreadMethodInstance);
  16565. }
  16566. }
  16567. void BfModule::EmitGCMarkMembers()
  16568. {
  16569. auto methodDef = mCurMethodInstance->mMethodDef;
  16570. auto gcType = ResolveTypeDef(mCompiler->mGCTypeDef, BfPopulateType_DataAndMethods);
  16571. BfModuleMethodInstance markFromGCThreadMethodInstance;
  16572. if (gcType != NULL)
  16573. markFromGCThreadMethodInstance = GetMethodByName(gcType->ToTypeInstance(), "Mark", 1);
  16574. if ((markFromGCThreadMethodInstance.mMethodInstance != NULL) && (!mCurMethodInstance->mIsUnspecialized))
  16575. {
  16576. if (mCurTypeInstance->IsBoxed())
  16577. {
  16578. // This already gets filled in by the normal boxed forwarding
  16579. }
  16580. else
  16581. {
  16582. auto thisValue = GetThis();
  16583. if (thisValue.IsSplat())
  16584. {
  16585. BfIRFunction func = mCurMethodInstance->mIRFunction;
  16586. int argIdx = 0;
  16587. std::function<void(BfType*)> checkTypeLambda = [&](BfType* checkType)
  16588. {
  16589. if (checkType->IsStruct())
  16590. {
  16591. auto checkTypeInstance = checkType->ToTypeInstance();
  16592. if (checkTypeInstance->mBaseType != NULL)
  16593. checkTypeLambda(checkTypeInstance->mBaseType);
  16594. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  16595. {
  16596. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  16597. if (fieldInstance->mDataIdx >= 0)
  16598. checkTypeLambda(fieldInstance->GetResolvedType());
  16599. }
  16600. }
  16601. else if (checkType->IsMethodRef())
  16602. {
  16603. BFMODULE_FATAL(this, "Not handled");
  16604. }
  16605. else if (checkType->WantsGCMarking())
  16606. {
  16607. BfTypedValue markValue(mBfIRBuilder->GetArgument(argIdx), checkType);
  16608. EmitGCMarkValue(markValue, markFromGCThreadMethodInstance);
  16609. argIdx++;
  16610. }
  16611. };
  16612. checkTypeLambda(thisValue.mType);
  16613. }
  16614. else if (!methodDef->mIsStatic)
  16615. {
  16616. if ((mCurTypeInstance->mBaseType != NULL) && (!mCurTypeInstance->IsTypedPrimitive()) && (mCurTypeInstance->mBaseType->WantsGCMarking()))
  16617. {
  16618. BfModuleMethodInstance moduleMethodInst = GetMethodByName(mCurTypeInstance->mBaseType, BF_METHODNAME_MARKMEMBERS, 0, true);
  16619. if (moduleMethodInst)
  16620. {
  16621. auto methodBaseType = moduleMethodInst.mMethodInstance->GetOwner();
  16622. bool wantsBaseMarking = true;
  16623. if (methodBaseType == mContext->mBfObjectType)
  16624. {
  16625. wantsBaseMarking = false;
  16626. PopulateType(methodBaseType);
  16627. for (auto& fieldInstance : mContext->mBfObjectType->mFieldInstances)
  16628. {
  16629. if ((fieldInstance.GetFieldDef()->mDeclaringType->IsExtension()) &&
  16630. (fieldInstance.mResolvedType->WantsGCMarking()))
  16631. wantsBaseMarking = true;
  16632. }
  16633. }
  16634. if (wantsBaseMarking)
  16635. {
  16636. auto thisValue = GetThis();
  16637. auto baseValue = Cast(NULL, thisValue, methodBaseType, BfCastFlags_Explicit);
  16638. SizedArray<BfIRValue, 1> args;
  16639. if ((!mIsComptimeModule) && (moduleMethodInst.mMethodInstance->GetParamIsSplat(-1)))
  16640. {
  16641. BfExprEvaluator exprEvaluator(this);
  16642. exprEvaluator.SplatArgs(baseValue, args);
  16643. }
  16644. else
  16645. {
  16646. args.push_back(baseValue.mValue);
  16647. }
  16648. mBfIRBuilder->CreateCall(moduleMethodInst.mFunc, args);
  16649. }
  16650. }
  16651. }
  16652. }
  16653. if (!methodDef->mIsStatic)
  16654. {
  16655. HashSet<int> objectOffsets;
  16656. EmitGCMarkValue(thisValue, mCurTypeInstance, 0, 0, objectOffsets, markFromGCThreadMethodInstance);
  16657. }
  16658. else
  16659. {
  16660. for (auto& fieldInst : mCurTypeInstance->mFieldInstances)
  16661. {
  16662. if (thisValue.IsSplat())
  16663. break;
  16664. auto fieldDef = fieldInst.GetFieldDef();
  16665. if (fieldDef == NULL)
  16666. continue;
  16667. if (fieldInst.mIsThreadLocal)
  16668. continue;
  16669. if (fieldDef->mIsStatic == methodDef->mIsStatic)
  16670. {
  16671. // For extensions, only handle these fields in the appropriate extension
  16672. if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
  16673. continue;
  16674. if (!fieldInst.mFieldIncluded)
  16675. continue;
  16676. auto fieldType = fieldInst.mResolvedType;
  16677. auto fieldDef = fieldInst.GetFieldDef();
  16678. BfTypedValue markVal;
  16679. if (fieldDef->mIsConst)
  16680. continue;
  16681. if ((!fieldType->IsObjectOrInterface()) && (!fieldType->IsComposite()))
  16682. continue;
  16683. mBfIRBuilder->PopulateType(fieldType);
  16684. if (fieldType->IsValuelessType())
  16685. continue;
  16686. if ((fieldDef->mIsStatic) && (!fieldDef->mIsConst))
  16687. {
  16688. StringT<512> staticVarName;
  16689. BfMangler::Mangle(staticVarName, mCompiler->GetMangleKind(), &fieldInst);
  16690. if (staticVarName.StartsWith('#'))
  16691. continue;
  16692. markVal = ReferenceStaticField(&fieldInst);
  16693. }
  16694. else if (!fieldDef->mIsStatic)
  16695. {
  16696. markVal = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(thisValue.mValue, 0, fieldInst.mDataIdx/*, fieldDef->mName*/), fieldInst.mResolvedType, true);
  16697. }
  16698. if (markVal)
  16699. EmitGCMarkValue(markVal, markFromGCThreadMethodInstance);
  16700. }
  16701. }
  16702. }
  16703. if (mCurMethodInstance->mChainType == BfMethodChainType_ChainHead)
  16704. CallChainedMethods(mCurMethodInstance, false);
  16705. }
  16706. }
  16707. }
  16708. void BfModule::EmitGCFindTLSMembers()
  16709. {
  16710. auto methodDef = mCurMethodInstance->mMethodDef;
  16711. auto gcTypeInst = ResolveTypeDef(mCompiler->mGCTypeDef)->ToTypeInstance();
  16712. auto reportTLSMark = GetMethodByName(gcTypeInst, "ReportTLSMember", 2);
  16713. BF_ASSERT(reportTLSMark);
  16714. for (auto& fieldInst : mCurTypeInstance->mFieldInstances)
  16715. {
  16716. auto fieldDef = fieldInst.GetFieldDef();
  16717. if (fieldDef == NULL)
  16718. continue;
  16719. if (!fieldInst.mIsThreadLocal)
  16720. continue;
  16721. // For extensions, only handle these fields in the appropriate extension
  16722. if ((fieldDef->mDeclaringType->mTypeDeclaration != methodDef->mDeclaringType->mTypeDeclaration))
  16723. continue;
  16724. if (!fieldInst.mFieldIncluded)
  16725. continue;
  16726. if (fieldDef->mIsConst)
  16727. continue;
  16728. auto fieldType = fieldInst.mResolvedType;
  16729. if ((!fieldType->IsObjectOrInterface()) && (!fieldType->IsComposite()))
  16730. continue;
  16731. if (fieldType->IsValuelessType())
  16732. continue;
  16733. BfTypedValue markVal = ReferenceStaticField(&fieldInst);
  16734. if (markVal)
  16735. {
  16736. BfIRValue fieldRefPtr = mBfIRBuilder->CreateBitCast(markVal.mValue, mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_NullPtr)));
  16737. BfIRValue markFuncPtr = GetMarkFuncPtr(fieldType);
  16738. SizedArray<BfIRValue, 2> llvmArgs;
  16739. llvmArgs.push_back(fieldRefPtr);
  16740. llvmArgs.push_back(markFuncPtr);
  16741. mBfIRBuilder->CreateCall(reportTLSMark.mFunc, llvmArgs);
  16742. }
  16743. }
  16744. if (mCurMethodInstance->mChainType == BfMethodChainType_ChainHead)
  16745. CallChainedMethods(mCurMethodInstance, false);
  16746. }
  16747. void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup, bool forceIRWrites)
  16748. {
  16749. BP_ZONE_F("BfModule::ProcessMethod %s", BP_DYN_STR(methodInstance->mMethodDef->mName.c_str()));
  16750. if (mIsComptimeModule)
  16751. {
  16752. BF_ASSERT(!mCompiler->IsAutocomplete());
  16753. }
  16754. if (mAwaitingInitFinish)
  16755. FinishInit();
  16756. if (!methodInstance->mIsReified)
  16757. BF_ASSERT(!mIsReified);
  16758. BF_ASSERT((!methodInstance->GetOwner()->IsUnspecializedTypeVariation()) || (mIsComptimeModule));
  16759. if (methodInstance->mMethodInfoEx != NULL)
  16760. {
  16761. for (auto methodGenericArg : methodInstance->mMethodInfoEx->mMethodGenericArguments)
  16762. {
  16763. if (methodGenericArg->IsMethodRef())
  16764. {
  16765. auto methodRefType = (BfMethodRefType*)methodGenericArg;
  16766. BF_ASSERT(methodRefType->mOwnerRevision == methodRefType->mOwner->mRevision);
  16767. }
  16768. }
  16769. }
  16770. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, (mWantsIRIgnoreWrites || methodInstance->mIsUnspecialized) && (!forceIRWrites));
  16771. if ((HasCompiledOutput()) && (!mBfIRBuilder->mIgnoreWrites))
  16772. {
  16773. BF_ASSERT(!methodInstance->mIRFunction.IsFake() || (methodInstance->GetImportCallKind() != BfImportCallKind_None));
  16774. }
  16775. SetAndRestoreValue<bool> prevIsClassifying;
  16776. if (((methodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) || (methodInstance->mIsForeignMethodDef) || (methodInstance->IsSpecializedGenericMethod())) &&
  16777. (mCompiler->mResolvePassData != NULL))
  16778. {
  16779. // Don't classify on the CtorCalcAppend, just on the actual Ctor
  16780. prevIsClassifying.Init(mCompiler->mResolvePassData->mIsClassifying, false);
  16781. }
  16782. if (methodInstance->mHasBeenProcessed)
  16783. {
  16784. BfLogSysM("ProcessMethod %p HasBeenProcessed\n", methodInstance);
  16785. return;
  16786. }
  16787. if (methodInstance->mFailedConstraints)
  16788. {
  16789. // The only way this should be able to happen is if we fail our generic param check
  16790. BF_ASSERT(methodInstance->IsSpecializedGenericMethod());
  16791. BfLogSysM("Method instance marked as 'failed' at start of ProcessMethod %p\n", methodInstance);
  16792. methodInstance->mHasBeenProcessed = true;
  16793. return;
  16794. }
  16795. if (HasExecutedOutput())
  16796. {
  16797. BF_ASSERT(mIsModuleMutable);
  16798. }
  16799. BfMethodInstance* defaultMethodInstance = methodInstance->mMethodInstanceGroup->mDefault;
  16800. if (!mIsComptimeModule)
  16801. {
  16802. BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet);
  16803. if ((methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
  16804. (methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Referenced))
  16805. {
  16806. auto owningModule = methodInstance->GetOwner()->mModule;
  16807. if (owningModule->mIsScratchModule)
  16808. {
  16809. BF_ASSERT(owningModule->mOnDemandMethodCount == 0);
  16810. }
  16811. else
  16812. {
  16813. BF_ASSERT((owningModule->mOnDemandMethodCount > 0) || (!HasCompiledOutput()) || (owningModule->mExtensionCount > 0));
  16814. if (owningModule->mOnDemandMethodCount > 0)
  16815. owningModule->mOnDemandMethodCount--;
  16816. }
  16817. methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Referenced;
  16818. VerifyOnDemandMethods();
  16819. }
  16820. }
  16821. // We set mHasBeenProcessed to true immediately -- this helps avoid stack overflow during recursion for things like
  16822. // self-referencing append allocations in ctor@calcAppend
  16823. methodInstance->mHasBeenProcessed = true;
  16824. mIncompleteMethodCount--;
  16825. BF_ASSERT((mIsSpecialModule) || (mIncompleteMethodCount >= 0));
  16826. auto typeDef = methodInstance->mMethodInstanceGroup->mOwner->mTypeDef;
  16827. auto methodDef = methodInstance->mMethodDef;
  16828. auto methodDeclaration = methodDef->GetMethodDeclaration();
  16829. if ((methodDef->mHasComptime) && (!mIsComptimeModule))
  16830. mBfIRBuilder->mIgnoreWrites = true;
  16831. if ((methodInstance->mIsReified) && (methodInstance->mVirtualTableIdx != -1))
  16832. {
  16833. // If we reify a virtual method in a HotCompile then we need to make sure the type data gets written out
  16834. // so we get the new vdata for it
  16835. methodInstance->GetOwner()->mDirty = true;
  16836. }
  16837. int dependentGenericStartIdx = 0;
  16838. if ((methodDef->mIsLocalMethod) && (mCurMethodState != NULL)) // See DoMethodDeclaration for an explaination of dependentGenericStartIdx
  16839. dependentGenericStartIdx = (int)mCurMethodState->GetRootMethodState()->mMethodInstance->GetNumGenericArguments();
  16840. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
  16841. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, methodInstance->mMethodInstanceGroup->mOwner);
  16842. SetAndRestoreValue<BfFilePosition> prevFilePos(mCurFilePosition);
  16843. SetAndRestoreValue<bool> prevHadBuildError(mHadBuildError, false);
  16844. SetAndRestoreValue<bool> prevHadWarning(mHadBuildWarning, false);
  16845. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors);
  16846. SetAndRestoreValue<bool> prevIgnoreWarnings(mIgnoreWarnings, mIsComptimeModule);
  16847. if ((!mIsComptimeModule) && (methodInstance->mIsReified) &&
  16848. ((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorNoBody)))
  16849. {
  16850. mCurTypeInstance->mHasBeenInstantiated = true;
  16851. }
  16852. // Warnings are shown in the capture phase
  16853. if ((methodDef->mIsLocalMethod) || (mCurTypeInstance->IsClosure()))
  16854. mIgnoreWarnings = true;
  16855. if ((methodDeclaration == NULL) && (mCurMethodState == NULL))
  16856. UseDefaultSrcPos();
  16857. if ((mIsComptimeModule) && (methodDef->mIsStatic))
  16858. {
  16859. PopulateType(mCurTypeInstance, BfPopulateType_AllowStaticMethods);
  16860. }
  16861. else
  16862. {
  16863. // We may not actually be populated in relatively rare autocompelte cases
  16864. PopulateType(mCurTypeInstance, BfPopulateType_DataAndMethods);
  16865. mBfIRBuilder->PopulateType(mCurTypeInstance, BfIRPopulateType_Full);
  16866. }
  16867. BfAstNode* nameNode = NULL;
  16868. if (methodDeclaration != NULL)
  16869. {
  16870. nameNode = methodDeclaration->mNameNode;
  16871. if (nameNode == NULL)
  16872. {
  16873. if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
  16874. nameNode = ctorDeclaration->mThisToken;
  16875. }
  16876. }
  16877. if ((mCompiler->mResolvePassData != NULL) && (methodDeclaration != NULL) && (nameNode != NULL) &&
  16878. (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Method) &&
  16879. (methodDef->mIdx >= 0) && (!methodInstance->mIsForeignMethodDef))
  16880. {
  16881. if (methodInstance->GetExplicitInterface() == NULL)
  16882. mCompiler->mResolvePassData->HandleMethodReference(nameNode, typeDef, methodDef);
  16883. else
  16884. {
  16885. for (auto& ifaceEntry : mCurTypeInstance->mInterfaces)
  16886. {
  16887. auto ifaceInst = ifaceEntry.mInterfaceType;
  16888. int startIdx = ifaceEntry.mStartInterfaceTableIdx;
  16889. int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
  16890. if (methodInstance->GetExplicitInterface() != ifaceInst)
  16891. continue;
  16892. ifaceInst->mTypeDef->PopulateMemberSets();
  16893. BfMethodDef* nextMethod = NULL;
  16894. BfMemberSetEntry* entry = NULL;
  16895. if (ifaceInst->mTypeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  16896. nextMethod = (BfMethodDef*)entry->mMemberDef;
  16897. while (nextMethod != NULL)
  16898. {
  16899. auto checkMethod = nextMethod;
  16900. nextMethod = nextMethod->mNextWithSameName;
  16901. BfMethodInstance* implMethodInst = mCurTypeInstance->mInterfaceMethodTable[startIdx + checkMethod->mIdx].mMethodRef;
  16902. if (implMethodInst == methodInstance)
  16903. {
  16904. auto ifaceMethodDef = ifaceInst->mTypeDef->mMethods[checkMethod->mIdx];
  16905. mCompiler->mResolvePassData->HandleMethodReference(nameNode, ifaceInst->mTypeDef, ifaceMethodDef);
  16906. }
  16907. }
  16908. }
  16909. }
  16910. if (methodDef->mIsOverride)
  16911. {
  16912. for (int virtIdx = 0; virtIdx < (int)mCurTypeInstance->mVirtualMethodTable.size(); virtIdx++)
  16913. {
  16914. auto& ventry = mCurTypeInstance->mVirtualMethodTable[virtIdx];
  16915. if (ventry.mDeclaringMethod.mMethodNum == -1)
  16916. continue;
  16917. BfMethodInstance* virtMethod = ventry.mImplementingMethod;
  16918. if (virtMethod != NULL)
  16919. {
  16920. if (virtMethod == methodInstance)
  16921. {
  16922. // Is matching method
  16923. if (virtIdx < (int)mCurTypeInstance->mBaseType->mVirtualMethodTable.size())
  16924. {
  16925. auto baseType = mCurTypeInstance->mBaseType;
  16926. if (baseType != NULL)
  16927. {
  16928. while ((baseType->mBaseType != NULL) && (virtIdx < baseType->mBaseType->mVirtualMethodTableSize))
  16929. baseType = baseType->mBaseType;
  16930. BfMethodInstance* baseVirtMethod = baseType->mVirtualMethodTable[virtIdx].mImplementingMethod;
  16931. mCompiler->mResolvePassData->HandleMethodReference(nameNode, baseType->mTypeDef, baseVirtMethod->mMethodDef);
  16932. }
  16933. }
  16934. break;
  16935. }
  16936. }
  16937. }
  16938. }
  16939. }
  16940. BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d Incomplete:%d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified, mIncompleteMethodCount);
  16941. int importStrNum = -1;
  16942. auto importKind = methodInstance->GetImportKind();
  16943. if ((!mCompiler->mIsResolveOnly) &&
  16944. ((importKind == BfImportKind_Import_Static) || (importKind == BfImportKind_Import_Dynamic)))
  16945. {
  16946. if (auto customAttr = methodInstance->GetCustomAttributes()->Get(mCompiler->mImportAttributeTypeDef))
  16947. {
  16948. if (customAttr->mCtorArgs.size() == 1)
  16949. {
  16950. auto fileNameArg = customAttr->mCtorArgs[0];
  16951. auto constant = mCurTypeInstance->mConstHolder->GetConstant(fileNameArg);
  16952. if (constant != NULL)
  16953. {
  16954. if (!constant->IsNull())
  16955. importStrNum = constant->mInt32;
  16956. }
  16957. else
  16958. {
  16959. importStrNum = GetStringPoolIdx(fileNameArg, mCurTypeInstance->mConstHolder);
  16960. }
  16961. if (importStrNum != -1)
  16962. {
  16963. if (!mStringPoolRefs.Contains(importStrNum))
  16964. mStringPoolRefs.Add(importStrNum);
  16965. }
  16966. }
  16967. }
  16968. }
  16969. if (methodInstance->GetImportCallKind() != BfImportCallKind_None)
  16970. {
  16971. if (mBfIRBuilder->mIgnoreWrites)
  16972. return;
  16973. BfLogSysM("DllImportGlobalVar processing %p\n", methodInstance);
  16974. if (!methodInstance->mIRFunction)
  16975. {
  16976. BfIRValue dllImportGlobalVar = CreateDllImportGlobalVar(methodInstance, true);
  16977. methodInstance->mIRFunction = mBfIRBuilder->GetFakeVal();
  16978. BF_ASSERT(dllImportGlobalVar || methodInstance->mHasFailed);
  16979. mFuncReferences[mCurMethodInstance] = dllImportGlobalVar;
  16980. }
  16981. if (HasCompiledOutput())
  16982. {
  16983. BfDllImportEntry dllImportEntry;
  16984. dllImportEntry.mFuncVar = methodInstance->mIRFunction;
  16985. dllImportEntry.mMethodInstance = mCurMethodInstance;
  16986. mDllImportEntries.push_back(dllImportEntry);
  16987. }
  16988. return;
  16989. }
  16990. StringT<512> mangledName;
  16991. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
  16992. if (!methodInstance->mIRFunction)
  16993. {
  16994. bool isIntrinsic = false;
  16995. SetupIRFunction(methodInstance, mangledName, false, &isIntrinsic);
  16996. }
  16997. if (methodInstance->mIsIntrinsic)
  16998. return;
  16999. if (mCurTypeInstance->IsFunction())
  17000. return;
  17001. auto prevActiveFunction = mBfIRBuilder->GetActiveFunction();
  17002. mBfIRBuilder->SetActiveFunction(mCurMethodInstance->mIRFunction);
  17003. if (methodDef->mBody != NULL)
  17004. UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
  17005. else if (methodDeclaration != NULL)
  17006. UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);
  17007. else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
  17008. UpdateSrcPos(methodDef->mDeclaringType->GetRefNode(), BfSrcPosFlag_NoSetDebugLoc);
  17009. else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
  17010. UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);
  17011. if ((mCurMethodState == NULL) && (!IsInSpecializedSection())) // Only do initial classify for the 'outer' method state, not any local methods or lambdas
  17012. {
  17013. if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()))
  17014. {
  17015. if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(methodDef->mBody))
  17016. sourceClassifier->VisitChildNoRef(methodDef->mBody);
  17017. }
  17018. }
  17019. BfHotDataReferenceBuilder hotDataReferenceBuilder;
  17020. BfMethodState methodState;
  17021. if (mCurMethodState != NULL)
  17022. methodState.mClosureState = mCurMethodState->mClosureState;
  17023. if ((mCompiler->mOptions.mAllowHotSwapping) && (methodInstance->mIsReified) && (!methodInstance->mIsUnspecialized) && (!isInlineDup))
  17024. {
  17025. //BF_ASSERT(methodInstance->mHotMethod != NULL);
  17026. if (methodInstance->mHotMethod == NULL)
  17027. CheckHotMethod(methodInstance, mangledName);
  17028. methodState.mHotDataReferenceBuilder = &hotDataReferenceBuilder;
  17029. }
  17030. methodState.mPrevMethodState = mCurMethodState;
  17031. methodState.mMethodInstance = methodInstance;
  17032. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  17033. if (methodInstance->GetCustomAttributes() != NULL)
  17034. {
  17035. int typeOptionsIdx = GenerateTypeOptions(methodInstance->GetCustomAttributes(), mCurTypeInstance, false);
  17036. if (typeOptionsIdx != -1)
  17037. methodState.mMethodTypeOptions = mSystem->GetTypeOptions(typeOptionsIdx);
  17038. }
  17039. BfTypeState typeState(mCurTypeInstance);
  17040. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  17041. bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (mCurTypeInstance->IsUnspecializedTypeVariation());
  17042. BfMethodInstance* unspecializedMethodInstance = NULL;
  17043. if ((prevMethodState.mPrevVal != NULL) &&
  17044. ((methodState.mClosureState == NULL) || (methodState.mClosureState->mActiveDeferredLocalMethod == NULL)))
  17045. {
  17046. // This is 'inner' (probably a closure) - use binding from outer function
  17047. methodState.mGenericTypeBindings = prevMethodState.mPrevVal->mGenericTypeBindings;
  17048. }
  17049. else if ((methodInstance->mIsUnspecialized) ||
  17050. ((mCurTypeInstance->IsUnspecializedType()) && (!isGenericVariation)))
  17051. {
  17052. methodState.mGenericTypeBindings = &methodInstance->GetMethodInfoEx()->mGenericTypeBindings;
  17053. }
  17054. else if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
  17055. ((mCurTypeInstance->IsGenericTypeInstance()) && (!isGenericVariation || mIsComptimeModule) && (!methodInstance->mMethodDef->mIsLocalMethod) && (!methodInstance->mMethodDef->mDeclaringType->IsEmitted()))))
  17056. {
  17057. unspecializedMethodInstance = GetUnspecializedMethodInstance(methodInstance, !methodInstance->mMethodDef->mIsLocalMethod);
  17058. if ((mIsComptimeModule) && (!unspecializedMethodInstance->mHasBeenProcessed))
  17059. {
  17060. // This will have already been populated by CeMachine
  17061. methodState.mGenericTypeBindings = &methodInstance->GetMethodInfoEx()->mGenericTypeBindings;
  17062. }
  17063. else
  17064. {
  17065. BF_ASSERT(unspecializedMethodInstance != methodInstance);
  17066. if (!unspecializedMethodInstance->mHasBeenProcessed)
  17067. {
  17068. // Make sure the unspecialized method is processed so we can take its bindings
  17069. // Clear mCurMethodState so we don't think we're in a local method
  17070. SetAndRestoreValue<BfMethodState*> prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal);
  17071. if (unspecializedMethodInstance->mMethodProcessRequest == NULL)
  17072. unspecializedMethodInstance->mDeclModule->mIncompleteMethodCount++;
  17073. mContext->ProcessMethod(unspecializedMethodInstance);
  17074. }
  17075. methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings;
  17076. }
  17077. }
  17078. if (methodDef->mMethodType == BfMethodType_Operator)
  17079. {
  17080. auto operatorDef = (BfOperatorDef*) methodDef;
  17081. BfAstNode* refNode = operatorDef->mOperatorDeclaration->mOperatorToken;
  17082. auto paramErrorRefNode = refNode;
  17083. if (operatorDef->mOperatorDeclaration->mOpenParen != NULL)
  17084. paramErrorRefNode = operatorDef->mOperatorDeclaration->mOpenParen;
  17085. if ((mCurMethodInstance->GetParamCount() > 0) && (mCurMethodInstance->GetParamTypeRef(0) != NULL))
  17086. paramErrorRefNode = mCurMethodInstance->GetParamTypeRef(0);
  17087. if (operatorDef->mOperatorDeclaration->mBinOp != BfBinaryOp_None)
  17088. {
  17089. if (methodDef->mParams.size() != 2)
  17090. {
  17091. Fail("Binary operators must declare two parameters", paramErrorRefNode);
  17092. }
  17093. else
  17094. {
  17095. auto checkParam0 = mCurMethodInstance->GetParamType(0);
  17096. if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
  17097. checkParam0 = checkParam0->GetUnderlyingType();
  17098. auto checkParam1 = mCurMethodInstance->GetParamType(1);
  17099. if ((checkParam1->IsRef()) && (!checkParam1->IsOut()))
  17100. checkParam1 = checkParam1->GetUnderlyingType();
  17101. if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()) &&
  17102. (checkParam1 != mCurTypeInstance) && (!checkParam1->IsSelf()))
  17103. {
  17104. Fail("At least one of the parameters of a binary operator must be the containing type", paramErrorRefNode);
  17105. }
  17106. }
  17107. BfType* wantType = NULL;
  17108. if (operatorDef->mOperatorDeclaration->mBinOp == BfBinaryOp_Compare)
  17109. {
  17110. wantType = GetPrimitiveType(BfTypeCode_IntPtr);
  17111. }
  17112. if ((wantType != NULL) && (methodInstance->mReturnType != wantType))
  17113. Fail(StrFormat("The return type for the '%s' operator must be '%s'", BfGetOpName(operatorDef->mOperatorDeclaration->mBinOp),
  17114. TypeToString(wantType).c_str()), operatorDef->mOperatorDeclaration->mReturnType);
  17115. }
  17116. else if (operatorDef->mOperatorDeclaration->mUnaryOp != BfUnaryOp_None)
  17117. {
  17118. if (methodDef->mIsStatic)
  17119. {
  17120. if (methodDef->mParams.size() != 1)
  17121. {
  17122. Fail("Unary operators must declare one parameter", paramErrorRefNode);
  17123. }
  17124. else
  17125. {
  17126. auto checkParam0 = mCurMethodInstance->GetParamType(0);
  17127. if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
  17128. checkParam0 = checkParam0->GetUnderlyingType();
  17129. if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()))
  17130. {
  17131. Fail("The parameter of a unary operator must be the containing type", paramErrorRefNode);
  17132. }
  17133. }
  17134. if (((operatorDef->mOperatorDeclaration->mUnaryOp == BfUnaryOp_Increment) ||
  17135. (operatorDef->mOperatorDeclaration->mUnaryOp == BfUnaryOp_Decrement)) &&
  17136. (!TypeIsSubTypeOf(mCurMethodInstance->mReturnType->ToTypeInstance(), mCurTypeInstance)))
  17137. {
  17138. Fail("The return type for the '++' or '--' operator must match the parameter type or be derived from the parameter type", operatorDef->mOperatorDeclaration->mReturnType);
  17139. }
  17140. }
  17141. else
  17142. {
  17143. if (methodDef->mParams.size() != 0)
  17144. {
  17145. Fail("Non-static unary operators not declare any parameters", paramErrorRefNode);
  17146. }
  17147. if (!mCurMethodInstance->mReturnType->IsVoid())
  17148. {
  17149. Fail("The return type for non-static operator must be 'void'", operatorDef->mOperatorDeclaration->mReturnType);
  17150. }
  17151. }
  17152. }
  17153. else if (operatorDef->mOperatorDeclaration->mAssignOp != BfAssignmentOp_None)
  17154. {
  17155. if (methodDef->mParams.size() != 1)
  17156. {
  17157. Fail("Assignment operators must declare one parameter", paramErrorRefNode);
  17158. }
  17159. if (!mCurMethodInstance->mReturnType->IsVoid())
  17160. {
  17161. Fail("The return type for assignment operator must be 'void'", operatorDef->mOperatorDeclaration->mReturnType);
  17162. }
  17163. }
  17164. else // Conversion
  17165. {
  17166. if (!operatorDef->mOperatorDeclaration->mIsConvOperator)
  17167. {
  17168. if (operatorDef->mOperatorDeclaration->mReturnType != NULL)
  17169. Fail("Conversion operators must declare their target type after the 'operator' token, not before", operatorDef->mOperatorDeclaration->mReturnType);
  17170. }
  17171. if (methodDef->mParams.size() != 1)
  17172. {
  17173. auto refNode = paramErrorRefNode;
  17174. if (!operatorDef->mOperatorDeclaration->mCommas.empty())
  17175. refNode = operatorDef->mOperatorDeclaration->mCommas[0];
  17176. Fail("Conversion operators must declare one parameter", refNode);
  17177. }
  17178. else if ((methodInstance->mMethodInfoEx == NULL) ||
  17179. (methodInstance->mMethodInfoEx->mMethodGenericArguments.IsEmpty()) ||
  17180. ((methodInstance->mIsUnspecialized) && (!methodInstance->mIsUnspecializedVariation)))
  17181. {
  17182. auto checkParam0 = mCurMethodInstance->GetParamType(0);
  17183. if ((checkParam0->IsRef()) && (!checkParam0->IsOut()))
  17184. checkParam0 = checkParam0->GetUnderlyingType();
  17185. if ((checkParam0 != mCurTypeInstance) && (!checkParam0->IsSelf()) &&
  17186. (mCurMethodInstance->mReturnType != mCurTypeInstance) && (!mCurMethodInstance->mReturnType->IsSelf()))
  17187. Fail("User-defined conversion must convert to or from the enclosing type", paramErrorRefNode);
  17188. if (checkParam0 == mCurMethodInstance->mReturnType)
  17189. Fail("User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type", operatorDef->mOperatorDeclaration->mReturnType);
  17190. // On type lookup error we default to 'object', so don't do the 'base class' error if that may have
  17191. // happened here
  17192. if ((!mHadBuildError) || ((mCurMethodInstance->mReturnType != mContext->mBfObjectType) && (checkParam0 != mContext->mBfObjectType)))
  17193. {
  17194. auto isToBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, mCurMethodInstance->mReturnType->ToTypeInstance());
  17195. bool isFromBase = TypeIsSubTypeOf(mCurTypeInstance->mBaseType, checkParam0->ToTypeInstance());
  17196. if ((mCurTypeInstance->IsObject()) && (isToBase || isFromBase))
  17197. Fail("User-defined conversions to or from a base class are not allowed", paramErrorRefNode);
  17198. else if ((mCurTypeInstance->IsStruct()) && (isToBase))
  17199. Fail("User-defined conversions to a base struct are not allowed", paramErrorRefNode);
  17200. }
  17201. }
  17202. }
  17203. }
  17204. bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (!methodDef->IsEmptyPartial()) && (!mBfIRBuilder->mIgnoreWrites) && (mHasFullDebugInfo);
  17205. if (methodDef->mMethodType == BfMethodType_Mixin)
  17206. wantsDIData = false;
  17207. if (mCurTypeInstance->IsUnspecializedType())
  17208. wantsDIData = false;
  17209. if ((mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType != BfMethodType_Ctor))
  17210. wantsDIData = false;
  17211. bool wantsDIVariables = wantsDIData;
  17212. if (methodDef->mIsExtern)
  17213. wantsDIVariables = false;
  17214. SizedArray<BfIRMDNode, 8> diParams;
  17215. diParams.push_back(mBfIRBuilder->DbgGetType(methodInstance->mReturnType));
  17216. bool isThisStruct = mCurTypeInstance->IsStruct() && !mCurTypeInstance->IsTypedPrimitive();
  17217. BfType* thisType = NULL;
  17218. if (!methodDef->mIsStatic)
  17219. {
  17220. if ((methodState.mClosureState != NULL) && (methodState.mClosureState->mClosureType != NULL))
  17221. thisType = methodState.mClosureState->mClosureType;
  17222. else
  17223. thisType = mCurTypeInstance;
  17224. }
  17225. PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
  17226. ProcessMethod_SetupParams(methodInstance, thisType, wantsDIData, &diParams);
  17227. //////////////////////////////////////////////////////////////////////////
  17228. //
  17229. {
  17230. if (methodDeclaration != NULL)
  17231. UpdateSrcPos(methodDeclaration, BfSrcPosFlag_NoSetDebugLoc);
  17232. else if (methodDef->mBody != NULL)
  17233. UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
  17234. else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
  17235. UpdateSrcPos(methodDef->mDeclaringType->GetRefNode(), BfSrcPosFlag_NoSetDebugLoc);
  17236. else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
  17237. UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration, BfSrcPosFlag_NoSetDebugLoc);
  17238. }
  17239. BfIRMDNode diFunction;
  17240. if (wantsDIData)
  17241. {
  17242. BP_ZONE("BfModule::DoMethodDeclaration.DISetup");
  17243. BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParams);
  17244. int defLine = mCurFilePosition.mCurLine;
  17245. if (mDICompileUnit)
  17246. {
  17247. int flags = 0;
  17248. BfIRMDNode funcScope = mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance);
  17249. if (methodDef->mProtection == BfProtection_Public)
  17250. flags = llvm::DINode::FlagPublic;
  17251. else if (methodDef->mProtection == BfProtection_Protected)
  17252. flags = llvm::DINode::FlagProtected;
  17253. else
  17254. flags = llvm::DINode::FlagPrivate;
  17255. if (methodDef->mIsOverride)
  17256. {
  17257. //flags |= llvm::DINode::FlagVirtual;
  17258. }
  17259. else if (methodDef->mIsVirtual)
  17260. flags |= llvm::DINode::FlagIntroducedVirtual;
  17261. if ((methodDef->mIsStatic) || (methodDef->mMethodType == BfMethodType_Mixin))
  17262. flags |= llvm::DINode::FlagStaticMember;
  17263. else
  17264. {
  17265. if ((mCurTypeInstance->IsValuelessType()) ||
  17266. ((!mIsComptimeModule) && (mCurTypeInstance->IsSplattable())))
  17267. flags |= llvm::DINode::FlagStaticMember;
  17268. }
  17269. flags |= llvm::DINode::FlagPrototyped;
  17270. if (methodDef->mMethodType == BfMethodType_Ctor)
  17271. {
  17272. flags |= llvm::DINode::FlagArtificial;
  17273. }
  17274. auto llvmFunction = methodInstance->mIRFunction;
  17275. SizedArray<BfIRMDNode, 1> genericArgs;
  17276. SizedArray<BfIRValue, 1> genericConstValueArgs;
  17277. String methodName;
  17278. if (methodInstance->GetForeignType() != NULL)
  17279. {
  17280. methodName += TypeToString(methodInstance->GetForeignType());
  17281. methodName += ".";
  17282. }
  17283. if (methodInstance->GetExplicitInterface() != NULL)
  17284. {
  17285. methodName += TypeToString(methodInstance->GetExplicitInterface());
  17286. methodName += ".";
  17287. }
  17288. methodName += methodDef->mName;
  17289. if (methodInstance->GetNumGenericArguments() != 0)
  17290. {
  17291. for (auto genericArg : methodInstance->mMethodInfoEx->mMethodGenericArguments)
  17292. {
  17293. if (genericArg->IsConstExprValue())
  17294. {
  17295. BfConstExprValueType* constExprValueType = (BfConstExprValueType*)genericArg;
  17296. while (genericConstValueArgs.size() < genericArgs.size())
  17297. genericConstValueArgs.push_back(BfIRValue());
  17298. genericConstValueArgs.push_back(mBfIRBuilder->CreateConst(BfTypeCode_UInt64, constExprValueType->mValue.mUInt64));
  17299. genericArgs.push_back(mBfIRBuilder->DbgGetType(GetPrimitiveType(BfTypeCode_Int64)));
  17300. }
  17301. else
  17302. genericArgs.push_back(mBfIRBuilder->DbgGetType(genericArg));
  17303. }
  17304. methodName += "<";
  17305. for (int i = 0; i < (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size(); i++)
  17306. {
  17307. if (i > 0)
  17308. methodName += ", ";
  17309. BfType* type = methodInstance->mMethodInfoEx->mMethodGenericArguments[i];
  17310. methodName += TypeToString(type);
  17311. }
  17312. methodName += ">";
  17313. }
  17314. if ((methodName.empty()) && (methodDeclaration != NULL))
  17315. {
  17316. if (auto operatorDecl = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
  17317. {
  17318. methodName += "operator";
  17319. if (operatorDecl->mIsConvOperator)
  17320. {
  17321. methodName += " ";
  17322. methodName += TypeToString(methodInstance->mReturnType);
  17323. }
  17324. else if (operatorDecl->mOpTypeToken != NULL)
  17325. methodName += operatorDecl->mOpTypeToken->ToString();
  17326. }
  17327. }
  17328. if (methodDef->mCheckedKind == BfCheckedKind_Checked)
  17329. methodName += "$CHK";
  17330. else if (methodDef->mCheckedKind == BfCheckedKind_Unchecked)
  17331. methodName += "$UCHK";
  17332. methodState.mDIFile = mCurFilePosition.mFileInstance->mDIFile;
  17333. // diFunction = mBfIRBuilder->DbgCreateMethod(funcScope, methodName, mangledName, methodState.mDIFile,
  17334. // defLine + 1, diFuncType, false, true,
  17335. // (methodInstance->mVirtualTableIdx != -1) ? llvm::dwarf::DW_VIRTUALITY_virtual : llvm::dwarf::DW_VIRTUALITY_none,
  17336. // (methodInstance->mVirtualTableIdx != -1) ? methodInstance->DbgGetVirtualMethodNum() : 0,
  17337. // nullptr, flags, IsOptimized(), llvmFunction, genericArgs, genericConstValueArgs);
  17338. diFunction = mBfIRBuilder->DbgCreateMethod(funcScope, methodName, mangledName, methodState.mDIFile,
  17339. defLine + 1, diFuncType, false, true,
  17340. llvm::dwarf::DW_VIRTUALITY_none,
  17341. 0,
  17342. BfIRMDNode(), flags, IsOptimized(), llvmFunction, genericArgs, genericConstValueArgs);
  17343. }
  17344. else
  17345. {
  17346. methodState.mDIFile = mCurFilePosition.mFileInstance->mDIFile;
  17347. }
  17348. }
  17349. //////////////////////////////////////////////////////////////////////////
  17350. // Head and Init get rolled into Entry afterwards.
  17351. methodState.mIRFunction = methodInstance->mIRFunction;
  17352. methodState.mIRHeadBlock = mBfIRBuilder->CreateBlock("head", true);
  17353. methodState.mIRInitBlock = mBfIRBuilder->CreateBlock("init", true);
  17354. methodState.mIREntryBlock = mBfIRBuilder->CreateBlock("entry", true);
  17355. methodState.mCurScope->mDIScope = diFunction;
  17356. auto llvmEntryBlock = methodState.mIREntryBlock;
  17357. mBfIRBuilder->SetInsertPoint(llvmEntryBlock);
  17358. if (methodDef->mName == "__MALFORMED")
  17359. {
  17360. auto newBlock = mBfIRBuilder->CreateBlock("malformed", true);
  17361. mBfIRBuilder->SetInsertPoint(newBlock);
  17362. }
  17363. if (methodDef->mBody != NULL)
  17364. {
  17365. UpdateSrcPos(methodDef->mBody, BfSrcPosFlag_NoSetDebugLoc);
  17366. }
  17367. else if ((mHasFullDebugInfo) && (diFunction) && (typeDef->mTypeDeclaration != NULL))
  17368. {
  17369. // We want to be able to step into delegate invokes -- we actually step over them
  17370. if (methodDef->mName != "Invoke")
  17371. {
  17372. UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
  17373. mBfIRBuilder->DbgCreateAnnotation(diFunction, "StepOver", GetConstValue32(1));
  17374. }
  17375. }
  17376. // Clear out DebugLoc - to mark the ".addr" code as part of prologue
  17377. mBfIRBuilder->ClearDebugLocation();
  17378. bool isTypedPrimitiveFunc = mCurTypeInstance->IsTypedPrimitive() && (methodDef->mMethodType != BfMethodType_Ctor);
  17379. int irParamCount = methodInstance->GetIRFunctionParamCount(this);
  17380. if (methodInstance->GetImportKind() != BfImportKind_Import_Dynamic)
  17381. {
  17382. int localIdx = 0;
  17383. int argIdx = 0;
  17384. Array<BfIRValue> splatAddrValues;
  17385. for ( ; argIdx < irParamCount; localIdx++)
  17386. {
  17387. bool isThis = ((localIdx == 0) && (!mCurMethodInstance->mMethodDef->mIsStatic));
  17388. if ((isThis) && (thisType->IsValuelessType()))
  17389. isThis = false;
  17390. if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() == argIdx))
  17391. {
  17392. argIdx++;
  17393. if (argIdx == irParamCount)
  17394. break;
  17395. }
  17396. BfLocalVariable* paramVar = NULL;
  17397. while (true)
  17398. {
  17399. BF_ASSERT(localIdx < methodState.mLocals.size());
  17400. paramVar = methodState.mLocals[localIdx];
  17401. if ((paramVar->mCompositeCount == -1) &&
  17402. (!paramVar->mIsConst) &&
  17403. ((!paramVar->mResolvedType->IsValuelessType()) || (paramVar->mResolvedType->IsMethodRef())))
  17404. break;
  17405. localIdx++;
  17406. }
  17407. if ((isThis) && (mCurTypeInstance->IsValueType()) && (methodDef->mMethodType != BfMethodType_Ctor) && (!methodDef->HasNoThisSplat()))
  17408. {
  17409. paramVar->mIsReadOnly = true;
  17410. }
  17411. bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) ||
  17412. ((!mIsComptimeModule) && (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter)));
  17413. if (paramVar->mResolvedType->IsMethodRef())
  17414. wantsAddr = false;
  17415. // if ((methodDef->mHasAppend) && (argIdx == 1))
  17416. // {
  17417. // BF_ASSERT(paramVar->mName == "appendIdx");
  17418. // wantsAddr = true;
  17419. // }
  17420. if (paramVar->mIsSplat)
  17421. {
  17422. auto prevInsert = mBfIRBuilder->GetInsertBlock();
  17423. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  17424. BfTypeUtils::SplatIterate([&](BfType* checkType)
  17425. {
  17426. BfIRType splatIRType;
  17427. if (checkType->IsComposite())
  17428. splatIRType = mBfIRBuilder->MapType(CreatePointerType(checkType));
  17429. else
  17430. splatIRType = mBfIRBuilder->MapType(checkType);
  17431. auto allocaInst = mBfIRBuilder->CreateAlloca(splatIRType);
  17432. mBfIRBuilder->SetAllocaAlignment(allocaInst, checkType->mAlign);
  17433. if (!paramVar->mAddr)
  17434. paramVar->mAddr = allocaInst;
  17435. if (WantsLifetimes())
  17436. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(allocaInst);
  17437. splatAddrValues.push_back(allocaInst);
  17438. }, paramVar->mResolvedType);
  17439. mBfIRBuilder->SetInsertPoint(prevInsert);
  17440. }
  17441. else if (isThis)
  17442. {
  17443. if (wantsAddr)
  17444. {
  17445. auto prevInsert = mBfIRBuilder->GetInsertBlock();
  17446. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  17447. BfIRType thisAddrType = mBfIRBuilder->MapType(thisType);
  17448. if (paramVar->mIsSplat)
  17449. {
  17450. //
  17451. }
  17452. else
  17453. {
  17454. bool wantPtr = (thisType->IsComposite()) && (!paramVar->mIsLowered);
  17455. if ((thisType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
  17456. wantPtr = true;
  17457. if (wantPtr)
  17458. {
  17459. thisAddrType = mBfIRBuilder->MapTypeInstPtr(thisType->ToTypeInstance());
  17460. }
  17461. auto allocaInst = mBfIRBuilder->CreateAlloca(thisAddrType);
  17462. mBfIRBuilder->SetName(allocaInst, paramVar->mName + ".addr");
  17463. mBfIRBuilder->SetAllocaAlignment(allocaInst, mSystem->mPtrSize);
  17464. paramVar->mAddr = allocaInst;
  17465. if (WantsLifetimes())
  17466. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(allocaInst);
  17467. }
  17468. mBfIRBuilder->SetInsertPoint(prevInsert);
  17469. }
  17470. }
  17471. else if ((!isThis) && ((paramVar->mIsStruct) || (paramVar->mResolvedType->IsRef())))
  17472. {
  17473. // Address doesn't change so we don't have to alloca it
  17474. BfIRType allocType;
  17475. int alignSize = mSystem->mPtrSize;
  17476. if (paramVar->mResolvedType->IsRef())
  17477. {
  17478. allocType = mBfIRBuilder->MapType(paramVar->mResolvedType);
  17479. }
  17480. else if ((paramVar->mIsSplat) || (paramVar->mIsLowered))
  17481. {
  17482. allocType = mBfIRBuilder->MapType(paramVar->mResolvedType);
  17483. alignSize = paramVar->mResolvedType->mAlign;
  17484. }
  17485. else
  17486. {
  17487. paramVar->mHasLocalStructBacking = true;
  17488. auto typeInst = paramVar->mResolvedType->ToTypeInstance();
  17489. if (typeInst != NULL)
  17490. allocType = mBfIRBuilder->MapTypeInstPtr(paramVar->mResolvedType->ToTypeInstance());
  17491. else
  17492. allocType = mBfIRBuilder->MapType(CreatePointerType(paramVar->mResolvedType));
  17493. }
  17494. if (wantsAddr)
  17495. {
  17496. auto prevInsert = mBfIRBuilder->GetInsertBlock();
  17497. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRHeadBlock);
  17498. mBfIRBuilder->PopulateType(paramVar->mResolvedType);
  17499. auto allocaInst = mBfIRBuilder->CreateAlloca(allocType);
  17500. mBfIRBuilder->SetName(allocaInst, paramVar->mName + ".addr");
  17501. mBfIRBuilder->SetAllocaAlignment(allocaInst, alignSize);
  17502. paramVar->mAddr = allocaInst;
  17503. mBfIRBuilder->SetInsertPoint(prevInsert);
  17504. if (WantsLifetimes())
  17505. mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(allocaInst);
  17506. }
  17507. }
  17508. else if (wantsAddr)
  17509. {
  17510. auto allocaInst = CreateAlloca(paramVar->mResolvedType);
  17511. mBfIRBuilder->SetName(allocaInst, paramVar->mName + ".addr");
  17512. paramVar->mAddr = allocaInst;
  17513. }
  17514. if (paramVar->mIsSplat)
  17515. {
  17516. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
  17517. }
  17518. else if (paramVar->mIsLowered)
  17519. {
  17520. BfTypeCode loweredTypeCode = BfTypeCode_None;
  17521. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  17522. paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
  17523. argIdx++;
  17524. if (loweredTypeCode2 != BfTypeCode_None)
  17525. argIdx++;
  17526. }
  17527. else
  17528. {
  17529. argIdx++;
  17530. }
  17531. }
  17532. if (methodDef->mBody != NULL)
  17533. UpdateSrcPos(methodDef->mBody);
  17534. else if ((methodDef->mDeclaringType != NULL) && (methodDef->mDeclaringType->GetRefNode() != NULL))
  17535. UpdateSrcPos(methodDef->mDeclaringType->GetRefNode());
  17536. else if (mCurTypeInstance->mTypeDef->mTypeDeclaration != NULL)
  17537. UpdateSrcPos(mCurTypeInstance->mTypeDef->mTypeDeclaration);
  17538. localIdx = 0;
  17539. argIdx = 0;
  17540. int splatAddrIdx = 0;
  17541. while (localIdx < (int)methodState.mLocals.size())
  17542. {
  17543. if ((!mIsComptimeModule) && (argIdx == methodInstance->GetStructRetIdx()))
  17544. argIdx++;
  17545. int curLocalIdx = localIdx++;
  17546. BfLocalVariable* paramVar = methodState.mLocals[curLocalIdx];
  17547. if (paramVar->mIsConst)
  17548. continue;
  17549. if (!paramVar->IsParam())
  17550. continue;
  17551. if (paramVar->mCompositeCount != -1)
  17552. continue;
  17553. bool isThis = ((curLocalIdx == 0) && (!mCurMethodInstance->mMethodDef->mIsStatic));
  17554. if ((isThis) && (thisType->IsValuelessType()))
  17555. isThis = false;
  17556. if (paramVar->mValue.IsArg())
  17557. BF_ASSERT(paramVar->mValue.mId == argIdx);
  17558. BfIRMDNode diVariable;
  17559. if (wantsDIData)
  17560. {
  17561. String paramName = paramVar->mName;
  17562. BfIRMDNode diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
  17563. if (isThis)
  17564. {
  17565. if ((mCurMethodState->mClosureState != NULL) && (mCurMethodState->mClosureState->mClosureType != NULL))
  17566. paramName = "__closure";
  17567. if ((paramVar->mResolvedType->IsValueType()) && (!paramVar->mIsSplat) && (!paramVar->mIsLowered))
  17568. {
  17569. diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
  17570. bool wantRef = paramVar->mResolvedType->IsComposite();
  17571. if ((paramVar->mResolvedType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
  17572. wantRef = true;
  17573. if (wantRef)
  17574. diType = mBfIRBuilder->DbgCreateReferenceType(diType);
  17575. }
  17576. else if (!paramVar->mResolvedType->IsValueType())
  17577. {
  17578. diType = mBfIRBuilder->DbgCreateArtificialType(diType);
  17579. }
  17580. }
  17581. else
  17582. {
  17583. if ((paramVar->mResolvedType->IsComposite()) && (!paramVar->mIsSplat) && (!paramVar->mIsLowered))
  17584. {
  17585. diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
  17586. diType = mBfIRBuilder->DbgCreateReferenceType(diType);
  17587. diType = mBfIRBuilder->DbgCreateConstType(diType);
  17588. }
  17589. }
  17590. if (!paramVar->mIsSplat)
  17591. {
  17592. if ((paramVar->mParamIdx >= 0) && (paramVar->mParamIdx < methodInstance->mDefaultValues.mSize))
  17593. {
  17594. auto defaultValue = methodInstance->mDefaultValues[paramVar->mParamIdx];
  17595. auto constant = mCurTypeInstance->mConstHolder->GetConstant(defaultValue.mValue);
  17596. if ((constant != NULL) &&
  17597. ((BfIRConstHolder::IsIntable(constant->mTypeCode)) || (BfIRConstHolder::IsFloat(constant->mTypeCode))))
  17598. {
  17599. int64 writeVal = constant->mInt64;
  17600. if (constant->mTypeCode == BfTypeCode_Float)
  17601. {
  17602. // We need to do this because Singles are stored in mDouble, so we need to reduce here
  17603. float floatVal = (float)constant->mDouble;
  17604. writeVal = *(uint32*)&floatVal;
  17605. }
  17606. if (writeVal < 0)
  17607. paramName += StrFormat("$_%llu", -writeVal);
  17608. else
  17609. paramName += StrFormat("$%llu", writeVal);
  17610. }
  17611. }
  17612. if (paramVar->mResolvedType->IsValuelessType())
  17613. {
  17614. diVariable = mBfIRBuilder->DbgCreateAutoVariable(diFunction,
  17615. paramName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
  17616. }
  17617. else if (paramVar->mIsImplicitParam)
  17618. {
  17619. // Annotate this specially?
  17620. diVariable = mBfIRBuilder->DbgCreateParameterVariable(diFunction,
  17621. paramName, argIdx + 1, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType, true, 0);
  17622. }
  17623. else
  17624. {
  17625. diVariable = mBfIRBuilder->DbgCreateParameterVariable(diFunction,
  17626. paramName, argIdx + 1, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType, true, 0);
  17627. }
  17628. paramVar->mDbgVarInst = diVariable;
  17629. }
  17630. else if ((paramVar->mIsSplat) && (paramVar->mResolvedType->GetSplatCount() == 0))
  17631. {
  17632. // if ((mBfIRBuilder->HasDebugLocation()) && (wantsDIVariables))
  17633. // {
  17634. // // Only add this placeholder if we don't have any values
  17635. // auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  17636. // paramName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
  17637. // mBfIRBuilder->DbgInsertValueIntrinsic(GetConstValue(0), diVariable);
  17638. // }
  17639. }
  17640. }
  17641. bool isTypedPrimCtor = mCurTypeInstance->IsTypedPrimitive() && (methodDef->mMethodType == BfMethodType_Ctor);
  17642. if ((!paramVar->mParamFailed) && (paramVar->mAddr))
  17643. {
  17644. // Write our argument value into the .addr
  17645. mBfIRBuilder->ClearDebugLocation();
  17646. if (paramVar->mIsSplat)
  17647. {
  17648. mBfIRBuilder->PopulateType(paramVar->mResolvedType);
  17649. //
  17650. }
  17651. else
  17652. {
  17653. bool handled = false;
  17654. if (paramVar->mIsLowered)
  17655. {
  17656. BfTypeCode loweredTypeCode = BfTypeCode_None;
  17657. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  17658. if (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2))
  17659. {
  17660. BfIRValue targetAddr = paramVar->mAddr;
  17661. bool isTempTarget = false;
  17662. int loweredSize = mBfIRBuilder->GetSize(loweredTypeCode) + mBfIRBuilder->GetSize(loweredTypeCode2);
  17663. if (paramVar->mResolvedType->mSize < loweredSize)
  17664. {
  17665. isTempTarget = true;
  17666. targetAddr = CreateAlloca(GetPrimitiveType(BfTypeCode_Int8), true, NULL, GetConstValue(loweredSize));
  17667. mBfIRBuilder->SetAllocaAlignment(targetAddr,
  17668. BF_MAX(paramVar->mResolvedType->mAlign,
  17669. BF_MAX(mBfIRBuilder->GetSize(loweredTypeCode), mBfIRBuilder->GetSize(loweredTypeCode2))));
  17670. }
  17671. // We have a lowered type coming in, so we have to cast the .addr before storing
  17672. auto primType = mBfIRBuilder->GetPrimitiveType(loweredTypeCode);
  17673. auto primPtrType = mBfIRBuilder->GetPointerTo(primType);
  17674. auto primPtrVal = mBfIRBuilder->CreateBitCast(targetAddr, primPtrType);
  17675. mBfIRBuilder->CreateAlignedStore(paramVar->mValue, primPtrVal, mCurTypeInstance->mAlign);
  17676. if (loweredTypeCode2 != BfTypeCode_None)
  17677. {
  17678. auto primType2 = mBfIRBuilder->GetPrimitiveType(loweredTypeCode2);
  17679. auto primPtrType2 = mBfIRBuilder->GetPointerTo(primType2);
  17680. BfIRValue primPtrVal2;
  17681. if (mBfIRBuilder->GetSize(loweredTypeCode) < mBfIRBuilder->GetSize(loweredTypeCode2))
  17682. primPtrVal2 = mBfIRBuilder->CreateInBoundsGEP(mBfIRBuilder->CreateBitCast(primPtrVal, primPtrType2), 1);
  17683. else
  17684. primPtrVal2 = mBfIRBuilder->CreateBitCast(mBfIRBuilder->CreateInBoundsGEP(primPtrVal, 1), primPtrType2);
  17685. mBfIRBuilder->CreateStore(mBfIRBuilder->GetArgument(argIdx + 1), primPtrVal2);
  17686. }
  17687. if (isTempTarget)
  17688. {
  17689. auto castedTempPtr = mBfIRBuilder->CreateBitCast(targetAddr, mBfIRBuilder->MapType(CreatePointerType(paramVar->mResolvedType)));
  17690. auto tempVal = mBfIRBuilder->CreateAlignedLoad(castedTempPtr, paramVar->mResolvedType->mAlign);
  17691. mBfIRBuilder->CreateAlignedStore(tempVal, paramVar->mAddr, paramVar->mResolvedType->mAlign);
  17692. }
  17693. // We don't want to allow directly using value
  17694. paramVar->mValue = BfIRValue();
  17695. handled = true;
  17696. }
  17697. else
  17698. {
  17699. BF_ASSERT("Expected lowered");
  17700. }
  17701. }
  17702. if (!handled)
  17703. mBfIRBuilder->CreateAlignedStore(paramVar->mValue, paramVar->mAddr, paramVar->mResolvedType->mAlign);
  17704. }
  17705. }
  17706. if (methodDef->mBody != NULL)
  17707. UpdateSrcPos(methodDef->mBody);
  17708. else if (methodDef->mDeclaringType->mTypeDeclaration != NULL)
  17709. UpdateSrcPos(methodDef->mDeclaringType->mTypeDeclaration);
  17710. else if (methodDeclaration == NULL)
  17711. UseDefaultSrcPos();
  17712. // Write our argument value into the .addr
  17713. if (paramVar->mIsSplat)
  17714. {
  17715. int splatComponentIdx = 0;
  17716. auto curArgIdx = argIdx;
  17717. auto _FinishSplats = [&] (BfType* checkType, const StringImpl& name)
  17718. {
  17719. BfIRValue splatAddrValue = splatAddrValues[splatAddrIdx++];
  17720. methodState.mSplatDecompAddrs.push_back(splatAddrValue);
  17721. auto storeInst = mBfIRBuilder->CreateAlignedStore(mBfIRBuilder->GetArgument(curArgIdx), splatAddrValue, checkType->mAlign);
  17722. mBfIRBuilder->ClearDebugLocation(storeInst);
  17723. if (wantsDIData)
  17724. {
  17725. BfIRMDNode diType;
  17726. if (checkType->IsComposite())
  17727. diType = mBfIRBuilder->DbgGetType(CreateRefType(checkType));
  17728. else
  17729. diType = mBfIRBuilder->DbgGetType(checkType);
  17730. auto diVariable = mBfIRBuilder->DbgCreateParameterVariable(diFunction,
  17731. name, curArgIdx + 1, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
  17732. if (wantsDIVariables)
  17733. {
  17734. mBfIRBuilder->DbgInsertDeclare(splatAddrValue, diVariable);
  17735. }
  17736. }
  17737. curArgIdx++;
  17738. splatComponentIdx++;
  17739. };
  17740. std::function<void(BfType*, const StringImpl&)> _FinishSplatsIterate = [&](BfType* checkType, const StringImpl& name)
  17741. {
  17742. if (checkType->IsStruct())
  17743. {
  17744. auto checkTypeInstance = checkType->ToTypeInstance();
  17745. if (checkTypeInstance->mBaseType != NULL)
  17746. {
  17747. _FinishSplatsIterate(checkTypeInstance->mBaseType, name + "$b");
  17748. }
  17749. if (checkTypeInstance->mIsUnion)
  17750. {
  17751. auto unionInnerType = checkTypeInstance->GetUnionInnerType();
  17752. if (!unionInnerType->IsValuelessType())
  17753. {
  17754. _FinishSplatsIterate(unionInnerType, name + "$u");
  17755. }
  17756. if (checkTypeInstance->IsEnum())
  17757. {
  17758. auto dscrType = checkTypeInstance->GetDiscriminatorType();
  17759. _FinishSplatsIterate(dscrType, name + "$d");
  17760. }
  17761. }
  17762. else
  17763. {
  17764. for (int fieldIdx = 0; fieldIdx < (int)checkTypeInstance->mFieldInstances.size(); fieldIdx++)
  17765. {
  17766. auto fieldInstance = (BfFieldInstance*)&checkTypeInstance->mFieldInstances[fieldIdx];
  17767. auto fieldDef = fieldInstance->GetFieldDef();
  17768. if (fieldInstance->mDataIdx >= 0)
  17769. {
  17770. _FinishSplatsIterate(fieldInstance->GetResolvedType(), name + "$m$" + fieldDef->mName);
  17771. }
  17772. }
  17773. }
  17774. }
  17775. else if (checkType->IsMethodRef())
  17776. {
  17777. auto methodRefType = (BfMethodRefType*)checkType;
  17778. BfMethodInstance* methodInstance = methodRefType->mMethodRef;
  17779. // int implicitParamCount = methodInstance->GetImplicitParamCount();
  17780. // for (int implicitParamIdx = methodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
  17781. // {
  17782. // auto paramType = methodInstance->GetParamType(implicitParamIdx);
  17783. // if (!paramType->IsValuelessType())
  17784. // _FinishSplats(paramType, name + "$m$" + methodInstance->GetParamName(implicitParamIdx));
  17785. // }
  17786. for (int dataIdx = 0; dataIdx < methodRefType->GetCaptureDataCount(); dataIdx++)
  17787. {
  17788. int paramIdx = methodRefType->GetParamIdxFromDataIdx(dataIdx);
  17789. String paramName = methodInstance->GetParamName(paramIdx);
  17790. if (paramName == "this")
  17791. paramName = "__this";
  17792. if (methodRefType->WantsDataPassedAsSplat(dataIdx))
  17793. {
  17794. _FinishSplatsIterate(methodRefType->GetCaptureType(dataIdx), name + "$m$" + paramName);
  17795. }
  17796. else
  17797. {
  17798. _FinishSplats(methodRefType->GetCaptureType(dataIdx), name + "$m$" + paramName);
  17799. }
  17800. }
  17801. }
  17802. else if (!checkType->IsValuelessType())
  17803. {
  17804. _FinishSplats(checkType, name);
  17805. }
  17806. };
  17807. mBfIRBuilder->PopulateType(paramVar->mResolvedType);
  17808. if (!paramVar->mConstValue)
  17809. _FinishSplatsIterate(paramVar->mResolvedType, "$" + paramVar->mName);
  17810. }
  17811. BfIRValue declareCall;
  17812. if (diVariable)
  17813. {
  17814. if ((mBfIRBuilder->HasDebugLocation()) && (wantsDIVariables))
  17815. {
  17816. if (!paramVar->mAddr)
  17817. {
  17818. if ((!paramVar->mValue) || (paramVar->mValue.IsFake()))
  17819. {
  17820. if ((!paramVar->mIsThis) && (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU)) // DWARF chokes on this:
  17821. {
  17822. // We don't need to set the location for this
  17823. mBfIRBuilder->DbgInsertValueIntrinsic(BfIRValue(), diVariable);
  17824. }
  17825. }
  17826. else
  17827. declareCall = mBfIRBuilder->DbgInsertDeclare(paramVar->mValue, diVariable);
  17828. }
  17829. else
  17830. {
  17831. declareCall = mBfIRBuilder->DbgInsertDeclare(paramVar->mAddr, diVariable);
  17832. }
  17833. }
  17834. }
  17835. if ((isThis) && (!paramVar->mIsSplat) && (paramVar->mAddr))
  17836. {
  17837. // We don't allow actually assignment to "this", so we just do a single load
  17838. // Keep in mind we don't use the ACTUAL mValue value because that's a register, but
  17839. // we need to store it in the stack frame for debugging purposes
  17840. auto loadedThis = mBfIRBuilder->CreateAlignedLoad(paramVar->mAddr/*, "this"*/, paramVar->mResolvedType->mAlign);
  17841. mBfIRBuilder->ClearDebugLocation(loadedThis);
  17842. paramVar->mValue = loadedThis;
  17843. }
  17844. if ((wantsDIData) && (declareCall))
  17845. mBfIRBuilder->UpdateDebugLocation(declareCall);
  17846. if (paramVar->mIsSplat)
  17847. {
  17848. BfTypeUtils::SplatIterate([&](BfType* checkType) { argIdx++; }, paramVar->mResolvedType);
  17849. }
  17850. else if (paramVar->mIsLowered)
  17851. {
  17852. argIdx++;
  17853. BfTypeCode loweredTypeCode = BfTypeCode_None;
  17854. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  17855. paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
  17856. if (loweredTypeCode2 != BfTypeCode_None)
  17857. argIdx++;
  17858. }
  17859. else if (!paramVar->mResolvedType->IsValuelessType())
  17860. {
  17861. argIdx++;
  17862. }
  17863. }
  17864. if (wantsDIData)
  17865. {
  17866. BF_ASSERT(splatAddrIdx == (int)splatAddrValues.size());
  17867. }
  17868. }
  17869. for (int varIdx = 0; varIdx < (int)mCurMethodState->mLocals.size(); varIdx++)
  17870. {
  17871. auto paramVar = mCurMethodState->mLocals[varIdx];
  17872. // We don't need this because the debug func type records the type of the splat param, and then the same can be inferred from the first
  17873. // splat member. If the "splat" is valueless then we do create a placeholder, but further up in this method
  17874. // if (paramVar->mIsSplat)
  17875. // {
  17876. // if (wantsDIVariables)
  17877. // {
  17878. // auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(diFunction, paramVar->mName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(paramVar->mResolvedType));
  17879. // mBfIRBuilder->DbgInsertValueIntrinsic(mBfIRBuilder->CreateConst(BfTypeCode_Int64, 0), diVariable);
  17880. // }
  17881. // }
  17882. if (paramVar->mResolvedType->IsValuelessType())
  17883. {
  17884. if ((mBfIRBuilder->HasDebugLocation()) && (wantsDIVariables) && (mCompiler->mOptions.mToolsetType != BfToolsetType_GNU)) // DWARF chokes on this:
  17885. {
  17886. // Only add this placeholder if we don't have any values
  17887. auto diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
  17888. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
  17889. paramVar->mName, mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, diType);
  17890. mBfIRBuilder->DbgInsertValueIntrinsic(BfIRValue(), diVariable);
  17891. }
  17892. }
  17893. }
  17894. if (IsTargetingBeefBackend())
  17895. mCurMethodState->mCurScope->mValueScopeStart = mBfIRBuilder->CreateValueScopeStart();
  17896. if (methodState.mClosureState != NULL)
  17897. {
  17898. for (auto& constLocal : methodState.mClosureState->mConstLocals)
  17899. {
  17900. BfLocalVariable* localVar = new BfLocalVariable();
  17901. *localVar = constLocal;
  17902. localVar->mIsBumpAlloc = false;
  17903. AddLocalVariableDef(localVar, true);
  17904. }
  17905. }
  17906. bool wantsRemoveBody = false;
  17907. bool skipBody = false;
  17908. bool skipUpdateSrcPos = false;
  17909. bool skipEndChecks = false;
  17910. bool hasExternSpecifier = (methodDeclaration != NULL) && (methodDeclaration->mExternSpecifier != NULL) && (methodInstance->GetImportKind() != BfImportKind_Import_Dynamic);
  17911. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  17912. if ((methodDef != NULL) && (propertyDeclaration != NULL) && (propertyDeclaration->mExternSpecifier != NULL))
  17913. hasExternSpecifier = true;
  17914. // Allocate, clear, set classVData
  17915. if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic))
  17916. {
  17917. CreateStaticCtor();
  17918. }
  17919. else if ((mCurTypeInstance->IsBoxed()) && (methodDef->mMethodType != BfMethodType_Ctor) && (methodDef->mName != BF_METHODNAME_DYNAMICCAST) && (methodDef->mName != BF_METHODNAME_DYNAMICCAST_INTERFACE))
  17920. {
  17921. skipBody = true;
  17922. skipEndChecks = true;
  17923. if (HasExecutedOutput())
  17924. {
  17925. // Clear out DebugLoc - to mark the ".addr" code as part of prologue
  17926. mBfIRBuilder->ClearDebugLocation();
  17927. BfBoxedType* boxedType = (BfBoxedType*) mCurTypeInstance;
  17928. BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
  17929. PopulateType(innerType, BfPopulateType_DataAndMethods);
  17930. mBfIRBuilder->PopulateType(mCurTypeInstance);
  17931. BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None;
  17932. if (methodInstance->mIsForeignMethodDef)
  17933. {
  17934. flags = BfGetMethodInstanceFlag_ForeignMethodDef;
  17935. }
  17936. BfTypeVector methodGenericArguments;
  17937. if (methodInstance->mMethodInfoEx != NULL)
  17938. methodGenericArguments = methodInstance->mMethodInfoEx->mMethodGenericArguments;
  17939. auto innerMethodInstance = GetMethodInstance(innerType, methodDef, methodGenericArguments, flags, methodInstance->GetForeignType());
  17940. if (innerMethodInstance.mMethodInstance->IsSkipCall())
  17941. {
  17942. if (!methodInstance->mReturnType->IsValuelessType())
  17943. {
  17944. auto retVal = GetDefaultValue(methodInstance->mReturnType);
  17945. CreateReturn(retVal);
  17946. }
  17947. else
  17948. mBfIRBuilder->CreateRetVoid();
  17949. }
  17950. else
  17951. {
  17952. auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef;
  17953. BF_ASSERT(innerMethodDef == methodDef);
  17954. SizedArray<BfIRValue, 8> innerParams;
  17955. BfExprEvaluator exprEvaluator(this);
  17956. if (!innerType->IsValuelessType())
  17957. {
  17958. BfIRValue thisValue = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, 1);
  17959. BfTypedValue innerVal(thisValue, innerType, true);
  17960. if (boxedType->IsBoxedStructPtr())
  17961. {
  17962. innerVal = LoadValue(innerVal);
  17963. innerVal = BfTypedValue(innerVal.mValue, innerType, true);
  17964. }
  17965. exprEvaluator.PushThis(NULL, innerVal, innerMethodInstance.mMethodInstance, innerParams);
  17966. }
  17967. for (int i = 1; i < (int)mCurMethodState->mLocals.size(); i++)
  17968. {
  17969. BfLocalVariable* localVar = mCurMethodState->mLocals[i];
  17970. BfTypedValue localVal = exprEvaluator.LoadLocal(localVar, true);
  17971. exprEvaluator.PushArg(localVal, innerParams);
  17972. }
  17973. if (!innerMethodInstance.mFunc)
  17974. {
  17975. BF_ASSERT(innerType->IsUnspecializedType());
  17976. }
  17977. else if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() != -1))
  17978. {
  17979. mBfIRBuilder->PopulateType(methodInstance->mReturnType);
  17980. auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
  17981. exprEvaluator.mReceivingValue = &returnType;
  17982. auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, BfCreateCallFlags_TailCall);
  17983. BF_ASSERT(exprEvaluator.mReceivingValue == NULL); // Ensure it was actually used
  17984. mBfIRBuilder->CreateRetVoid();
  17985. }
  17986. else
  17987. {
  17988. mBfIRBuilder->PopulateType(methodInstance->mReturnType);
  17989. auto retVal = exprEvaluator.CreateCall(NULL, innerMethodInstance.mMethodInstance, innerMethodInstance.mFunc, true, innerParams, NULL, BfCreateCallFlags_TailCall);
  17990. if (mCurMethodInstance->mReturnType->IsValueType())
  17991. retVal = LoadValue(retVal);
  17992. CreateReturn(retVal.mValue);
  17993. }
  17994. }
  17995. }
  17996. mCurMethodState->SetHadReturn(true);
  17997. mCurMethodState->mLeftBlockUncond = true;
  17998. }
  17999. else if (methodDef->mMethodType == BfMethodType_CtorClear)
  18000. {
  18001. SetIllegalSrcPos();
  18002. mBfIRBuilder->ClearDebugLocation();
  18003. PopulateType(mCurTypeInstance, BfPopulateType_Data);
  18004. auto thisVal = GetThis();
  18005. int prevSize = 0;
  18006. if (mContext->mBfObjectType != NULL)
  18007. {
  18008. prevSize = mContext->mBfObjectType->mInstSize;
  18009. PopulateType(mContext->mBfObjectType);
  18010. // If we have object extensions, clear out starting at the extension
  18011. for (auto& fieldInstance : mContext->mBfObjectType->mFieldInstances)
  18012. {
  18013. if (fieldInstance.GetFieldDef()->mDeclaringType->IsExtension())
  18014. {
  18015. prevSize = fieldInstance.mDataOffset;
  18016. break;
  18017. }
  18018. }
  18019. }
  18020. int curSize = mCurTypeInstance->mInstSize;
  18021. if (curSize > prevSize)
  18022. {
  18023. auto int8PtrType = CreatePointerType(GetPrimitiveType(BfTypeCode_Int8));
  18024. auto int8PtrVal = mBfIRBuilder->CreateBitCast(thisVal.mValue, mBfIRBuilder->MapType(int8PtrType));
  18025. int8PtrVal = mBfIRBuilder->CreateInBoundsGEP(int8PtrVal, GetConstValue(prevSize));
  18026. mBfIRBuilder->CreateMemSet(int8PtrVal, GetConstValue8(0), GetConstValue(curSize - prevSize), GetConstValue(mCurTypeInstance->mInstAlign));
  18027. }
  18028. skipUpdateSrcPos = true;
  18029. }
  18030. else if (((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorNoBody)) && (!hasExternSpecifier))
  18031. {
  18032. EmitCtorBody(skipBody);
  18033. }
  18034. else if ((methodDef->mMethodType == BfMethodType_Dtor) && (!hasExternSpecifier))
  18035. {
  18036. EmitDtorBody();
  18037. skipBody = true;
  18038. }
  18039. if ((!mCurTypeInstance->IsBoxed()) && (methodDeclaration != NULL) && (methodDeclaration->mHadYield) && (methodDef->mBody != NULL))
  18040. {
  18041. EmitIteratorBlock(skipBody);
  18042. }
  18043. if (methodDef->mName == BF_METHODNAME_MARKMEMBERS)
  18044. {
  18045. // We need to be able to mark deleted objects
  18046. mCurMethodState->mIgnoreObjectAccessCheck = true;
  18047. }
  18048. auto customAttributes = methodInstance->GetCustomAttributes();
  18049. if (customAttributes != NULL)
  18050. {
  18051. if (customAttributes->Contains(mCompiler->mDisableObjectAccessChecksAttributeTypeDef))
  18052. mCurMethodState->mIgnoreObjectAccessCheck = true;
  18053. if (customAttributes->Contains(mCompiler->mDisableChecksAttributeTypeDef))
  18054. mCurMethodState->mDisableChecks = true;
  18055. }
  18056. if ((methodDef->mMethodType == BfMethodType_CtorNoBody) && (!methodDef->mIsStatic) &&
  18057. ((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
  18058. {
  18059. // We chain even non-default ctors to the default ctors
  18060. auto defaultCtor = methodInstance;
  18061. if (defaultCtor->mChainType == BfMethodChainType_ChainHead)
  18062. CallChainedMethods(defaultCtor, false);
  18063. }
  18064. auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody);
  18065. if (!mCompiler->mHasRequiredTypes)
  18066. {
  18067. // Skip processing to avoid errors
  18068. }
  18069. else if (methodDef->mBody == NULL)
  18070. {
  18071. if (methodDeclaration != NULL)
  18072. {
  18073. if (auto operatorDeclaration = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
  18074. {
  18075. if (operatorDeclaration->mIsConvOperator)
  18076. wantsRemoveBody = true;
  18077. }
  18078. }
  18079. bool isDllImport = false;
  18080. if ((importKind == BfImportKind_Import_Static) || (importKind == BfImportKind_Import_Dynamic))
  18081. {
  18082. if (importStrNum != -1)
  18083. {
  18084. if (importKind == BfImportKind_Import_Static)
  18085. {
  18086. if (!mImportFileNames.Contains(importStrNum))
  18087. {
  18088. mImportFileNames.Add(importStrNum);
  18089. }
  18090. }
  18091. }
  18092. }
  18093. else if (methodInstance->GetImportKind() == BfImportKind_Import_Dynamic)
  18094. {
  18095. CreateDllImportMethod();
  18096. }
  18097. else if (((mCurTypeInstance->mTypeDef->mIsDelegate) || (mCurTypeInstance->mTypeDef->mIsFunction)) &&
  18098. (methodDef->mName == "Invoke") && (methodDef->mMethodType == BfMethodType_Normal))
  18099. {
  18100. if (mCurTypeInstance->mTypeDef->mIsFunction)
  18101. {
  18102. // Emit nothing
  18103. }
  18104. else
  18105. {
  18106. CreateDelegateInvokeMethod();
  18107. mCurMethodState->SetHadReturn(true);
  18108. mCurMethodState->mLeftBlockUncond = true;
  18109. }
  18110. }
  18111. else if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) || (methodDef->mName == BF_METHODNAME_DYNAMICCAST_INTERFACE))
  18112. {
  18113. if (mCurTypeInstance->IsObject())
  18114. {
  18115. CreateDynamicCastMethod();
  18116. }
  18117. else
  18118. {
  18119. mBfIRBuilder->CreateRet(GetDefaultValue(methodInstance->mReturnType));
  18120. mCurMethodState->mHadReturn = true;
  18121. }
  18122. }
  18123. else if ((methodDef->mName == BF_METHODNAME_ENUM_HASFLAG) && (mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()))
  18124. {
  18125. BfIRValue ret;
  18126. if (mCurMethodState->mLocals[1]->mResolvedType != mCurTypeInstance)
  18127. {
  18128. // This can happen if we provide an invalid name
  18129. AssertErrorState();
  18130. ret = mBfIRBuilder->CreateRet(GetDefaultValue(GetPrimitiveType(BfTypeCode_Boolean)));
  18131. }
  18132. else
  18133. {
  18134. // Unfortunate DebugLoc shenanigans-
  18135. // Our params get removed if we don't have any DebugLocs, but we don't want to actually be able to step into this method,
  18136. // so we only set the loc on the CreateRet which gets inlined out
  18137. mBfIRBuilder->SaveDebugLocation();
  18138. mBfIRBuilder->ClearDebugLocation();
  18139. BfIRValue fromBool;
  18140. if (!mCurTypeInstance->IsTypedPrimitive())
  18141. {
  18142. fromBool = GetDefaultValue(methodInstance->mReturnType);
  18143. }
  18144. else
  18145. {
  18146. auto andResult = mBfIRBuilder->CreateAnd(mCurMethodState->mLocals[0]->mValue, mCurMethodState->mLocals[1]->mValue);
  18147. auto toBool = mBfIRBuilder->CreateCmpNE(andResult, GetDefaultValue(mCurMethodState->mLocals[0]->mResolvedType));
  18148. fromBool = mBfIRBuilder->CreateNumericCast(toBool, false, BfTypeCode_Boolean);
  18149. }
  18150. mBfIRBuilder->RestoreDebugLocation();
  18151. ret = mBfIRBuilder->CreateRet(fromBool);
  18152. //ExtendLocalLifetimes(0);
  18153. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18154. }
  18155. mCurMethodState->SetHadReturn(true);
  18156. mCurMethodState->mLeftBlockUncond = true;
  18157. }
  18158. else if (((methodDef->mName == BF_METHODNAME_ENUM_GETUNDERLYINGREF) || (methodDef->mName == BF_METHODNAME_ENUM_GETUNDERLYING)) &&
  18159. (mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()))
  18160. {
  18161. BfIRValue ret;
  18162. // Unfortunate DebugLoc shenanigans-
  18163. // Our params get removed if we don't have any DebugLocs, but we don't want to actually be able to step into this method,
  18164. // so we only set the loc on the CreateRet which gets inlined out
  18165. mBfIRBuilder->SaveDebugLocation();
  18166. mBfIRBuilder->ClearDebugLocation();
  18167. BfIRValue fromBool;
  18168. mBfIRBuilder->RestoreDebugLocation();
  18169. ret = mBfIRBuilder->CreateRet(GetThis().mValue);
  18170. //ExtendLocalLifetimes(0);
  18171. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18172. mCurMethodState->SetHadReturn(true);
  18173. mCurMethodState->mLeftBlockUncond = true;
  18174. }
  18175. else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
  18176. {
  18177. auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
  18178. if (HasExecutedOutput())
  18179. {
  18180. EmitEnumToStringBody();
  18181. }
  18182. mBfIRBuilder->CreateRetVoid();
  18183. mCurMethodState->SetHadReturn(true);
  18184. mCurMethodState->mLeftBlockUncond = true;
  18185. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18186. }
  18187. else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
  18188. {
  18189. auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
  18190. if (HasExecutedOutput())
  18191. {
  18192. EmitTupleToStringBody();
  18193. }
  18194. mBfIRBuilder->CreateRetVoid();
  18195. mCurMethodState->SetHadReturn(true);
  18196. mCurMethodState->mLeftBlockUncond = true;
  18197. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18198. }
  18199. else if (methodDef->mName == BF_METHODNAME_DEFAULT_EQUALS)
  18200. {
  18201. CreateValueTypeEqualsMethod(false);
  18202. skipBody = true;
  18203. skipEndChecks = true;
  18204. }
  18205. else if (methodDef->mName == BF_METHODNAME_DEFAULT_STRICT_EQUALS)
  18206. {
  18207. CreateValueTypeEqualsMethod(true);
  18208. skipBody = true;
  18209. skipEndChecks = true;
  18210. }
  18211. else if ((methodDef->mName == BF_METHODNAME_EQUALS) && (typeDef->GetDefinition() == mCompiler->mValueTypeTypeDef))
  18212. {
  18213. CreateValueTypeEqualsMethod(false);
  18214. skipBody = true;
  18215. skipEndChecks = true;
  18216. }
  18217. else if ((methodDef->mName == BF_METHODNAME_EQUALS) && (mCurTypeInstance->IsDelegate()))
  18218. {
  18219. CreateDelegateEqualsMethod();
  18220. skipBody = true;
  18221. skipEndChecks = true;
  18222. }
  18223. else
  18224. {
  18225. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  18226. if ((propertyDeclaration != NULL) && (!typeDef->HasAutoProperty(propertyDeclaration)))
  18227. {
  18228. if ((!mCurTypeInstance->IsInterface()) && (!hasExternSpecifier))
  18229. Fail("Body expected", methodDef->mBody);
  18230. }
  18231. else if (methodDef->mMethodType == BfMethodType_PropertyGetter)
  18232. {
  18233. if ((methodInstance->mReturnType->IsRef()) && (!methodDef->mIsMutating) && (mCurTypeInstance->IsValueType()))
  18234. Fail("Auto-implemented ref property getters must declare 'mut'", methodInstance->mMethodDef->GetRefNode());
  18235. if (methodInstance->mReturnType->IsValuelessType())
  18236. {
  18237. mBfIRBuilder->CreateRetVoid();
  18238. }
  18239. else if (HasExecutedOutput())
  18240. {
  18241. String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
  18242. BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);
  18243. BfFieldDef* fieldDef = NULL;
  18244. if (fieldInstance != NULL)
  18245. fieldDef = fieldInstance->GetFieldDef();
  18246. BfType* retType = methodInstance->mReturnType;
  18247. if (retType->IsRef())
  18248. retType = retType->GetUnderlyingType();
  18249. if ((fieldInstance != NULL) && (fieldInstance->GetResolvedType() == retType) &&
  18250. ((fieldInstance->mDataIdx >= 0) || (fieldDef->IsNonConstStatic())))
  18251. {
  18252. BfTypedValue lookupValue;
  18253. if (fieldDef->IsNonConstStatic())
  18254. lookupValue = ReferenceStaticField(fieldInstance);
  18255. else if (mCurTypeInstance->IsObject())
  18256. lookupValue = BfTypedValue(mBfIRBuilder->CreateInBoundsGEP(GetThis().mValue, 0, fieldInstance->mDataIdx), fieldInstance->mResolvedType, true);
  18257. else
  18258. lookupValue = ExtractValue(GetThis(), fieldInstance, fieldInstance->mDataIdx);
  18259. if (methodInstance->mReturnType->IsRef())
  18260. {
  18261. if ((!lookupValue.IsAddr()) && (!lookupValue.mType->IsValuelessType()))
  18262. lookupValue = MakeAddressable(lookupValue);
  18263. }
  18264. else
  18265. lookupValue = LoadOrAggregateValue(lookupValue);
  18266. CreateReturn(lookupValue.mValue);
  18267. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18268. }
  18269. else
  18270. {
  18271. // This can happen if we have two properties with the same name but different types
  18272. CreateReturn(GetDefaultValue(mCurMethodInstance->mReturnType));
  18273. EmitDefaultReturn();
  18274. }
  18275. }
  18276. else
  18277. {
  18278. CreateReturn(GetDefaultValue(mCurMethodInstance->mReturnType));
  18279. EmitDefaultReturn();
  18280. }
  18281. mCurMethodState->SetHadReturn(true);
  18282. }
  18283. else if (methodDef->mMethodType == BfMethodType_PropertySetter)
  18284. {
  18285. if ((!methodDef->mIsMutating) && (!methodDef->mIsStatic) && (mCurTypeInstance->IsValueType()))
  18286. {
  18287. Fail("Auto-setter must be marked as 'mut'", methodDef->GetRefNode(), true);
  18288. }
  18289. else if (!mCompiler->IsAutocomplete())
  18290. {
  18291. String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
  18292. BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);
  18293. auto fieldDef = fieldInstance->GetFieldDef();
  18294. auto& lastParam = mCurMethodState->mLocals.back();
  18295. if ((fieldInstance != NULL) && (fieldInstance->GetResolvedType() == lastParam->mResolvedType) &&
  18296. ((fieldInstance->mDataIdx >= 0) || (fieldDef->IsNonConstStatic())))
  18297. {
  18298. BfIRValue lookupAddr;
  18299. if (fieldDef->IsNonConstStatic())
  18300. lookupAddr = ReferenceStaticField(fieldInstance).mValue;
  18301. else
  18302. {
  18303. auto thisValue = GetThis();
  18304. if (thisValue.IsSplat())
  18305. {
  18306. BFMODULE_FATAL(this, "Should not happen");
  18307. }
  18308. if (mCurTypeInstance->IsObject())
  18309. thisValue = LoadValue(thisValue);
  18310. lookupAddr = mBfIRBuilder->CreateInBoundsGEP(thisValue.mValue, 0, fieldInstance->mDataIdx);
  18311. }
  18312. BfExprEvaluator exprEvaluator(this);
  18313. auto localVal = exprEvaluator.LoadLocal(lastParam);
  18314. localVal = LoadOrAggregateValue(localVal);
  18315. if (!localVal.mType->IsValuelessType())
  18316. mBfIRBuilder->CreateAlignedStore(localVal.mValue, lookupAddr, localVal.mType->mAlign);
  18317. }
  18318. else if (!fieldInstance->mResolvedType->IsValuelessType())
  18319. {
  18320. // This can happen if we have two properties with the same name but different types
  18321. AssertErrorState();
  18322. }
  18323. }
  18324. }
  18325. else if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) || (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC))
  18326. {
  18327. if (mCompiler->mOptions.mEnableRealtimeLeakCheck)
  18328. {
  18329. if (HasCompiledOutput())
  18330. EmitGCMarkMembers();
  18331. }
  18332. else if (!mCurTypeInstance->IsObject())
  18333. {
  18334. }
  18335. }
  18336. else if (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS)
  18337. {
  18338. if (mCompiler->mOptions.mEnableRealtimeLeakCheck)
  18339. {
  18340. if (HasCompiledOutput())
  18341. EmitGCFindTLSMembers();
  18342. }
  18343. }
  18344. }
  18345. }
  18346. else if (!skipBody)
  18347. {
  18348. bool isEmptyBodied = BfNodeDynCast<BfTokenNode>(methodDef->mBody) != NULL;
  18349. bool wantsRetVal = true;
  18350. if ((mIsComptimeModule) && (methodDef->mMethodType != BfMethodType_CtorCalcAppend))
  18351. wantsRetVal = false;
  18352. else if (mCurMethodInstance->mReturnType->IsVar())
  18353. wantsRetVal = false;
  18354. if ((!mCurMethodInstance->mReturnType->IsValuelessType()) && (!isEmptyBodied))
  18355. {
  18356. mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType);
  18357. if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
  18358. {
  18359. auto ptrType = CreatePointerType(mCurMethodInstance->mReturnType);
  18360. auto allocaInst = AllocLocalVariable(ptrType, "__return.addr", false);
  18361. auto storeInst = mBfIRBuilder->CreateAlignedStore(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()), allocaInst, mCurMethodInstance->mReturnType->mAlign);
  18362. mBfIRBuilder->ClearDebugLocation(storeInst);
  18363. mCurMethodState->mRetValAddr = allocaInst;
  18364. }
  18365. else if (wantsRetVal)
  18366. {
  18367. auto allocaInst = AllocLocalVariable(mCurMethodInstance->mReturnType, "__return", false);
  18368. mCurMethodState->mRetVal = BfTypedValue(allocaInst, mCurMethodInstance->mReturnType, true);
  18369. }
  18370. }
  18371. if (methodDef->mMethodType == BfMethodType_CtorCalcAppend)
  18372. {
  18373. mBfIRBuilder->CreateAlignedStore(GetConstValue(0), mCurMethodState->mRetVal.mValue, mCurMethodState->mRetVal.mType->mAlign);
  18374. BfGetSymbolReferenceKind prevSymbolKind;
  18375. BfAutoComplete* prevAutoComplete;
  18376. if (mCompiler->mResolvePassData != NULL)
  18377. {
  18378. prevSymbolKind = mCompiler->mResolvePassData->mGetSymbolReferenceKind;
  18379. prevAutoComplete = mCompiler->mResolvePassData->mAutoComplete;
  18380. mCompiler->mResolvePassData->mGetSymbolReferenceKind = BfGetSymbolReferenceKind_None;
  18381. }
  18382. EmitCtorCalcAppend();
  18383. if (mCompiler->mResolvePassData != NULL)
  18384. {
  18385. mCompiler->mResolvePassData->mGetSymbolReferenceKind = prevSymbolKind;
  18386. mCompiler->mResolvePassData->mAutoComplete = prevAutoComplete;
  18387. }
  18388. }
  18389. else if (!isEmptyBodied)
  18390. {
  18391. if (!mCurMethodState->mIRExitBlock)
  18392. mCurMethodState->mIRExitBlock = mBfIRBuilder->CreateBlock("exit", true);
  18393. bool isExpressionBody = false;
  18394. if (methodDeclaration != NULL)
  18395. {
  18396. if (methodDeclaration->mFatArrowToken != NULL)
  18397. isExpressionBody = true;
  18398. }
  18399. else if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
  18400. {
  18401. auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
  18402. if ((propertyMethodDeclaration != NULL) && (propertyMethodDeclaration->mFatArrowToken != NULL))
  18403. isExpressionBody = true;
  18404. if (auto propBodyExpr = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
  18405. {
  18406. isExpressionBody = true;
  18407. }
  18408. }
  18409. else
  18410. {
  18411. if (auto block = BfNodeDynCast<BfBlock>(methodDef->mBody))
  18412. {
  18413. if (!block->mChildArr.IsEmpty())
  18414. {
  18415. if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(block->mChildArr.GetLast()))
  18416. {
  18417. if (exprStmt->mTrailingSemicolon == NULL)
  18418. isExpressionBody = true;
  18419. }
  18420. }
  18421. }
  18422. else
  18423. isExpressionBody = true;
  18424. }
  18425. DoCEEmit(methodInstance);
  18426. if (methodInstance->mCeCancelled)
  18427. mIgnoreErrors = true;
  18428. if (auto fieldDtorBody = BfNodeDynCast<BfFieldDtorDeclaration>(methodDef->mBody))
  18429. {
  18430. while (fieldDtorBody != NULL)
  18431. {
  18432. VisitEmbeddedStatement(fieldDtorBody->mBody);
  18433. fieldDtorBody = fieldDtorBody->mNextFieldDtor;
  18434. }
  18435. }
  18436. else if (!isExpressionBody)
  18437. {
  18438. auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody);
  18439. mCurMethodState->mHeadScope.mAstBlock = bodyBlock;
  18440. mCurMethodState->mHeadScope.mCloseNode = bodyBlock->mCloseBrace;
  18441. VisitCodeBlock(bodyBlock);
  18442. }
  18443. else if (auto expressionBody = BfNodeDynCast<BfExpression>(methodDef->mBody))
  18444. {
  18445. // if ((methodDef->mMethodType != BfMethodType_Normal) && (propertyDeclaration == NULL))
  18446. // {
  18447. // BF_ASSERT(methodDeclaration->mFatArrowToken != NULL);
  18448. // Fail("Only normal methods can have expression bodies", methodDeclaration->mFatArrowToken);
  18449. // }
  18450. auto expectingType = mCurMethodInstance->mReturnType;
  18451. // What was this error for?
  18452. // if ((expectingType->IsVoid()) && (IsInSpecializedSection()))
  18453. // {
  18454. // Warn(0, "Using a 'void' return with an expression-bodied method isn't needed. Consider removing '=>' token", methodDeclaration->mFatArrowToken);
  18455. // }
  18456. BfEvalExprFlags exprEvalFlags = (BfEvalExprFlags)(BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_IsExpressionBody);
  18457. if (expectingType->IsVoid())
  18458. {
  18459. exprEvalFlags = (BfEvalExprFlags)(exprEvalFlags | BfEvalExprFlags_NoCast);
  18460. bool wasReturnGenericParam = false;
  18461. if ((mCurMethodState->mClosureState != NULL) && (mCurMethodState->mClosureState->mReturnType != NULL))
  18462. {
  18463. wasReturnGenericParam = mCurMethodState->mClosureState->mReturnType->IsGenericParam();
  18464. }
  18465. else
  18466. {
  18467. auto unspecializedMethodInstance = GetUnspecializedMethodInstance(mCurMethodInstance);
  18468. if ((unspecializedMethodInstance != NULL) && (unspecializedMethodInstance->mReturnType->IsGenericParam()))
  18469. wasReturnGenericParam = true;
  18470. }
  18471. // If we the void return was from a generic specialization, allow us to return a void result,
  18472. // otherwise treat expression as though it must be a statement
  18473. bool isStatement = expressionBody->VerifyIsStatement(mCompiler->mPassInstance, wasReturnGenericParam);
  18474. if (isStatement)
  18475. expectingType = NULL;
  18476. }
  18477. BfExprEvaluator exprEvaluator(this);
  18478. if (mCurMethodInstance->mMethodDef->mIsReadOnly)
  18479. exprEvaluator.mAllowReadOnlyReference = true;
  18480. UpdateSrcPos(expressionBody);
  18481. auto retVal = CreateValueFromExpression(exprEvaluator, expressionBody, expectingType, exprEvalFlags);
  18482. if ((retVal) && (!retVal.mType->IsVar()) && (expectingType != NULL))
  18483. {
  18484. mCurMethodState->mHadReturn = true;
  18485. retVal = LoadOrAggregateValue(retVal);
  18486. EmitReturn(retVal);
  18487. }
  18488. }
  18489. }
  18490. }
  18491. BF_ASSERT(mCurMethodState->mCurScope == &mCurMethodState->mHeadScope);
  18492. if (skipUpdateSrcPos)
  18493. {
  18494. // Skip
  18495. }
  18496. else if ((bodyBlock != NULL) && (bodyBlock->mCloseBrace != NULL))
  18497. UpdateSrcPos(bodyBlock->mCloseBrace);
  18498. else if (methodDef->mBody != NULL)
  18499. UpdateSrcPos(methodDef->mBody);
  18500. else if (methodDeclaration != NULL)
  18501. UpdateSrcPos(methodDeclaration);
  18502. else if (methodDef->mDeclaringType->mTypeDeclaration != NULL)
  18503. UpdateSrcPos(methodDef->mDeclaringType->mTypeDeclaration);
  18504. else
  18505. UseDefaultSrcPos();
  18506. if (methodDef->mMethodType == BfMethodType_CtorCalcAppend)
  18507. {
  18508. if (mCurMethodState->mRetVal)
  18509. {
  18510. mCurMethodState->SetHadReturn(true);
  18511. auto retVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetVal.mValue);
  18512. mBfIRBuilder->CreateRet(retVal);
  18513. }
  18514. else
  18515. AssertErrorState();
  18516. }
  18517. if (!mCurMethodState->mHadReturn)
  18518. {
  18519. // Clear off the stackallocs that have occurred after a scopeData break
  18520. EmitDeferredScopeCalls(false, &mCurMethodState->mHeadScope, mCurMethodState->mIRExitBlock);
  18521. }
  18522. if (mCurMethodState->mIRExitBlock)
  18523. {
  18524. for (auto preExitBlock : mCurMethodState->mHeadScope.mAtEndBlocks)
  18525. mBfIRBuilder->MoveBlockToEnd(preExitBlock);
  18526. mBfIRBuilder->MoveBlockToEnd(mCurMethodState->mIRExitBlock);
  18527. mBfIRBuilder->SetInsertPoint(mCurMethodState->mIRExitBlock);
  18528. if ((!mCurMethodState->mDIRetVal) && (wantsDIData))
  18529. CreateDIRetVal();
  18530. }
  18531. for (auto localVar : mCurMethodState->mLocals)
  18532. {
  18533. if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
  18534. {
  18535. //
  18536. }
  18537. else if ((skipEndChecks) || (methodDef->mBody == NULL))
  18538. break;
  18539. LocalVariableDone(localVar, true);
  18540. }
  18541. if (mCurMethodState->mIRExitBlock)
  18542. {
  18543. if ((mCurMethodState->mRetVal) &&
  18544. ((mIsComptimeModule) || (mCurMethodInstance->GetStructRetIdx() == -1)))
  18545. {
  18546. auto loadedVal = mBfIRBuilder->CreateAlignedLoad(mCurMethodState->mRetVal.mValue, mCurMethodState->mRetVal.mType->mAlign);
  18547. CreateReturn(loadedVal);
  18548. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18549. if (mCurMethodState->mDIRetVal)
  18550. mBfIRBuilder->DbgLifetimeEnd(mCurMethodState->mDIRetVal);
  18551. }
  18552. else
  18553. {
  18554. // Have something on the last line to step onto
  18555. if (mHasFullDebugInfo)
  18556. {
  18557. if ((bodyBlock != NULL) && (bodyBlock->mCloseBrace != NULL))
  18558. UpdateSrcPos(bodyBlock->mCloseBrace);
  18559. EmitEnsureInstructionAt();
  18560. if ((irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping))
  18561. {
  18562. // This may be a case where we only emit 4 bytes, whereas we need 5 for a hot replace jump
  18563. mBfIRBuilder->EnsureFunctionPatchable();
  18564. }
  18565. }
  18566. mBfIRBuilder->CreateRetVoid();
  18567. EmitLifetimeEnds(&mCurMethodState->mHeadScope);
  18568. if (mCurMethodState->mDIRetVal)
  18569. mBfIRBuilder->DbgLifetimeEnd(mCurMethodState->mDIRetVal);
  18570. }
  18571. }
  18572. if ((mCurMethodInstance->mReturnType == NULL) || (mCurMethodInstance->mReturnType->IsValuelessType()))
  18573. {
  18574. if ((!mCurMethodState->mHadReturn) && (!mCurMethodState->mIRExitBlock))
  18575. {
  18576. if ((!mIsComptimeModule) && (irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping))
  18577. {
  18578. // This may be a case where we only emit 4 bytes, whereas we need 5 for a hot replace jump
  18579. mBfIRBuilder->EnsureFunctionPatchable();
  18580. }
  18581. mBfIRBuilder->CreateRetVoid();
  18582. }
  18583. }
  18584. else
  18585. {
  18586. if (!mCurMethodState->mHadReturn)
  18587. {
  18588. auto refNode = mCurMethodInstance->mMethodDef->GetRefNode();
  18589. if (bodyBlock != NULL)
  18590. {
  18591. if (bodyBlock->mCloseBrace != NULL)
  18592. {
  18593. BfAstNode* target = bodyBlock->mCloseBrace;
  18594. if (!mCompiler->mHasRequiredTypes)
  18595. {
  18596. AddFailType(mCurTypeInstance);
  18597. mHadBuildError = true;
  18598. }
  18599. else
  18600. Fail("Method must return value", target);
  18601. }
  18602. else
  18603. {
  18604. // It's possible to not have a closing brace if the method ends in an EOF
  18605. AssertErrorState();
  18606. }
  18607. }
  18608. }
  18609. }
  18610. // Move 'init' into 'entry'
  18611. mBfIRBuilder->MergeBlockDown(mCurMethodState->mIRInitBlock, mCurMethodState->mIREntryBlock);
  18612. mBfIRBuilder->MergeBlockDown(mCurMethodState->mIRHeadBlock, mCurMethodState->mIREntryBlock);
  18613. if (((mCurMethodInstance->mIsUnspecialized) /*|| (typeDef->mIsFunction)*/ || (mCurTypeInstance->IsUnspecializedType())) &&
  18614. (!mIsComptimeModule))
  18615. {
  18616. // Don't keep instructions for unspecialized types
  18617. mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
  18618. }
  18619. // Avoid linking any internal funcs that were just supposed to be comptime-accessible
  18620. /*if ((methodDef->mHasComptime) && (!mIsComptimeModule))
  18621. wantsRemoveBody = true;*/
  18622. if ((hasExternSpecifier) && (!skipBody))
  18623. {
  18624. // If we hot swap, we want to make sure at least one method refers to this extern method so it gets pulled in
  18625. // incase it gets called later by some hot-loaded coded
  18626. if ((mCompiler->mOptions.mAllowHotSwapping) && (mCurMethodInstance->mIRFunction) && (!mCurMethodInstance->mIRFunction.IsFake()) && (mCurTypeInstance != mContext->mBfObjectType))
  18627. {
  18628. if (!mCurMethodInstance->mMethodDef->mName.StartsWith("Comptime_"))
  18629. CreateFakeCallerMethod(mangledName);
  18630. }
  18631. mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
  18632. }
  18633. else if ((methodInstance->GetImportKind() == BfImportKind_Import_Dynamic) && (!mCompiler->IsHotCompile()))
  18634. {
  18635. // We only need the DLL stub when we may be hot swapping
  18636. mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
  18637. }
  18638. else if (wantsRemoveBody)
  18639. mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
  18640. // We don't want to hold on to pointers to LLVMFunctions of unspecialized types.
  18641. // This allows us to delete the mScratchModule LLVM module without rebuilding all
  18642. // unspecialized types
  18643. if (((mCurTypeInstance->IsUnspecializedType()) && (!mIsComptimeModule)) ||
  18644. (mCurTypeInstance->IsInterface()))
  18645. {
  18646. BfLogSysM("ProcessMethod Clearing IRFunction: %p\n", methodInstance);
  18647. methodInstance->mIRFunction = BfIRFunction();
  18648. }
  18649. CheckAddFailType();
  18650. if (mHadBuildError)
  18651. prevHadBuildError.CancelRestore();
  18652. if (mHadBuildWarning)
  18653. prevHadWarning.CancelRestore();
  18654. if (!methodDef->mIsLocalMethod)
  18655. ProcessMethod_ProcessDeferredLocals();
  18656. mBfIRBuilder->SetActiveFunction(prevActiveFunction);
  18657. if (methodState.mHotDataReferenceBuilder != NULL)
  18658. {
  18659. AddHotDataReferences(&hotDataReferenceBuilder);
  18660. }
  18661. else
  18662. {
  18663. if ((methodInstance->mHotMethod != NULL) && (!methodInstance->mIsReified))
  18664. {
  18665. // Remove the hot method data
  18666. auto hotMethod = methodInstance->mHotMethod;
  18667. auto prevMethod = hotMethod->mPrevVersion;
  18668. if (prevMethod != NULL)
  18669. {
  18670. // If there's a prev method then pull its data into the main HotMethod.
  18671. // This, in effect, removes the 'hotMethod' data and rebases 'prevMethod'
  18672. // over to the main HotMethod definition to keep the HotMethod address
  18673. // invariant
  18674. for (auto ref : hotMethod->mReferences)
  18675. ref->Deref();
  18676. hotMethod->mReferences.Clear();
  18677. BF_ASSERT(prevMethod->mRefCount == 1);
  18678. hotMethod->mReferences = prevMethod->mReferences;
  18679. if (hotMethod->mSrcTypeVersion != NULL)
  18680. hotMethod->mSrcTypeVersion->Deref();
  18681. hotMethod->mSrcTypeVersion = prevMethod->mSrcTypeVersion;
  18682. prevMethod->mSrcTypeVersion = NULL;
  18683. prevMethod->mReferences.Clear();
  18684. hotMethod->mPrevVersion = prevMethod->mPrevVersion;
  18685. prevMethod->mPrevVersion = NULL;
  18686. prevMethod->Deref();
  18687. }
  18688. hotMethod->Deref();
  18689. methodInstance->mHotMethod = NULL;
  18690. }
  18691. }
  18692. }
  18693. String BfModule::GetLocalMethodName(const StringImpl& baseName, BfAstNode* anchorNode, BfMethodState* declMethodState, BfMixinState* declMixinState)
  18694. {
  18695. String name;
  18696. bool found = false;
  18697. auto checkMethodState = mCurMethodState;
  18698. while (checkMethodState != NULL)
  18699. {
  18700. if (checkMethodState->mClosureState == NULL)
  18701. break;
  18702. if (checkMethodState->mClosureState->mClosureMethodDef != NULL)
  18703. {
  18704. found = true;
  18705. name += checkMethodState->mClosureState->mClosureMethodDef->mName;
  18706. break;
  18707. }
  18708. checkMethodState = checkMethodState->mPrevMethodState;
  18709. }
  18710. if (!found)
  18711. name += mCurMethodInstance->mMethodDef->mName;
  18712. int prevSepPos = (int)name.LastIndexOf('$');
  18713. if (prevSepPos != -1)
  18714. {
  18715. name.RemoveToEnd(prevSepPos);
  18716. }
  18717. name += "@";
  18718. name += baseName;
  18719. HashContext hashCtx;
  18720. if (anchorNode != NULL)
  18721. {
  18722. hashCtx.Mixin(anchorNode->GetStartCharId());
  18723. }
  18724. //
  18725. {
  18726. auto checkMethodState = declMethodState;
  18727. auto checkMixinState = declMixinState;
  18728. while (checkMethodState != NULL)
  18729. {
  18730. if (checkMixinState != NULL)
  18731. {
  18732. hashCtx.Mixin(checkMixinState->mSource->GetStartCharId());
  18733. }
  18734. checkMethodState = checkMethodState->mPrevMethodState;
  18735. if (checkMethodState != NULL)
  18736. checkMixinState = checkMethodState->mMixinState;
  18737. }
  18738. }
  18739. auto rootMethodState = mCurMethodState->GetRootMethodState();
  18740. if ((rootMethodState != NULL) && (rootMethodState->mMethodInstance != NULL) && (rootMethodState->mMethodInstance->mMethodInfoEx != NULL))
  18741. {
  18742. for (auto methodGenericArg : rootMethodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments)
  18743. {
  18744. StringT<512> genericTypeName;
  18745. BfMangler::Mangle(genericTypeName, mCompiler->GetMangleKind(), methodGenericArg);
  18746. hashCtx.MixinStr(genericTypeName);
  18747. }
  18748. }
  18749. uint64 hashVal = hashCtx.Finish64();
  18750. name += "$";
  18751. name += BfTypeUtils::HashEncode64(hashVal);
  18752. return name;
  18753. }
  18754. BfMethodDef* BfModule::GetLocalMethodDef(BfLocalMethod* localMethod)
  18755. {
  18756. if (localMethod->mMethodDef != NULL)
  18757. return localMethod->mMethodDef;
  18758. auto rootMethodState = mCurMethodState->GetRootMethodState();
  18759. auto declMethodState = localMethod->mDeclMethodState;
  18760. auto declMixinState = localMethod->mDeclMixinState;
  18761. auto typeInst = mCurTypeInstance;
  18762. BfAstNode* body = NULL;
  18763. BfAstNode* anchorNode = NULL;
  18764. auto _AllocDirectTypeRef = [&](BfType* type)
  18765. {
  18766. BfDirectTypeReference* directTypeRef = localMethod->mDirectTypeRefs.Alloc();
  18767. directTypeRef->Init(type);
  18768. return directTypeRef;
  18769. };
  18770. auto methodDeclaration = localMethod->mMethodDeclaration;
  18771. if (methodDeclaration != NULL)
  18772. {
  18773. body = methodDeclaration->mBody;
  18774. anchorNode = methodDeclaration->mOpenParen;
  18775. }
  18776. else
  18777. {
  18778. body = localMethod->mLambdaBindExpr->mBody;
  18779. anchorNode = localMethod->mLambdaBindExpr->mFatArrowToken;
  18780. }
  18781. BF_ASSERT(rootMethodState->mCurLocalVarId >= 0);
  18782. int methodLocalIdx = rootMethodState->mCurLocalVarId++;
  18783. BfMethodDef* methodDef;
  18784. BfMethodDef* outerMethodDef = NULL;
  18785. if (localMethod->mOuterLocalMethod != NULL)
  18786. outerMethodDef = localMethod->mOuterLocalMethod->mMethodDef;
  18787. else if (rootMethodState->mMethodInstance != NULL)
  18788. outerMethodDef = rootMethodState->mMethodInstance->mMethodDef;
  18789. if (methodDeclaration != NULL)
  18790. {
  18791. BfDefBuilder defBuilder(mCompiler->mSystem);
  18792. defBuilder.mCurSource = localMethod->mMethodDeclaration->GetParser();
  18793. defBuilder.mPassInstance = mCompiler->mPassInstance;
  18794. defBuilder.mCurTypeDef = mCurMethodInstance->mMethodDef->mDeclaringType;
  18795. defBuilder.mCurDeclaringTypeDef = defBuilder.mCurTypeDef;
  18796. methodDef = defBuilder.CreateMethodDef(methodDeclaration, outerMethodDef);
  18797. }
  18798. else
  18799. {
  18800. auto invokeMethod = localMethod->mLambdaInvokeMethodInstance;
  18801. methodDef = new BfMethodDef();
  18802. methodDef->mName = localMethod->mMethodName;
  18803. methodDef->mDeclaringType = mCurMethodInstance->mMethodDef->mDeclaringType;
  18804. methodDef->mReturnTypeRef = _AllocDirectTypeRef(invokeMethod->mReturnType);
  18805. methodDef->mBody = body;
  18806. for (int paramIdx = 0; paramIdx < invokeMethod->GetParamCount(); paramIdx++)
  18807. {
  18808. auto paramType = invokeMethod->GetParamType(paramIdx);
  18809. String paramName;
  18810. if (paramIdx < (int)localMethod->mLambdaBindExpr->mParams.size())
  18811. paramName = localMethod->mLambdaBindExpr->mParams[paramIdx]->ToString();
  18812. else
  18813. paramName = invokeMethod->GetParamName(paramIdx);
  18814. auto paramDef = new BfParameterDef();
  18815. paramDef->mTypeRef = _AllocDirectTypeRef(paramType);
  18816. paramDef->mName = paramName;
  18817. methodDef->mParams.Add(paramDef);
  18818. }
  18819. if (outerMethodDef != NULL)
  18820. {
  18821. for (auto genericParam : outerMethodDef->mGenericParams)
  18822. {
  18823. auto* copiedGenericParamDef = new BfGenericParamDef();
  18824. *copiedGenericParamDef = *genericParam;
  18825. methodDef->mGenericParams.Add(copiedGenericParamDef);
  18826. }
  18827. }
  18828. }
  18829. methodDef->mIdx = ~methodLocalIdx;
  18830. BF_ASSERT(!localMethod->mExpectedFullName.IsEmpty());
  18831. methodDef->mName = localMethod->mExpectedFullName;
  18832. // methodDef->mName = GetLocalMethodName(methodDef->mName, anchorNode, declMethodState, declMixinState);
  18833. //
  18834. // if (!localMethod->mExpectedFullName.IsEmpty())
  18835. // BF_ASSERT(methodDef->mName == localMethod->mExpectedFullName);
  18836. methodDef->mIsStatic = true;
  18837. methodDef->mIsLocalMethod = true;
  18838. methodDef->mIsVirtual = false;
  18839. localMethod->mMethodDef = methodDef;
  18840. auto methodInstanceGroup = new BfMethodInstanceGroup();
  18841. localMethod->mMethodInstanceGroup = methodInstanceGroup;
  18842. methodInstanceGroup->mMethodIdx = -1;
  18843. methodInstanceGroup->mOwner = mCurTypeInstance;
  18844. methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
  18845. if ((declMethodState->mMixinState != NULL) && (declMethodState->mMixinState->mTarget))
  18846. {
  18847. methodInstanceGroup->mOwner = declMethodState->mMixinState->mTarget.mType->ToTypeInstance();
  18848. BF_ASSERT(methodInstanceGroup->mOwner != NULL);
  18849. }
  18850. if ((mCompiler->mResolvePassData != NULL) && (methodDeclaration != NULL))
  18851. {
  18852. mCompiler->mResolvePassData->HandleLocalReference(methodDeclaration->mNameNode, typeInst->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, methodLocalIdx);
  18853. auto autoComplete = mCompiler->mResolvePassData->mAutoComplete;
  18854. if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(methodDeclaration->mNameNode)))
  18855. {
  18856. autoComplete->SetDefinitionLocation(methodDeclaration->mNameNode);
  18857. autoComplete->mInsertStartIdx = methodDeclaration->mNameNode->GetSrcStart();
  18858. autoComplete->mInsertEndIdx = methodDeclaration->mNameNode->GetSrcEnd();
  18859. autoComplete->mDefType = typeInst->mTypeDef;
  18860. autoComplete->mDefMethod = rootMethodState->mMethodInstance->mMethodDef;
  18861. autoComplete->mReplaceLocalId = methodLocalIdx;
  18862. }
  18863. }
  18864. return localMethod->mMethodDef;
  18865. }
  18866. BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMethod, const BfTypeVector& methodGenericArguments, BfMethodInstance* methodInstance, bool force)
  18867. {
  18868. BP_ZONE_F("GetLocalMethodInstance %s", localMethod->mMethodName.c_str());
  18869. BfLogSysM("GetLocalMethodInstance %p\n", localMethod);
  18870. auto rootMethodState = mCurMethodState->GetRootMethodState();
  18871. auto declMethodState = localMethod->mDeclMethodState;
  18872. auto declMixinState = localMethod->mDeclMixinState;
  18873. auto callerMethodState = mCurMethodState;
  18874. auto typeInst = mCurTypeInstance;
  18875. if (mCurMethodState->mMixinState != NULL)
  18876. {
  18877. typeInst = mCurMethodState->mMixinState->mMixinMethodInstance->GetOwner();
  18878. }
  18879. auto methodDef = GetLocalMethodDef(localMethod);
  18880. BfAstNode* body = NULL;
  18881. auto methodDeclaration = localMethod->mMethodDeclaration;
  18882. if (methodDeclaration != NULL)
  18883. {
  18884. body = methodDeclaration->mBody;
  18885. }
  18886. else
  18887. {
  18888. body = localMethod->mLambdaBindExpr->mBody;
  18889. }
  18890. bool hadConcreteInterfaceGenericArgument = false;
  18891. BfTypeVector sanitizedMethodGenericArguments;
  18892. // Ignore the outermost method's generic method arguments for the purpose of determining if we are the 'default' (ie: unspecialized)
  18893. // version of this method for this pass through the outermost method
  18894. int dependentGenericStartIdx = 0;
  18895. if ((rootMethodState->mMethodInstance != NULL) && (rootMethodState->mMethodInstance->mMethodInfoEx != NULL))
  18896. dependentGenericStartIdx = (int)rootMethodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
  18897. BfMethodInstance* outerMethodInstance = mCurMethodInstance;
  18898. if (methodGenericArguments.size() == 0)
  18899. {
  18900. if ((rootMethodState->mMethodInstance != NULL) && (rootMethodState->mMethodInstance->mMethodInfoEx != NULL))
  18901. sanitizedMethodGenericArguments = rootMethodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments;
  18902. }
  18903. else
  18904. {
  18905. int genericArgIdx = 0;
  18906. // for (; genericArgIdx < (int)outerMethodInstance->mMethodGenericArguments.size(); genericArgIdx++)
  18907. // {
  18908. // BF_ASSERT(methodGenericArguments[genericArgIdx] == outerMethodInstance->mMethodGenericArguments[genericArgIdx]);
  18909. // sanitizedMethodGenericArguments.push_back(methodGenericArguments[genericArgIdx]);
  18910. // }
  18911. for (; genericArgIdx < (int)methodGenericArguments.size(); genericArgIdx++)
  18912. {
  18913. auto genericArgType = methodGenericArguments[genericArgIdx];
  18914. BF_ASSERT(!genericArgType->IsRef());
  18915. if (genericArgType->IsConcreteInterfaceType())
  18916. {
  18917. hadConcreteInterfaceGenericArgument = true;
  18918. auto concreteInterfaceType = (BfConcreteInterfaceType*)genericArgType;
  18919. genericArgType = concreteInterfaceType->mInterface;
  18920. }
  18921. sanitizedMethodGenericArguments.push_back(genericArgType);
  18922. }
  18923. }
  18924. bool wantPrematureMethodInstance = false;
  18925. if (!force)
  18926. {
  18927. wantPrematureMethodInstance = (callerMethodState->mClosureState != NULL) && (callerMethodState->mClosureState->mCaptureVisitingBody);
  18928. }
  18929. auto methodInstGroup = localMethod->mMethodInstanceGroup;
  18930. bool isDefaultPass = true;
  18931. BfTypeVector lookupMethodGenericArguments;
  18932. for (int genericArgIdx = dependentGenericStartIdx; genericArgIdx < (int)methodGenericArguments.size(); genericArgIdx++)
  18933. {
  18934. auto genericArgType = methodGenericArguments[genericArgIdx];
  18935. BF_ASSERT(!genericArgType->IsRef());
  18936. lookupMethodGenericArguments.Add(genericArgType);
  18937. if (genericArgType->IsGenericParam())
  18938. {
  18939. auto genericParam = (BfGenericParamType*)genericArgType;
  18940. if ((genericParam->mGenericParamKind != BfGenericParamKind_Method) || (genericParam->mGenericParamIdx != genericArgIdx))
  18941. isDefaultPass = false;
  18942. }
  18943. else
  18944. {
  18945. isDefaultPass = false;
  18946. }
  18947. }
  18948. bool hadExistingMethodInstance = false;
  18949. if (methodInstance != NULL)
  18950. {
  18951. hadExistingMethodInstance = true;
  18952. }
  18953. else
  18954. {
  18955. if (isDefaultPass)
  18956. {
  18957. methodInstance = methodInstGroup->mDefault;
  18958. if (methodInstance != NULL)
  18959. {
  18960. hadExistingMethodInstance = true;
  18961. }
  18962. else
  18963. {
  18964. methodInstance = new BfMethodInstance();
  18965. methodInstGroup->mDefault = methodInstance;
  18966. }
  18967. }
  18968. else
  18969. {
  18970. BF_ASSERT(sanitizedMethodGenericArguments.size() != 0);
  18971. if (methodInstGroup->mMethodSpecializationMap == NULL)
  18972. methodInstGroup->mMethodSpecializationMap = new BfMethodInstanceGroup::MapType();
  18973. BfMethodInstance** methodInstancePtr = NULL;
  18974. if (!methodInstGroup->mMethodSpecializationMap->TryAdd(lookupMethodGenericArguments, NULL, &methodInstancePtr))
  18975. {
  18976. methodInstance = *methodInstancePtr;
  18977. hadExistingMethodInstance = true;
  18978. }
  18979. else
  18980. {
  18981. methodInstance = new BfMethodInstance();
  18982. *methodInstancePtr = methodInstance;
  18983. }
  18984. }
  18985. }
  18986. if (hadExistingMethodInstance)
  18987. {
  18988. if ((!methodInstance->mDisallowCalling) ||
  18989. ((wantPrematureMethodInstance) && (methodInstance->mDisallowCalling)))
  18990. return BfModuleMethodInstance(methodInstance);
  18991. BF_ASSERT((methodInstance->mMethodInfoEx == NULL) || (methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState == NULL));
  18992. }
  18993. else
  18994. {
  18995. auto methodInfoEx = methodInstance->GetMethodInfoEx();
  18996. methodInfoEx->mClosureInstanceInfo = new BfClosureInstanceInfo();
  18997. methodInfoEx->mClosureInstanceInfo->mLocalMethod = localMethod;
  18998. methodInstance->mIsReified = mCurMethodInstance->mIsReified;
  18999. methodInstance->mIsAutocompleteMethod = mCurMethodInstance->mIsAutocompleteMethod;
  19000. methodInstance->mMethodDef = methodDef;
  19001. methodInstance->mMethodInstanceGroup = localMethod->mMethodInstanceGroup;
  19002. if (hadConcreteInterfaceGenericArgument)
  19003. methodInstance->mIgnoreBody = true;
  19004. methodInfoEx->mMethodGenericArguments = sanitizedMethodGenericArguments;
  19005. for (auto genericArg : sanitizedMethodGenericArguments)
  19006. {
  19007. if (genericArg->IsPrimitiveType())
  19008. genericArg = GetWrappedStructType(genericArg);
  19009. AddDependency(genericArg, typeInst, BfDependencyMap::DependencyFlag_MethodGenericArg);
  19010. }
  19011. for (int genericParamIdx = (int)sanitizedMethodGenericArguments.size(); genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
  19012. {
  19013. auto genericParamType = GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
  19014. methodInfoEx->mMethodGenericArguments.push_back(genericParamType);
  19015. }
  19016. SetupMethodIdHash(methodInstance);
  19017. }
  19018. auto _SetupMethodInstance = [&]()
  19019. {
  19020. BF_ASSERT(methodInstance->GetNumGenericParams() == 0);
  19021. // Generic constraints
  19022. for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
  19023. {
  19024. auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
  19025. methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
  19026. }
  19027. };
  19028. //////////////////////////////////////////////////////////////////////////
  19029. auto _VisitLambdaBody = [&]()
  19030. {
  19031. if (localMethod->mDeclOnly)
  19032. return;
  19033. if (mCompiler->mCanceling)
  19034. return;
  19035. if (auto blockBody = BfNodeDynCast<BfBlock>(body))
  19036. {
  19037. VisitCodeBlock(blockBody);
  19038. }
  19039. else if (auto bodyExpr = BfNodeDynCast<BfExpression>(body))
  19040. {
  19041. BfType* expectType = NULL;
  19042. if (!methodInstance->mReturnType->IsVoid())
  19043. expectType = methodInstance->mReturnType;
  19044. CreateValueFromExpression(bodyExpr, expectType, BfEvalExprFlags_AllowRefExpr);
  19045. }
  19046. };
  19047. auto _SafeResolveTypeRef = [&](BfTypeReference* typeRef)
  19048. {
  19049. SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);
  19050. auto result = ResolveTypeRef(typeRef);
  19051. if (result == NULL)
  19052. result = mContext->mBfObjectType;
  19053. return result;
  19054. };
  19055. BfTypeInstance* outerClosure = NULL;
  19056. if ((declMethodState->mClosureState != NULL) && (!declMethodState->mClosureState->mCapturing))
  19057. outerClosure = declMethodState->mClosureState->mClosureType;
  19058. BfMethodState methodState;
  19059. methodState.mPrevMethodState = declMethodState;//mCurMethodState;
  19060. BfIRFunctionType funcType;
  19061. auto voidType = GetPrimitiveType(BfTypeCode_None);
  19062. SizedArray<BfIRType, 0> paramTypes;
  19063. funcType = mBfIRBuilder->CreateFunctionType(mBfIRBuilder->MapType(voidType), paramTypes, methodInstance->IsVarArgs());
  19064. mBfIRBuilder->SaveDebugLocation();
  19065. auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
  19066. auto prevActiveFunction = mBfIRBuilder->GetActiveFunction();
  19067. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
  19068. BfDeferredLocalAssignData deferredLocalAssignData;
  19069. //TODO: Why did we do this? It can cause us to pull in local variables that don't belong to us...
  19070. /*if (declMethodState->mDeferredLocalAssignData != NULL)
  19071. deferredLocalAssignData.ExtendFrom(declMethodState->mDeferredLocalAssignData);*/
  19072. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  19073. methodState.mIRHeadBlock = mBfIRBuilder->CreateBlock("head", true);
  19074. methodState.mIRInitBlock = mBfIRBuilder->CreateBlock("init", true);
  19075. methodState.mIREntryBlock = mBfIRBuilder->CreateBlock("entry", true);
  19076. methodState.mCurScope->mDIScope = localMethod->mDeclDIScope; //declMethodState->mCurScope->mDIScope ;
  19077. //methodState.mCurLocalVarId = declMethodState->mCurLocalVarId;
  19078. methodState.mIRFunction = declMethodState->mIRFunction;
  19079. methodState.mDeferredLocalAssignData = &deferredLocalAssignData;
  19080. if (auto blockBody = BfNodeDynCast<BfBlock>(body))
  19081. {
  19082. methodState.mCurScope->mAstBlock = blockBody;
  19083. methodState.mCurScope->mCloseNode = blockBody->mCloseBrace;
  19084. }
  19085. mBfIRBuilder->SetInsertPoint(methodState.mIREntryBlock);
  19086. BfClosureState closureState;
  19087. if (methodDef->mMethodType == BfMethodType_Mixin)
  19088. {
  19089. if (declMethodState != NULL)
  19090. {
  19091. if ((declMethodState->mClosureState != NULL) && (declMethodState->mClosureState->mReturnType != NULL))
  19092. closureState.mReturnType = declMethodState->mClosureState->mReturnType;
  19093. else if (declMethodState->mMethodInstance != NULL)
  19094. closureState.mReturnType = declMethodState->mMethodInstance->mReturnType;
  19095. }
  19096. }
  19097. if (closureState.mReturnType == NULL)
  19098. closureState.mReturnType = _SafeResolveTypeRef(methodDef->mReturnTypeRef);
  19099. closureState.mCapturing = true;
  19100. closureState.mLocalMethod = localMethod;
  19101. closureState.mClosureInstanceInfo = methodInstance->mMethodInfoEx->mClosureInstanceInfo;
  19102. closureState.mDeclaringMethodIsMutating = mCurMethodInstance->mMethodDef->mIsMutating;
  19103. methodState.mClosureState = &closureState;
  19104. closureState.mClosureType = outerClosure;
  19105. int outerLocalsCount = (int)methodState.mLocals.size();
  19106. if (!hadExistingMethodInstance)
  19107. {
  19108. BfLogSysM("LocalMethod %p premature DoMethodDeclaration %p (Source:%p)\n", localMethod, methodInstance, (methodDeclaration != NULL) ? methodDeclaration->GetSourceData() : NULL);
  19109. SetAndRestoreValue<bool> prevIgnoreWrites(mWantsIRIgnoreWrites, true);
  19110. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, true);
  19111. // Prematurely do declaration. We will have to undo this later, so don't write this one and don't throw errors
  19112. auto declareModule = this;
  19113. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(declareModule->mCurMethodInstance, methodInstance);
  19114. SetAndRestoreValue<BfFilePosition> prevFilePos(declareModule->mCurFilePosition);
  19115. BF_ASSERT(declareModule != NULL);
  19116. methodInstance->mDeclModule = declareModule;
  19117. _SetupMethodInstance();
  19118. declareModule->DoMethodDeclaration(localMethod->mMethodDef->GetMethodDeclaration(), false, false);
  19119. methodInstance->mDisallowCalling = true; // Don't allow us to ACTUALLY call until we add the captures
  19120. }
  19121. if (wantPrematureMethodInstance)
  19122. {
  19123. // Return a premature methodInstance -- since we are partway through determining the capture of a local method, we can't rely on its
  19124. // capture information. This returned method instance can only be used for method matching, but we will visit it later to create
  19125. // its true method instance
  19126. //auto moduleMethodInstance = _CheckReturnedMethod(methodInstance);
  19127. //BF_ASSERT(moduleMethodInstance);
  19128. return BfModuleMethodInstance(methodInstance);
  19129. }
  19130. auto checkInsertBlock = mBfIRBuilder->GetInsertBlock();
  19131. BF_ASSERT(methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState == NULL);
  19132. closureState.mCaptureStartAccessId = mCurMethodState->GetRootMethodState()->mCurAccessId;
  19133. methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState = &closureState;
  19134. closureState.mClosureMethodDef = methodDef;
  19135. bool wantsVisitBody = true;
  19136. if ((methodDef->mMethodType == BfMethodType_Mixin) && (!methodGenericArguments.IsEmpty()))
  19137. wantsVisitBody = false;
  19138. if (methodInstance->IsOrInUnspecializedVariation())
  19139. wantsVisitBody = false;
  19140. bool allowCapture = (methodDeclaration == NULL) || (methodDeclaration->mStaticSpecifier == NULL);
  19141. if (wantsVisitBody)
  19142. {
  19143. BP_ZONE("VisitLambdaBody");
  19144. // For generic methods, we capture for each specialization, so make sure mIsStatic is set to 'true' for
  19145. // this capture stage for each of those times
  19146. SetAndRestoreValue<bool> prevWasStatis(methodDef->mIsStatic, true);
  19147. /*
  19148. // Only generate errors once. Also there are some errors that will occur during this scanning phase
  19149. // that will not occur during the actual lambda method generation, for example: returning a value
  19150. // when our current method is a 'void' method. This shouldn't affect capture scanning since all
  19151. // our AST nodes will still be visited
  19152. SetAndRestoreValue<bool> ignoreError(mIgnoreErrors, true);
  19153. */
  19154. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
  19155. //SetAndRestoreValue<bool> wantsIgnoreWrites(mWantsISIgnoreWrites, true);
  19156. mBfIRBuilder->SaveDebugLocation();
  19157. closureState.mCaptureVisitingBody = true;
  19158. BF_ASSERT(methodInstance->mMethodInfoEx != NULL);
  19159. methodState.mGenericTypeBindings = &methodInstance->mMethodInfoEx->mGenericTypeBindings;
  19160. methodState.mMethodInstance = methodInstance;
  19161. NewScopeState();
  19162. ProcessMethod_SetupParams(methodInstance, NULL, false, NULL);
  19163. if (methodInstance->mMethodDef->mMethodType == BfMethodType_Mixin)
  19164. {
  19165. // Allow assigning to arguments when we're capturing - which may or may not be legal at the injection site (we throw error there)
  19166. for (auto localDef : methodState.mLocals)
  19167. {
  19168. if (localDef->mResolvedType->IsVar())
  19169. continue;
  19170. localDef->mAddr = CreateAlloca(localDef->mResolvedType);
  19171. }
  19172. }
  19173. // Keep outs for being marked as assigned
  19174. auto rootMethodState = mCurMethodState->GetRootMethodState();
  19175. BfDeferredLocalAssignData deferredLocalAssignData(rootMethodState->mCurScope);
  19176. deferredLocalAssignData.mVarIdBarrier = rootMethodState->mCurLocalVarId;
  19177. SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(rootMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
  19178. if (!mIgnoreErrors)
  19179. localMethod->mDidBodyErrorPass = true;
  19180. _VisitLambdaBody();
  19181. RestoreScopeState();
  19182. closureState.mCaptureVisitingBody = false;
  19183. mBfIRBuilder->RestoreDebugLocation();
  19184. }
  19185. // If we ended up being called by a method with a lower captureStartAccessId, propagate that to whoever is calling us, too...
  19186. if ((methodState.mPrevMethodState->mClosureState != NULL) && (methodState.mPrevMethodState->mClosureState->mCapturing))
  19187. {
  19188. auto prevClosureState = methodState.mPrevMethodState->mClosureState;
  19189. if (closureState.mCaptureStartAccessId < prevClosureState->mCaptureStartAccessId)
  19190. prevClosureState->mCaptureStartAccessId = closureState.mCaptureStartAccessId;
  19191. }
  19192. // Actually get the referenced local methods. It's important we wait until after visiting the body, because then our own capture information
  19193. // can be used by these methods (which will be necessary if any of these methods call us directly or indirectly)
  19194. closureState.mClosureMethodDef = NULL;
  19195. for (auto methodInstance : closureState.mLocalMethodRefs)
  19196. {
  19197. GetLocalMethodInstance(methodInstance->mMethodInfoEx->mClosureInstanceInfo->mLocalMethod, BfTypeVector(), methodInstance);
  19198. }
  19199. methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState = NULL;
  19200. prevIgnoreWrites.Restore();
  19201. std::multiset<BfClosureCapturedEntry> capturedEntries;
  19202. //
  19203. {
  19204. auto varMethodState = declMethodState;
  19205. while (varMethodState != NULL)
  19206. {
  19207. if ((varMethodState->mMixinState != NULL) && (varMethodState->mMixinState->mLastTargetAccessId >= closureState.mCaptureStartAccessId))
  19208. {
  19209. BF_ASSERT(methodInstance->GetOwner() == varMethodState->mMixinState->mTarget.mType);
  19210. methodDef->mIsStatic = false;
  19211. if (rootMethodState->mMethodInstance->mMethodDef->mIsMutating)
  19212. methodDef->mIsMutating = true;
  19213. }
  19214. bool copyOuterCaptures = false;
  19215. for (int localIdx = 0; localIdx < varMethodState->mLocals.size(); localIdx++)
  19216. {
  19217. auto localVar = varMethodState->mLocals[localIdx];
  19218. if ((localVar->mReadFromId >= closureState.mCaptureStartAccessId) || (localVar->mWrittenToId >= closureState.mCaptureStartAccessId))
  19219. {
  19220. if (!allowCapture)
  19221. {
  19222. if ((!localVar->mIsStatic) && (!localVar->mConstValue))
  19223. continue;
  19224. }
  19225. if (localVar->mIsThis)
  19226. {
  19227. // We can only set mutating if our owning type is mutating
  19228. if (localVar->mWrittenToId >= closureState.mCaptureStartAccessId)
  19229. {
  19230. if (typeInst->IsValueType())
  19231. {
  19232. if (rootMethodState->mMethodInstance->mMethodDef->mIsMutating)
  19233. methodDef->mIsMutating = true;
  19234. }
  19235. }
  19236. methodDef->mIsStatic = false;
  19237. continue;
  19238. }
  19239. if ((localVar->mIsThis) && (outerClosure != NULL))
  19240. {
  19241. continue;
  19242. }
  19243. if ((localVar->mConstValue) || (localVar->mIsStatic) || (localVar->mResolvedType->IsValuelessType()))
  19244. {
  19245. closureState.mConstLocals.push_back(*localVar);
  19246. continue;
  19247. }
  19248. BfClosureCapturedEntry capturedEntry;
  19249. auto capturedType = localVar->mResolvedType;
  19250. bool captureByRef = false;
  19251. if (!capturedType->IsRef())
  19252. {
  19253. if (localVar->mIsThis)
  19254. {
  19255. if ((localVar->mResolvedType->IsValueType()) && (mCurMethodInstance->mMethodDef->HasNoThisSplat()))
  19256. captureByRef = true;
  19257. }
  19258. else if ((!localVar->mIsReadOnly) && (localVar->mWrittenToId >= closureState.mCaptureStartAccessId))
  19259. captureByRef = true;
  19260. }
  19261. else
  19262. {
  19263. if (localVar->mWrittenToId < closureState.mCaptureStartAccessId)
  19264. {
  19265. capturedType = ((BfRefType*)capturedType)->mElementType;
  19266. }
  19267. }
  19268. if (captureByRef)
  19269. {
  19270. //capturedEntry.mIsByReference = true;
  19271. capturedType = CreateRefType(capturedType);
  19272. }
  19273. else
  19274. {
  19275. //capturedEntry.mIsByReference = false;
  19276. }
  19277. capturedEntry.mNameNode = localVar->mNameNode;
  19278. capturedEntry.mType = capturedType;
  19279. capturedEntry.mName = localVar->mName;
  19280. //capturedEntry.mLocalVarDef = localVar;
  19281. capturedEntries.insert(capturedEntry);
  19282. }
  19283. }
  19284. varMethodState = varMethodState->mPrevMethodState;
  19285. if ((varMethodState == NULL) ||
  19286. (varMethodState->mMixinState != NULL) ||
  19287. ((varMethodState->mClosureState != NULL) && (!varMethodState->mClosureState->mCapturing)))
  19288. break;
  19289. }
  19290. }
  19291. for (auto& copyField : closureState.mReferencedOuterClosureMembers)
  19292. {
  19293. auto fieldDef = copyField->GetFieldDef();
  19294. BfClosureCapturedEntry capturedEntry;
  19295. capturedEntry.mName = copyField->GetFieldDef()->mName;
  19296. capturedEntry.mType = copyField->mResolvedType;
  19297. if (capturedEntry.mType->IsRef())
  19298. {
  19299. // Keep by ref
  19300. }
  19301. else if (!fieldDef->mIsReadOnly)
  19302. {
  19303. capturedEntry.mType = CreateRefType(capturedEntry.mType);
  19304. }
  19305. capturedEntries.insert(capturedEntry);
  19306. }
  19307. int captureIdx = 0;
  19308. for (auto& capturedEntry : capturedEntries)
  19309. {
  19310. methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries.Add(capturedEntry);
  19311. }
  19312. /*if (isDefaultPass)
  19313. {
  19314. // Insert captured members a params at the start. If we added at the end then it would screw up varargs methods
  19315. int captureIdx = 0;
  19316. for (auto& capturedEntry : capturedEntries)
  19317. {
  19318. methodInstance->mClosureInstanceInfo->mCaptureNodes.Add(BfNodeDynCast<BfIdentifierNode>(capturedEntry.mNameNode));
  19319. BfParameterDef* paramDef = new BfParameterDef();
  19320. paramDef->mName = capturedEntry.mName;
  19321. BfDirectTypeReference* directTypeRef = new BfDirectTypeReference();
  19322. directTypeRef->mType = capturedEntry.mType;
  19323. typeInst->mTypeDef->mDirectAllocNodes.push_back(directTypeRef);
  19324. paramDef->mTypeRef = directTypeRef;
  19325. paramDef->mParamKind = BfParamKind_ImplicitCapture;
  19326. methodDef->mParams.Insert(captureIdx, paramDef);
  19327. captureIdx++;
  19328. }
  19329. }
  19330. else
  19331. {
  19332. auto defaultMethodInstance = methodInstGroup->mDefault;
  19333. methodInstance->mClosureInstanceInfo->mCaptureNodes = defaultMethodInstance->mClosureInstanceInfo->mCaptureNodes;
  19334. }*/
  19335. methodState.Reset();
  19336. closureState.mCapturing = false;
  19337. //////////////////////////////////////////////////////////////////////////
  19338. SetAndRestoreValue<bool> prevIgnoreErrors(mIgnoreErrors, false);
  19339. if (methodInstance->mReturnType != NULL)
  19340. {
  19341. BF_ASSERT(methodInstance->mDisallowCalling);
  19342. // We did a premature declaration (without captures)
  19343. methodInstance->UndoDeclaration();
  19344. methodInstance->mDisallowCalling = false;
  19345. BfLogSysM("LocalMethod %p UndoingDeclaration %p\n", localMethod, methodInstance);
  19346. }
  19347. auto declareModule = this;
  19348. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(declareModule->mCurMethodInstance, methodInstance);
  19349. SetAndRestoreValue<BfFilePosition> prevFilePos(declareModule->mCurFilePosition);
  19350. BF_ASSERT(declareModule != NULL);
  19351. methodInstance->mDeclModule = declareModule;
  19352. _SetupMethodInstance();
  19353. BfLogSysM("LocalMethod %p DoMethodDeclaration %p\n", localMethod, methodInstance);
  19354. declareModule->DoMethodDeclaration(localMethod->mMethodDef->GetMethodDeclaration(), false, false);
  19355. closureState.mReturnType = methodInstance->mReturnType;
  19356. mCompiler->mStats.mMethodsQueued++;
  19357. mCompiler->UpdateCompletion();
  19358. declareModule->mIncompleteMethodCount++;
  19359. mCompiler->mStats.mMethodsProcessed++;
  19360. if (!methodInstance->mIsReified)
  19361. mCompiler->mStats.mUnreifiedMethodsProcessed++;
  19362. auto deferMethodState = rootMethodState;
  19363. // Since we handle errors & warnings in the capture phase, we don't need to process any local methods for resolve-only (unless we're doing a mDbgVerifyCodeGen)
  19364. if ((!localMethod->mDeclOnly) && (!methodInstance->IsOrInUnspecializedVariation()) &&
  19365. (methodDef->mMethodType != BfMethodType_Mixin) &&
  19366. ((!mWantsIRIgnoreWrites) || (!localMethod->mDidBodyErrorPass)) &&
  19367. (!mCompiler->IsDataResolvePass()))
  19368. {
  19369. BP_ZONE("BfDeferredLocalMethod:create");
  19370. BfDeferredLocalMethod* deferredLocalMethod = new BfDeferredLocalMethod();
  19371. deferredLocalMethod->mLocalMethod = localMethod;
  19372. deferredLocalMethod->mConstLocals = closureState.mConstLocals;
  19373. deferredLocalMethod->mMethodInstance = methodInstance;
  19374. auto checkMethodState = declMethodState;
  19375. while (checkMethodState != NULL)
  19376. {
  19377. if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL))
  19378. {
  19379. for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords)
  19380. deferredLocalMethod->mMixinStateRecords.Add(mixinRecord);
  19381. }
  19382. if (checkMethodState->mMixinState != NULL)
  19383. {
  19384. BfMixinRecord mixinRecord;
  19385. mixinRecord.mSource = checkMethodState->mMixinState->mSource;
  19386. deferredLocalMethod->mMixinStateRecords.Add(mixinRecord);
  19387. }
  19388. checkMethodState = checkMethodState->mPrevMethodState;
  19389. }
  19390. rootMethodState->mDeferredLocalMethods.Add(deferredLocalMethod);
  19391. }
  19392. mBfIRBuilder->SetActiveFunction(prevActiveFunction);
  19393. mBfIRBuilder->SetInsertPoint(prevInsertBlock);
  19394. mBfIRBuilder->RestoreDebugLocation();
  19395. if (methodInstance == localMethod->mMethodInstanceGroup->mDefault)
  19396. {
  19397. auto checkMethodState = mCurMethodState;
  19398. while (checkMethodState != NULL)
  19399. {
  19400. BfLocalMethod* nextLocalMethod = NULL;
  19401. if (checkMethodState->mLocalMethodMap.TryGetValue(localMethod->mMethodName, &nextLocalMethod))
  19402. {
  19403. while (nextLocalMethod != NULL)
  19404. {
  19405. auto checkLocalMethod = nextLocalMethod;
  19406. nextLocalMethod = nextLocalMethod->mNextWithSameName;
  19407. if (checkLocalMethod == localMethod)
  19408. continue;
  19409. if (checkLocalMethod->mMethodInstanceGroup == NULL)
  19410. continue;
  19411. auto checkMethodInstance = checkLocalMethod->mMethodInstanceGroup->mDefault;
  19412. if (checkMethodInstance == NULL)
  19413. continue; // Not generated yet
  19414. if (CompareMethodSignatures(localMethod->mMethodInstanceGroup->mDefault, checkMethodInstance))
  19415. {
  19416. String error = "Method already declared with the same parameter types";
  19417. auto bfError = Fail(error, methodInstance->mMethodDef->GetRefNode(), true);
  19418. if ((bfError != NULL) && (methodInstance->mMethodDef->GetRefNode() != checkMethodInstance->mMethodDef->GetRefNode()))
  19419. mCompiler->mPassInstance->MoreInfo("First declaration", checkMethodInstance->mMethodDef->GetRefNode());
  19420. }
  19421. }
  19422. }
  19423. checkMethodState = checkMethodState->mPrevMethodState;
  19424. }
  19425. }
  19426. return BfModuleMethodInstance(methodInstance);
  19427. }
  19428. int BfModule::GetLocalInferrableGenericArgCount(BfMethodDef* methodDef)
  19429. {
  19430. if ((!methodDef->mIsLocalMethod) || (methodDef->mGenericParams.size() == 0))
  19431. return 0;
  19432. auto rootMethodState = mCurMethodState->GetRootMethodState();
  19433. int rootMethodGenericParamCount = 0;
  19434. if (rootMethodState->mMethodInstance->mMethodInfoEx != NULL)
  19435. rootMethodGenericParamCount = (int)rootMethodState->mMethodInstance->mMethodInfoEx->mGenericParams.size();
  19436. if (mCurMethodInstance == NULL)
  19437. return rootMethodGenericParamCount;
  19438. if ((mCurMethodInstance->mMethodInfoEx == NULL) || (mCurMethodInstance->mMethodInfoEx->mClosureInstanceInfo == NULL))
  19439. return rootMethodGenericParamCount;
  19440. BfLocalMethod* callerLocalMethod = mCurMethodInstance->mMethodInfoEx->mClosureInstanceInfo->mLocalMethod;
  19441. if (callerLocalMethod == NULL)
  19442. return rootMethodGenericParamCount;
  19443. BfLocalMethod* calledLocalMethod = NULL;
  19444. rootMethodState->mLocalMethodCache.TryGetValue(methodDef->mName, &calledLocalMethod);
  19445. while ((calledLocalMethod != NULL) && (callerLocalMethod != NULL))
  19446. {
  19447. if (calledLocalMethod->mOuterLocalMethod == callerLocalMethod)
  19448. return (int)callerLocalMethod->mMethodDef->mGenericParams.size();
  19449. callerLocalMethod = calledLocalMethod->mOuterLocalMethod;
  19450. }
  19451. return rootMethodGenericParamCount;
  19452. }
  19453. void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
  19454. {
  19455. auto methodDef = methodInstance->mMethodDef;
  19456. auto customAttributes = methodInstance->GetCustomAttributes();
  19457. if (customAttributes != NULL)
  19458. return;
  19459. auto methodDeclaration = methodDef->GetMethodDeclaration();
  19460. auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
  19461. auto typeInstance = methodInstance->GetOwner();
  19462. BfTypeState typeState(typeInstance);
  19463. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  19464. SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeInstance);
  19465. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, methodInstance);
  19466. BfAttributeTargets attrTarget = ((methodDef->mMethodType == BfMethodType_Ctor) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend)) ? BfAttributeTargets_Constructor : BfAttributeTargets_Method;
  19467. BfAttributeDirective* attributeDirective = NULL;
  19468. if (methodDeclaration != NULL)
  19469. attributeDirective = methodDeclaration->mAttributes;
  19470. else if (propertyMethodDeclaration != NULL)
  19471. {
  19472. attributeDirective = propertyMethodDeclaration->mAttributes;
  19473. if (auto exprBody = BfNodeDynCast<BfPropertyBodyExpression>(propertyMethodDeclaration->mPropertyDeclaration->mDefinitionBlock))
  19474. {
  19475. attributeDirective = propertyMethodDeclaration->mPropertyDeclaration->mAttributes;
  19476. attrTarget = (BfAttributeTargets)(BfAttributeTargets_Property | BfAttributeTargets_Method);
  19477. }
  19478. }
  19479. if (attributeDirective != NULL)
  19480. {
  19481. if (methodInstance->GetMethodInfoEx()->mMethodCustomAttributes == NULL)
  19482. methodInstance->mMethodInfoEx->mMethodCustomAttributes = new BfMethodCustomAttributes();
  19483. if ((methodInstance == methodInstance->mMethodInstanceGroup->mDefault) && (methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes != NULL))
  19484. {
  19485. // Take over prevoiusly-generated custom attributes
  19486. methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes;
  19487. methodInstance->mMethodInstanceGroup->mDefaultCustomAttributes = NULL;
  19488. }
  19489. else
  19490. methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = GetCustomAttributes(attributeDirective, attrTarget);
  19491. }
  19492. if ((propertyMethodDeclaration != NULL) && (propertyMethodDeclaration->mPropertyDeclaration->mAttributes != NULL) && ((attrTarget & BfAttributeTargets_Property) == 0))
  19493. {
  19494. if (methodInstance->GetMethodInfoEx()->mMethodCustomAttributes != NULL)
  19495. {
  19496. GetCustomAttributes(methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes, propertyMethodDeclaration->mPropertyDeclaration->mAttributes, BfAttributeTargets_Property);
  19497. }
  19498. else
  19499. {
  19500. methodInstance->GetMethodInfoEx()->mMethodCustomAttributes = new BfMethodCustomAttributes();
  19501. methodInstance->mMethodInfoEx->mMethodCustomAttributes->mCustomAttributes = GetCustomAttributes(propertyMethodDeclaration->mPropertyDeclaration->mAttributes, BfAttributeTargets_Property);
  19502. }
  19503. }
  19504. customAttributes = methodInstance->GetCustomAttributes();
  19505. if (customAttributes == NULL)
  19506. {
  19507. auto owner = methodInstance->GetOwner();
  19508. if ((owner->IsDelegate()) || (owner->IsFunction()))
  19509. customAttributes = owner->mCustomAttributes;
  19510. }
  19511. methodInstance->mCallingConvention = methodDef->mCallingConvention;
  19512. if (customAttributes != NULL)
  19513. {
  19514. auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef);
  19515. if (linkNameAttr != NULL)
  19516. {
  19517. if (linkNameAttr->mCtorArgs.size() == 1)
  19518. {
  19519. auto constant = typeInstance->mConstHolder->GetConstant(linkNameAttr->mCtorArgs[0]);
  19520. if (constant != NULL)
  19521. methodInstance->mCallingConvention = (BfCallingConvention)constant->mInt32;
  19522. }
  19523. }
  19524. if (methodDef->mHasComptime)
  19525. methodInstance->mComptimeFlags = BfComptimeFlag_Comptime;
  19526. auto comptimeAttr = customAttributes->Get(mCompiler->mComptimeAttributeTypeDef);
  19527. if (comptimeAttr != NULL)
  19528. {
  19529. for (auto setProp : comptimeAttr->mSetProperties)
  19530. {
  19531. BfPropertyDef* propertyDef = setProp.mPropertyRef;
  19532. if (propertyDef->mName == "OnlyFromComptime")
  19533. {
  19534. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  19535. if ((constant != NULL) && (constant->mBool))
  19536. methodInstance->mComptimeFlags = (BfComptimeFlags)(methodInstance->mComptimeFlags | BfComptimeFlag_OnlyFromComptime);
  19537. }
  19538. else if (propertyDef->mName == "ConstEval")
  19539. {
  19540. auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue);
  19541. if ((constant != NULL) && (constant->mBool))
  19542. methodInstance->mComptimeFlags = (BfComptimeFlags)(methodInstance->mComptimeFlags | BfComptimeFlag_ConstEval);
  19543. }
  19544. }
  19545. }
  19546. }
  19547. auto delegateInfo = typeInstance->GetDelegateInfo();
  19548. if ((delegateInfo != NULL) && (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) && (methodInstance->mMethodDef->mName == "Invoke"))
  19549. methodInstance->mCallingConvention = delegateInfo->mCallingConvention;
  19550. }
  19551. void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& mangledName, bool isTemporaryFunc, bool* outIsIntrinsic)
  19552. {
  19553. if (methodInstance->GetImportCallKind() == BfImportCallKind_GlobalVar)
  19554. {
  19555. // Don't create a func
  19556. return;
  19557. }
  19558. auto typeInstance = methodInstance->GetOwner();
  19559. auto methodDef = methodInstance->mMethodDef;
  19560. BfIRFunctionType funcType = mBfIRBuilder->MapMethod(methodInstance);
  19561. if (isTemporaryFunc)
  19562. {
  19563. BF_ASSERT(((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) ||
  19564. (methodInstance->GetOwner()->mDefineState < BfTypeDefineState_Defined));
  19565. mangledName = "autocomplete_tmp";
  19566. }
  19567. if (!mBfIRBuilder->mIgnoreWrites)
  19568. {
  19569. BfIRFunction prevFunc;
  19570. // Remove old version (if we have one)
  19571. prevFunc = mBfIRBuilder->GetFunction(mangledName);
  19572. if (prevFunc)
  19573. {
  19574. if ((methodDef->mIsOverride) && (mCurTypeInstance->mTypeDef->mIsCombinedPartial))
  19575. {
  19576. bool takeover = false;
  19577. mCurTypeInstance->mTypeDef->PopulateMemberSets();
  19578. BfMethodDef* nextMethod = NULL;
  19579. BfMemberSetEntry* entry = NULL;
  19580. if (mCurTypeInstance->mTypeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  19581. nextMethod = (BfMethodDef*)entry->mMemberDef;
  19582. while (nextMethod != NULL)
  19583. {
  19584. auto checkMethod = nextMethod;
  19585. nextMethod = nextMethod->mNextWithSameName;
  19586. if (checkMethod == methodDef)
  19587. continue;
  19588. if (checkMethod->mIsOverride)
  19589. {
  19590. auto checkMethodInstance = mCurTypeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
  19591. if (checkMethodInstance == NULL)
  19592. continue;
  19593. if ((checkMethodInstance->mIRFunction == prevFunc) &&
  19594. (checkMethodInstance->mMethodDef->mMethodDeclaration != NULL) &&
  19595. (checkMethodInstance->mVirtualTableIdx < 0))
  19596. {
  19597. BfAstNode* refNode = methodDef->GetRefNode();
  19598. if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
  19599. refNode = propertyMethodDeclaration->mPropertyDeclaration->mVirtualSpecifier;
  19600. else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  19601. refNode = methodDeclaration->mVirtualSpecifier;
  19602. auto error = Fail(StrFormat("Conflicting extension override method '%s'", MethodToString(mCurMethodInstance).c_str()), refNode);
  19603. if (error != NULL)
  19604. mCompiler->mPassInstance->MoreInfo("See previous override", checkMethod->GetRefNode());
  19605. takeover = false;
  19606. break;
  19607. }
  19608. }
  19609. if (!checkMethod->mIsExtern)
  19610. continue;
  19611. auto checkMethodInstance = mCurTypeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
  19612. if (checkMethodInstance == NULL)
  19613. continue;
  19614. if (!CompareMethodSignatures(checkMethodInstance, mCurMethodInstance))
  19615. continue;
  19616. // Take over function
  19617. takeover = true;
  19618. }
  19619. if (takeover)
  19620. mCurMethodInstance->mIRFunction = prevFunc;
  19621. if (!mCurMethodInstance->mIRFunction)
  19622. {
  19623. BfLogSysM("Function collision from inner override erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
  19624. if (!mIsComptimeModule)
  19625. mBfIRBuilder->Func_SafeRename(prevFunc);
  19626. }
  19627. }
  19628. else if (methodDef->mIsExtern)
  19629. {
  19630. // Allow this
  19631. BfLogSysM("Function collision allowed multiple extern functions for %p: %d\n", methodInstance, prevFunc.mId);
  19632. }
  19633. else if (typeInstance->IsIRFuncUsed(prevFunc))
  19634. {
  19635. // We can have a collision of names when we have generic methods that differ only in
  19636. // their constraints, but they should only collide in their unspecialized form
  19637. // since only one will be chosen for a given concrete type
  19638. if (!mIsComptimeModule)
  19639. mCurMethodInstance->mMangleWithIdx = true;
  19640. mangledName.Clear();
  19641. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
  19642. prevFunc = mBfIRBuilder->GetFunction(mangledName);
  19643. BfLogSysM("Function collision forced mangleWithIdx for %p: %d\n", methodInstance, prevFunc.mId);
  19644. }
  19645. else
  19646. {
  19647. BfLogSysM("Function collision erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
  19648. if (!mIsComptimeModule)
  19649. mBfIRBuilder->Func_SafeRename(prevFunc);
  19650. }
  19651. }
  19652. }
  19653. if (typeInstance != mContext->mBfObjectType)
  19654. {
  19655. // Only allow attributes on System.Object methods that can be handled inside the DefBuilder
  19656. GetMethodCustomAttributes(methodInstance);
  19657. }
  19658. // if (prevFunc)
  19659. // {
  19660. // if (methodDef->mIsExtern)
  19661. // {
  19662. // BfLogSysM("Reusing function for %p: %d\n", methodInstance, prevFunc.mId);
  19663. // methodInstance->mIRFunction = prevFunc;
  19664. // }
  19665. // else
  19666. // {
  19667. // if ((methodInstance->IsSpecializedByAutoCompleteMethod()) ||
  19668. // ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mResolveType >= BfResolveType_GoToDefinition)))
  19669. // {
  19670. // // If we're doing re-pass over the methods for something like BfResolveType_ShowFileSymbolReferences, then allow this collision
  19671. // BfLogSysM("Ignoring function name collision\n");
  19672. // }
  19673. // else
  19674. // {
  19675. // if (methodDef->mMethodDeclaration == NULL)
  19676. // {
  19677. // AssertErrorState();
  19678. // }
  19679. // else
  19680. // {
  19681. // BF_ASSERT(mIsSpecialModule);
  19682. // if ((mCompiler->mRevision == 1) && (HasCompiledOutput()))
  19683. // {
  19684. // // We shouldn't have name collisions on the first run!
  19685. // AssertErrorState();
  19686. // }
  19687. // }
  19688. // }
  19689. // BfLogSysM("Before erase\n");
  19690. // mBfIRBuilder->Func_EraseFromParent(prevFunc);
  19691. // }
  19692. // }
  19693. bool isIntrinsic = false;
  19694. if (!methodInstance->mIRFunction)
  19695. {
  19696. BfIRFunction func;
  19697. bool wantsLLVMFunc = ((!typeInstance->IsUnspecializedType() || (mIsComptimeModule)) &&
  19698. (!methodDef->IsEmptyPartial())) && (funcType);
  19699. /*if (mCurTypeInstance->mTypeDef->mName->ToString() == "ClassA")
  19700. {
  19701. if (!mIsReified)
  19702. wantsLLVMFunc = false;
  19703. }*/
  19704. if (wantsLLVMFunc)
  19705. {
  19706. func = GetIntrinsic(methodInstance, true);
  19707. if (func)
  19708. {
  19709. isIntrinsic = true;
  19710. }
  19711. else
  19712. {
  19713. func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, mangledName);
  19714. BfLogSysM("Creating FuncId:%d %s in module %p\n", func.mId, mangledName.c_str(), this);
  19715. if (methodInstance->mAlwaysInline)
  19716. mBfIRBuilder->Func_AddAttribute(func, -1, BFIRAttribute_AlwaysInline);
  19717. // if (prevFunc)
  19718. // BfLogSysM("Removing Func %d, replacing with %d\n", prevFunc.mId, func.mId);
  19719. }
  19720. methodInstance->mIRFunction = func;
  19721. //if (!ignoreWrites)
  19722. //BF_ASSERT(!func.IsFake());
  19723. }
  19724. }
  19725. if (outIsIntrinsic != NULL)
  19726. *outIsIntrinsic = isIntrinsic;
  19727. if (!isIntrinsic)
  19728. SetupIRMethod(methodInstance, methodInstance->mIRFunction, methodInstance->mAlwaysInline);
  19729. }
  19730. void BfModule::CheckHotMethod(BfMethodInstance* methodInstance, const StringImpl& inMangledName)
  19731. {
  19732. if (methodInstance->mHotMethod != NULL)
  19733. return;
  19734. if ((mCompiler->mOptions.mAllowHotSwapping) && (!methodInstance->mIsUnspecialized))
  19735. {
  19736. auto srcTypeInst = methodInstance->GetOwner();
  19737. StringT<128> mangledName = inMangledName;
  19738. if (mangledName.IsEmpty())
  19739. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
  19740. // We always keep the current primary method at the same address
  19741. BfHotMethod* hotMethod;
  19742. BfHotMethod** hotMethodPtr;
  19743. if (mCompiler->mHotData->mMethodMap.TryAdd(mangledName, NULL, &hotMethodPtr))
  19744. {
  19745. hotMethod = new BfHotMethod();
  19746. *hotMethodPtr = hotMethod;
  19747. hotMethod->mRefCount = 1;
  19748. hotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_IsBound);
  19749. #ifdef BF_DBG_HOTMETHOD_IDX
  19750. static int sMethodIdx = 0;
  19751. hotMethod->mMethodIdx = sMethodIdx++;
  19752. #endif
  19753. BfLogSysM("HotMethodData %p created for method %p %s - %s\n", hotMethod, methodInstance, MethodToString(methodInstance).c_str(), mangledName.c_str());
  19754. }
  19755. else
  19756. {
  19757. hotMethod = *hotMethodPtr;
  19758. if ((hotMethod->mFlags & BfHotDepDataFlag_IsBound) != 0)
  19759. {
  19760. // This is a duplicate mangled name - we link to this new entry via a 'BfHotDupMethod'
  19761. auto prevHotMethod = *hotMethodPtr;
  19762. hotMethod = new BfHotMethod();
  19763. hotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_IsBound);
  19764. BfHotDupMethod* hotDupMethod = new BfHotDupMethod(hotMethod);
  19765. hotDupMethod->mRefCount++;
  19766. prevHotMethod->mReferences.Add(hotDupMethod);
  19767. prevHotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_HasDup);
  19768. BfLogSysM("HotMethodData %p (duplicate of %p) created for method %p %s - %s\n", hotMethod, prevHotMethod, methodInstance, MethodToString(methodInstance).c_str(), mangledName.c_str());
  19769. }
  19770. else if (mCompiler->IsHotCompile())
  19771. {
  19772. // Link the previous version into the mPrevVersion
  19773. BfHotMethod* prevMethod = new BfHotMethod();
  19774. prevMethod->mRefCount = 1;
  19775. prevMethod->mPrevVersion = hotMethod->mPrevVersion;
  19776. hotMethod->mPrevVersion = prevMethod;
  19777. prevMethod->mSrcTypeVersion = hotMethod->mSrcTypeVersion;
  19778. hotMethod->mSrcTypeVersion = NULL;
  19779. prevMethod->mFlags = hotMethod->mFlags;
  19780. hotMethod->mFlags = BfHotDepDataFlag_IsBound;
  19781. hotMethod->mReferences.MoveTo(prevMethod->mReferences);
  19782. #ifdef BF_DBG_HOTMETHOD_NAME
  19783. prevMethod->mMangledName = hotMethod->mMangledName;
  19784. #endif
  19785. BfLogSysM("HotMethodData %p created for prevmethod of %p for method %p %s\n", prevMethod, hotMethod, methodInstance, MethodToString(methodInstance).c_str());
  19786. }
  19787. else
  19788. {
  19789. BfLogSysM("HotMethodData %p used for method %p %s - %s\n", hotMethod, methodInstance, MethodToString(methodInstance).c_str(), mangledName.c_str());
  19790. hotMethod->Clear(true);
  19791. hotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_IsBound);
  19792. }
  19793. }
  19794. if (methodInstance->mIsClosure)
  19795. {
  19796. hotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_RetainMethodWithoutBinding);
  19797. }
  19798. hotMethod->mSrcTypeVersion = srcTypeInst->mHotTypeData->GetLatestVersion();
  19799. hotMethod->mSrcTypeVersion->mRefCount++;
  19800. hotMethod->mRefCount++;
  19801. #ifdef BF_DBG_HOTMETHOD_NAME
  19802. hotMethod->mMangledName = mangledName;
  19803. #endif
  19804. if ((methodInstance->mMethodInstanceGroup->IsImplemented()) && (!IsHotCompile()))
  19805. hotMethod->mFlags = (BfHotDepDataFlags)(hotMethod->mFlags | BfHotDepDataFlag_IsOriginalBuild);
  19806. methodInstance->mHotMethod = hotMethod;
  19807. }
  19808. }
  19809. static void StackOverflow()
  19810. {
  19811. int i = 0;
  19812. if (i == 0)
  19813. StackOverflow();
  19814. }
  19815. void BfModule::StartMethodDeclaration(BfMethodInstance* methodInstance, BfMethodState* prevMethodState)
  19816. {
  19817. methodInstance->mHasStartedDeclaration = true;
  19818. auto methodDef = methodInstance->mMethodDef;
  19819. auto typeInstance = methodInstance->GetOwner();
  19820. bool hasNonGenericParams = false;
  19821. bool hasGenericParams = false;
  19822. int dependentGenericStartIdx = 0;
  19823. if (methodDef->mIsLocalMethod)
  19824. {
  19825. // If we're a local generic method inside an outer generic method, we can still be considered unspecialized
  19826. // if our outer method's generic args are specialized but ours are unspecialized. This is because locals get
  19827. // instantiated uniquely for each specialized or unspecialized pass through the outer method, but the local
  19828. // method still 'inherits' the outer's generic arguments -- but we still need to make an unspecialized pass
  19829. // over the local method each time
  19830. auto rootMethodInstance = prevMethodState->GetRootMethodState()->mMethodInstance;
  19831. dependentGenericStartIdx = 0;
  19832. if (rootMethodInstance != NULL)
  19833. {
  19834. if (rootMethodInstance->mMethodInfoEx != NULL)
  19835. dependentGenericStartIdx = (int)rootMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
  19836. methodInstance->mIsUnspecialized = rootMethodInstance->mIsUnspecialized;
  19837. methodInstance->mIsUnspecializedVariation = rootMethodInstance->mIsUnspecializedVariation;
  19838. }
  19839. }
  19840. for (int genericArgIdx = dependentGenericStartIdx; genericArgIdx < (int)methodInstance->GetNumGenericArguments(); genericArgIdx++)
  19841. {
  19842. auto genericArgType = methodInstance->mMethodInfoEx->mMethodGenericArguments[genericArgIdx];
  19843. if (genericArgType->IsGenericParam())
  19844. {
  19845. hasGenericParams = true;
  19846. auto genericParam = (BfGenericParamType*)genericArgType;
  19847. methodInstance->mIsUnspecialized = true;
  19848. if ((genericParam->mGenericParamKind != BfGenericParamKind_Method) || (genericParam->mGenericParamIdx != genericArgIdx))
  19849. methodInstance->mIsUnspecializedVariation = true;
  19850. }
  19851. else
  19852. {
  19853. hasNonGenericParams = true;
  19854. if (genericArgType->IsUnspecializedType())
  19855. {
  19856. methodInstance->mIsUnspecialized = true;
  19857. methodInstance->mIsUnspecializedVariation = true;
  19858. }
  19859. }
  19860. }
  19861. if ((hasGenericParams) && (hasNonGenericParams))
  19862. {
  19863. methodInstance->mIsUnspecializedVariation = true;
  19864. }
  19865. if (typeInstance->IsUnspecializedType())
  19866. {
  19867. // A specialized method within an unspecialized type is considered an unspecialized variation -- in the sense that we don't
  19868. // actually want to do method processing on it
  19869. if ((!methodInstance->mIsUnspecialized) && (methodInstance->GetNumGenericArguments() != 0))
  19870. methodInstance->mIsUnspecializedVariation = true;
  19871. methodInstance->mIsUnspecialized = true;
  19872. }
  19873. if (methodInstance->mIsUnspecializedVariation)
  19874. BF_ASSERT(methodInstance->mIsUnspecialized);
  19875. //TODO: Why did we do this?
  19876. if (methodDef->mMethodType == BfMethodType_Mixin)
  19877. {
  19878. if (methodInstance->IsSpecializedGenericMethod())
  19879. methodInstance->mIsUnspecializedVariation = true;
  19880. methodInstance->mIsUnspecialized = true;
  19881. }
  19882. }
  19883. // methodDeclaration is NULL for default constructors
  19884. void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool isTemporaryFunc, bool addToWorkList)
  19885. {
  19886. BF_ASSERT((mCompiler->mCeMachine == NULL) || (!mCompiler->mCeMachine->mDbgPaused));
  19887. BP_ZONE("BfModule::DoMethodDeclaration");
  19888. // We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here
  19889. // to effectively make mIgnoreWrites method-scoped
  19890. SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized || mCurTypeInstance->mResolvingVarField);
  19891. SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
  19892. SetAndRestoreValue<bool> prevAllowLockYield(mContext->mAllowLockYield, false);
  19893. BfTypeState typeState(mCurTypeInstance);
  19894. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  19895. if (mCompiler->IsAutocomplete())
  19896. prevIsCapturingMethodMatchInfo.Init(mCompiler->mResolvePassData->mAutoComplete->mIsCapturingMethodMatchInfo, false);
  19897. if (mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference)
  19898. mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
  19899. BfMethodState methodState;
  19900. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  19901. methodState.mTempKind = BfMethodState::TempKind_Static;
  19902. defer({ mCurMethodInstance->mHasBeenDeclared = true; });
  19903. // If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info
  19904. BF_ASSERT((!mCurTypeInstance->mResolvingVarField) || (mBfIRBuilder->mIgnoreWrites));
  19905. bool ignoreWrites = mBfIRBuilder->mIgnoreWrites;
  19906. // if ((!isTemporaryFunc) && (mCurTypeInstance->mDefineState < BfTypeDefineState_Defined))
  19907. // {
  19908. // BF_ASSERT(mContext->mResolvingVarField);
  19909. // isTemporaryFunc = true;
  19910. // }
  19911. if ((mAwaitingInitFinish) && (!mBfIRBuilder->mIgnoreWrites))
  19912. FinishInit();
  19913. auto typeInstance = mCurTypeInstance;
  19914. auto typeDef = typeInstance->mTypeDef;
  19915. auto methodDef = mCurMethodInstance->mMethodDef;
  19916. BF_ASSERT(methodDef->mName != "__ASSERTNAME");
  19917. if (methodDef->mName == "__FATALERRORNAME")
  19918. BFMODULE_FATAL(this, "__FATALERRORNAME");
  19919. if (methodDef->mName == "__STACKOVERFLOW")
  19920. StackOverflow();
  19921. if (typeInstance->IsClosure())
  19922. {
  19923. if (methodDef->mName == "Invoke")
  19924. return;
  19925. }
  19926. auto methodInstance = mCurMethodInstance;
  19927. if ((methodInstance->IsSpecializedByAutoCompleteMethod()) || (mCurTypeInstance->IsFunction()))
  19928. addToWorkList = false;
  19929. if (!methodInstance->mHasStartedDeclaration)
  19930. StartMethodDeclaration(methodInstance, prevMethodState.mPrevVal);
  19931. BfAutoComplete* bfAutocomplete = NULL;
  19932. if (mCompiler->mResolvePassData != NULL)
  19933. bfAutocomplete = mCompiler->mResolvePassData->mAutoComplete;
  19934. if (methodInstance->mMethodInfoEx != NULL)
  19935. {
  19936. BfTypeInstance* unspecializedTypeInstance = NULL;
  19937. Array<BfTypeReference*> deferredResolveTypes;
  19938. for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
  19939. {
  19940. auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
  19941. if (genericParamIdx < (int)methodDef->mGenericParams.size())
  19942. {
  19943. genericParam->mExternType = GetGenericParamType(BfGenericParamKind_Method, genericParamIdx);
  19944. }
  19945. else
  19946. {
  19947. auto externConstraintDef = genericParam->GetExternConstraintDef();
  19948. genericParam->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
  19949. auto autoComplete = mCompiler->GetAutoComplete();
  19950. if (autoComplete != NULL)
  19951. autoComplete->CheckTypeRef(externConstraintDef->mTypeRef, false);
  19952. if (genericParam->mExternType != NULL)
  19953. {
  19954. //
  19955. }
  19956. else
  19957. genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
  19958. }
  19959. ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized, &deferredResolveTypes);
  19960. if (genericParamIdx < (int)methodDef->mGenericParams.size())
  19961. {
  19962. auto genericParamDef = methodDef->mGenericParams[genericParamIdx];
  19963. if (bfAutocomplete != NULL)
  19964. {
  19965. for (auto nameNode : genericParamDef->mNameNodes)
  19966. {
  19967. HandleMethodGenericParamRef(nameNode, typeDef, methodDef, genericParamIdx);
  19968. }
  19969. }
  19970. }
  19971. }
  19972. for (auto typeRef : deferredResolveTypes)
  19973. auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
  19974. if (methodInstance->mMethodInfoEx != NULL)
  19975. {
  19976. ValidateGenericParams(BfGenericParamKind_Method,
  19977. Span<BfGenericParamInstance*>((BfGenericParamInstance**)methodInstance->mMethodInfoEx->mGenericParams.mVals,
  19978. methodInstance->mMethodInfoEx->mGenericParams.mSize));
  19979. }
  19980. for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
  19981. AddDependency(genericParam, mCurTypeInstance);
  19982. }
  19983. if ((methodInstance->mIsAutocompleteMethod) && (methodDeclaration != NULL) && (!methodInstance->IsSpecializedGenericMethod()) && (methodDef->mIdx >= 0))
  19984. {
  19985. auto autoComplete = mCompiler->mResolvePassData->mAutoComplete;
  19986. BfAstNode* nameNode = methodDeclaration->mNameNode;
  19987. if (nameNode == NULL)
  19988. {
  19989. if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
  19990. nameNode = ctorDeclaration->mThisToken;
  19991. }
  19992. if ((autoComplete->IsAutocompleteNode(nameNode)) && (autoComplete->mResolveType != BfResolveType_Autocomplete))
  19993. {
  19994. autoComplete->mInsertStartIdx = nameNode->GetSrcStart();
  19995. autoComplete->mInsertEndIdx = nameNode->GetSrcEnd();
  19996. autoComplete->mDefType = typeDef;
  19997. autoComplete->mDefMethod = methodDef;
  19998. autoComplete->SetDefinitionLocation(nameNode);
  19999. if (methodDef->mIsOverride)
  20000. {
  20001. bool found = false;
  20002. for (int virtIdx = 0; virtIdx < (int)typeInstance->mVirtualMethodTable.size(); virtIdx++)
  20003. {
  20004. auto& ventry = typeInstance->mVirtualMethodTable[virtIdx];
  20005. if (ventry.mDeclaringMethod.mMethodNum == -1)
  20006. continue;
  20007. BfMethodInstance* virtMethod = ventry.mImplementingMethod;
  20008. if (virtMethod != NULL)
  20009. {
  20010. auto virtMethodDeclaration = virtMethod->mMethodDef->GetMethodDeclaration();
  20011. if ((virtMethod->GetOwner() == typeInstance) && (virtMethodDeclaration != NULL) &&
  20012. (virtMethodDeclaration->GetSrcStart() == methodDeclaration->GetSrcStart()))
  20013. {
  20014. // Is matching method
  20015. if (virtIdx < (int)typeInstance->mBaseType->mVirtualMethodTable.size())
  20016. {
  20017. auto baseType = typeInstance->mBaseType;
  20018. if (baseType != NULL)
  20019. {
  20020. found = true;
  20021. while ((baseType->mBaseType != NULL) && (virtIdx < baseType->mBaseType->mVirtualMethodTableSize))
  20022. baseType = baseType->mBaseType;
  20023. BfMethodInstance* baseVirtMethod = baseType->mVirtualMethodTable[virtIdx].mImplementingMethod;
  20024. autoComplete->SetDefinitionLocation(baseVirtMethod->mMethodDef->GetRefNode(), true);
  20025. autoComplete->mDefType = baseType->mTypeDef;
  20026. autoComplete->mDefMethod = baseVirtMethod->mMethodDef;
  20027. }
  20028. }
  20029. break;
  20030. }
  20031. }
  20032. }
  20033. if ((!found) && (autoComplete->mIsGetDefinition) && (methodDef->mDeclaringType->IsExtension()))
  20034. {
  20035. for (auto& methodGroup : typeInstance->mMethodInstanceGroups)
  20036. {
  20037. auto defaultMethod = methodGroup.mDefault;
  20038. if (defaultMethod == NULL)
  20039. continue;
  20040. if (!defaultMethod->mMethodDef->mIsExtern)
  20041. continue;
  20042. if (!CompareMethodSignatures(defaultMethod, methodInstance))
  20043. continue;
  20044. autoComplete->SetDefinitionLocation(defaultMethod->mMethodDef->GetRefNode(), true);
  20045. autoComplete->mDefType = typeInstance->mTypeDef;
  20046. autoComplete->mDefMethod = defaultMethod->mMethodDef;
  20047. }
  20048. }
  20049. }
  20050. }
  20051. }
  20052. bool reportErrors = true;
  20053. if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL))
  20054. reportErrors = true;
  20055. // Only the defining contexts needs to report errors here
  20056. SetAndRestoreValue<bool> prevReporErrors(mReportErrors, reportErrors);
  20057. if (methodDef->mMethodType == BfMethodType_Dtor)
  20058. {
  20059. if (methodDef->mIsStatic)
  20060. {
  20061. }
  20062. else
  20063. {
  20064. if ((typeInstance->IsStruct()) || (typeInstance->IsTypedPrimitive()))
  20065. {
  20066. BfAstNode* refNode = methodDeclaration;
  20067. if (refNode == NULL)
  20068. {
  20069. // Whatever caused this ctor to be generated should have caused another failure
  20070. // But that failure might not be generated until the ctor is generated
  20071. }
  20072. else
  20073. {
  20074. auto dtorDecl = BfNodeDynCast<BfDestructorDeclaration>(methodDeclaration);
  20075. if (dtorDecl != NULL)
  20076. refNode = dtorDecl->mThisToken;
  20077. Fail("Structs cannot have destructors", refNode);
  20078. }
  20079. }
  20080. auto methodDeclaration = methodDef->GetMethodDeclaration();
  20081. if ((methodDeclaration != NULL) && (methodDeclaration->mVirtualSpecifier != NULL) &&
  20082. (mCurTypeInstance != mContext->mBfObjectType))
  20083. {
  20084. Fail("Virtual specifier is not required, all destructors are implicitly virtual.", methodDeclaration->mVirtualSpecifier);
  20085. }
  20086. }
  20087. }
  20088. BfType* resolvedReturnType = NULL;
  20089. if (((methodDef->mMethodType == BfMethodType_Normal) || (methodDef->mMethodType == BfMethodType_Extension) || (methodDef->mMethodType == BfMethodType_CtorCalcAppend) ||
  20090. (methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_Operator)) &&
  20091. (methodDef->mReturnTypeRef != NULL))
  20092. {
  20093. SetAndRestoreValue<bool> prevIngoreErrors(mIgnoreErrors, mIgnoreErrors || (methodDef->GetPropertyDeclaration() != NULL));
  20094. BfResolveTypeRefFlags flags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric);
  20095. if ((((methodInstance->mComptimeFlags & BfComptimeFlag_ConstEval) != 0) || (methodInstance->mIsAutocompleteMethod))
  20096. && (methodDef->mReturnTypeRef->IsA<BfVarTypeReference>()))
  20097. resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
  20098. else
  20099. resolvedReturnType = ResolveTypeRef(methodDef->mReturnTypeRef, BfPopulateType_Declaration, flags);
  20100. if (resolvedReturnType == NULL)
  20101. resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
  20102. if ((methodDef->mIsReadOnly) && (!resolvedReturnType->IsRef()))
  20103. {
  20104. if (auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration))
  20105. if (methodDeclaration->mReadOnlySpecifier != NULL)
  20106. Fail("Readonly specifier is only valid on 'ref' return types", methodDeclaration->mReadOnlySpecifier);
  20107. }
  20108. }
  20109. else
  20110. {
  20111. resolvedReturnType = ResolveTypeDef(mSystem->mTypeVoid);
  20112. }
  20113. BF_ASSERT(resolvedReturnType != NULL);
  20114. mCurMethodInstance->mReturnType = resolvedReturnType;
  20115. //TODO: We used to NOT add the return value dependency for specialized methods, but when we have types that are
  20116. // specialized based on the method's generic param then they can get deleted if no one else has referred to them (yet)
  20117. //if (!methodInstance->IsSpecializedGenericMethod())
  20118. AddDependency(resolvedReturnType, typeInstance, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
  20119. if (methodDef->mExplicitInterface != NULL)
  20120. {
  20121. auto autoComplete = mCompiler->GetAutoComplete();
  20122. if (autoComplete != NULL)
  20123. autoComplete->CheckTypeRef(methodDef->mExplicitInterface, false);
  20124. auto explicitType = ResolveTypeRef(methodDef->mExplicitInterface, BfPopulateType_Declaration);
  20125. BfTypeInstance* explicitInterface = NULL;
  20126. if (explicitType != NULL)
  20127. explicitInterface = explicitType->ToTypeInstance();
  20128. if (explicitInterface != NULL)
  20129. {
  20130. mCurMethodInstance->GetMethodInfoEx()->mExplicitInterface = explicitInterface->ToTypeInstance();
  20131. if (autoComplete != NULL)
  20132. {
  20133. BfTokenNode* dotToken = NULL;
  20134. BfAstNode* nameNode = NULL;
  20135. if (auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodDef->mMethodDeclaration))
  20136. {
  20137. dotToken = methodDeclaration->mExplicitInterfaceDotToken;
  20138. nameNode = methodDeclaration->mNameNode;
  20139. }
  20140. autoComplete->CheckExplicitInterface(explicitInterface, dotToken, nameNode);
  20141. }
  20142. }
  20143. if ((mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mExplicitInterface != NULL))
  20144. {
  20145. bool interfaceFound = false;
  20146. for (auto ifaceInst : typeInstance->mInterfaces)
  20147. interfaceFound |= ifaceInst.mInterfaceType == mCurMethodInstance->mMethodInfoEx->mExplicitInterface;
  20148. if ((!interfaceFound) && (!typeInstance->mTypeFailed))
  20149. {
  20150. if (methodDef->mMethodDeclaration != NULL)
  20151. Fail("Containing class has not declared to implement this interface", methodDef->mMethodDeclaration);
  20152. else
  20153. {
  20154. // For property decls, we should have already given the error during type population
  20155. if (mCompiler->mRevision == 1)
  20156. AssertErrorState();
  20157. }
  20158. }
  20159. }
  20160. }
  20161. bool isThisStruct = mCurTypeInstance->IsStruct();
  20162. BfType* thisType = NULL;
  20163. if ((!methodDef->mIsStatic) && (!mCurTypeInstance->IsValuelessType()))
  20164. {
  20165. if ((isThisStruct) || (mCurTypeInstance->IsTypedPrimitive()))
  20166. {
  20167. thisType = mCurTypeInstance;
  20168. if (thisType == NULL)
  20169. return;
  20170. if ((thisType->IsSplattable()) && (!methodDef->HasNoThisSplat()))
  20171. {
  20172. BfTypeUtils::SplatIterate([&](BfType* checkType)
  20173. {
  20174. PopulateType(checkType, BfPopulateType_Data);
  20175. }, thisType);
  20176. }
  20177. }
  20178. else
  20179. {
  20180. thisType = mCurTypeInstance;
  20181. PopulateType(thisType, BfPopulateType_Declaration);
  20182. }
  20183. }
  20184. int implicitParamCount = 0;
  20185. if ((mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mClosureInstanceInfo != NULL))
  20186. implicitParamCount = (int)methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries.size();
  20187. methodInstance->mMethodDef->mParams.Reserve((int)methodDef->mParams.size());
  20188. bool hadDelegateParams = false;
  20189. bool hadParams = false;
  20190. for (int paramIdx = 0; paramIdx < (int)methodDef->mParams.size() + implicitParamCount; paramIdx++)
  20191. {
  20192. BfClosureCapturedEntry* closureCaptureEntry = NULL;
  20193. BfParameterDef* paramDef = NULL;
  20194. int paramDefIdx = -1;
  20195. if (paramIdx < implicitParamCount)
  20196. closureCaptureEntry = &methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureEntries[paramIdx];
  20197. else
  20198. {
  20199. paramDefIdx = paramIdx - implicitParamCount;
  20200. paramDef = methodDef->mParams[paramDefIdx];
  20201. }
  20202. if (hadParams)
  20203. break;
  20204. if ((paramDef != NULL) && (paramDef->mParamKind == BfParamKind_VarArgs))
  20205. continue;
  20206. if ((paramDef != NULL) && (mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) &&
  20207. (paramDef->mParamKind != BfParamKind_AppendIdx))
  20208. {
  20209. mCompiler->mResolvePassData->mAutoComplete->CheckTypeRef(paramDef->mTypeRef, false);
  20210. if (mCompiler->mResolvePassData->mAutoComplete->IsAutocompleteNode(paramDef->mTypeRef))
  20211. mCompiler->mResolvePassData->mAutoComplete->AddEntry(AutoCompleteEntry("token", "in"), paramDef->mTypeRef->ToString());
  20212. }
  20213. if ((paramDef != NULL) && (paramDef->mParamDeclaration != NULL) && (paramDef->mParamDeclaration->mAttributes != NULL))
  20214. {
  20215. if (methodInstance->GetMethodInfoEx()->mMethodCustomAttributes == NULL)
  20216. methodInstance->mMethodInfoEx->mMethodCustomAttributes = new BfMethodCustomAttributes();
  20217. while ((int)methodInstance->mMethodInfoEx->mMethodCustomAttributes->mParamCustomAttributes.size() < paramIdx)
  20218. methodInstance->mMethodInfoEx->mMethodCustomAttributes->mParamCustomAttributes.push_back(NULL);
  20219. auto customAttributes = GetCustomAttributes(paramDef->mParamDeclaration->mAttributes, BfAttributeTargets_Parameter);
  20220. methodInstance->mMethodInfoEx->mMethodCustomAttributes->mParamCustomAttributes.push_back(customAttributes);
  20221. }
  20222. BfType* resolvedParamType = NULL;
  20223. if (closureCaptureEntry != NULL)
  20224. resolvedParamType = closureCaptureEntry->mType;
  20225. else if ((paramDef->mTypeRef != NULL) && (paramDef->mTypeRef->IsA<BfLetTypeReference>()))
  20226. {
  20227. Fail("Cannot declare 'let' parameters", paramDef->mTypeRef);
  20228. resolvedParamType = mContext->mBfObjectType;
  20229. }
  20230. else if ((paramDef->mTypeRef != NULL) && (paramDef->mTypeRef->IsA<BfVarTypeReference>()))
  20231. {
  20232. if (methodDef->mMethodType != BfMethodType_Mixin)
  20233. {
  20234. Fail("Cannot declare var parameters", paramDef->mTypeRef);
  20235. resolvedParamType = mContext->mBfObjectType;
  20236. }
  20237. else
  20238. resolvedParamType = GetPrimitiveType(BfTypeCode_Var);
  20239. }
  20240. BfType* unresolvedParamType = resolvedParamType;
  20241. bool wasGenericParam = false;
  20242. if (resolvedParamType == NULL)
  20243. {
  20244. BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoResolveGenericParam | BfResolveTypeRefFlag_AllowRef | BfResolveTypeRefFlag_AllowRefGeneric | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue);
  20245. if (paramDef->mParamKind == BfParamKind_ExplicitThis)
  20246. resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_NoWarnOnMut);
  20247. resolvedParamType = ResolveTypeRef(paramDef->mTypeRef, BfPopulateType_Declaration, resolveFlags);
  20248. if ((paramDef->mParamKind == BfParamKind_ExplicitThis) && (resolvedParamType != NULL) && (resolvedParamType->IsRef()))
  20249. resolvedParamType = resolvedParamType->GetUnderlyingType();
  20250. }
  20251. if (resolvedParamType == NULL)
  20252. {
  20253. resolvedParamType = GetPrimitiveType(BfTypeCode_Var);
  20254. unresolvedParamType = resolvedParamType;
  20255. if (mCurTypeInstance->IsBoxed())
  20256. {
  20257. auto boxedType = (BfBoxedType*)mCurTypeInstance;
  20258. // If we failed a lookup here then we better have also failed it in the original type
  20259. BF_ASSERT(boxedType->mElementType->ToTypeInstance()->mModule->mHadBuildError || mContext->mFailTypes.Contains(boxedType->mElementType->ToTypeInstance()));
  20260. }
  20261. }
  20262. BF_ASSERT(!resolvedParamType->IsDeleting());
  20263. if (!methodInstance->IsSpecializedGenericMethod())
  20264. AddDependency(resolvedParamType, typeInstance, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
  20265. PopulateType(resolvedParamType, BfPopulateType_Declaration);
  20266. AddDependency(resolvedParamType, mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
  20267. if ((paramDef != NULL) && (paramDef->mParamDeclaration != NULL) && (paramDef->mParamDeclaration->mInitializer != NULL) &&
  20268. (!paramDef->mParamDeclaration->mInitializer->IsA<BfBlock>()))
  20269. {
  20270. if (paramDef->mParamKind == BfParamKind_Params)
  20271. {
  20272. BfAstNode* refNode = paramDef->mParamDeclaration->mEqualsNode;
  20273. if (refNode != NULL)
  20274. refNode = paramDef->mParamDeclaration->mModToken;
  20275. Fail("Cannot specify a default value for a 'params' parameter", refNode);
  20276. }
  20277. BfTypedValue defaultValue;
  20278. if (resolvedParamType->IsConstExprValue())
  20279. {
  20280. auto constExprType = (BfConstExprValueType*)resolvedParamType;
  20281. BfExprEvaluator exprEvaluator(this);
  20282. exprEvaluator.mExpectingType = constExprType->mType;
  20283. exprEvaluator.GetLiteral(NULL, constExprType->mValue);
  20284. defaultValue = exprEvaluator.GetResult();
  20285. }
  20286. else
  20287. {
  20288. BfTypeState typeState;
  20289. typeState.mType = mCurTypeInstance;
  20290. typeState.mCurTypeDef = methodDef->mDeclaringType;
  20291. //typeState.mCurMethodDef = methodDef;
  20292. SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
  20293. BfConstResolver constResolver(this);
  20294. defaultValue = constResolver.Resolve(paramDef->mParamDeclaration->mInitializer, resolvedParamType, (BfConstResolveFlags)(BfConstResolveFlag_NoCast | BfConstResolveFlag_AllowGlobalVariable));
  20295. if ((defaultValue) && (defaultValue.mType != resolvedParamType))
  20296. {
  20297. SetAndRestoreValue<bool> prevIgnoreWrite(mBfIRBuilder->mIgnoreWrites, true);
  20298. auto castedDefaultValue = Cast(paramDef->mParamDeclaration->mInitializer, defaultValue, resolvedParamType, (BfCastFlags)(BfCastFlags_SilentFail | BfCastFlags_NoConversionOperator));
  20299. if ((castedDefaultValue) && (castedDefaultValue.mValue.IsConst()))
  20300. {
  20301. defaultValue = castedDefaultValue; // Good!
  20302. }
  20303. else if (!CanCast(defaultValue, resolvedParamType))
  20304. {
  20305. // We only care that we get a constant value that can be implicitly casted at the callsite- even if that requires
  20306. // a conversion operator.
  20307. // This should throw an error
  20308. defaultValue = Cast(paramDef->mParamDeclaration->mInitializer, defaultValue, resolvedParamType);
  20309. AssertErrorState();
  20310. if (!defaultValue.mValue.IsConst())
  20311. defaultValue = BfTypedValue();
  20312. }
  20313. }
  20314. }
  20315. if (!defaultValue)
  20316. {
  20317. defaultValue = GetDefaultTypedValue(resolvedParamType);
  20318. if (!defaultValue.mValue.IsConst())
  20319. defaultValue = BfTypedValue();
  20320. }
  20321. if (defaultValue)
  20322. {
  20323. if (defaultValue.mType->IsVar())
  20324. {
  20325. AssertErrorState();
  20326. }
  20327. else
  20328. {
  20329. BF_ASSERT(defaultValue.mValue.IsConst());
  20330. while ((int)mCurMethodInstance->mDefaultValues.size() < paramDefIdx)
  20331. mCurMethodInstance->mDefaultValues.Add(BfTypedValue());
  20332. CurrentAddToConstHolder(defaultValue.mValue);
  20333. mCurMethodInstance->mDefaultValues.Add(defaultValue);
  20334. }
  20335. }
  20336. }
  20337. if ((paramDef != NULL) && (paramDef->mParamKind == BfParamKind_Params))
  20338. {
  20339. bool addParams = true;
  20340. bool isValid = false;
  20341. auto resolvedParamTypeInst = resolvedParamType->ToTypeInstance();
  20342. if ((resolvedParamTypeInst != NULL) && (resolvedParamTypeInst->IsInstanceOf(mCompiler->mSpanTypeDef)))
  20343. {
  20344. // Span<T>
  20345. isValid = true;
  20346. }
  20347. else if (resolvedParamType->IsArray())
  20348. {
  20349. // Array is the 'normal' params type
  20350. isValid = true;
  20351. }
  20352. else if (resolvedParamType->IsSizedArray())
  20353. {
  20354. isValid = true;
  20355. }
  20356. else if (resolvedParamType->IsVar())
  20357. {
  20358. isValid = true;
  20359. }
  20360. else if ((resolvedParamType->IsDelegate()) || (resolvedParamType->IsFunction()) || (resolvedParamType->IsMethodRef()))
  20361. {
  20362. hadDelegateParams = true;
  20363. // This means we copy the params from a delegate
  20364. BfMethodParam methodParam;
  20365. methodParam.mResolvedType = resolvedParamType;
  20366. methodParam.mParamDefIdx = paramDefIdx;
  20367. methodParam.mDelegateParamIdx = 0;
  20368. auto invokeMethodInstance = methodParam.GetDelegateParamInvoke();
  20369. for (int delegateParamIdx = 0; delegateParamIdx < invokeMethodInstance->GetParamCount(); delegateParamIdx++)
  20370. {
  20371. methodParam.mDelegateParamIdx = delegateParamIdx;
  20372. mCurMethodInstance->mParams.Add(methodParam);
  20373. auto paramType = invokeMethodInstance->GetParamType(delegateParamIdx);
  20374. if (!methodInstance->IsSpecializedGenericMethod())
  20375. AddDependency(paramType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ParamOrReturnValue);
  20376. }
  20377. isValid = true;
  20378. addParams = false;
  20379. }
  20380. else if (resolvedParamType->IsGenericParam())
  20381. {
  20382. auto genericParamInstance = GetGenericParamInstance((BfGenericParamType*)resolvedParamType);
  20383. if (genericParamInstance->mTypeConstraint != NULL)
  20384. {
  20385. auto typeInstConstraint = genericParamInstance->mTypeConstraint->ToTypeInstance();
  20386. if ((genericParamInstance->mTypeConstraint->IsArray()) || (genericParamInstance->mTypeConstraint->IsSizedArray()))
  20387. {
  20388. BfMethodParam methodParam;
  20389. methodParam.mResolvedType = resolvedParamType;
  20390. methodParam.mParamDefIdx = paramDefIdx;
  20391. mCurMethodInstance->mParams.Add(methodParam);
  20392. isValid = true;
  20393. }
  20394. else if ((genericParamInstance->mTypeConstraint->IsDelegate()) || (genericParamInstance->mTypeConstraint->IsFunction()) ||
  20395. ((genericParamInstance != NULL) && (typeInstConstraint != NULL) &&
  20396. ((typeInstConstraint->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (typeInstConstraint->IsInstanceOf(mCompiler->mFunctionTypeDef)))))
  20397. {
  20398. mCurMethodInstance->mHadGenericDelegateParams = true;
  20399. isValid = true;
  20400. addParams = false;
  20401. }
  20402. }
  20403. }
  20404. else
  20405. {
  20406. auto paramTypeInst = resolvedParamType->ToTypeInstance();
  20407. if ((paramTypeInst != NULL) &&
  20408. ((paramTypeInst->IsInstanceOf(mCompiler->mDelegateTypeDef)) || (paramTypeInst->IsInstanceOf(mCompiler->mFunctionTypeDef))))
  20409. {
  20410. // If we have a 'params T' and 'T' gets specialized with actually 'Delegate' or 'Function' then just ignore it
  20411. isValid = true;
  20412. addParams = false;
  20413. }
  20414. }
  20415. if (!isValid)
  20416. {
  20417. Fail("Parameters with 'params' specifiers can only be used for array, span, delegate, or function types", paramDef->mParamDeclaration->mModToken);
  20418. // Failure case, make it an Object[]
  20419. resolvedParamType = CreateArrayType(mContext->mBfObjectType, 1);
  20420. }
  20421. if ((addParams) && (resolvedParamType != NULL))
  20422. {
  20423. BfMethodParam methodParam;
  20424. methodParam.mResolvedType = resolvedParamType;
  20425. methodParam.mParamDefIdx = paramDefIdx;
  20426. mCurMethodInstance->mParams.push_back(methodParam);
  20427. }
  20428. if (paramDefIdx < (int)methodDef->mParams.size() - 1)
  20429. {
  20430. Fail("Only the last parameter can specify 'params'", paramDef->mParamDeclaration->mModToken);
  20431. }
  20432. }
  20433. else
  20434. {
  20435. BfMethodParam methodParam;
  20436. methodParam.mResolvedType = resolvedParamType;
  20437. methodParam.mParamDefIdx = paramDefIdx;
  20438. mCurMethodInstance->mParams.Add(methodParam);
  20439. }
  20440. }
  20441. if (hadDelegateParams)
  20442. {
  20443. HashSet<String> usedNames;
  20444. Dictionary<int, int> usedParamDefIdx;
  20445. for (auto methodParam : methodDef->mParams)
  20446. {
  20447. usedNames.Add(methodParam->mName);
  20448. }
  20449. for (auto& methodParam : mCurMethodInstance->mParams)
  20450. {
  20451. if ((methodParam.mParamDefIdx != -1) && (methodParam.mDelegateParamIdx == 0))
  20452. {
  20453. int* refCount = NULL;
  20454. usedParamDefIdx.TryAdd(methodParam.mParamDefIdx, NULL, &refCount);
  20455. (*refCount)++;
  20456. }
  20457. }
  20458. for (auto& methodParam : mCurMethodInstance->mParams)
  20459. {
  20460. if (methodParam.mDelegateParamIdx != -1)
  20461. {
  20462. if (usedParamDefIdx[methodParam.mParamDefIdx] > 1)
  20463. methodParam.mDelegateParamNameCombine = true;
  20464. BfMethodInstance* invokeMethodInstance = methodParam.GetDelegateParamInvoke();
  20465. String paramName = invokeMethodInstance->GetParamName(methodParam.mDelegateParamIdx);
  20466. if (usedNames.Contains(paramName))
  20467. methodParam.mDelegateParamNameCombine = true;
  20468. }
  20469. }
  20470. }
  20471. int argIdx = 0;
  20472. PopulateType(methodInstance->mReturnType, BfPopulateType_Data);
  20473. if ((!methodDef->mIsStatic) && (!methodDef->mHasExplicitThis))
  20474. {
  20475. int thisIdx = methodDef->mHasExplicitThis ? 0 : -1;
  20476. auto thisType = methodInstance->GetOwner();
  20477. if (methodInstance->GetParamIsSplat(thisIdx))
  20478. argIdx += methodInstance->GetParamType(thisIdx)->GetSplatCount();
  20479. else if (!thisType->IsValuelessType())
  20480. {
  20481. BfTypeCode loweredTypeCode = BfTypeCode_None;
  20482. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  20483. if ((!mIsComptimeModule) && (!methodDef->mIsMutating))
  20484. thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
  20485. argIdx++;
  20486. if (loweredTypeCode2 != BfTypeCode_None)
  20487. argIdx++;
  20488. }
  20489. }
  20490. if ((!mIsComptimeModule) && (methodInstance->GetStructRetIdx() != -1))
  20491. argIdx++;
  20492. for (int paramIdx = 0; paramIdx < mCurMethodInstance->mParams.size(); paramIdx++)
  20493. {
  20494. auto& methodParam = mCurMethodInstance->mParams[paramIdx];
  20495. BfType* checkType = methodParam.mResolvedType;
  20496. int checkArgIdx = argIdx;
  20497. if ((paramIdx == 0) && (methodDef->mHasExplicitThis))
  20498. {
  20499. checkArgIdx = 0;
  20500. checkType = methodInstance->GetThisType();
  20501. }
  20502. if (checkType->IsMethodRef())
  20503. {
  20504. methodParam.mIsSplat = true;
  20505. }
  20506. else if ((checkType->IsComposite()) && (methodInstance->AllowsSplatting(paramIdx)))
  20507. {
  20508. PopulateType(checkType, BfPopulateType_Data);
  20509. if (checkType->IsSplattable())
  20510. {
  20511. bool isSplat = false;
  20512. auto checkTypeInstance = checkType->ToTypeInstance();
  20513. if ((checkTypeInstance != NULL) && (checkTypeInstance->mIsCRepr))
  20514. isSplat = true;
  20515. int splatCount = checkType->GetSplatCount();
  20516. if (checkArgIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
  20517. isSplat = true;
  20518. if (isSplat)
  20519. {
  20520. methodParam.mIsSplat = true;
  20521. argIdx += splatCount;
  20522. continue;
  20523. }
  20524. }
  20525. else if (!checkType->IsValuelessType())
  20526. {
  20527. BfTypeCode loweredTypeCode = BfTypeCode_None;
  20528. BfTypeCode loweredTypeCode2 = BfTypeCode_None;
  20529. if (!mIsComptimeModule)
  20530. checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
  20531. argIdx++;
  20532. if (loweredTypeCode2 != BfTypeCode_None)
  20533. argIdx++;
  20534. continue;
  20535. }
  20536. }
  20537. argIdx++;
  20538. }
  20539. bool hasExternSpecifier = (methodDeclaration != NULL) && (methodDeclaration->mExternSpecifier != NULL);
  20540. if ((hasExternSpecifier) && (methodDeclaration->mBody != NULL))
  20541. {
  20542. Fail("Cannot 'extern' and declare a body", methodDeclaration->mExternSpecifier);
  20543. }
  20544. else if ((methodDeclaration != NULL) && (methodDeclaration->mBody == NULL) && (!hasExternSpecifier) &&
  20545. (!typeInstance->IsInterface()) && (!mCurTypeInstance->IsDelegate()) && (!mCurTypeInstance->IsFunction()) &&
  20546. (!methodDef->mIsPartial) && (!methodDef->mIsAbstract) &&
  20547. (!methodDef->mIsSkipCall))
  20548. {
  20549. if (methodDeclaration->mEndSemicolon == NULL)
  20550. {
  20551. if (auto autoCtorDecl = BfNodeDynCast<BfAutoConstructorDeclaration>(methodDeclaration))
  20552. {
  20553. //
  20554. }
  20555. else
  20556. AssertParseErrorState();
  20557. }
  20558. else
  20559. {
  20560. bool isError = true;
  20561. if (typeInstance->IsTypedPrimitive())
  20562. {
  20563. if (auto operatorDeclaration = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
  20564. {
  20565. if ((operatorDeclaration->mIsConvOperator) && (methodInstance->mParams.size() == 1))
  20566. {
  20567. if (((methodInstance->mReturnType == typeInstance) && (methodInstance->GetParamType(0) == typeInstance->GetUnderlyingType())) ||
  20568. ((methodInstance->mReturnType == typeInstance->GetUnderlyingType()) && (methodInstance->GetParamType(0) == typeInstance)))
  20569. {
  20570. isError = false;
  20571. }
  20572. }
  20573. }
  20574. }
  20575. if (isError)
  20576. {
  20577. Fail(StrFormat("'%s' must declare a body because it is not marked abstract, extern, or partial",
  20578. MethodToString(methodInstance).c_str()),
  20579. methodDef->GetRefNode());
  20580. }
  20581. }
  20582. }
  20583. if (methodDef->IsEmptyPartial())
  20584. hasExternSpecifier = true;
  20585. if (!methodInstance->IsAutocompleteMethod())
  20586. {
  20587. auto defaultMethodInstance = methodInstance->mMethodInstanceGroup->mDefault;
  20588. int implicitParamCount = methodInstance->GetImplicitParamCount();
  20589. int defaultImplicitParamCount = defaultMethodInstance->GetImplicitParamCount();
  20590. int actualParamCount = (int)methodInstance->mParams.size() - implicitParamCount;
  20591. BF_ASSERT((actualParamCount == defaultMethodInstance->mParams.size() - defaultImplicitParamCount) || (defaultMethodInstance->mHadGenericDelegateParams));
  20592. mCurMethodInstance->mHadGenericDelegateParams = defaultMethodInstance->mHadGenericDelegateParams;
  20593. int paramIdx = 0;
  20594. int defaultParamIdx = 0;
  20595. while (true)
  20596. {
  20597. bool isDone = paramIdx + implicitParamCount >= (int)methodInstance->mParams.size();
  20598. bool isDefaultDone = defaultParamIdx + defaultImplicitParamCount >= (int)defaultMethodInstance->mParams.size();
  20599. if ((!isDone) && (methodInstance->mParams[paramIdx + implicitParamCount].mDelegateParamIdx >= 0))
  20600. {
  20601. paramIdx++;
  20602. continue;
  20603. }
  20604. if ((!isDefaultDone) && (defaultMethodInstance->mParams[defaultParamIdx + defaultImplicitParamCount].mDelegateParamIdx >= 0))
  20605. {
  20606. defaultParamIdx++;
  20607. continue;
  20608. }
  20609. if ((isDone) || (isDefaultDone))
  20610. {
  20611. // If we have generic delegate params, it's possible we will fail constraints later if we specialize with an invalid type, but we can't allow that
  20612. // to cause us to throw an assertion in the declaration here
  20613. if ((!defaultMethodInstance->mHadGenericDelegateParams) && (!methodInstance->mHasFailed) && (!defaultMethodInstance->mHasFailed))
  20614. BF_ASSERT((isDone) && (isDefaultDone));
  20615. break;
  20616. }
  20617. BfType* paramType = defaultMethodInstance->mParams[defaultParamIdx + defaultImplicitParamCount].mResolvedType;
  20618. if (paramType->IsRef())
  20619. paramType = paramType->GetUnderlyingType();
  20620. methodInstance->mParams[paramIdx + implicitParamCount].mWasGenericParam = paramType->IsGenericParam();
  20621. paramIdx++;
  20622. defaultParamIdx++;
  20623. }
  20624. }
  20625. StringT<4096> mangledName;
  20626. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), mCurMethodInstance);
  20627. for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
  20628. {
  20629. auto paramType = methodInstance->GetParamType(paramIdx);
  20630. if (paramType->IsComposite())
  20631. PopulateType(paramType, BfPopulateType_Data);
  20632. if (!methodInstance->IsParamSkipped(paramIdx))
  20633. {
  20634. if (paramType->IsStruct())
  20635. {
  20636. //
  20637. }
  20638. else
  20639. {
  20640. PopulateType(paramType, BfPopulateType_Declaration);
  20641. }
  20642. }
  20643. }
  20644. // Only process method in default unspecialized mode, not in variations
  20645. if (methodInstance->mIsUnspecializedVariation)
  20646. return;
  20647. PopulateType(resolvedReturnType, BfPopulateType_Data);
  20648. auto retLLVMType = mBfIRBuilder->MapType(resolvedReturnType);
  20649. if (resolvedReturnType->IsValuelessType())
  20650. retLLVMType = mBfIRBuilder->GetPrimitiveType(BfTypeCode_None);
  20651. if (!mBfIRBuilder->mIgnoreWrites)
  20652. {
  20653. bool isIntrinsic = false;
  20654. if (!methodInstance->mIRFunction)
  20655. SetupIRFunction(methodInstance, mangledName, isTemporaryFunc, &isIntrinsic);
  20656. if (isIntrinsic)
  20657. {
  20658. addToWorkList = false;
  20659. }
  20660. }
  20661. else
  20662. {
  20663. GetMethodCustomAttributes(methodInstance);
  20664. }
  20665. auto func = methodInstance->mIRFunction;
  20666. // if (methodInstance->mIsReified)
  20667. // CheckHotMethod(methodInstance, mangledName);
  20668. for (auto& param : methodInstance->mParams)
  20669. {
  20670. BF_ASSERT(!param.mResolvedType->IsDeleting());
  20671. }
  20672. BfLogSysM("DoMethodDeclaration %s Module: %p Type: %p MethodInst: %p Reified: %d Unspecialized: %d IRFunction: %d MethodId:%llx\n", mangledName.c_str(), this, mCurTypeInstance, methodInstance, methodInstance->mIsReified, mCurTypeInstance->IsUnspecializedType(), methodInstance->mIRFunction.mId, methodInstance->mIdHash);
  20673. SizedArray<BfIRMDNode, 8> diParams;
  20674. diParams.push_back(mBfIRBuilder->DbgGetType(resolvedReturnType));
  20675. if ((!methodDef->mIsStatic) && (typeDef->mIsStatic) && (methodDef->mMethodDeclaration != NULL))
  20676. {
  20677. //CS0708
  20678. Fail("Cannot declare instance members in a static class", methodDef->GetRefNode());
  20679. }
  20680. if ((methodDef->mIsVirtual) && (methodDef->mGenericParams.size() != 0))
  20681. {
  20682. Fail("Virtual generic methods not supported", methodDeclaration->mVirtualSpecifier);
  20683. methodDef->mIsVirtual = false;
  20684. }
  20685. BfAstNode* mutSpecifier = NULL;
  20686. if (methodDeclaration != NULL)
  20687. mutSpecifier = methodDeclaration->mMutSpecifier;
  20688. else if (methodDef->GetPropertyMethodDeclaration() != NULL)
  20689. {
  20690. mutSpecifier = methodDef->GetPropertyMethodDeclaration()->mMutSpecifier;
  20691. if (mutSpecifier == NULL)
  20692. {
  20693. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  20694. if (propertyDeclaration != NULL)
  20695. {
  20696. if (auto propExprBody = BfNodeDynCast<BfPropertyBodyExpression>(propertyDeclaration->mDefinitionBlock))
  20697. mutSpecifier = propExprBody->mMutSpecifier;
  20698. }
  20699. }
  20700. }
  20701. if ((mutSpecifier != NULL) && (!mCurTypeInstance->IsBoxed()) && (!methodInstance->mIsForeignMethodDef))
  20702. {
  20703. if (methodDef->mIsStatic)
  20704. Warn(0, "Unnecessary 'mut' specifier, static methods have no implicit 'this' target to mutate", mutSpecifier);
  20705. else if ((!mCurTypeInstance->IsValueType()) && (!mCurTypeInstance->IsInterface()))
  20706. Warn(0, "Unnecessary 'mut' specifier, methods of reference types are implicitly mutating", mutSpecifier);
  20707. else if (methodDef->mMethodType == BfMethodType_Ctor)
  20708. Warn(0, "Unnecessary 'mut' specifier, constructors are implicitly mutating", mutSpecifier);
  20709. else if (methodDef->mMethodType == BfMethodType_Dtor)
  20710. Warn(0, "Unnecessary 'mut' specifier, destructors are implicitly mutating", mutSpecifier);
  20711. }
  20712. if (isTemporaryFunc)
  20713. {
  20714. // This handles temporary methods for autocomplete types
  20715. //BF_ASSERT(mIsScratchModule);
  20716. //BF_ASSERT(mCompiler->IsAutocomplete());
  20717. BfLogSysM("DoMethodDeclaration isTemporaryFunc bailout\n");
  20718. return; // Bail out early for autocomplete pass
  20719. }
  20720. //TODO: We used to have this (this != mContext->mExternalFuncModule) check, but it caused us to keep around
  20721. // an invalid mFuncRefernce (which came from GetMethodInstanceAtIdx) which later got remapped by the
  20722. // autocompleter. Why did we have this check anyway?
  20723. /*if ((typeInstance->mContext != mContext) && (!methodDef->IsEmptyPartial()))
  20724. {
  20725. AddMethodReference(methodInstance);
  20726. mFuncReferences[methodInstance] = func;
  20727. BfLogSysM("Adding func reference (DoMethodDeclaration). Module:%p MethodInst:%p LLVMFunc:%p\n", this, methodInstance, func);
  20728. }*/
  20729. if (mParentModule != NULL)
  20730. {
  20731. // For extension modules we need to keep track of our own methods so we can know which methods
  20732. // we have defined ourselves and which are from the parent module or other extensions
  20733. if (!func.IsFake())
  20734. {
  20735. if (func)
  20736. mFuncReferences[methodInstance] = func;
  20737. }
  20738. }
  20739. if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
  20740. {
  20741. methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
  20742. auto owningModule = methodInstance->GetOwner()->mModule;
  20743. if (!owningModule->mIsScratchModule)
  20744. owningModule->mOnDemandMethodCount++;
  20745. VerifyOnDemandMethods();
  20746. }
  20747. bool wasAwaitingDecl = methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl;
  20748. if (wasAwaitingDecl)
  20749. methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
  20750. if (addToWorkList)
  20751. {
  20752. if ((!methodDef->mIsAbstract) && (!methodInstance->mIgnoreBody))
  20753. {
  20754. AddMethodToWorkList(methodInstance);
  20755. }
  20756. else
  20757. {
  20758. BfLogSysM("DoMethodDeclaration ignoring method body %d %d %d\n", hasExternSpecifier, methodDef->mIsAbstract, methodInstance->mIgnoreBody);
  20759. methodInstance->mIgnoreBody = true;
  20760. if (typeInstance->IsUnspecializedType())
  20761. {
  20762. // Don't hold on to actual Function for unspecialized types
  20763. methodInstance->mIRFunction = BfIRFunction();
  20764. }
  20765. }
  20766. }
  20767. else
  20768. {
  20769. //BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference);
  20770. }
  20771. if ((!methodInstance->IsSpecializedGenericMethodOrType()) && (!mCurTypeInstance->IsBoxed()) &&
  20772. (!methodDef->mIsLocalMethod) &&
  20773. (!CheckDefineMemberProtection(methodDef->mProtection, methodInstance->mReturnType)) &&
  20774. (!methodDef->mReturnTypeRef->IsTemporary()))
  20775. {
  20776. if (methodDef->mMethodType == BfMethodType_PropertyGetter)
  20777. {
  20778. //TODO:
  20779. //CS0053
  20780. Fail(StrFormat("Inconsistent accessibility: property type '%s' is less accessible than property '%s'",
  20781. TypeToString(methodInstance->mReturnType).c_str(), MethodToString(methodInstance).c_str()),
  20782. methodDef->mReturnTypeRef, true);
  20783. }
  20784. else
  20785. {
  20786. //CS0050
  20787. Fail(StrFormat("Inconsistent accessibility: return type '%s' is less accessible than method '%s'",
  20788. TypeToString(methodInstance->mReturnType).c_str(), MethodToString(methodInstance).c_str()),
  20789. methodDef->mReturnTypeRef, true);
  20790. }
  20791. }
  20792. if (typeInstance->IsInterface())
  20793. {
  20794. if (methodDef->mMethodType == BfMethodType_Ctor)
  20795. Fail("Interfaces cannot contain constructors", methodDeclaration);
  20796. if (methodDeclaration != NULL)
  20797. {
  20798. if (methodDef->mBody == NULL)
  20799. {
  20800. if (methodDef->mProtection != BfProtection_Public) //TODO: MAKE AN ERROR
  20801. Warn(0, "Protection specifiers can only be used with interface methods containing a default implementation body", methodDeclaration->mProtectionSpecifier);
  20802. if ((methodDeclaration->mVirtualSpecifier != NULL) &&
  20803. (methodDeclaration->mVirtualSpecifier->mToken != BfToken_Abstract) &&
  20804. (methodDeclaration->mVirtualSpecifier->mToken != BfToken_Concrete)) //TODO: MAKE AN ERROR
  20805. Warn(0, "Virtual specifiers can only be used with interface methods containing a default implementation body", methodDeclaration->mVirtualSpecifier);
  20806. }
  20807. }
  20808. }
  20809. bool foundHiddenMethod = false;
  20810. BfTokenNode* virtualToken = NULL;
  20811. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  20812. if (propertyDeclaration != NULL)
  20813. virtualToken = propertyDeclaration->mVirtualSpecifier;
  20814. else if (methodDeclaration != NULL)
  20815. virtualToken = methodDeclaration->mVirtualSpecifier;
  20816. // Don't compare specialized generic methods against normal methods
  20817. if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) &&
  20818. (!methodDef->mIsLocalMethod) && (!mCurTypeInstance->IsUnspecializedTypeVariation()))
  20819. {
  20820. if ((!methodInstance->mIsForeignMethodDef) && (methodDef->mMethodType != BfMethodType_Init))
  20821. {
  20822. typeDef->PopulateMemberSets();
  20823. BfMethodDef* nextMethod = NULL;
  20824. BfMemberSetEntry* entry = NULL;
  20825. if (typeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  20826. nextMethod = (BfMethodDef*)entry->mMemberDef;
  20827. while (nextMethod != NULL)
  20828. {
  20829. auto checkMethod = nextMethod;
  20830. nextMethod = nextMethod->mNextWithSameName;
  20831. if (checkMethod == methodDef)
  20832. continue;
  20833. auto checkMethodInstance = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
  20834. if (checkMethodInstance == NULL)
  20835. {
  20836. if ((methodDef->mIsNew) && (methodDef->mDeclaringType->IsExtension()) && (!checkMethod->mDeclaringType->IsExtension()))
  20837. checkMethodInstance = GetRawMethodInstanceAtIdx(typeInstance, checkMethod->mIdx);
  20838. if (checkMethodInstance == NULL)
  20839. continue;
  20840. }
  20841. if (((checkMethodInstance->mChainType == BfMethodChainType_None) || (checkMethodInstance->mChainType == BfMethodChainType_ChainHead)) &&
  20842. (checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) &&
  20843. (checkMethod->mIsMutating == methodDef->mIsMutating) &&
  20844. (CompareMethodSignatures(checkMethodInstance, mCurMethodInstance)))
  20845. {
  20846. bool canChain = false;
  20847. if ((methodDef->mParams.empty()) &&
  20848. (checkMethodInstance->mMethodDef->mIsStatic == methodInstance->mMethodDef->mIsStatic))
  20849. {
  20850. if ((methodDef->mMethodType == BfMethodType_CtorNoBody) || (methodDef->mMethodType == BfMethodType_Dtor))
  20851. canChain = true;
  20852. else if (methodDef->mMethodType == BfMethodType_Normal)
  20853. {
  20854. if ((methodDef->mName == BF_METHODNAME_MARKMEMBERS) ||
  20855. (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC) ||
  20856. (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS))
  20857. canChain = true;
  20858. }
  20859. }
  20860. if (canChain)
  20861. {
  20862. bool isBetter;
  20863. bool isWorse;
  20864. CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
  20865. if (isBetter && !isWorse)
  20866. {
  20867. methodInstance->mChainType = BfMethodChainType_ChainHead;
  20868. checkMethodInstance->mChainType = BfMethodChainType_ChainMember;
  20869. }
  20870. else
  20871. {
  20872. checkMethodInstance->mChainType = BfMethodChainType_ChainHead;
  20873. methodInstance->mChainType = BfMethodChainType_ChainMember;
  20874. }
  20875. }
  20876. else
  20877. {
  20878. if (!typeInstance->IsTypeMemberAccessible(checkMethod->mDeclaringType, methodDef->mDeclaringType))
  20879. continue;
  20880. bool silentlyAllow = false;
  20881. bool extensionWarn = false;
  20882. if (checkMethod->mDeclaringType != methodDef->mDeclaringType)
  20883. {
  20884. if (typeInstance->IsInterface())
  20885. {
  20886. if (methodDef->mIsOverride)
  20887. silentlyAllow = true;
  20888. }
  20889. else
  20890. {
  20891. if ((methodDef->mIsOverride) && (checkMethod->mIsExtern))
  20892. {
  20893. silentlyAllow = true;
  20894. methodInstance->mIsInnerOverride = true;
  20895. CheckOverridenMethod(methodInstance, checkMethodInstance);
  20896. }
  20897. else if ((methodDef->mDeclaringType->mProject != checkMethod->mDeclaringType->mProject) &&
  20898. (!checkMethod->mDeclaringType->IsExtension()))
  20899. {
  20900. foundHiddenMethod = true;
  20901. if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic))
  20902. silentlyAllow = true;
  20903. else if (methodDef->mIsNew)
  20904. {
  20905. silentlyAllow = true;
  20906. }
  20907. else
  20908. extensionWarn = true;
  20909. }
  20910. else
  20911. silentlyAllow = true;
  20912. }
  20913. }
  20914. if ((checkMethod->mCommutableKind == BfCommutableKind_Reverse) || (methodDef->mCommutableKind == BfCommutableKind_Reverse))
  20915. silentlyAllow = true;
  20916. if (!silentlyAllow)
  20917. {
  20918. if ((!methodDef->mName.IsEmpty()) || (checkMethodInstance->mMethodDef->mIsOperator))
  20919. {
  20920. auto refNode = methodDef->GetRefNode();
  20921. BfError* bfError;
  20922. if (extensionWarn)
  20923. bfError = Warn(BfWarning_CS0114_MethodHidesInherited,
  20924. StrFormat("This method hides a method in the root type definition. Use the 'new' keyword if the hiding was intentional. Note that this method is not callable from project '%s'.",
  20925. checkMethod->mDeclaringType->mProject->mName.c_str()), refNode);
  20926. else
  20927. {
  20928. bfError = Fail(StrFormat("Method '%s' already declared with the same parameter types", MethodToString(checkMethodInstance).c_str()), refNode, true);
  20929. }
  20930. if ((bfError != NULL) && (checkMethod->GetRefNode() != refNode))
  20931. mCompiler->mPassInstance->MoreInfo("First declaration", checkMethod->GetRefNode());
  20932. }
  20933. }
  20934. }
  20935. }
  20936. }
  20937. }
  20938. // Virtual methods give their error while slotting
  20939. if ((!typeInstance->IsBoxed()) && (!methodDef->mIsVirtual) && (methodDef->mProtection != BfProtection_Private) &&
  20940. (!methodDef->mIsLocalMethod) &&
  20941. (!methodInstance->mIsForeignMethodDef) && (typeInstance->mBaseType != NULL) &&
  20942. (methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mMethodDeclaration != NULL))
  20943. {
  20944. auto baseType = typeInstance->mBaseType;
  20945. while (baseType != NULL)
  20946. {
  20947. auto baseTypeDef = baseType->mTypeDef;
  20948. baseTypeDef->PopulateMemberSets();
  20949. BfMethodDef* checkMethod = NULL;
  20950. BfMemberSetEntry* entry = NULL;
  20951. if (baseTypeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  20952. checkMethod = (BfMethodDef*)entry->mMemberDef;
  20953. while (checkMethod != NULL)
  20954. {
  20955. if (checkMethod->mMethodDeclaration == NULL)
  20956. {
  20957. checkMethod = checkMethod->mNextWithSameName;
  20958. continue;
  20959. }
  20960. if (baseType->mMethodInstanceGroups.size() == 0)
  20961. {
  20962. BF_ASSERT(baseType->IsIncomplete() && mCompiler->IsAutocomplete());
  20963. break;
  20964. }
  20965. if (checkMethod == methodDef)
  20966. {
  20967. checkMethod = checkMethod->mNextWithSameName;
  20968. continue;
  20969. }
  20970. if (checkMethod->mName != methodDef->mName)
  20971. {
  20972. checkMethod = checkMethod->mNextWithSameName;
  20973. continue;
  20974. }
  20975. auto checkMethodInstance = GetRawMethodInstanceAtIdx(baseType, checkMethod->mIdx);
  20976. if (checkMethodInstance != NULL)
  20977. {
  20978. if ((checkMethodInstance->GetExplicitInterface() == methodInstance->GetExplicitInterface()) &&
  20979. (checkMethod->mProtection != BfProtection_Private) &&
  20980. (CompareMethodSignatures(checkMethodInstance, mCurMethodInstance)))
  20981. {
  20982. if (!methodDef->mIsNew)
  20983. {
  20984. BfAstNode* refNode = methodInstance->mMethodDef->GetRefNode();
  20985. if (refNode != NULL)
  20986. {
  20987. BfError* bfError = Warn(BfWarning_CS0114_MethodHidesInherited, StrFormat("Method hides inherited member from '%s'. Use the 'new' keyword if the hiding was intentional.", TypeToString(baseType).c_str()), refNode); //CDH TODO should we mention override keyword in warning text?
  20988. if (bfError != NULL)
  20989. bfError->mIsPersistent = true;
  20990. }
  20991. }
  20992. foundHiddenMethod = true;
  20993. break;
  20994. }
  20995. }
  20996. checkMethod = checkMethod->mNextWithSameName;
  20997. }
  20998. if (foundHiddenMethod)
  20999. break;
  21000. baseType = baseType->mBaseType;
  21001. }
  21002. if ((methodDef->mIsNew) && (!foundHiddenMethod) && (!mCurTypeInstance->IsSpecializedType()))
  21003. {
  21004. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  21005. auto tokenNode = (propertyDeclaration != NULL) ? propertyDeclaration->mNewSpecifier :
  21006. methodDeclaration->mNewSpecifier;
  21007. Fail("Method does not hide an inherited member. The 'new' keyword is not required", tokenNode, true);
  21008. }
  21009. }
  21010. }
  21011. if ((methodDef->mIsConcrete) && (!methodInstance->mIsForeignMethodDef) && (!mCurTypeInstance->IsInterface()))
  21012. {
  21013. Fail("Only interfaces methods can be declared as 'concrete'", methodDeclaration->mVirtualSpecifier);
  21014. }
  21015. if ((methodDef->mIsVirtual) && (methodDef->mIsStatic) && (!methodInstance->mIsInnerOverride))
  21016. {
  21017. if ((virtualToken != NULL) && (virtualToken->mToken == BfToken_Override) && (methodDef->mDeclaringType->mTypeCode == BfTypeCode_Extension))
  21018. Fail("No suitable method found to override", virtualToken, true);
  21019. else
  21020. Fail("Static members cannot be marked as override, virtual, or abstract", virtualToken, true);
  21021. }
  21022. else if (methodDef->mIsVirtual)
  21023. {
  21024. if ((methodDef->mProtection == BfProtection_Private) && (virtualToken != NULL))
  21025. Fail("Virtual or abstract members cannot be 'private'", virtualToken, true);
  21026. if ((methodDef->mProtection == BfProtection_Internal) && (virtualToken != NULL))
  21027. Fail("Virtual or abstract members cannot be 'internal'. Consider using the 'protected internal' access specifier.", virtualToken, true);
  21028. }
  21029. mCompiler->mStats.mMethodDeclarations++;
  21030. mCompiler->UpdateCompletion();
  21031. }
  21032. void BfModule::UniqueSlotVirtualMethod(BfMethodInstance* methodInstance)
  21033. {
  21034. BF_ASSERT(methodInstance->GetOwner() == mCurTypeInstance);
  21035. auto typeInstance = mCurTypeInstance;
  21036. auto methodDef = methodInstance->mMethodDef;
  21037. int virtualMethodMatchIdx = -1;
  21038. if (typeInstance->mHotTypeData != NULL)
  21039. {
  21040. if (typeInstance->mHotTypeData->mVTableOrigLength != -1)
  21041. {
  21042. BF_ASSERT(mCompiler->IsHotCompile());
  21043. // In the 'normal' case we'd assert that mIsOverride is false, but if we can't find the declaring method then we
  21044. // may slot this override anyway (?)
  21045. int vTableStart = 0;
  21046. auto implBaseType = typeInstance->GetImplBaseType();
  21047. if (implBaseType != NULL)
  21048. vTableStart = implBaseType->mVirtualMethodTableSize;
  21049. StringT<512> mangledName;
  21050. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
  21051. for (int checkIdxOfs = 0; checkIdxOfs < (int)typeInstance->mHotTypeData->mVTableEntries.size(); checkIdxOfs++)
  21052. {
  21053. // O(1) checking when virtual methods haven't changed
  21054. int checkIdx = (typeInstance->mVirtualMethodTableSize - vTableStart + checkIdxOfs) % (int)typeInstance->mHotTypeData->mVTableEntries.size();
  21055. auto& entry = typeInstance->mHotTypeData->mVTableEntries[checkIdx];
  21056. if (mangledName == entry.mFuncName)
  21057. {
  21058. virtualMethodMatchIdx = vTableStart + checkIdx;
  21059. break;
  21060. }
  21061. }
  21062. if (virtualMethodMatchIdx != -1)
  21063. {
  21064. methodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
  21065. typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod = methodInstance;
  21066. typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod = methodInstance;
  21067. }
  21068. typeInstance->mVirtualMethodTableSize = (int)typeInstance->mVirtualMethodTable.size();
  21069. }
  21070. }
  21071. if (virtualMethodMatchIdx == -1)
  21072. {
  21073. methodInstance->mVirtualTableIdx = typeInstance->mVirtualMethodTableSize++;
  21074. BfVirtualMethodEntry entry = { methodInstance, methodInstance };
  21075. typeInstance->mVirtualMethodTable.push_back(entry);
  21076. }
  21077. }
  21078. void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse)
  21079. {
  21080. if ((!prevDeclType->IsExtension()) && (newDeclType->IsExtension()))
  21081. {
  21082. // When we provide an extension override in the same project a root type override
  21083. isBetter = true;
  21084. isWorse = false;
  21085. }
  21086. else
  21087. {
  21088. isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject);
  21089. isWorse = prevDeclType->mProject->ContainsReference(newDeclType->mProject);
  21090. }
  21091. }
  21092. bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext)
  21093. {
  21094. BP_ZONE("BfModule::SlotVirtualMethod");
  21095. if (mCurTypeInstance->IsUnspecializedTypeVariation())
  21096. return false;
  21097. auto _AddVirtualDecl = [&](BfMethodInstance* declMethodInstance)
  21098. {
  21099. if (!mCompiler->mOptions.mAllowHotSwapping)
  21100. return;
  21101. if ((!methodInstance->mIsReified) || (!declMethodInstance->mIsReified))
  21102. return;
  21103. if (methodInstance->mHotMethod == NULL)
  21104. CheckHotMethod(methodInstance, "");
  21105. if (methodInstance->mHotMethod == NULL)
  21106. return;
  21107. //BF_ASSERT(declMethodInstance->mHotMethod != NULL);
  21108. if (declMethodInstance->mHotMethod == NULL)
  21109. CheckHotMethod(declMethodInstance, "");
  21110. auto virtualDecl = mCompiler->mHotData->GetVirtualDeclaration(declMethodInstance->mHotMethod);
  21111. virtualDecl->mRefCount++;
  21112. methodInstance->mHotMethod->mReferences.Add(virtualDecl);
  21113. };
  21114. auto typeInstance = mCurTypeInstance;
  21115. auto typeDef = typeInstance->mTypeDef;
  21116. auto methodDef = methodInstance->mMethodDef;
  21117. auto methodDeclaration = methodDef->GetMethodDeclaration();
  21118. auto propertyDeclaration = methodDef->GetPropertyDeclaration();
  21119. auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration();
  21120. if (methodInstance->mIsInnerOverride)
  21121. return false;
  21122. BfAstNode* declaringNode = methodDeclaration;
  21123. if (propertyMethodDeclaration != NULL)
  21124. declaringNode = propertyMethodDeclaration->mNameNode;
  21125. BfMethodInstance* methodOverriden = NULL;
  21126. bool usedMethod = false;
  21127. BfTokenNode* virtualToken = NULL;
  21128. if (propertyDeclaration != NULL)
  21129. virtualToken = propertyDeclaration->mVirtualSpecifier;
  21130. else if (methodDeclaration != NULL)
  21131. virtualToken = methodDeclaration->mVirtualSpecifier;
  21132. if ((methodDef->mIsVirtual) && (methodDef->mIsStatic))
  21133. {
  21134. //Fail: Static members cannot be marked as override, virtual, or abstract
  21135. }
  21136. else if (methodDef->mIsVirtual)
  21137. {
  21138. if (IsHotCompile())
  21139. mContext->EnsureHotMangledVirtualMethodName(methodInstance);
  21140. BfTypeInstance* checkBase = typeInstance;
  21141. // If we are in an extension, look in ourselves first
  21142. if (methodDef->mDeclaringType->mTypeDeclaration == typeInstance->mTypeDef->mTypeDeclaration)
  21143. checkBase = checkBase->mBaseType;
  21144. if (typeInstance->IsValueType())
  21145. {
  21146. if (typeInstance->mBaseType == NULL)
  21147. return false; // It's actually ValueType
  21148. // We allow structs to override object methods for when they get boxed, so just ignore 'override' keyword until it gets boxed
  21149. if (!methodDef->mIsOverride)
  21150. {
  21151. Fail("Structs cannot have virtual methods", virtualToken, true);
  21152. return false;
  21153. }
  21154. checkBase = mContext->mBfObjectType;
  21155. if (checkBase->mVirtualMethodTableSize == 0)
  21156. PopulateType(checkBase, BfPopulateType_Full);
  21157. if (checkBase->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
  21158. return false; // System circular ref, don't do struct checking on those
  21159. }
  21160. int virtualMethodMatchIdx = -1;
  21161. bool hadHidingError = false;
  21162. BfMethodInstance* bestOverrideMethodInstance = NULL;
  21163. BfMethodInstance* ambiguousOverrideMethodInstance = NULL;
  21164. int bestOverrideMethodIdx = -1;
  21165. int ambiguousOverrideMethodIdx = -1;
  21166. if (checkBase != NULL)
  21167. {
  21168. auto& baseVirtualMethodTable = checkBase->mVirtualMethodTable;
  21169. auto lookupType = checkBase;
  21170. while (lookupType != NULL)
  21171. {
  21172. lookupType->mTypeDef->PopulateMemberSets();
  21173. BfMethodDef* nextMethodDef = NULL;
  21174. BfMemberSetEntry* entry;
  21175. if (lookupType->mTypeDef->mMethodSet.TryGetWith((StringImpl&)methodInstance->mMethodDef->mName, &entry))
  21176. nextMethodDef = (BfMethodDef*)entry->mMemberDef;
  21177. while (nextMethodDef != NULL)
  21178. {
  21179. auto checkMethodDef = nextMethodDef;
  21180. nextMethodDef = nextMethodDef->mNextWithSameName;
  21181. if ((!checkMethodDef->mIsVirtual) || (checkMethodDef->mIsOverride))
  21182. continue;
  21183. BfMethodInstance* baseMethodInstance = NULL;
  21184. int checkMethodIdx = -1;
  21185. BfMethodInstance* lookupMethodInstance = lookupType->mMethodInstanceGroups[checkMethodDef->mIdx].mDefault;
  21186. if ((lookupMethodInstance == NULL) || (lookupMethodInstance->mVirtualTableIdx == -1))
  21187. {
  21188. if (lookupType->IsUnspecializedTypeVariation())
  21189. {
  21190. if (!lookupMethodInstance->mMethodDef->mIsOverride)
  21191. {
  21192. baseMethodInstance = lookupMethodInstance;
  21193. checkMethodIdx = -2;
  21194. }
  21195. }
  21196. if (baseMethodInstance == NULL)
  21197. continue;
  21198. }
  21199. if (baseMethodInstance == NULL)
  21200. {
  21201. checkMethodIdx = lookupMethodInstance->mVirtualTableIdx;
  21202. if (checkMethodIdx >= baseVirtualMethodTable.mSize)
  21203. FatalError("SlotVirtualMethod OOB in baseVirtualMethodTable[checkMethodIdx]");
  21204. auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx];
  21205. if (baseMethodRef.mDeclaringMethod.mMethodNum == -1)
  21206. {
  21207. BF_ASSERT(mCompiler->mOptions.mHasVDataExtender);
  21208. continue;
  21209. }
  21210. baseMethodInstance = baseVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21211. if (baseMethodInstance == NULL)
  21212. {
  21213. AssertErrorState();
  21214. continue;
  21215. }
  21216. }
  21217. if ((baseMethodInstance != NULL) && (CompareMethodSignatures(baseMethodInstance, methodInstance)))
  21218. {
  21219. if (methodDef->mIsOverride)
  21220. {
  21221. BfMethodInstance* checkMethodInstance;
  21222. if (checkMethodIdx == -2)
  21223. checkMethodInstance = baseMethodInstance;
  21224. else if (typeInstance->IsValueType())
  21225. checkMethodInstance = checkBase->mVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21226. else
  21227. checkMethodInstance = typeInstance->mVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21228. auto newDeclType = checkMethodInstance->mMethodDef->mDeclaringType;
  21229. if (!typeInstance->IsTypeMemberAccessible(newDeclType, methodDef->mDeclaringType->mProject))
  21230. continue;
  21231. if (bestOverrideMethodInstance != NULL)
  21232. {
  21233. auto prevDeclType = bestOverrideMethodInstance->mMethodDef->mDeclaringType;
  21234. bool isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject);
  21235. bool isWorse = prevDeclType->mProject->ContainsReference(newDeclType->mProject);
  21236. if (isBetter == isWorse)
  21237. {
  21238. ambiguousOverrideMethodInstance = bestOverrideMethodInstance;
  21239. }
  21240. else
  21241. {
  21242. if (isWorse)
  21243. continue;
  21244. ambiguousOverrideMethodInstance = NULL;
  21245. }
  21246. }
  21247. bestOverrideMethodInstance = checkMethodInstance;
  21248. bestOverrideMethodIdx = checkMethodIdx;
  21249. }
  21250. else
  21251. {
  21252. if ((baseMethodInstance->GetOwner() != methodInstance->GetOwner()) && (!methodDef->mIsNew))
  21253. {
  21254. if (!hadHidingError)
  21255. Warn(BfWarning_CS0114_MethodHidesInherited, StrFormat("Method hides inherited member from '%s'. Use either 'override' or 'new'.", TypeToString(checkBase).c_str()), declaringNode);
  21256. hadHidingError = true;
  21257. }
  21258. }
  21259. }
  21260. }
  21261. lookupType = lookupType->mBaseType;
  21262. }
  21263. }
  21264. //TODO:
  21265. if ((checkBase != NULL)
  21266. && (false)
  21267. )
  21268. {
  21269. auto& baseVirtualMethodTable = checkBase->mVirtualMethodTable;
  21270. for (int checkMethodIdx = (int) baseVirtualMethodTable.size() - 1; checkMethodIdx >= 0; checkMethodIdx--)
  21271. {
  21272. auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx];
  21273. if (baseMethodRef.mDeclaringMethod.mMethodNum == -1)
  21274. {
  21275. BF_ASSERT(mCompiler->mOptions.mHasVDataExtender);
  21276. continue;
  21277. }
  21278. BfMethodInstance* baseMethodInstance = baseVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21279. if (baseMethodInstance == NULL)
  21280. {
  21281. AssertErrorState();
  21282. continue;
  21283. }
  21284. if ((baseMethodInstance != NULL) && (CompareMethodSignatures(baseMethodInstance, methodInstance)))
  21285. {
  21286. if (methodDef->mIsOverride)
  21287. {
  21288. BfMethodInstance* checkMethodInstance;
  21289. if (typeInstance->IsValueType())
  21290. checkMethodInstance = checkBase->mVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21291. else
  21292. checkMethodInstance = typeInstance->mVirtualMethodTable[checkMethodIdx].mDeclaringMethod;
  21293. auto newDeclType = checkMethodInstance->mMethodDef->mDeclaringType;
  21294. if (!typeInstance->IsTypeMemberAccessible(newDeclType, methodDef->mDeclaringType->mProject))
  21295. continue;
  21296. if (bestOverrideMethodInstance != NULL)
  21297. {
  21298. auto prevDeclType = bestOverrideMethodInstance->mMethodDef->mDeclaringType;
  21299. bool isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject);
  21300. bool isWorse = prevDeclType->mProject->ContainsReference(newDeclType->mProject);
  21301. if (isBetter == isWorse)
  21302. {
  21303. ambiguousOverrideMethodInstance = bestOverrideMethodInstance;
  21304. }
  21305. else
  21306. {
  21307. if (isWorse)
  21308. continue;
  21309. ambiguousOverrideMethodInstance = NULL;
  21310. }
  21311. }
  21312. bestOverrideMethodInstance = checkMethodInstance;
  21313. bestOverrideMethodIdx = checkMethodIdx;
  21314. }
  21315. else
  21316. {
  21317. if ((baseMethodInstance->GetOwner() != methodInstance->GetOwner()) && (!methodDef->mIsNew))
  21318. {
  21319. if (!hadHidingError)
  21320. Warn(BfWarning_CS0114_MethodHidesInherited, StrFormat("Method hides inherited member from '%s'. Use either 'override' or 'new'.", TypeToString(checkBase).c_str()), declaringNode);
  21321. hadHidingError = true;
  21322. }
  21323. }
  21324. }
  21325. }
  21326. }
  21327. if (bestOverrideMethodInstance != NULL)
  21328. {
  21329. if (ambiguousOverrideMethodInstance != NULL)
  21330. {
  21331. bool allow = false;
  21332. // If neither of these declarations "include" each other then it's okay. This can happen when we have two extensions that create the same virtual method but with different constraints.
  21333. // When when specialize, the specialized type will determine wither it has illegally pulled in both declarations or not
  21334. bool canSeeEachOther = false;
  21335. //
  21336. {
  21337. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, ambiguousOverrideMethodInstance);
  21338. if (bestOverrideMethodInstance->GetOwner()->IsTypeMemberIncluded(bestOverrideMethodInstance->mMethodDef->mDeclaringType, ambiguousOverrideMethodInstance->mMethodDef->mDeclaringType, this))
  21339. canSeeEachOther = true;
  21340. }
  21341. //
  21342. {
  21343. SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, bestOverrideMethodInstance);
  21344. if (ambiguousOverrideMethodInstance->GetOwner()->IsTypeMemberIncluded(ambiguousOverrideMethodInstance->mMethodDef->mDeclaringType, bestOverrideMethodInstance->mMethodDef->mDeclaringType, this))
  21345. canSeeEachOther = true;
  21346. }
  21347. if (!canSeeEachOther)
  21348. {
  21349. BF_ASSERT(bestOverrideMethodInstance->GetOwner()->IsUnspecializedType() && ambiguousOverrideMethodInstance->GetOwner()->IsUnspecializedType());
  21350. }
  21351. else
  21352. {
  21353. auto error = Fail(StrFormat("Method '%s' is an ambiguous override", MethodToString(methodInstance).c_str()), methodDef->GetRefNode());
  21354. if (error != NULL)
  21355. {
  21356. mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", MethodToString(bestOverrideMethodInstance).c_str()), bestOverrideMethodInstance->mMethodDef->GetRefNode());
  21357. mCompiler->mPassInstance->MoreInfo(StrFormat("'%s' is a candidate", MethodToString(ambiguousOverrideMethodInstance).c_str()), ambiguousOverrideMethodInstance->mMethodDef->GetRefNode());
  21358. }
  21359. }
  21360. }
  21361. }
  21362. if (bestOverrideMethodIdx == -2)
  21363. {
  21364. // Comes from an unspecialized variation
  21365. virtualMethodMatchIdx = bestOverrideMethodIdx;
  21366. }
  21367. else if ((bestOverrideMethodInstance != NULL) && (bestOverrideMethodIdx != -1))
  21368. {
  21369. auto& baseVirtualMethodTable = checkBase->mVirtualMethodTable;
  21370. BfMethodInstance* baseVirtualMethodInstance = baseVirtualMethodTable[bestOverrideMethodIdx].mDeclaringMethod;
  21371. if ((baseVirtualMethodInstance != methodInstance) && (methodDef->mIsOverride))
  21372. {
  21373. if (baseVirtualMethodInstance->mReturnType != methodInstance->mReturnType)
  21374. {
  21375. BfTypeReference* returnTypeRef;
  21376. if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
  21377. {
  21378. returnTypeRef = propertyDeclaration->mTypeRef;
  21379. Fail("Property differs from overridden property by type", returnTypeRef, true);
  21380. }
  21381. else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  21382. {
  21383. returnTypeRef = methodDeclaration->mReturnType;
  21384. Fail("Method differs from overridden method by return value", returnTypeRef, true);
  21385. }
  21386. else
  21387. {
  21388. Fail(StrFormat("Internal error with method '%s'", MethodToString(methodInstance).c_str()));
  21389. }
  21390. return usedMethod;
  21391. }
  21392. }
  21393. if (methodDef->mIsOverride)
  21394. {
  21395. // We can have multiple matches when a virtual method is used to implement interface methods
  21396. // It doesn't matter what we set mVirtualTableIdx, as all base classes will override all matching
  21397. // vtable entries for this method signature
  21398. virtualMethodMatchIdx = bestOverrideMethodIdx;
  21399. if (!typeInstance->IsValueType())
  21400. methodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
  21401. if (typeInstance->IsValueType())
  21402. {
  21403. methodOverriden = checkBase->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod;
  21404. }
  21405. else
  21406. {
  21407. methodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
  21408. bool preferRootDefinition = (methodDef->mName == BF_METHODNAME_MARKMEMBERS) || (methodDef->mMethodType == BfMethodType_Dtor);
  21409. BfMethodInstance* setMethodInstance = methodInstance;
  21410. bool doOverride = false;
  21411. auto& overridenRef = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod;
  21412. if (overridenRef.mKind != BfMethodRefKind_AmbiguousRef)
  21413. {
  21414. methodOverriden = overridenRef;
  21415. doOverride = true;
  21416. if (methodOverriden->GetOwner() == methodInstance->GetOwner())
  21417. {
  21418. bool isBetter = false;
  21419. bool isWorse = false;
  21420. CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, methodOverriden->mMethodDef->mDeclaringType, isBetter, isWorse);
  21421. if (isBetter == isWorse)
  21422. {
  21423. // We have to resolve later per-project
  21424. if ((ambiguityContext != NULL) && (ambiguityContext->mIsProjectSpecific))
  21425. {
  21426. auto declMethodInstance = checkBase->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod;
  21427. ambiguityContext->Add(virtualMethodMatchIdx, NULL, -1, methodOverriden, methodInstance);
  21428. }
  21429. if ((ambiguityContext == NULL) || (!ambiguityContext->mIsProjectSpecific))
  21430. typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod.mKind = BfMethodRefKind_AmbiguousRef;
  21431. doOverride = false;
  21432. }
  21433. else
  21434. {
  21435. if ((isBetter) && (ambiguityContext != NULL))
  21436. {
  21437. ambiguityContext->Remove(virtualMethodMatchIdx);
  21438. }
  21439. if ((isBetter) && (methodInstance->GetOwner() == methodOverriden->GetOwner()))
  21440. {
  21441. if (preferRootDefinition)
  21442. {
  21443. // Leave the master GCMarkMember
  21444. isBetter = false;
  21445. isWorse = true;
  21446. }
  21447. }
  21448. doOverride = isBetter;
  21449. }
  21450. }
  21451. }
  21452. else if ((preferRootDefinition) && (!methodDef->mDeclaringType->IsExtension()))
  21453. {
  21454. methodOverriden = overridenRef;
  21455. doOverride = true;
  21456. }
  21457. if (doOverride)
  21458. {
  21459. auto declMethodInstance = (BfMethodInstance*)typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod;
  21460. _AddVirtualDecl(declMethodInstance);
  21461. setMethodInstance->mVirtualTableIdx = virtualMethodMatchIdx;
  21462. auto& implMethodRef = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod;
  21463. if ((!mCompiler->mIsResolveOnly) && (implMethodRef.mMethodNum >= 0) &&
  21464. (implMethodRef.mTypeInstance == typeInstance) && (methodInstance->GetOwner() == typeInstance))
  21465. {
  21466. auto prevImplMethodInstance = (BfMethodInstance*)implMethodRef;
  21467. if (prevImplMethodInstance->mMethodDef->mDeclaringType->mProject != methodInstance->mMethodDef->mDeclaringType->mProject)
  21468. {
  21469. // We may need to have to previous method reified when we must re-slot in another project during vdata creation
  21470. BfReifyMethodDependency dep;
  21471. dep.mDepMethod = typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mDeclaringMethod;
  21472. dep.mMethodIdx = implMethodRef.mMethodNum;
  21473. typeInstance->mReifyMethodDependencies.Add(dep);
  21474. }
  21475. if (!methodInstance->mMangleWithIdx)
  21476. {
  21477. // Keep mangled names from conflicting
  21478. methodInstance->mMangleWithIdx = true;
  21479. if ((methodInstance->mIRFunction) && (methodInstance->mDeclModule->mIsModuleMutable))
  21480. {
  21481. StringT<4096> mangledName;
  21482. BfMangler::Mangle(mangledName, mCompiler->GetMangleKind(), methodInstance);
  21483. methodInstance->mDeclModule->mBfIRBuilder->SetFunctionName(methodInstance->mIRFunction, mangledName);
  21484. }
  21485. }
  21486. }
  21487. typeInstance->mVirtualMethodTable[virtualMethodMatchIdx].mImplementingMethod = setMethodInstance;
  21488. }
  21489. }
  21490. if (methodOverriden != NULL)
  21491. {
  21492. CheckOverridenMethod(methodInstance, methodOverriden);
  21493. }
  21494. }
  21495. }
  21496. if ((virtualMethodMatchIdx == -1) && ((ambiguityContext == NULL) || (!ambiguityContext->mIsReslotting)))
  21497. {
  21498. if (methodDef->mIsOverride)
  21499. {
  21500. BfTokenNode* overrideToken = NULL;
  21501. if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
  21502. overrideToken = propertyMethodDeclaration->mPropertyDeclaration->mVirtualSpecifier;
  21503. else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  21504. overrideToken = methodDeclaration->mVirtualSpecifier;
  21505. if (overrideToken != NULL)
  21506. {
  21507. if ((propertyDeclaration != NULL) && (propertyDeclaration->mNameNode != NULL) &&
  21508. ((methodDef->mMethodType == BfMethodType_PropertyGetter) || (methodDef->mMethodType == BfMethodType_PropertySetter)))
  21509. Fail(StrFormat("No suitable method found to override for '%s.%s'",
  21510. propertyDeclaration->mNameNode->ToString().c_str(), (methodDef->mMethodType == BfMethodType_PropertyGetter) ? "get" : "set"), overrideToken, true);
  21511. else
  21512. Fail("No suitable method found to override", overrideToken, true);
  21513. }
  21514. return usedMethod;
  21515. }
  21516. UniqueSlotVirtualMethod(methodInstance);
  21517. }
  21518. else
  21519. usedMethod = true;
  21520. if (typeInstance->IsValueType())
  21521. return usedMethod;
  21522. }
  21523. bool foundInterface = false;
  21524. bool hadAnyMatch = false;
  21525. // See if this method matches interfaces
  21526. for (auto& ifaceTypeInst : typeInstance->mInterfaces)
  21527. {
  21528. auto ifaceInst = ifaceTypeInst.mInterfaceType;
  21529. if (ifaceInst->IsIncomplete())
  21530. PopulateType(ifaceInst, BfPopulateType_DataAndMethods);
  21531. int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
  21532. int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
  21533. // See "bidirectional" rules mentioned in DoTypeInstanceMethodProcessing
  21534. if ((!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, ifaceTypeInst.mDeclaringType)) &&
  21535. (!typeInstance->IsTypeMemberAccessible(ifaceTypeInst.mDeclaringType, methodDef->mDeclaringType)))
  21536. continue;
  21537. if (!typeInstance->IsTypeMemberIncluded(methodDef->mDeclaringType, ifaceTypeInst.mDeclaringType, this))
  21538. continue;
  21539. bool hadMatch = false;
  21540. BfMethodInstance* hadNameMatch = NULL;
  21541. BfType* expectedReturnType = NULL;
  21542. bool showedError = false;
  21543. // We go through our VTable looking for NULL entries within the interface sections
  21544. // The only instance of finding a "better" method is when we have explicitly interface-dotted method
  21545. // because a normal method declared in this type could have matched earlier
  21546. //for (int iMethodIdx = 0; iMethodIdx < iMethodCount; iMethodIdx++)
  21547. ifaceInst->mTypeDef->PopulateMemberSets();
  21548. BfMethodDef* checkMethodDef = NULL;
  21549. BfMemberSetEntry* entry;
  21550. if (ifaceInst->mTypeDef->mMethodSet.TryGetWith((StringImpl&)methodInstance->mMethodDef->mName, &entry))
  21551. checkMethodDef = (BfMethodDef*)entry->mMemberDef;
  21552. while (checkMethodDef != NULL)
  21553. {
  21554. int iMethodIdx = checkMethodDef->mIdx;
  21555. int iTableIdx = iMethodIdx + startIdx;
  21556. BfTypeInterfaceMethodEntry* interfaceMethodEntry = &typeInstance->mInterfaceMethodTable[iTableIdx];
  21557. auto iMethodPtr = &interfaceMethodEntry->mMethodRef;
  21558. bool storeIFaceMethod = false;
  21559. if ((mCompiler->mPassInstance->HasFailed()) && (iMethodIdx >= (int)ifaceInst->mMethodInstanceGroups.size()))
  21560. {
  21561. checkMethodDef = checkMethodDef->mNextWithSameName;
  21562. continue;
  21563. }
  21564. auto& iMethodGroup = ifaceInst->mMethodInstanceGroups[iMethodIdx];
  21565. auto iMethodInst = iMethodGroup.mDefault;
  21566. if (iMethodInst == NULL)
  21567. {
  21568. if ((!ifaceInst->IsGenericTypeInstance()) || (!ifaceInst->mTypeDef->mIsCombinedPartial))
  21569. AssertErrorState();
  21570. checkMethodDef = checkMethodDef->mNextWithSameName;
  21571. continue;
  21572. }
  21573. if (iMethodInst->mMethodDef->mName == methodInstance->mMethodDef->mName)
  21574. hadNameMatch = iMethodInst;
  21575. bool doesMethodSignatureMatch = CompareMethodSignatures(iMethodInst, methodInstance);
  21576. if ((!doesMethodSignatureMatch) && (interfaceMethodEntry->mMethodRef.IsNull()))
  21577. {
  21578. doesMethodSignatureMatch = IsCompatibleInterfaceMethod(iMethodInst, methodInstance);
  21579. }
  21580. if ((doesMethodSignatureMatch) && (methodInstance->GetOwner()->IsValueType()))
  21581. {
  21582. if ((!iMethodInst->mMethodDef->mIsMutating) && (methodInstance->mMethodDef->mIsMutating))
  21583. {
  21584. if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface == ifaceInst))
  21585. {
  21586. auto error = mCompiler->mPassInstance->Fail(StrFormat("Implementation method '%s' cannot specify 'mut' because the interface method does not allow it",
  21587. MethodToString(methodInstance).c_str()), methodInstance->mMethodDef->GetMutNode());
  21588. if (error != NULL)
  21589. mCompiler->mPassInstance->MoreInfo(StrFormat("Declare the interface method as 'mut' to allow matching 'mut' implementations"), iMethodInst->mMethodDef->mMethodDeclaration);
  21590. showedError = true;
  21591. }
  21592. }
  21593. }
  21594. if (doesMethodSignatureMatch)
  21595. {
  21596. usedMethod = true;
  21597. hadMatch = true;
  21598. hadAnyMatch = true;
  21599. storeIFaceMethod = true;
  21600. if ((iMethodPtr->mKind != BfMethodRefKind_AmbiguousRef) && (iMethodPtr->mTypeInstance != NULL))
  21601. {
  21602. auto prevMethod = (BfMethodInstance*)*iMethodPtr;
  21603. if ((mCompiler->mIsResolveOnly) && (prevMethod == methodInstance) && (!mIsComptimeModule))
  21604. {
  21605. // When autocompletion regenerates a single method body but not the whole type then
  21606. // we will see ourselves in the vtable already
  21607. return usedMethod;
  21608. }
  21609. bool isBetter = false;
  21610. bool isWorse = false;
  21611. isBetter = (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL);
  21612. isWorse = (prevMethod->mMethodInfoEx != NULL) && (prevMethod->mMethodInfoEx->mExplicitInterface != NULL);
  21613. if (isBetter == isWorse)
  21614. CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, prevMethod->mMethodDef->mDeclaringType, isBetter, isWorse);
  21615. if (isBetter == isWorse)
  21616. {
  21617. if (ambiguityContext != NULL)
  21618. {
  21619. ambiguityContext->Add(~iTableIdx, &ifaceTypeInst, iMethodIdx, prevMethod, methodInstance);
  21620. }
  21621. iMethodPtr->mKind = BfMethodRefKind_AmbiguousRef;
  21622. storeIFaceMethod = true;
  21623. }
  21624. else
  21625. {
  21626. if ((isBetter) && (ambiguityContext != NULL))
  21627. ambiguityContext->Remove(~iTableIdx);
  21628. storeIFaceMethod = isBetter;
  21629. }
  21630. }
  21631. }
  21632. if (storeIFaceMethod)
  21633. {
  21634. if (methodInstance->GetNumGenericParams() != 0)
  21635. _AddVirtualDecl(iMethodInst);
  21636. *iMethodPtr = methodInstance;
  21637. }
  21638. checkMethodDef = checkMethodDef->mNextWithSameName;
  21639. }
  21640. if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface == ifaceInst) && (!hadMatch) && (!showedError))
  21641. {
  21642. if (expectedReturnType != NULL)
  21643. Fail(StrFormat("Wrong return type, expected '%s'", TypeToString(expectedReturnType).c_str()), declaringNode, true);
  21644. else if (hadNameMatch != NULL)
  21645. {
  21646. auto error = Fail("Method parameters don't match interface method", declaringNode, true);
  21647. if (error != NULL)
  21648. mCompiler->mPassInstance->MoreInfo("See interface method declaration", hadNameMatch->mMethodDef->GetRefNode());
  21649. }
  21650. else
  21651. {
  21652. auto propertyDecl = methodDef->GetPropertyDeclaration();
  21653. if (propertyDecl != NULL)
  21654. {
  21655. auto propertyMethodDecl = methodDef->GetPropertyMethodDeclaration();
  21656. String name;
  21657. if (auto indexerDeclaration = BfNodeDynCast<BfIndexerDeclaration>(propertyDecl))
  21658. name = "this[]";
  21659. else if (propertyDecl->mNameNode != NULL)
  21660. propertyDecl->mNameNode->ToString(name);
  21661. Fail(StrFormat("Property '%s' %s accessor not defined in interface '%s'", name.c_str(),
  21662. (methodDef->mMethodType == BfMethodType_PropertyGetter) ? "get" : "set", TypeToString(ifaceInst).c_str()), methodDef->GetRefNode(), true);
  21663. }
  21664. else
  21665. Fail(StrFormat("Method '%s' not found in interface '%s'", methodDef->mName.c_str(), TypeToString(ifaceInst).c_str()), methodDef->GetRefNode(), true);
  21666. }
  21667. }
  21668. }
  21669. // Any overriden virtual methods that were used in interfaces also need to be replaced
  21670. if (methodOverriden != NULL)
  21671. {
  21672. for (auto& methodEntry : typeInstance->mInterfaceMethodTable)
  21673. {
  21674. if (methodEntry.mMethodRef == methodOverriden)
  21675. methodEntry.mMethodRef = methodInstance;
  21676. }
  21677. }
  21678. return usedMethod;
  21679. }
  21680. void BfModule::CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden)
  21681. {
  21682. auto methodDef = methodInstance->mMethodDef;
  21683. auto prevProtection = methodOverriden->mMethodDef->mProtection;
  21684. if ((methodDef->mProtection != prevProtection) && (methodDef->mMethodType != BfMethodType_Dtor))
  21685. {
  21686. const char* protectionNames[] = { "hidden", "private", "internal", "protected", "protected internal", "public" };
  21687. BF_STATIC_ASSERT(BF_ARRAY_COUNT(protectionNames) == BfProtection_COUNT);
  21688. BfAstNode* protectionRefNode = NULL;
  21689. if (auto propertyMethodDeclaration = methodDef->GetPropertyMethodDeclaration())
  21690. {
  21691. protectionRefNode = propertyMethodDeclaration->mProtectionSpecifier;
  21692. if (protectionRefNode == NULL)
  21693. protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mProtectionSpecifier;
  21694. if (protectionRefNode == NULL)
  21695. protectionRefNode = propertyMethodDeclaration->mPropertyDeclaration->mNameNode;
  21696. }
  21697. else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  21698. {
  21699. protectionRefNode = methodDeclaration->mProtectionSpecifier;
  21700. if (protectionRefNode == NULL)
  21701. protectionRefNode = methodDeclaration->mNameNode;
  21702. }
  21703. if (protectionRefNode != NULL)
  21704. Fail(StrFormat("Cannot change access modifiers when overriding '%s' inherited member", protectionNames[(int)prevProtection]), protectionRefNode, true);
  21705. }
  21706. }
  21707. bool BfModule::SlotInterfaceMethod(BfMethodInstance* methodInstance)
  21708. {
  21709. auto typeInstance = mCurTypeInstance;
  21710. auto methodDef = methodInstance->mMethodDef;
  21711. if (methodDef->mMethodType == BfMethodType_Ctor)
  21712. return true;
  21713. bool foundOverride = false;
  21714. if ((methodDef->mBody == NULL) && (methodDef->mProtection == BfProtection_Private))
  21715. {
  21716. auto methodDeclaration = methodDef->GetMethodDeclaration();
  21717. BfAstNode* refNode = NULL;
  21718. if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
  21719. refNode = propertyDeclaration->mProtectionSpecifier;
  21720. else if (methodDeclaration != NULL)
  21721. refNode = methodDeclaration->mProtectionSpecifier;
  21722. Fail("Private interface methods must provide a body", refNode);
  21723. }
  21724. if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL) && (!methodDef->mIsOverride))
  21725. {
  21726. Fail("Explicit interfaces can only be specified for overrides in interface declarations", methodDef->GetMethodDeclaration()->mExplicitInterface);
  21727. }
  21728. BfAstNode* declaringNode = methodDef->GetRefNode();
  21729. for (auto& ifaceTypeInst : typeInstance->mInterfaces)
  21730. {
  21731. auto ifaceInst = ifaceTypeInst.mInterfaceType;
  21732. int startIdx = ifaceTypeInst.mStartInterfaceTableIdx;
  21733. int iMethodCount = (int)ifaceInst->mMethodInstanceGroups.size();
  21734. if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != ifaceInst))
  21735. continue;
  21736. ifaceInst->mTypeDef->PopulateMemberSets();
  21737. BfMethodDef* nextMethod = NULL;
  21738. BfMemberSetEntry* entry = NULL;
  21739. if (ifaceInst->mTypeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  21740. nextMethod = (BfMethodDef*)entry->mMemberDef;
  21741. while (nextMethod != NULL)
  21742. {
  21743. auto checkMethod = nextMethod;
  21744. nextMethod = nextMethod->mNextWithSameName;
  21745. auto ifaceMethod = ifaceInst->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
  21746. if (ifaceMethod == NULL)
  21747. continue;
  21748. if (CompareMethodSignatures(ifaceMethod, methodInstance))
  21749. {
  21750. if (methodDef->mIsOverride)
  21751. {
  21752. if (ifaceMethod->mMethodDef->mProtection == BfProtection_Private)
  21753. {
  21754. auto error = Fail(StrFormat("Interface method '%s' cannot override private interface method '%s'", MethodToString(methodInstance).c_str(), MethodToString(ifaceMethod).c_str()), declaringNode);
  21755. if (error != NULL)
  21756. {
  21757. mCompiler->mPassInstance->MoreInfo("See base interface method", ifaceMethod->mMethodDef->GetRefNode());
  21758. }
  21759. }
  21760. foundOverride = true;
  21761. }
  21762. else if (!methodDef->mIsNew)
  21763. {
  21764. Warn(BfWarning_CS0114_MethodHidesInherited, StrFormat("Method hides inherited member from '%s'. Use the 'new' keyword if hiding was intentional.", TypeToString(ifaceInst).c_str()), declaringNode);
  21765. }
  21766. }
  21767. }
  21768. }
  21769. if ((methodDef->mIsOverride) && (!foundOverride))
  21770. {
  21771. // This allows us to declare a method in the base definition or in an extension and then provide
  21772. // an implementation in a more-specific extension
  21773. typeInstance->mTypeDef->PopulateMemberSets();
  21774. BfMethodDef* nextMethod = NULL;
  21775. BfMemberSetEntry* entry = NULL;
  21776. if (typeInstance->mTypeDef->mMethodSet.TryGet(BfMemberSetEntry(methodDef), &entry))
  21777. nextMethod = (BfMethodDef*)entry->mMemberDef;
  21778. while (nextMethod != NULL)
  21779. {
  21780. auto checkMethod = nextMethod;
  21781. nextMethod = nextMethod->mNextWithSameName;
  21782. auto ifaceMethod = typeInstance->mMethodInstanceGroups[checkMethod->mIdx].mDefault;
  21783. if (ifaceMethod == NULL)
  21784. continue;
  21785. if (ifaceMethod->mMethodDef->mDeclaringType == methodInstance->mMethodDef->mDeclaringType)
  21786. continue;
  21787. if (CompareMethodSignatures(ifaceMethod, methodInstance))
  21788. {
  21789. foundOverride = true;
  21790. }
  21791. }
  21792. // for (int methodIdx = 0; methodIdx < typeInstance->mMethodInstanceGroups.size(); methodIdx++)
  21793. // {
  21794. // auto ifaceMethod = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
  21795. // if (ifaceMethod == NULL)
  21796. // continue;
  21797. // if (ifaceMethod->mMethodDef->mDeclaringType == methodInstance->mMethodDef->mDeclaringType)
  21798. // continue;
  21799. //
  21800. // if (CompareMethodSignatures(ifaceMethod, methodInstance))
  21801. // {
  21802. // foundOverride = true;
  21803. // }
  21804. // }
  21805. }
  21806. if (methodDef->mIsOverride)
  21807. {
  21808. if (!foundOverride)
  21809. {
  21810. BfTokenNode* overrideToken = NULL;
  21811. if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
  21812. overrideToken = propertyDeclaration->mVirtualSpecifier;
  21813. else if (auto methodDeclaration = methodDef->GetMethodDeclaration())
  21814. overrideToken = methodDeclaration->mVirtualSpecifier;
  21815. if (overrideToken != NULL)
  21816. {
  21817. Fail("No suitable method found to override", overrideToken, true);
  21818. }
  21819. else
  21820. {
  21821. // Possible cause - DTOR with params
  21822. AssertErrorState();
  21823. }
  21824. }
  21825. return true;
  21826. }
  21827. // Generic methods can't be called virtually
  21828. if (methodInstance->GetNumGenericParams() != 0)
  21829. return true;
  21830. // Only public methods can be called virtually
  21831. if (methodDef->mProtection != BfProtection_Public)
  21832. return true;
  21833. UniqueSlotVirtualMethod(methodInstance);
  21834. return true;
  21835. }
  21836. void BfModule::SetMethodDependency(BfMethodInstance* methodInstance)
  21837. {
  21838. if (methodInstance->mMethodInfoEx == NULL)
  21839. return;
  21840. int wantMinDepth = -1;
  21841. if (mCurTypeInstance != NULL)
  21842. wantMinDepth = mCurTypeInstance->mDependencyMap.mMinDependDepth + 1;
  21843. if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth != -1))
  21844. {
  21845. int wantTypeMinDepth = mCurMethodInstance->mMethodInfoEx->mMinDependDepth + 1;
  21846. if ((wantMinDepth == -1) || (wantTypeMinDepth < wantMinDepth))
  21847. wantMinDepth = wantTypeMinDepth;
  21848. }
  21849. if ((methodInstance->mMethodInfoEx->mMinDependDepth == -1) || (wantMinDepth < methodInstance->mMethodInfoEx->mMinDependDepth))
  21850. methodInstance->mMethodInfoEx->mMinDependDepth = wantMinDepth;
  21851. }
  21852. void BfModule::DbgFinish()
  21853. {
  21854. if ((mBfIRBuilder == NULL) || (mExtensionCount != 0))
  21855. return;
  21856. if (mAwaitingInitFinish)
  21857. FinishInit();
  21858. if (mHasForceLinkMarker)
  21859. return;
  21860. String markerName;
  21861. BfIRValue linkMarker;
  21862. if (mBfIRBuilder->DbgHasInfo())
  21863. {
  21864. bool needForceLinking = false;
  21865. for (auto& ownedType : mOwnedTypeInstances)
  21866. {
  21867. bool hasConfirmedReference = false;
  21868. for (auto& methodInstGroup : ownedType->mMethodInstanceGroups)
  21869. {
  21870. if ((methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) &&
  21871. (!methodInstGroup.mDefault->mMethodDef->mIsStatic) && (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mAlwaysInline) &&
  21872. ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Referenced)) &&
  21873. (methodInstGroup.mHasEmittedReference))
  21874. {
  21875. hasConfirmedReference = true;
  21876. }
  21877. }
  21878. if ((!hasConfirmedReference) || (ownedType->IsBoxed()))
  21879. needForceLinking = true;
  21880. }
  21881. if ((needForceLinking) && (mProject->mCodeGenOptions.mAsmKind == BfAsmKind_None))
  21882. {
  21883. BfMethodState methodState;
  21884. SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
  21885. methodState.mTempKind = BfMethodState::TempKind_Static;
  21886. mHasForceLinkMarker = true;
  21887. auto voidType = mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_None));
  21888. SizedArray<BfIRType, 0> paramTypes;
  21889. BfIRFunctionType funcType = mBfIRBuilder->CreateFunctionType(voidType, paramTypes);
  21890. String linkName = "FORCELINKMOD_" + mModuleName;
  21891. BfIRFunction func = mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, linkName);
  21892. mBfIRBuilder->SetActiveFunction(func);
  21893. auto entryBlock = mBfIRBuilder->CreateBlock("main", true);
  21894. mBfIRBuilder->SetInsertPoint(entryBlock);
  21895. auto firstType = mOwnedTypeInstances[0];
  21896. UpdateSrcPos(mContext->mBfObjectType->mTypeDef->GetRefNode());
  21897. SizedArray<BfIRMDNode, 1> diParamTypes;
  21898. diParamTypes.Add(mBfIRBuilder->DbgGetType(GetPrimitiveType(BfTypeCode_None)));
  21899. BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes);
  21900. auto diScope = mBfIRBuilder->DbgCreateFunction(mDICompileUnit, "FORCELINKMOD", linkName, mCurFilePosition.mFileInstance->mDIFile,
  21901. mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, 0, false, func);
  21902. methodState.mCurScope->mDIScope = diScope;
  21903. UpdateSrcPos(mContext->mBfObjectType->mTypeDef->GetRefNode(), BfSrcPosFlag_Force);
  21904. SizedArray<BfIRValue, 8> args;
  21905. BfExprEvaluator exprEvaluator(this);
  21906. for (auto& ownedType : mOwnedTypeInstances)
  21907. {
  21908. auto alloca = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(GetPrimitiveType(BfTypeCode_Int8)));
  21909. auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(diScope, "variable", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(ownedType));
  21910. mBfIRBuilder->DbgInsertDeclare(alloca, diVariable);
  21911. }
  21912. mBfIRBuilder->CreateRetVoid();
  21913. mBfIRBuilder->SetActiveFunction(BfIRFunction());
  21914. }
  21915. }
  21916. }
  21917. bool BfModule::Finish()
  21918. {
  21919. BP_ZONE("BfModule::Finish");
  21920. BfLogSysM("BfModule finish: %p\n", this);
  21921. if (mHadBuildError)
  21922. {
  21923. // Don't AssertErrorState here, this current pass may not have failed but
  21924. // the module was still queued in mFinishedModuleWorkList
  21925. ClearModule();
  21926. return true;
  21927. }
  21928. if (mUsedSlotCount != -1)
  21929. {
  21930. BF_ASSERT(mCompiler->mMaxInterfaceSlots != -1);
  21931. mUsedSlotCount = mCompiler->mMaxInterfaceSlots;
  21932. }
  21933. if ((!mGeneratesCode) && (!mAddedToCount))
  21934. return true;
  21935. BF_ASSERT(mAddedToCount);
  21936. mAddedToCount = false;
  21937. mAwaitingFinish = false;
  21938. mCompiler->mStats.mModulesFinished++;
  21939. if (HasCompiledOutput())
  21940. {
  21941. BF_ASSERT(!mBfIRBuilder->mIgnoreWrites);
  21942. DbgFinish();
  21943. if (mAwaitingInitFinish)
  21944. FinishInit();
  21945. for (auto ownedTypeInst : mOwnedTypeInstances)
  21946. {
  21947. // Generate dbg info and add global variables if we haven't already
  21948. mBfIRBuilder->PopulateType(ownedTypeInst);
  21949. }
  21950. if (mBfIRBuilder->DbgHasInfo())
  21951. {
  21952. mBfIRBuilder->DbgFinalize();
  21953. }
  21954. String objOutputPath;
  21955. String irOutputPath;
  21956. mIsModuleMutable = false;
  21957. //mOutFileNames.Clear();
  21958. BF_ASSERT(((int)mOutFileNames.size() >= mExtensionCount) || (mParentModule != NULL));
  21959. bool writeModule = mBfIRBuilder->HasExports();
  21960. String outputPath;
  21961. BfCodeGenOptions codeGenOptions = mProject->mCodeGenOptions;
  21962. auto& compilerOpts = mCompiler->mOptions;
  21963. codeGenOptions.mSIMDSetting = compilerOpts.mSIMDSetting;
  21964. auto moduleOptions = GetModuleOptions();
  21965. codeGenOptions.mOptLevel = moduleOptions.mOptLevel;
  21966. codeGenOptions.mSIMDSetting = moduleOptions.mSIMDSetting;
  21967. codeGenOptions.mWriteLLVMIR = mCompiler->mOptions.mWriteIR;
  21968. codeGenOptions.mWriteObj = mCompiler->mOptions.mGenerateObj;
  21969. codeGenOptions.mWriteBitcode = mCompiler->mOptions.mGenerateBitcode;
  21970. codeGenOptions.mVirtualMethodOfs = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots;
  21971. codeGenOptions.mDynSlotOfs = mSystem->mPtrSize - mCompiler->GetDynCastVDataCount() * 4;
  21972. mCompiler->mStats.mIRBytes += mBfIRBuilder->mStream.GetSize();
  21973. mCompiler->mStats.mConstBytes += mBfIRBuilder->mTempAlloc.GetAllocSize();
  21974. bool allowWriteToLib = true;
  21975. if ((allowWriteToLib) && (codeGenOptions.mOptLevel == BfOptLevel_OgPlus) &&
  21976. (!mCompiler->IsHotCompile()) && (mModuleName != "vdata"))
  21977. {
  21978. codeGenOptions.mWriteToLib = true;
  21979. mWroteToLib = true;
  21980. }
  21981. else
  21982. {
  21983. mWroteToLib = false;
  21984. }
  21985. for (int fileIdx = 0; fileIdx <= mExtensionCount; fileIdx++)
  21986. {
  21987. outputPath = mModuleName;
  21988. outputPath = mCompiler->mOutputDirectory + "/" + mProject->mName + "/" + outputPath;
  21989. BfModuleFileName moduleFileName;
  21990. if (mParentModule != NULL)
  21991. {
  21992. for (auto&& checkPair : mParentModule->mSpecializedMethodModules)
  21993. {
  21994. if (checkPair.mValue == this)
  21995. moduleFileName.mProjects = checkPair.mKey;
  21996. }
  21997. }
  21998. moduleFileName.mProjects.Add(mProject);
  21999. if (fileIdx > 0)
  22000. outputPath += StrFormat("@%d", fileIdx + 1);
  22001. if (mCompiler->mOptions.mWriteIR)
  22002. irOutputPath = outputPath + ".ll";
  22003. if (mCompiler->mOptions.mGenerateObj)
  22004. {
  22005. objOutputPath = outputPath + BF_OBJ_EXT;
  22006. moduleFileName.mFileName = objOutputPath;
  22007. }
  22008. else if (mCompiler->mOptions.mWriteIR)
  22009. {
  22010. moduleFileName.mFileName = irOutputPath;
  22011. }
  22012. else if ((!mCompiler->mOptions.mGenerateObj) && (!mCompiler->mOptions.mGenerateBitcode) && (!mCompiler->mOptions.mWriteIR))
  22013. {
  22014. BFMODULE_FATAL(this, "Neither obj nor IR specified");
  22015. }
  22016. moduleFileName.mModuleWritten = writeModule;
  22017. moduleFileName.mWroteToLib = mWroteToLib;
  22018. if (!mOutFileNames.Contains(moduleFileName))
  22019. mOutFileNames.Add(moduleFileName);
  22020. }
  22021. if (mCompiler->IsHotCompile())
  22022. {
  22023. codeGenOptions.mIsHotCompile = true;
  22024. if (mParentModule != NULL)
  22025. mParentModule->mHadHotObjectWrites = true;
  22026. mHadHotObjectWrites = true;
  22027. }
  22028. //TODO: Testing VDATA
  22029. /*if (mModuleName == "vdata")
  22030. {
  22031. codeGenOptions.mOptLevel = 4;
  22032. }*/
  22033. codeGenOptions.GenerateHash();
  22034. BP_ZONE("BfModule::Finish.WriteObjectFile");
  22035. if ((writeModule) && (!mBfIRBuilder->mIgnoreWrites))
  22036. mCompiler->mCodeGen.WriteObjectFile(this, outputPath, codeGenOptions);
  22037. mLastModuleWrittenRevision = mCompiler->mRevision;
  22038. }
  22039. else
  22040. {
  22041. for (auto type : mOwnedTypeInstances)
  22042. {
  22043. BF_ASSERT((!type->IsIncomplete()) || (type->IsSpecializedByAutoCompleteMethod()));
  22044. }
  22045. }
  22046. for (auto& specModulePair : mSpecializedMethodModules)
  22047. {
  22048. auto specModule = specModulePair.mValue;
  22049. if ((specModule->mIsModuleMutable) && (!specModule->mAwaitingFinish))
  22050. {
  22051. BfLogSysM(" Mutable spec module remaining: %p\n", specModule);
  22052. }
  22053. }
  22054. CleanupFileInstances();
  22055. // We can't ClearModuleData here because we need the mSpecializedMethodModules to remain valid until we Finish them too
  22056. return true;
  22057. }
  22058. void BfModule::ReportMemory(MemReporter* memReporter)
  22059. {
  22060. memReporter->Add(sizeof(BfModule));
  22061. if (mBfIRBuilder != NULL)
  22062. {
  22063. memReporter->BeginSection("IRBuilder_ConstData");
  22064. memReporter->Add("Used", mBfIRBuilder->mTempAlloc.GetAllocSize());
  22065. memReporter->Add("Unused", mBfIRBuilder->mTempAlloc.GetTotalAllocSize() - mBfIRBuilder->mTempAlloc.GetAllocSize());
  22066. memReporter->EndSection();
  22067. memReporter->BeginSection("IRBuilder_BFIR");
  22068. memReporter->Add("Used", (int)(mBfIRBuilder->mStream.GetSize()));
  22069. memReporter->Add("Unused", (int)(mBfIRBuilder->mStream.mPools.size() * ChunkedDataBuffer::ALLOC_SIZE) - mBfIRBuilder->mStream.GetSize());
  22070. memReporter->EndSection();
  22071. memReporter->Add(sizeof(BfIRBuilder));
  22072. }
  22073. memReporter->BeginSection("FileInstanceMap");
  22074. memReporter->AddMap(mFileInstanceMap);
  22075. memReporter->AddMap(mNamedFileInstanceMap);
  22076. memReporter->Add((int)mNamedFileInstanceMap.size() * sizeof(BfFileInstance));
  22077. memReporter->EndSection();
  22078. memReporter->AddVec(mOwnedTypeInstances, false);
  22079. memReporter->AddVec(mSpecializedMethodModules, false);
  22080. memReporter->AddVec(mOutFileNames, false);
  22081. memReporter->AddMap("FuncReferences", mFuncReferences, false);
  22082. memReporter->AddMap(mInterfaceSlotRefs, false);
  22083. memReporter->AddMap(mStaticFieldRefs, false);
  22084. memReporter->AddMap(mClassVDataRefs, false);
  22085. memReporter->AddMap("VDataExtMap", mClassVDataExtRefs, false);
  22086. memReporter->AddMap(mTypeDataRefs, false);
  22087. memReporter->AddMap(mDbgRawAllocDataRefs, false);
  22088. memReporter->AddMap(mDeferredMethodCallData, false);
  22089. memReporter->AddHashSet(mDeferredMethodIds, false);
  22090. memReporter->AddHashSet("ModuleRefs", mModuleRefs, false);
  22091. }
  22092. // ClearModuleData is called immediately after the module is compiled, so don't clear out any data that needs to
  22093. // be transient through the next compile
  22094. void BfModule::ClearModuleData(bool clearTransientData)
  22095. {
  22096. BfLogSysM("ClearModuleData %p\n", this);
  22097. if (mAddedToCount)
  22098. {
  22099. mCompiler->mStats.mModulesFinished++;
  22100. mAddedToCount = false;
  22101. }
  22102. mDICompileUnit = BfIRMDNode();
  22103. if (clearTransientData)
  22104. mIncompleteMethodCount = 0;
  22105. mHasGenericMethods = false;
  22106. // We don't want to clear these because we want it to persist through module extensions-
  22107. // otherwise we may think an extension succeeds even though the base module failed
  22108. //mHadBuildError = false;
  22109. //mHadBuildWarning = false;
  22110. mClassVDataRefs.Clear();
  22111. mClassVDataExtRefs.Clear();
  22112. for (auto& kv : mTypeDataRefs)
  22113. kv.mValue = BfIRValue();
  22114. mStringCharPtrPool.Clear();
  22115. mStringObjectPool.Clear();
  22116. mStaticFieldRefs.Clear();
  22117. BF_ASSERT(!mIgnoreErrors);
  22118. for (auto prevIRBuilder : mPrevIRBuilders)
  22119. delete prevIRBuilder;
  22120. mPrevIRBuilders.Clear();
  22121. for (auto& specPair : mSpecializedMethodModules)
  22122. {
  22123. auto specModule = specPair.mValue;
  22124. specModule->ClearModuleData();
  22125. }
  22126. for (int i = 0; i < BfBuiltInFuncType_Count; i++)
  22127. mBuiltInFuncs[i] = BfIRFunction();
  22128. if (mNextAltModule != NULL)
  22129. mNextAltModule->ClearModuleData();
  22130. BfLogSysM("ClearModuleData. Deleting IRBuilder: %p\n", mBfIRBuilder);
  22131. mIsModuleMutable = false;
  22132. delete mBfIRBuilder;
  22133. mBfIRBuilder = NULL;
  22134. mWantsIRIgnoreWrites = false;
  22135. }
  22136. void BfModule::DisownMethods()
  22137. {
  22138. for (int i = 0; i < BfBuiltInFuncType_Count; i++)
  22139. mBuiltInFuncs[i] = BfIRFunction();
  22140. BfModule* methodModule = this;
  22141. if (mParentModule != NULL)
  22142. methodModule = mParentModule;
  22143. for (auto typeInst : methodModule->mOwnedTypeInstances)
  22144. {
  22145. for (auto& methodGroup : typeInst->mMethodInstanceGroups)
  22146. {
  22147. if (methodGroup.mDefault != NULL)
  22148. {
  22149. if (methodGroup.mDefault->mIRFunction)
  22150. {
  22151. BF_ASSERT(methodGroup.mDefault->mDeclModule != NULL);
  22152. if (methodGroup.mDefault->mDeclModule == this)
  22153. {
  22154. methodGroup.mDefault->mIRFunction = BfIRFunction();
  22155. }
  22156. }
  22157. }
  22158. if (methodGroup.mMethodSpecializationMap != NULL)
  22159. {
  22160. for (auto& mapPair : *methodGroup.mMethodSpecializationMap)
  22161. {
  22162. auto methodInstance = mapPair.mValue;
  22163. if (methodInstance->mDeclModule == this)
  22164. {
  22165. methodInstance->mIRFunction = BfIRFunction();
  22166. }
  22167. }
  22168. }
  22169. }
  22170. }
  22171. }
  22172. void BfModule::ClearModule()
  22173. {
  22174. ClearModuleData();
  22175. DisownMethods();
  22176. for (auto& specPair : mSpecializedMethodModules)
  22177. {
  22178. auto specModule = specPair.mValue;
  22179. specModule->ClearModule();
  22180. }
  22181. if (mNextAltModule != NULL)
  22182. mNextAltModule->ClearModule();
  22183. }