| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400 | {    Symbol table implementation for the definitions    Copyright (c) 1998-2005 by Florian Klaempfl, Pierre Muller    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ****************************************************************************}unit symdef;{$i fpcdefs.inc}interface    uses       { common }       cclasses,widestr,       { global }       globtype,globals,tokens,constexp,       { symtable }       symconst,symbase,symtype,       { node }       node,       { aasm }       aasmtai,       cpuinfo,       cgbase,       parabase       ;    type{************************************************                    TDef************************************************}       tgenericconstraintdata=class         interfaces : tfpobjectlist;         interfacesderef : tfplist;         flags : tgenericconstraintflags;         { only required while parsing }         fileinfo : tfileposinfo;         constructor create;         destructor destroy;override;         procedure ppuload(ppufile:tcompilerppufile);         procedure ppuwrite(ppufile:tcompilerppufile);         procedure buildderef;         procedure deref;       end;       { trtti_attribute_list }       trtti_attribute = class          typesym         : tsym;          typesymderef    : tderef;          typeconstr      : tdef;          typeconstrderef : tderef;          { these two are not stored in PPU }          constructorcall : tnode;          constructorpd   : tdef;          paras           : array of tnode;          constructor ppuload(ppufile:tcompilerppufile);          procedure ppuwrite(ppufile:tcompilerppufile);          procedure ppuload_subentries(ppufile:tcompilerppufile);          procedure ppuwrite_subentries(ppufile:tcompilerppufile);          destructor destroy;override;          procedure buildderef;          procedure deref;       end;       trtti_attribute_list = class          rtti_attributes : TFPObjectList;          { if the attribute list is bound to a def or symbol }          is_bound : Boolean;          class procedure bind(var dangling,owned:trtti_attribute_list);          procedure addattribute(atypesym:tsym;typeconstr:tdef;constructorcall:tnode;constref paras:array of tnode);          procedure addattribute(attr:trtti_attribute);          destructor destroy; override;          function get_attribute_count:longint;          procedure buildderef;          procedure deref;          class function ppuload(ppufile:tcompilerppufile):trtti_attribute_list;          class procedure ppuwrite(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);          class procedure ppuload_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);          class procedure ppuwrite_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);       end;       { tstoreddef }       tstoreddef = class(tdef)       private{$ifdef symansistr}          _fullownerhierarchyname : ansistring;{$else symansistr}          _fullownerhierarchyname : pshortstring;{$endif symansistr}          procedure writeentry(ppufile: tcompilerppufile; ibnr: byte);       protected          typesymderef  : tderef;          procedure ppuwrite_platform(ppufile:tcompilerppufile);virtual;          procedure ppuload_platform(ppufile:tcompilerppufile);virtual;          { a (possibly) reusable def is always created on the basis of another            def, and contains a reference to this other def. If this other            def is in a non-persistent symboltable, the new def cannot actually            be safely reused everywhere in the current module. This routine            abtracts that checking, and also restores the symtable stack            (which had to be reset before creating the new def, so that the new             def did not automatically get added to its top) }          class procedure setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);       public{$ifdef EXTDEBUG}          fileinfo   : tfileposinfo;{$endif}          { generic support }          genericdef      : tstoreddef;          genericdefderef : tderef;          generictokenbuf : tdynamicarray;          { this list contains references to the symbols that make up the            generic parameters; the symbols are not owned by this list            Note: this list is allocated on demand! }          genericparas    : tfphashobjectlist;          genericparaderefs : tfplist;          { contains additional data if this def is a generic constraint            Note: this class is allocated on demand! }          genconstraintdata : tgenericconstraintdata;          { this is Nil if the def has no RTTI attributes }          rtti_attribute_list : trtti_attribute_list;          constructor create(dt:tdeftyp;doregister:boolean);          constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);          destructor  destroy;override;          function getcopy : tstoreddef;virtual;          procedure ppuwrite(ppufile:tcompilerppufile);virtual;          { this is called directly after ppuload }          procedure ppuload_subentries(ppufile:tcompilerppufile);virtual;          { this is called directly after ppuwrite }          procedure ppuwrite_subentries(ppufile:tcompilerppufile);virtual;          procedure buildderef;override;          procedure buildderefimpl;override;          procedure deref;override;          procedure derefimpl;override;          function  size:asizeint;override;          function  getvardef:longint;override;          function  alignment:shortint;override;          function  is_publishable : tpublishproperty;override;          function  needs_inittable : boolean;override;          function  has_non_trivial_init_child(check_parent:boolean):boolean;override;          function  rtti_mangledname(rt:trttitype):TSymStr;override;          function  OwnerHierarchyName: string; override;          function  fullownerhierarchyname(skipprocparams:boolean):TSymStr;override;          function  needs_separate_initrtti:boolean;override;          function  in_currentunit: boolean;          { regvars }          function is_intregable : boolean;          function is_fpuregable : boolean;          { def can be put into a register if it is const/immutable }          function is_const_intregable : boolean;          { generics }          procedure initgeneric;          { this function can be used to determine whether a def is really a            generic declaration or just a normal type declared inside another            generic }          function is_generic:boolean;          { same as above for specializations }          function is_specialization:boolean;          { generic utilities }          function is_generic_param_const(index:integer):boolean;inline;          function get_generic_param_def(index:integer):tdef;inline;          { registers this def in the unit's deflist; no-op if already registered }          procedure register_def; override;          { add the def to the top of the symtable stack if it's not yet owned            by another symtable }          procedure maybe_put_in_symtable_stack;       private          savesize  : asizeuint;       end;       tfiletyp = (ft_text,ft_typed,ft_untyped);       tfiledef = class(tstoreddef)          filetyp : tfiletyp;          typedfiledef : tdef;          typedfiledefderef : tderef;          constructor createtext;virtual;          constructor createuntyped;virtual;          constructor createtyped(def : tdef);virtual;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          procedure buildderef;override;          procedure deref;override;          function  GetTypeName:string;override;          function  getmangledparaname:TSymStr;override;          function  size:asizeint;override;          procedure setsize;          function alignment: shortint; override;       end;       tfiledefclass = class of tfiledef;       tvariantdef = class(tstoreddef)          varianttype : tvarianttype;          constructor create(v : tvarianttype);virtual;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          function GetTypeName:string;override;          function alignment : shortint;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  getvardef:longint;override;          procedure setsize;          function is_publishable : tpublishproperty;override;          function needs_inittable : boolean;override;       end;       tvariantdefclass = class of tvariantdef;       tformaldef = class(tstoreddef)          typed:boolean;          constructor create(Atyped:boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;       end;       tformaldefclass = class of tformaldef;       tforwarddef = class(tstoreddef)          tosymname : pshortstring;          forwardpos : tfileposinfo;          constructor create(const s:string;const pos:tfileposinfo);virtual;          destructor destroy;override;          function getcopy:tstoreddef;override;          function GetTypeName:string;override;       end;       tforwarddefclass = class of tforwarddef;       tundefineddef = class(tstoreddef)          constructor create(doregister:boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;       end;       tundefineddefclass = class of tundefineddef;       terrordef = class(tstoreddef)          constructor create;virtual;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;          function  getmangledparaname : TSymStr;override;       end;       terrordefclass = class of terrordef;       tabstractpointerdef = class(tstoreddef)          pointeddef : tdef;          pointeddefderef : tderef;          constructor create(dt:tdeftyp;def:tdef);          constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);          procedure ppuwrite(ppufile:tcompilerppufile);override;          procedure buildderef;override;          procedure deref;override;          function size:asizeint;override;          function alignment:shortint;override;       end;       tpointerdef = class(tabstractpointerdef)          has_pointer_math : boolean;          constructor create(def:tdef);virtual;          { returns a pointerdef for def, reusing an existing one in case it            exists in the current module }          class function getreusable(def: tdef): tpointerdef; virtual;          { same as above, but in case the def must never be freed after the            current module has been compiled -- even if the def was not written            to the ppu file (for defs in para locations, as we don't reset them            so we don't have to recalculate them all the time) }          class function getreusable_no_free(def: tdef): tpointerdef;          function size:asizeint;override;          function getcopy:tstoreddef;override;          constructor ppuload(ppufile:tcompilerppufile);          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;          {# returns the appropriate int type for pointer arithmetic with the given pointer type.             When adding or subtracting a number to/from a pointer, this function returns the             int type to which that number has to be converted, before the operation can be performed.             Normally, this is sinttype, except on i8086, where it takes into account the             special i8086 pointer types (near, far, huge). }          function pointer_arithmetic_int_type:tdef;virtual;          {# the unsigned version of pointer_arithmetic_int_type. Used with inc/dec. }          function pointer_arithmetic_uint_type:tdef;virtual;          {# returns the int type produced when subtracting two pointers of the given type.             Normally, this is sinttype, except on i8086, where it takes into account the             special i8086 pointer types (near, far, huge). }          function pointer_subtraction_result_type:tdef;virtual;          function compatible_with_pointerdef_size(ptr: tpointerdef): boolean; virtual;          {# the integer index type used to convert the pointer to array (i.e. denotes int_type in: ptr[int_type]) }          function converted_pointer_to_array_range_type:tdef;virtual;       end;       tpointerdefclass = class of tpointerdef;       tprocdef = class;       tabstractrecorddef= class(tstoreddef)       private          rttistring     : string;{$ifdef DEBUG_NODE_XML}       protected          procedure XMLPrintDefData(var T: Text; Sym: TSym); override;{$endif DEBUG_NODE_XML}       public          objname,          objrealname    : PShortString;          { for C++ classes: name of the library this class is imported from }          { for Java classes/records: package name }          import_lib     : PShortString;          symtable       : TSymtable;          cloneddef      : tabstractrecorddef;          cloneddefderef : tderef;          objectoptions  : tobjectoptions;          { for targets that initialise typed constants via explicit assignments            instead of by generating an initialised data sectino }          tcinitcode     : tnode;          constructor create(const n:string; dt:tdeftyp;doregister:boolean);          constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);          procedure ppuwrite(ppufile:tcompilerppufile);override;          destructor destroy; override;          procedure buildderefimpl;override;          procedure derefimpl;override;          procedure check_forwards; virtual;          function find_procdef_bytype(pt:tproctypeoption): tprocdef;          function GetSymtable(t:tGetSymtable):TSymtable;override;          function is_packed:boolean;          function RttiName: string;          { enumerator support }          function search_enumerator_get: tprocdef; virtual;          function search_enumerator_move: tprocdef; virtual;          function search_enumerator_current: tsym; virtual;          { JVM }          function jvm_full_typename(with_package_name: boolean): string;          { check if the symtable contains a float field }          function contains_float_field : boolean;          { check if the symtable contains a field that spans an aword boundary }          function contains_cross_aword_field: boolean;       end;       pvariantrecdesc = ^tvariantrecdesc;       tvariantrecbranch = record         { we store only single values here and no ranges because tvariantrecdesc is only needed in iso mode           which does not support range expressions in variant record definitions }         values : array of Tconstexprint;         nestedvariant : pvariantrecdesc;       end;       ppvariantrecdesc = ^pvariantrecdesc;       tvariantrecdesc = record         variantselector : tsym;         variantselectorderef : tderef;         branches : array of tvariantrecbranch;       end;       trecorddef = class(tabstractrecorddef){$ifdef DEBUG_NODE_XML}       protected          function XMLPrintType: ansistring; override;{$endif DEBUG_NODE_XML}       public          variantrecdesc : pvariantrecdesc;          isunion       : boolean;          constructor create(const n:string; p:TSymtable);virtual;          constructor create_global_internal(const n: string; packrecords, recordalignmin: shortint); virtual;          constructor create_internal(const n: string; packrecords, recordalignmin: shortint; where: tsymtable); virtual;          function add_field_by_def(const optionalname: TIDString; def: tdef): tsym;          procedure add_fields_from_deflist(fieldtypes: tfplist);          constructor ppuload(ppufile:tcompilerppufile);          destructor destroy;override;          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          procedure buildderef;override;          procedure deref;override;          function  size:asizeint;override;          function  alignment : shortint;override;          function  padalignment: shortint;          function  GetTypeName:string;override;          { debug }          function  needs_inittable : boolean;override;          function  needs_separate_initrtti:boolean;override;          function  has_non_trivial_init_child(check_parent:boolean):boolean;override;       end;       trecorddefclass = class of trecorddef;       tobjectdef = class;       { TImplementedInterface }       TImplementedInterface = class        private         fIOffset      : longint;         function GetIOffset: longint;        public         IntfDef      : tobjectdef;         IntfDefDeref : tderef;         IType        : tinterfaceentrytype;         VtblImplIntf : TImplementedInterface;         NameMappings : TFPHashList;         ProcDefs     : TFPObjectList;         ImplementsGetter :  tsym;         ImplementsGetterDeref : tderef;         ImplementsField : tsym;         constructor create(aintf: tobjectdef);virtual;         constructor create_deref(intfd,getterd:tderef);virtual;         destructor  destroy; override;         function  getcopy:TImplementedInterface;         procedure buildderef;         procedure deref;         procedure AddMapping(const origname, newname: string);         function  GetMapping(const origname: string):string;         procedure AddImplProc(pd:tprocdef);         function  IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;         property  IOffset: longint read GetIOffset write fIOffset;       end;       timplementedinterfaceclass = class of timplementedinterface;       { tvmtentry }       tvmtentry = record         procdef      : tprocdef;         procdefderef : tderef;         visibility   : tvisibility;       end;       pvmtentry = ^tvmtentry;       { tobjectdef }       tvmcallstatic = (vmcs_default, vmcs_yes, vmcs_no, vmcs_unreachable);       pmvcallstaticinfo = ^tmvcallstaticinfo;       tmvcallstaticinfo = array[0..1024*1024-1] of tvmcallstatic;       tobjectdef = class(tabstractrecorddef)       private          fcurrent_dispid: longint;{$ifdef DEBUG_NODE_XML}       protected          function XMLPrintType: ansistring; override;          procedure XMLPrintDefInfo(var T: Text; Sym: TSym); override;          procedure XMLPrintDefData(var T: Text; Sym: TSym); override;{$endif DEBUG_NODE_XML}       public          childof        : tobjectdef;          childofderef   : tderef;          { for Object Pascal helpers }          extendeddef   : tdef;          extendeddefderef: tderef;          helpertype : thelpertype;          { for Objective-C: protocols and classes can have the same name there }          objextname     : pshortstring;          { to be able to have a variable vmt position }          { and no vmt field for objects without virtuals }          vmtentries     : TFPList;          vmcallstaticinfo : pmvcallstaticinfo;          vmt_field       : tsym;          vmt_fieldderef  : tderef;          iidguid        : pguid;          iidstr         : pshortstring;          { store implemented interfaces defs and name mappings }          ImplementedInterfaces : TFPObjectList;          { number of abstract methods (used by JVM target to determine whether            or not the class should be marked as abstract: must be done if 1 or            more abstract methods) }          abstractcnt    : longint;          writing_class_record_dbginfo,          { a class of this type has been created in this module }          created_in_current_module,          { a loadvmtnode for this class has been created in this            module, so if a classrefdef variable of this or a parent            class is used somewhere to instantiate a class, then this            class may be instantiated          }          maybe_created_in_current_module,          { a "class of" this particular class has been created in            this module          }          classref_created_in_current_module : boolean;          objecttype     : tobjecttyp;          constructor create(ot:tobjecttyp;const n:string;c:tobjectdef;doregister:boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          destructor  destroy;override;          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function GetTypeName:string;override;          procedure buildderef;override;          procedure deref;override;          procedure derefimpl;override;          procedure copyvmtentries(objdef:tobjectdef);          function  getparentdef:tdef;override;          function  size : asizeint;override;          function  alignment:shortint;override;          function  vmtmethodoffset(index:longint):longint;          function  members_need_inittable : boolean;          { this should be called when this class implements an interface }          procedure prepareguid;          function  is_publishable : tpublishproperty;override;          function  needs_inittable : boolean;override;          function  needs_separate_initrtti : boolean;override;          function  has_non_trivial_init_child(check_parent:boolean):boolean;override;          function  rtti_mangledname(rt:trttitype):TSymStr;override;          function  is_unique_objpasdef: boolean;          function  vmt_mangledname : TSymStr;          function  vmt_def: trecorddef;          procedure check_forwards; override;          procedure insertvmt;          function  vmt_offset: asizeint;          procedure set_parent(c : tobjectdef);          function find_destructor: tprocdef;          function implements_any_interfaces: boolean;          function register_implemented_interface(intfdef:tobjectdef;useguid:boolean):timplementedinterface;          { dispinterface support }          function get_next_dispid: longint;          { enumerator support }          function search_enumerator_get: tprocdef; override;          function search_enumerator_move: tprocdef; override;          function search_enumerator_current: tsym; override;          { WPO }          procedure register_created_object_type;override;          procedure register_maybe_created_object_type;          procedure register_created_classref_type;          procedure register_vmt_call(index:longint);          { ObjC }          procedure finish_objc_data;          function check_objc_types: boolean;          { C++ }          procedure finish_cpp_data;       end;       tobjectdefclass = class of tobjectdef;       tclassrefdef = class(tabstractpointerdef)          constructor create(def:tdef);virtual;          constructor ppuload(ppufile:tcompilerppufile);          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function getcopy:tstoreddef;override;          function GetTypeName:string;override;          function is_publishable : tpublishproperty;override;          function rtti_mangledname(rt:trttitype):TSymStr;override;          procedure register_created_object_type;override;       end;       tclassrefdefclass = class of tclassrefdef;       tarraydef = class(tstoreddef)          lowrange,          highrange     : asizeint;          rangedef      : tdef;          rangedefderef : tderef;          arrayoptions  : tarraydefoptions;          symtable      : TSymtable;       protected          _elementdef      : tdef;          _elementdefderef : tderef;          procedure setelementdef(def:tdef);          class function getreusable_intern(def: tdef; elems: asizeint; const options: tarraydefoptions): tarraydef;       public          function elesize : asizeint;          function elepackedbitsize : asizeint;          function elecount : asizeuint;          constructor create_from_pointer(def: tpointerdef);virtual;          constructor create(l, h: asizeint; def: tdef);virtual;          constructor create_vector(l,h:asizeint; def:tdef);          constructor create_openarray;virtual;          class function getreusable(def: tdef; elems: asizeint): tarraydef;          class function getreusable_vector(def: tdef; elems: asizeint): tarraydef;          { same as above, but in case the def must never be freed after the            current module has been compiled -- even if the def was not written            to the ppu file (for defs in para locations, as we don't reset them            so we don't have to recalculate them all the time) }          class function getreusable_no_free(def: tdef; elems: asizeint): tarraydef;          class function getreusable_no_free_vector(def: tdef; elems: asizeint): tarraydef;          constructor ppuload(ppufile:tcompilerppufile);          destructor destroy; override;          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;          function  getmangledparaname : TSymStr;override;          procedure buildderef;override;          procedure deref;override;          function size : asizeint;override;          function alignment : shortint;override;          { returns the label of the range check string }          function needs_inittable : boolean;override;          function needs_separate_initrtti : boolean;override;          property elementdef : tdef read _elementdef write setelementdef;          function is_publishable : tpublishproperty;override;          function is_hwvector: boolean;       end;       tarraydefclass = class of tarraydef;       torddef = class(tstoreddef)          low,high : TConstExprInt;          ordtype  : tordtype;          constructor create(t : tordtype;v,b : TConstExprInt; doregister: boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  is_publishable : tpublishproperty;override;          function  GetTypeName:string;override;          function alignment:shortint;override;          procedure setsize;          function  packedbitsize: asizeint; override;          function getvardef : longint;override;       end;       torddefclass = class of torddef;       tfloatdef = class(tstoreddef)          floattype : tfloattype;          constructor create(t: tfloattype; doregister: boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;          function  is_publishable : tpublishproperty;override;          function alignment:shortint;override;          function structalignment: shortint;override;          procedure setsize;          function  getvardef:longint;override;       end;       tfloatdefclass = class of tfloatdef;       { tabstractprocdef }       tprocnameoption = (pno_showhidden, pno_proctypeoption, pno_paranames,         pno_ownername, pno_noclassmarker, pno_noleadingdollar,         pno_mangledname, pno_noparams, pno_prettynames);       tprocnameoptions = set of tprocnameoption;       tproccopytyp = (pc_normal,{$ifdef i8086}                       { the address in a far format }                       pc_far_address,                       { the offset part of the far address }                       pc_offset,{$endif i8086}                       { creates a procvardef describing only the code pointer                         of a method/netsted function/... }                       pc_address_only,                       { everything except for hidden parameters }                       pc_normal_no_hidden,                       { everything except for the parameters (because they                         might be moved over to the copy) }                       pc_normal_no_paras,                       { always creates a top-level function, removes all                         special parameters (self, vmt, parentfp, ...) }                       pc_bareproc                       );       tcacheableproccopytyp = pc_normal..pc_address_only;       tabstractprocdef = class(tstoreddef)          { saves a definition to the return type }          returndef       : tdef;          returndefderef  : tderef;          parast          : TSymtable;          paras           : tparalist;          proctypeoption  : tproctypeoption;          proccalloption  : tproccalloption;          procoptions     : tprocoptions;          callerargareasize,          calleeargareasize: pint;{$ifdef m68k}          exp_funcretloc : tregister;   { explicit funcretloc for AmigaOS }{$endif}          funcretloc : array[callerside..calleeside] of TCGPara;          has_paraloc_info : tcallercallee; { paraloc info is available }          { number of user visible parameters }          maxparacount,          minparacount    : byte;          constructor create(dt:tdeftyp;level:byte;doregister:boolean);          constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);          destructor destroy;override;          procedure  ppuwrite(ppufile:tcompilerppufile);override;          procedure buildderef;override;          procedure deref;override;          procedure calcparas;          function mangledprocparanames(oldlen : longint) : string;          function  typename_paras(pno: tprocnameoptions): ansistring;          function  is_methodpointer:boolean;virtual;          function  is_addressonly:boolean;virtual;          function  no_self_node:boolean;          { get either a copy as a procdef or procvardef }          function  getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef; virtual;          function  compatible_with_pointerdef_size(ptr: tpointerdef): boolean; virtual;          procedure check_mark_as_nested;          procedure init_paraloc_info(side: tcallercallee);          procedure done_paraloc_info(side: tcallercallee);          function stack_tainting_parameter(side: tcallercallee): boolean;          function is_pushleftright: boolean;virtual;          function address_type:tdef;virtual;          { address type, generated for ofs() }          function ofs_address_type:tdef;virtual;          procedure declared_far;virtual;          procedure declared_near;virtual;          function generate_safecall_wrapper: boolean; virtual;          { returns true if the def is a generic param of the procdef }          function is_generic_param(def:tdef): boolean;          function wpo_may_create_instance(optionalmethodpointer: tnode): boolean;       private          procedure count_para(p:TObject;arg:pointer);          procedure insert_para(p:TObject;arg:pointer);       end;       tprocvardef = class(tabstractprocdef)          constructor create(level:byte;doregister:boolean);virtual;          { returns a procvardef that represents the address of a proc(var)def }          class function getreusableprocaddr(def: tabstractprocdef; copytyp: tcacheableproccopytyp): tprocvardef; virtual;          { same as above, but in case the def must never be freed after the            current module has been compiled -- even if the def was not written            to the ppu file (for defs in para locations, as we don't reset them            so we don't have to recalculate them all the time) }          class function getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetSymtable(t:tGetSymtable):TSymtable;override;          function  size : asizeint;override;          function  GetTypeName:string;override;          function  is_publishable : tpublishproperty;override;          function  is_methodpointer:boolean;override;          function  is_addressonly:boolean;override;          function  getmangledparaname:TSymStr;override;          function getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef; override;       end;       tprocvardefclass = class of tprocvardef;       tmessageinf = record         case integer of           0 : (str : pshortstring);           1 : (i : longint);       end;       tinlininginfo = record          { node tree }          code  : tnode;          flags : tprocinfoflags;       end;       pinlininginfo = ^tinlininginfo;       tcapturedsyminfo = record         sym : tsym;         { the location where the symbol was first encountered }         fileinfo : tfileposinfo;       end;       pcapturedsyminfo = ^tcapturedsyminfo;       timplprocdefinfo = record          resultname : pshortstring;          parentfpstruct: tsym;          parentfpstructptrtype: tdef;          parentfpinitblock: tnode;          procstarttai,          procendtai   : tai;          skpara: pointer;          personality: tprocdef;          was_anonymous,          has_capturer,          forwarddef,          interfacedef : boolean;          hasforward  : boolean;          is_implemented : boolean;          capturedsyms : tfplist;       end;       pimplprocdefinfo = ^timplprocdefinfo;       { tprocdef }       tprocdef = class(tabstractprocdef)       protected{$ifdef symansistr}         _mangledname : ansistring;{$else symansistr}         _mangledname : pshortstring;{$endif}         _parentfpsym : tsym;         { information that is only required until the implementation of the           procdef has been handled }         implprocdefinfo : pimplprocdefinfo;         function store_localst:boolean;         function GetResultName: PShortString;         procedure SetResultName(AValue: PShortString);         function GetParentFPStruct: tsym;         procedure SetParentFPStruct(AValue: tsym);         function GetParentFPStructPtrType: tdef;         procedure SetParentFPStructPtrType(AValue: tdef);         function GetParentFPInitBlock: tnode;         procedure SetParentFPInitBlock(AValue: tnode);         function Getprocstarttai: tai;         procedure Setprocstarttai(AValue: tai);         function Getprocendtai: tai;         procedure Setprocendtai(AValue: tai);         function Getskpara: pointer;         procedure Setskpara(AValue: pointer);         function Getpersonality: tprocdef;         procedure Setpersonality(AValue: tprocdef);         function Getforwarddef: boolean;         procedure Setforwarddef(AValue: boolean);         function Getinterfacedef: boolean;         procedure Setinterfacedef(AValue: boolean);virtual;         function Gethasforward: boolean;         procedure Sethasforward(AValue: boolean);         function GetIsEmpty: boolean;         procedure SetIsEmpty(AValue: boolean);         function GetHasInliningInfo: boolean;         procedure SetHasInliningInfo(AValue: boolean);         function Getis_implemented: boolean;         procedure Setis_implemented(AValue: boolean);         function getwas_anonymous:boolean;         procedure setwas_anonymous(avalue:boolean);         function gethas_capturer:boolean;         procedure sethas_capturer(avalue:boolean);         function Getcapturedsyms:tfplist;         function getparentfpsym: tsym;       public          messageinf : tmessageinf;          dispid : longint;{$ifndef EXTDEBUG}          { where is this function defined and what were the symbol            flags, needed here because there            is only one symbol for all overloaded functions            EXTDEBUG has fileinfo in tdef (PFV) }          fileinfo : tfileposinfo;{$endif}          symoptions : tsymoptions;          deprecatedmsg : pshortstring;          { generic support }          genericdecltokenbuf : tdynamicarray;          { symbol owning this definition }          procsym : tsym;          procsymderef : tderef;          { alias names }          aliasnames : TCmdStrList;          { symtables }          localst : TSymtable;          funcretsym : tsym;          funcretsymderef : tderef;          struct : tabstractrecorddef;          structderef : tderef;          implprocoptions: timplprocoptions;          { import info }          import_dll,          import_name : pshortstring;          { info for inlining the subroutine, if this pointer is nil,            the procedure can't be inlined }          inlininginfo : pinlininginfo;          import_nr    : word;          extnumber    : word;          { set to a value different from tsk_none in case this procdef is for            a routine that has to be internally generated by the compiler }          synthetickind: tsynthetickind;          visibility   : tvisibility;{$ifndef DISABLE_FAST_OVERLOAD_PATCH}          seenmarker : pointer; // used for filtering in tcandidate{$endif}{$ifdef symansistr}         section: ansistring;{$else symansistr}         section: pshortstring;{$endif}          constructor create(level:byte;doregister:boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          destructor  destroy;override;          procedure   freeimplprocdefinfo;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          procedure buildderef;override;          procedure buildderefimpl;override;          procedure deref;override;          procedure derefimpl;override;          function  GetSymtable(t:tGetSymtable):TSymtable;override;          { warnings:              * the symtablestack top has to be the symtable to which the copy                should be added              * getcopy does not create a finished/ready-to-use procdef; it                needs to be finalised afterwards by calling                symcreat.finish_copied_procdef() afterwards          }          function  getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef; override;          function  getcopy: tstoreddef; override;          function  GetTypeName : string;override;          function  mangledname : TSymStr; virtual;          procedure setmangledname(const s : TSymStr);          function  needsglobalasmsym: boolean;          procedure setcompilerprocname;          function  fullprocname(showhidden:boolean):string;          function  customprocname(pno: tprocnameoptions):ansistring;          function  defaultmangledname: TSymStr;          function  cplusplusmangledname : TSymStr;          function  objcmangledname : TSymStr;          function  is_methodpointer:boolean;override;          function  is_addressonly:boolean;override;          procedure make_external;          procedure init_genericdecl;          function get_funcretsym_info(out ressym: tsym; out resdef: tdef): boolean; virtual;          function get_safecall_funcretsym_info(out ressym: tsym; out resdef: tdef): boolean; virtual;          procedure add_captured_sym(sym:tsym;const filepos:tfileposinfo);          { returns whether the mangled name or any of its aliases is equal to            s }          function  has_alias_name(const s: TSymStr):boolean;          { aliases to fields only required when a function is implemented in            the current unit }          property resultname: PShortString read GetResultName write SetResultName;          { temporary reference to structure containing copies of all local            variables and parameters accessed by nested routines; reference to            this structure is passed as "parent frame pointer" on targets that            lack this concept (at least JVM and LLVM); no need to save to/            restore from ppu, since nested routines are always in the same            unit }          property parentfpstruct: tsym read GetParentFPStruct write SetParentFPStruct;          { pointer to parentfpstruct's type (not yet valid during parsing, so            cannot be used for $parentfp parameter) (no need to save to ppu) }          property parentfpstructptrtype: tdef read GetParentFPStructPtrType write SetParentFPStructPtrType;          { code to copy the parameters accessed from nested routines into the            parentfpstruct (no need to save to ppu) }          property parentfpinitblock: tnode read GetParentFPInitBlock write SetParentFPInitBlock;          { First/last assembler symbol/instruction in aasmoutput list.            Note: initialised after compiling the code for the procdef, but              not saved to/restored from ppu. Used when inserting debug info }          property procstarttai: tai read Getprocstarttai write Setprocstarttai;          property procendtai: tai read Getprocendtai write Setprocendtai;          { optional parameter for the synthetic routine generation logic }          property skpara: pointer read Getskpara write Setskpara;          { ABI-conformant exception handling personality function }          property personality: tprocdef read Getpersonality write Setpersonality;          { true, if the procedure is only declared            (forward procedure) }          property forwarddef: boolean read Getforwarddef write Setforwarddef;          { true if the procedure is declared in the interface }          property interfacedef: boolean read Getinterfacedef write Setinterfacedef;          { true if the procedure has a forward declaration }          property hasforward: boolean read Gethasforward write Sethasforward;          { true if the routine's body is empty }          property isempty: boolean read GetIsEmpty write SetIsEmpty;          { true if all information required to inline this routine is available }          property has_inlininginfo: boolean read GetHasInliningInfo write SetHasInliningInfo;          { returns the $parentfp parameter for nested routines }          property parentfpsym: tsym read getparentfpsym;          { true if the implementation part for this procdef has been handled }          property is_implemented: boolean read Getis_implemented write Setis_implemented;          { valid if the procdef captures any symbols from outer scopes }          property capturedsyms:tfplist read Getcapturedsyms;          { true if this procdef was originally an anonymous function }          property was_anonymous:boolean read getwas_anonymous write setwas_anonymous;          { true if the procdef has a capturer for anonymous functions }          property has_capturer:boolean read gethas_capturer write sethas_capturer;       end;       tprocdefclass = class of tprocdef;       { single linked list of overloaded procs }       pprocdeflist = ^tprocdeflist;       tprocdeflist = record         def  : tprocdef;         defderef : tderef;         next : pprocdeflist;       end;       tstringdef = class(tstoreddef)          encoding   : tstringencoding;          stringtype : tstringtype;          len        : asizeint;          constructor createshort(l: byte; doregister: boolean);virtual;          constructor loadshort(ppufile:tcompilerppufile);          constructor createlong(l: asizeint; doregister: boolean);virtual;          constructor loadlong(ppufile:tcompilerppufile);          constructor createansi(aencoding: tstringencoding; doregister: boolean);virtual;          constructor loadansi(ppufile:tcompilerppufile);          constructor createwide(doregister: boolean);virtual;          constructor loadwide(ppufile:tcompilerppufile);          constructor createunicode(doregister: boolean);virtual;          constructor loadunicode(ppufile:tcompilerppufile);virtual;          function getcopy : tstoreddef;override;          function  stringtypname:string;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          function  GetTypeName:string;override;          function  getmangledparaname:TSymStr;override;          function  is_publishable : tpublishproperty;override;          function  size:asizeint;override;          function alignment : shortint;override;          function  needs_inittable : boolean;override;          function  getvardef:longint;override;          { returns the default char type def for the string }          function get_default_char_type: tdef;          { returns the default string type }          function get_default_string_type: tdef;       end;       tstringdefclass = class of tstringdef;       { tenumdef }       tenumdef = class(tstoreddef)          minval,          maxval    : asizeint;          basedef   : tenumdef;          basedefderef : tderef;          symtable  : TSymtable;          has_jumps : boolean;          constructor create;virtual;          constructor create_subrange(_basedef:tenumdef;_min,_max:asizeint);virtual;          constructor ppuload(ppufile:tcompilerppufile);          destructor destroy;override;          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          procedure buildderef;override;          procedure deref;override;          function  GetTypeName:string;override;          function  is_publishable : tpublishproperty;override;          procedure calcsavesize(packenum: shortint);          function  packedbitsize: asizeint; override;          procedure setmax(_max:asizeint);          procedure setmin(_min:asizeint);          function  min:asizeint;          function  max:asizeint;          function  getfirstsym:tsym;          function  int2enumsym(l: asizeint): tsym;          { returns basedef if assigned, otherwise self }          function getbasedef: tenumdef;       end;       tenumdefclass = class of tenumdef;       tsetdef = class(tstoreddef)          elementdef : tdef;          elementdefderef : tderef;          setbase,          setmax   : asizeint;          constructor create(def: tdef; low, high: asizeint; doregister: boolean);virtual;          constructor ppuload(ppufile:tcompilerppufile);          function getcopy : tstoreddef;override;          { do not override this routine in platform-specific subclasses,            override ppuwrite_platform instead }          procedure ppuwrite(ppufile:tcompilerppufile);override;final;          procedure buildderef;override;          procedure deref;override;          function  GetTypeName:string;override;          function  is_publishable : tpublishproperty;override;          function alignment: shortint; override;       end;       tsetdefclass = class of tsetdef;       tgenericdummyentry = class         dummysym : tsym;         resolvedsym : tsym;       end;       tdefawaresymtablestack = class(TSymtablestack)       private         procedure add_helpers_and_generics(st:tsymtable;addgenerics:boolean);         procedure remove_helpers_and_generics(st:tsymtable);inline;         procedure remove_helpers(st:tsymtable);         procedure remove_generics(st:tsymtable);         procedure pushcommon(st:tsymtable);inline;       public         procedure push(st: TSymtable); override;         procedure pushafter(st,afterst:TSymtable); override;         procedure pop(st: TSymtable); override;       end;    var       current_structdef: tabstractrecorddef; { used for private functions check !! }       current_genericdef: tstoreddef;        { used to reject declaration of generic class inside generic class }       current_specializedef: tstoreddef;     { used to implement usage of generic class in itself }       cfiledef: tfiledefclass;       cvariantdef: tvariantdefclass;       cformaldef: tformaldefclass;       cforwarddef: tforwarddefclass;       cundefineddef: tundefineddefclass;       cerrordef: terrordefclass;       cpointerdef: tpointerdefclass;       crecorddef: trecorddefclass;       cimplementedinterface: timplementedinterfaceclass;       cobjectdef: tobjectdefclass;       cclassrefdef: tclassrefdefclass;       carraydef: tarraydefclass;       corddef: torddefclass;       cfloatdef: tfloatdefclass;       cprocvardef: tprocvardefclass;       cprocdef: tprocdefclass;       cstringdef: tstringdefclass;       cenumdef: tenumdefclass;       csetdef: tsetdefclass;    { default types }       generrordef,               { error in definition }       voidpointertype,           { pointer for Void-pointeddef }       charpointertype,           { pointer for Char-pointeddef }       widecharpointertype,       { pointer for WideChar-pointeddef }       voidcodepointertype,       { pointer to code; corresponds to System.CodePointer }       voidstackpointertype,      { the pointer type used for accessing parameters and local vars on the stack }       parentfpvoidpointertype,   { void pointer with the size of the hidden parentfp parameter, passed to nested functions }{$ifdef x86}       voidnearpointertype,       voidnearcspointertype,       voidneardspointertype,       voidnearsspointertype,       voidnearespointertype,       voidnearfspointertype,       voidneargspointertype,  {$ifdef i8086}       voidfarpointertype,       voidhugepointertype,       charnearpointertype,       charfarpointertype,       charhugepointertype,       bytefarpointertype,        { used for Mem[] }       wordfarpointertype,        { used for MemW[] }       longintfarpointertype,     { used for MemL[] }  {$endif i8086}{$endif x86}       cundefinedtype,       cformaltype,               { unique formal definition }       ctypedformaltype,          { unique typed formal definition }       voidtype,                  { Void (procedure) }       cansichartype,             { Char }       cwidechartype,             { WideChar }       cchartype,                 { either cansichartype or cwidechartype. Do not free }       pasbool1type,              { boolean type }       pasbool8type,       pasbool16type,       pasbool32type,       pasbool64type,       bool8type,       bool16type,       bool32type,       bool64type,                { implement me }{$ifdef llvm}       llvmbool1type,             { LLVM i1 type }{$endif llvm}       u8inttype,                 { 8-Bit unsigned integer }       s8inttype,                 { 8-Bit signed integer }       u16inttype,                { 16-Bit unsigned integer }       s16inttype,                { 16-Bit signed integer }       u24inttype,                { 24-Bit unsigned integer }       s24inttype,                { 24-Bit signed integer }       u32inttype,                { 32-Bit unsigned integer }       s32inttype,                { 32-Bit signed integer }       u40inttype,                { 40-Bit unsigned integer }       s40inttype,                { 40-Bit signed integer }       u48inttype,                { 48-Bit unsigned integer }       s48inttype,                { 48-Bit signed integer }       u56inttype,                { 56-Bit unsigned integer }       s56inttype,                { 56-Bit signed integer }       u64inttype,                { 64-bit unsigned integer }       s64inttype,                { 64-bit signed integer }       u128inttype,               { 128-bit unsigned integer }       s128inttype,               { 128-bit signed integer }       s32floattype,              { 32 bit floating point number }       s64floattype,              { 64 bit floating point number }       s80floattype,              { 80 bit floating point number }       sc80floattype,             { 80 bit floating point number but stored like in C }       s64currencytype,           { pointer to a currency type }       cshortstringtype,          { pointer to type of short string const   }       clongstringtype,           { pointer to type of long string const   }       cansistringtype,           { pointer to type of ansi string const  }       cwidestringtype,           { pointer to type of wide string const  }       cunicodestringtype,       openshortstringtype,       { pointer to type of an open shortstring,                                    needed for readln() }       openchararraytype,         { pointer to type of an open array of char,                                    needed for readln() }       cfiletype,                 { get the same definition for all file }                                  { used for stabs }       methodpointertype,         { typecasting of methodpointers to extract self }       nestedprocpointertype,     { typecasting of nestedprocpointers to extract parentfp }       hresultdef,       typekindtype,              { def of TTypeKind for correct handling of GetTypeKind parameters }       { we use only one variant def for every variant class }       cvarianttype,       colevarianttype,       { default integer type, normally s32inttype on 32 bit systems and s64bittype on 64 bit systems }       sinttype,       uinttype,       { integer types corresponding to OS_SINT/OS_INT }       ossinttype,       osuinttype,       { integer types corresponding to the ALU size, sizeof(aint) and the ALUSInt/ALUUInt types in the system unit }       alusinttype,       aluuinttype,       { integer types corresponding to SizeInt and SizeUInt for the target platform }       sizeuinttype,       sizesinttype,       { unsigned and signed ord type with the same size as a pointer }       ptruinttype,       ptrsinttype,       { unsigned and signed ord type with the same size as a codepointer }       codeptruinttype,       codeptrsinttype,       { several types to simulate more or less C++ objects for GDB }       vmttype,       vmtarraytype,       { type of classrefs, used for stabs }       pvmttype,       { return type of the setjmp function }       exceptionreasontype      : tdef;       { pointer to the anchestor of all classes }       class_tobject : tobjectdef;       { pointer to the base type for custom attributes }       class_tcustomattribute : tobjectdef;       { pointer to the ancestor of all COM interfaces }       interface_iunknown : tobjectdef;       { pointer to the ancestor of all dispinterfaces }       interface_idispatch : tobjectdef;       { pointer to the TGUID type         of all interfaces         }       rec_tguid : trecorddef;       { jump buffer type, used by setjmp }       rec_jmp_buf : trecorddef;       { system.texceptaddr type, used by fpc_pushexceptaddr }       rec_exceptaddr: trecorddef;       { Objective-C base types }       objc_metaclasstype,       objc_superclasstype,       objc_idtype,       objc_seltype              : tpointerdef;       objc_objecttype           : trecorddef;       { base type of @protocol(protocolname) Objective-C statements }       objc_protocoltype         : tobjectdef;       { helper types for for-in "fast enumeration" support in Objective-C 2.0 }       objc_fastenumeration      : tobjectdef;       objc_fastenumerationstate : trecorddef;{$ifdef llvm}       { llvm types }       { a unique def to identify any kind of metadata }       llvm_metadatatype         : tdef;{$endif llvm}       { Java base types }       { java.lang.Object }       java_jlobject             : tobjectdef;       { java.lang.Throwable }       java_jlthrowable          : tobjectdef;       { FPC base type for records }       java_fpcbaserecordtype    : tobjectdef;       { java.lang.String }       java_jlstring             : tobjectdef;       { java.lang.Enum }       java_jlenum               : tobjectdef;       { java.util.EnumSet }       java_juenumset            : tobjectdef;       { java.util.BitSet }       java_jubitset             : tobjectdef;       { FPC java implementation of ansistrings }       java_ansistring           : tobjectdef;       { FPC java implementation of shortstrings }       java_shortstring          : tobjectdef;       { FPC java procvar base class }       java_procvarbase          : tobjectdef;       { x86 vector types }       x86_m64type,       x86_m128type,       x86_m128dtype,       x86_m128itype,       x86_m256type,       x86_m256dtype,       x86_m256itype             : tdef;    function make_mangledname(const typeprefix:TSymStr;st:TSymtable;const suffix:TSymStr):TSymStr;    function make_dllmangledname(const dllname,importname:TSymStr;                                 import_nr : word; pco : tproccalloption):TSymStr;    { should be in the types unit, but the types unit uses the node stuff :( }    function is_interfacecom(def: tdef): boolean;    function is_interfacecom_or_dispinterface(def: tdef): boolean;    function is_any_interface_kind(def: tdef): boolean;    function is_interfacecorba(def: tdef): boolean;    function is_interface(def: tdef): boolean;    function is_dispinterface(def: tdef): boolean;    function is_object(def: tdef): boolean;    function is_class(def: tdef): boolean;    function is_cppclass(def: tdef): boolean;    function is_objectpascal_helper(def: tdef): boolean;    function is_objcclass(def: tdef): boolean;    function is_objcclassref(def: tdef): boolean;    function is_objcprotocol(def: tdef): boolean;    function is_objccategory(def: tdef): boolean;    function is_objc_class_or_protocol(def: tdef): boolean;    function is_objc_protocol_or_category(def: tdef): boolean;    function is_classhelper(def: tdef): boolean;    function is_class_or_interface(def: tdef): boolean;    function is_class_or_interface_or_objc(def: tdef): boolean;    function is_class_or_interface_or_objc_or_java(def: tdef): boolean;    function is_class_or_interface_or_dispinterface_or_objc_or_java(def: tdef): boolean;    function is_class_or_interface_or_object(def: tdef): boolean;    function is_class_or_interface_or_dispinterface(def: tdef): boolean;    function is_implicit_pointer_object_type(def: tdef): boolean;    { returns true, if def is a type which is an implicit pointer to an array (dyn. array or dyn. string) }    function is_implicit_array_pointer(def: tdef): boolean;    function is_class_or_object(def: tdef): boolean;    function is_record(def: tdef): boolean;    function is_javaclass(def: tdef): boolean;    function is_javaclassref(def: tdef): boolean;    function is_javainterface(def: tdef): boolean;    function is_java_class_or_interface(def: tdef): boolean;    procedure loadobjctypes;    procedure maybeloadcocoatypes;    function use_vectorfpu(def : tdef) : boolean;    function getansistringcodepage:tstringencoding; inline;    function getansistringdef:tstringdef;    function getparaencoding(def:tdef):tstringencoding; inline;    function get_threadvar_record(def: tdef; out index_field, non_mt_data_field: tsym): trecorddef;    function get_recorddef(prefix:tinternaltypeprefix;const fields:array of tdef; packrecords:shortint): trecorddef;    { get a table def of the form        record          count: countdef;          elements: array[0..count-1] of elementdef        end;      Returns both the outer record and the inner arraydef    }    procedure get_tabledef(prefix:tinternaltypeprefix;countdef,elementdef:tdef;count:longint;packrecords:shortint;out recdef:trecorddef;out arrdef:tarraydef);    function fileinfo_of_typesym_in_def(def:tdef;sym:tsym;out filepos:tfileposinfo):boolean;implementation    uses      SysUtils,      cutils,      { global }      verbose,      { target }      systems,paramgr,      { symtable }      symsym,symtable,defutil,objcdef,      { parser }      pgenutil,      { module }      fmodule,ppu,      { other }      aasmbase,      gendef,      fpchash,      entfile      ;{****************************************************************************                                  Helpers****************************************************************************}    function fileinfo_of_typesym_in_def(def:tdef;sym:tsym;out filepos:tfileposinfo):boolean;      var        gst : tgetsymtable;        st : tsymtable;        i : longint;        srsym : tsym;      begin        result:=false;        if sym.typ<>typesym then          exit;        for gst:=low(tgetsymtable) to high(tgetsymtable) do          begin            st:=def.getsymtable(gst);            if not assigned(st) then              continue;            for i:=0 to st.symlist.count-1 do              begin                srsym:=tsym(st.symlist[i]);                case srsym.typ of                  fieldvarsym,                  paravarsym:                    if tabstractvarsym(srsym).vardef.typesym=sym then                      begin                        filepos:=srsym.fileinfo;                        result:=true;                        break;                      end;                  typesym:                    begin                      result:=fileinfo_of_typesym_in_def(ttypesym(srsym).typedef,sym,filepos);                      if result then                        break;                    end                  else                    ;                end;              end;            if result then              break;          end;        { for this we would need the position of the result declaration :/ }        {if not result and            (def.typ in [procdef,procvardef]) and            assigned(tabstractprocdef(def).returndef) and            (tabstractprocdef(def).returndef.typesym=sym) then          begin            result:=true;          end;}      end;    function getansistringcodepage:tstringencoding; inline;      begin        if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then          result:=current_settings.sourcecodepage        else          result:=0;      end;    function getansistringdef:tstringdef;      var        symtable:tsymtable;        oldstack : tsymtablestack;      begin        { if a codepage is explicitly defined in this mudule we need to return          a replacement for ansistring def }        if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then          begin            if not assigned(current_module) then              internalerror(2011101301);            { codepage can be redeclared only once per unit so we don't need a list of              redefined ansistring but only one pointer }            if not assigned(current_module.ansistrdef) then              begin                { if we did not create it yet we need to do this now }                if current_module.in_interface then                  symtable:=current_module.globalsymtable                else                  symtable:=current_module.localsymtable;                { create a temporary stack as it's not good (TM) to mess around                  with the order if the unit contains generics or helpers; don't                  use a def aware symtablestack though }                oldstack:=symtablestack;                symtablestack:=tsymtablestack.create;                symtablestack.push(symtable);                current_module.ansistrdef:=cstringdef.createansi(current_settings.sourcecodepage,true);                symtablestack.pop(symtable);                symtablestack.free;                symtablestack:=oldstack;              end;            result:=tstringdef(current_module.ansistrdef);          end        else          result:=tstringdef(cansistringtype);      end;    function getparaencoding(def:tdef):tstringencoding; inline;      begin        { don't pass CP_NONE encoding to internal functions          they expect 0 encoding instead          exception: result of string concatenation, because if you pass the          result of a string concatenation to a rawbytestring, the result of          that concatenation shouldn't be converted to defaultsystemcodepage          if all strings have the same type }        result:=tstringdef(def).encoding;        if result=globals.CP_NONE then          result:=0      end;    function get_threadvar_record(def: tdef; out index_field, non_mt_data_field: tsym): trecorddef;      var        typ: ttypesym;        name: string;      begin        name:=internaltypeprefixName[itp_threadvar_record]+def.unique_id_str;        typ:=try_search_current_module_type(name);        if assigned(typ) then          begin            result:=trecorddef(ttypesym(typ).typedef);            index_field:=tsym(result.symtable.symlist[0]);            non_mt_data_field:=tsym(result.symtable.symlist[1]);            exit;          end;        { set recordalinmin to sizeof(pint), so the second field gets put at          offset = sizeof(pint) as expected }        result:=crecorddef.create_global_internal(          name,sizeof(pint),sizeof(pint));{$ifdef cpu16bitaddr}        index_field:=result.add_field_by_def('',u16inttype);{$else cpu16bitaddr}        index_field:=result.add_field_by_def('',u32inttype);{$endif cpu16bitaddr}        non_mt_data_field:=result.add_field_by_def('',def);        { no need to add alignment padding, we won't create arrays of these }      end;    function get_recorddef(prefix:tinternaltypeprefix; const fields:array of tdef; packrecords:shortint): trecorddef;      var        fieldlist: tfplist;        srsym: tsym;        srsymtable: tsymtable;        i: longint;        name : TIDString;      begin        name:=copy(internaltypeprefixName[prefix],2,length(internaltypeprefixName[prefix]));        if searchsym_type(name,srsym,srsymtable) then          begin            result:=trecorddef(ttypesym(srsym).typedef);            exit          end;        { also always search in the current module (symtables are popped for          RTTI related code already) }        if searchsym_in_module(pointer(current_module),name,srsym,srsymtable) then          begin            result:=trecorddef(ttypesym(srsym).typedef);            exit;          end;        fieldlist:=tfplist.create;        for i:=low(fields) to high(fields) do          fieldlist.add(fields[i]);        result:=crecorddef.create_global_internal(internaltypeprefixName[prefix],packrecords,          targetinfos[target_info.system]^.alignment.recordalignmin);        result.add_fields_from_deflist(fieldlist);        fieldlist.free;      end;    procedure get_tabledef(prefix:tinternaltypeprefix;countdef,elementdef:tdef;count:longint;packrecords:shortint;out recdef:trecorddef;out arrdef:tarraydef);      var        fields: tfplist;        name: TIDString;        srsym: tsym;        srsymtable: tsymtable;      begin        { already created a message string table with this number of elements          in this unit -> reuse the def }        name:=internaltypeprefixName[prefix]+tostr(count);        if searchsym_type(copy(name,2,length(name)),srsym,srsymtable) then          begin            recdef:=trecorddef(ttypesym(srsym).typedef);            arrdef:=tarraydef(trecordsymtable(recdef.symtable).findfieldbyoffset(countdef.size).vardef);            exit          end;        { also always search in the current module (symtables are popped for          RTTI related code already) }        if searchsym_in_module(pointer(current_module),copy(name,2,length(name)),srsym,srsymtable) then          begin            recdef:=trecorddef(ttypesym(srsym).typedef);            arrdef:=tarraydef(trecordsymtable(recdef.symtable).findfieldbyoffset(countdef.size).vardef);            exit;          end;        recdef:=crecorddef.create_global_internal(name,packrecords,          targetinfos[target_info.system]^.alignment.recordalignmin);        fields:=tfplist.create;        fields.add(countdef);        if count>0 then          begin            arrdef:=carraydef.create(0,count-1,sizeuinttype);            arrdef.elementdef:=elementdef;            fields.add(arrdef);          end        else          arrdef:=nil;        recdef.add_fields_from_deflist(fields);        fields.free;      end;    function make_mangledname(const typeprefix:TSymStr;st:TSymtable;const suffix:TSymStr):TSymStr;      var        s,        prefix : TSymStr;        hash : qword;      begin        prefix:='';        if not assigned(st) then         internalerror(200204212);        repeat          { sub procedures }          while (st.symtabletype in [localsymtable,parasymtable]) do           begin             if st.defowner.typ<>procdef then              internalerror(200204173);             { Add the full mangledname of the routine to prevent               conflicts with two overloads both having a local entity               -- routine (tb0314), class, interface -- with the same name }             s:=tprocdef(st.defowner).procsym.name;             s:=s+tprocdef(st.defowner).mangledprocparanames(Length(s));             if prefix<>'' then               begin                 if length(prefix)>(maxidlen-length(s)-1) then                   begin                     hash:=0;                     hash:=UpdateFnv64(hash,prefix[1],length(prefix));                     prefix:='$H'+Base64Mangle(hash);                   end;                 prefix:=s+'_'+prefix               end             else               prefix:=s;             st:=st.defowner.owner;           end;          { object/classes symtable, nested type definitions in classes require the while loop }          while st.symtabletype in [ObjectSymtable,recordsymtable] do           begin             if not (st.defowner.typ in [objectdef,recorddef]) then              internalerror(200204174);             if length(prefix)>(maxidlen-length(tabstractrecorddef(st.defowner).objname^)-3) then               begin                 hash:=0;                 hash:=UpdateFnv64(hash,prefix[1],length(prefix));                 prefix:='$H'+Base64Mangle(hash);               end;             prefix:=tabstractrecorddef(st.defowner).objname^+'_$_'+prefix;             st:=st.defowner.owner;           end;          { local classes & interfaces are possible (because of closures) }          if st.symtabletype<>localsymtable then            break;          prefix:='$'+prefix;        until false;        { symtable must now be static or global }        if not(st.symtabletype in [staticsymtable,globalsymtable]) then          internalerror(200204175);        { The mangled name is made out of at most 4 parts:         1) Optional typeprefix given as first parameter            with '_$' appended if not empty         2) Unit name or 'P$'+program name (never empty)         3) optional prefix variable that contains a unique            name for the local symbol table (prepended with '$_$'            if not empty)         4) suffix as given as third parameter,            also optional (i.e. can be empty)            prepended by '_$$_' if not empty }        result:='';        if typeprefix<>'' then          result:=result+typeprefix+'_$';        { Add P$ for program, which can have the same name as          a unit }        if (TSymtable(main_module.localsymtable)=st) and           (not main_module.is_unit) then          result:=result+'P$'+st.name^        else          result:=result+st.name^;        if prefix<>'' then          result:=result+'$_$'+prefix;        if suffix<>'' then          result:=result+'_$$_'+suffix;        if length(result)>(maxidlen-1) then          begin            hash:=0;            hash:=UpdateFnv64(hash,result[1],length(result));            result:=copy(result,1,maxidlen-(high(Base64OfUint64String)-low(Base64OfUint64String)+1)-2)+'$H'+Base64Mangle(hash);          end;        { the Darwin assembler assumes that all symbols starting with 'L' are local }        { Further, the Mac OS X 10.5 linker does not consider symbols which do not  }        { start with '_' as regular symbols (it does not generate N_GSYM entries    }        { those in the debug map, leading to troubles with dsymutil). So always     }        { add an underscore on darwin.                                              }        if (target_info.system in systems_darwin) then          result := '_' + result;      end;    function make_dllmangledname(const dllname,importname:TSymStr;import_nr : word; pco : tproccalloption):TSymStr;       var         crc : cardinal;         i : longint;         use_crc : boolean;         dllprefix : TSymStr;      begin        if (target_info.system in (systems_all_windows + systems_nativent +                           [system_i386_emx, system_i386_os2]))            and (dllname <> '') then          begin            dllprefix:=lower(ExtractFileName(dllname));            { Remove .dll suffix if present }            if copy(dllprefix,length(dllprefix)-3,length(dllprefix))='.dll' then              dllprefix:=copy(dllprefix,1,length(dllprefix)-4);            use_crc:=false;            for i:=1 to length(dllprefix) do              if not (dllprefix[i] in ['a'..'z','A'..'Z','_','0'..'9']) then                begin                  use_crc:=true;                  break;                end;            if use_crc then              begin                crc:=0;                crc:=UpdateCrc32(crc,dllprefix[1],length(dllprefix));                dllprefix:='_$dll$crc$'+hexstr(crc,8)+'$';              end            else              dllprefix:='_$dll$'+dllprefix+'$';            if importname<>'' then              result:=dllprefix+importname            else              result:=dllprefix+'_index_'+tostr(import_nr);            { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }            { This allows to import VC++ mangled names from DLLs. }            { Do not perform replacement, if external symbol is not imported from DLL. }            if (dllname<>'') then              begin                Replace(result,'?','__q$$');    {$ifdef arm}                { @ symbol is not allowed in ARM assembler only }                Replace(result,'@','__a$$');    {$endif arm}             end;          end        else          begin            if importname<>'' then             begin               if not(pco in [pocall_cdecl,pocall_cppdecl]) then                 result:=importname               else                 result:=target_info.Cprefix+importname;             end            else              result:='_index_'+tostr(import_nr);          end;      end;{****************************************************************************           TDEFAWARESYMTABLESTACK           (symtablestack descendant that does some special actions on           the pushed/popped symtables)****************************************************************************}    procedure tdefawaresymtablestack.add_helpers_and_generics(st:tsymtable;addgenerics:boolean);      var        s: TSymStr;        list: TFPObjectList;        def: tdef;        sym : tsym;        i: integer;      begin        { search the symtable from first to last; the helper to use will be the          last one in the list }        for i:=0 to st.symlist.count-1 do          begin            sym:=tsym(st.symlist[i]);            if not (sym.typ in [typesym,procsym]) then              continue;            if sym.typ=typesym then              def:=ttypesym(st.SymList[i]).typedef            else              def:=nil;            if is_objectpascal_helper(def) then              begin                s:=generate_objectpascal_helper_key(tobjectdef(def).extendeddef);                Message1(sym_d_adding_helper_for,s);                list:=TFPObjectList(current_module.extendeddefs.Find(s));                if not assigned(list) then                  begin                    list:=TFPObjectList.Create(false);                    current_module.extendeddefs.Add(s,list);                  end;                list.Add(def);              end            else              begin                if addgenerics then                  add_generic_dummysym(sym);                { add nested helpers as well }                if assigned(def) and                    (def.typ in [recorddef,objectdef]) and                    (sto_has_helper in tabstractrecorddef(def).symtable.tableoptions) then                  add_helpers_and_generics(tabstractrecorddef(def).symtable,false);              end;          end;      end;    procedure tdefawaresymtablestack.remove_helpers_and_generics(st:tsymtable);      begin        if sto_has_helper in st.tableoptions then          remove_helpers(st);        if sto_has_generic in st.tableoptions then          remove_generics(st);      end;    procedure tdefawaresymtablestack.remove_helpers(st:TSymtable);      var        i, j: integer;        tmpst: TSymtable;        list: TFPObjectList;      begin        for i:=current_module.extendeddefs.count-1 downto 0 do          begin            list:=TFPObjectList(current_module.extendeddefs[i]);            for j:=list.count-1 downto 0 do              begin                if not (list[j] is tobjectdef) then                  Internalerror(2011031501);                tmpst:=tobjectdef(list[j]).owner;                repeat                  if tmpst=st then                    begin                      list.delete(j);                      break;                    end                  else                    begin                      if assigned(tmpst.defowner) then                        tmpst:=tmpst.defowner.owner                      else                        tmpst:=nil;                    end;                until not assigned(tmpst) or (tmpst.symtabletype in [globalsymtable,staticsymtable]);              end;            if list.count=0 then              current_module.extendeddefs.delete(i);          end;      end;    procedure tdefawaresymtablestack.remove_generics(st:tsymtable);      var        i,j : longint;        entry : tgenericdummyentry;        list : tfpobjectlist;      begin        for i:=current_module.genericdummysyms.count-1 downto 0 do          begin            list:=tfpobjectlist(current_module.genericdummysyms[i]);            if not assigned(list) then              continue;            for j:=list.count-1 downto 0 do              begin                entry:=tgenericdummyentry(list[j]);                if entry.dummysym.owner=st then                  list.delete(j);              end;            if list.count=0 then              current_module.genericdummysyms.delete(i);          end;      end;    procedure tdefawaresymtablestack.pushcommon(st:tsymtable);      begin        if (sto_has_generic in st.tableoptions) or            (              (st.symtabletype in [globalsymtable,staticsymtable]) and              (sto_has_helper in st.tableoptions)            ) then          { nested helpers will be added as well }          add_helpers_and_generics(st,true);      end;    procedure tdefawaresymtablestack.push(st: TSymtable);      begin        pushcommon(st);        inherited push(st);      end;    procedure tdefawaresymtablestack.pushafter(st,afterst:TSymtable);      begin        pushcommon(st);        inherited pushafter(st,afterst);      end;    procedure tdefawaresymtablestack.pop(st: TSymtable);      begin        inherited pop(st);        if (sto_has_generic in st.tableoptions) or            (              (st.symtabletype in [globalsymtable,staticsymtable]) and              (sto_has_helper in st.tableoptions)            ) then          { nested helpers will be removed as well }          remove_helpers_and_generics(st);      end;{****************************************************************************                     TDEF (base class for definitions)****************************************************************************}    constructor tgenericconstraintdata.create;      begin        interfaces:=tfpobjectlist.create(false);        interfacesderef:=tfplist.create;      end;    destructor tgenericconstraintdata.destroy;      var        i : longint;      begin        for i:=0 to interfacesderef.count-1 do          dispose(pderef(interfacesderef[i]));        interfacesderef.free;        interfaces.free;        inherited destroy;      end;    procedure tgenericconstraintdata.ppuload(ppufile: tcompilerppufile);      var        cnt,i : longint;        intfderef : pderef;      begin        ppufile.getset(tppuset1(flags));        cnt:=ppufile.getlongint;        for i:=0 to cnt-1 do          begin            new(intfderef);            ppufile.getderef(intfderef^);            interfacesderef.add(intfderef);          end;      end;    procedure tgenericconstraintdata.ppuwrite(ppufile: tcompilerppufile);      var        i : longint;      begin        ppufile.putset(tppuset1(flags));        ppufile.putlongint(interfacesderef.count);        for i:=0 to interfacesderef.count-1 do          ppufile.putderef(pderef(interfacesderef[i])^);      end;    procedure tgenericconstraintdata.buildderef;      var        intfderef : pderef;        i : longint;      begin        for i:=0 to interfaces.count-1 do          begin            new(intfderef);            intfderef^.build(tobjectdef(interfaces[i]));            interfacesderef.add(intfderef);          end;      end;    procedure tgenericconstraintdata.deref;      var        i : longint;      begin        for i:=0 to interfacesderef.count-1 do          interfaces.add(pderef(interfacesderef[i])^.resolve);      end;    procedure tstoreddef.writeentry(ppufile: tcompilerppufile; ibnr: byte);      begin        ppuwrite_platform(ppufile);        ppufile.writeentry(ibnr);      end;    procedure tstoreddef.ppuwrite_platform(ppufile: tcompilerppufile);      begin        { by default: do nothing }      end;    procedure tstoreddef.ppuload_platform(ppufile: tcompilerppufile);      begin        { by default: do nothing }      end;    class procedure tstoreddef.setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);      var        reusablesymtab: tsymtable;      begin        { must not yet belong to a symtable }        if assigned(newdef.owner) then          internalerror(2015111503);        reusablesymtab:=origdef.getreusablesymtab;        res^.Data:=newdef;        reusablesymtab.insertdef(newdef);        symtablestack:=oldsymtablestack;      end;    constructor tstoreddef.create(dt:tdeftyp;doregister:boolean);      begin         inherited create(dt);         savesize := 0;{$ifdef EXTDEBUG}         fileinfo := current_filepos;{$endif}         generictokenbuf:=nil;         genericdef:=nil;         typesymderef.reset;         genericdefderef.reset;         { Don't register forwarddefs, they are disposed at the           end of an type block }         if (dt=forwarddef) then           exit;         { Register in symtable stack }         if doregister then           begin             { immediately register interface defs, as they will always be               written to the ppu, their defid influences the interface crc and               if we wait, depending on e.g. compiler defines they may get a               different defid (e.g. when a function is called, its procdef is               registered, so depending on whether or not, or when, an interface               procedure is called in the implementation, that may change its               defid otherwise) }             if assigned(current_module) and                current_module.in_interface then               register_def             else               maybe_put_in_symtable_stack;           end;      end;    destructor tstoreddef.destroy;      var        i : longint;      begin        { Direct calls are not allowed, use symtable.deletedef() }        if assigned(owner) then          internalerror(200612311);        if assigned(generictokenbuf) then          begin            generictokenbuf.free;            generictokenbuf:=nil;          end;        rtti_attribute_list.free;        genericparas.free;        if assigned(genericparaderefs) then          for i:=0 to genericparaderefs.count-1 do            dispose(pderef(genericparaderefs[i]));        genericparaderefs.free;        genconstraintdata.free;{$ifndef symansistr}        stringdispose(_fullownerhierarchyname);{$endif not symansistr}        inherited destroy;      end;    constructor tstoreddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);      var        sizeleft,i,cnt : longint;        buf  : array[0..255] of byte;        symderef : pderef;      begin         inherited create(dt);         DefId:=ppufile.getlongint;         current_module.deflist[DefId]:=self;{$ifdef EXTDEBUG}         fillchar(fileinfo,sizeof(fileinfo),0);{$endif}         { load }         ppufile.getderef(typesymderef);         ppufile.getset(tppuset2(defoptions));         ppufile.getset(tppuset1(defstates));         if df_genconstraint in defoptions then           begin             genconstraintdata:=tgenericconstraintdata.create;             genconstraintdata.ppuload(ppufile);           end;         if [df_generic,df_specialization]*defoptions<>[] then           begin             cnt:=ppufile.getlongint;             if cnt>0 then               begin                 genericparas:=tfphashobjectlist.create(false);                 genericparaderefs:=tfplist.create;                 for i:=0 to cnt-1 do                   begin                     genericparas.add(ppufile.getstring,nil);                     New(symderef);                     ppufile.getderef(symderef^);                     genericparaderefs.add(symderef);                   end;               end;           end;         if df_generic in defoptions then           begin             sizeleft:=ppufile.getlongint;             initgeneric;             while sizeleft>0 do               begin                 if sizeleft>sizeof(buf) then                   i:=sizeof(buf)                 else                   i:=sizeleft;                 ppufile.getdata(buf,i);                 generictokenbuf.write(buf,i);                 dec(sizeleft,i);               end;           end;        if df_specialization in defoptions then          ppufile.getderef(genericdefderef);        rtti_attribute_list:=trtti_attribute_list.ppuload(ppufile);      end;    function tstoreddef.needs_separate_initrtti:boolean;      begin        result:=false;      end;    function tstoreddef.rtti_mangledname(rt : trttitype) : TSymStr;      var        prefix : string[4];      begin        if (rt=fullrtti) or (not needs_separate_initrtti) then          begin            prefix:='RTTI';            include(defstates,ds_rtti_table_used);          end        else          begin            prefix:='INIT';            include(defstates,ds_init_table_used);          end;        if assigned(typesym) and           (owner.symtabletype in [staticsymtable,globalsymtable]) then          result:=make_mangledname(prefix,typesym.owner,typesym.name)        else          result:=make_mangledname(prefix,findunitsymtable(owner),'def'+unique_id_str)      end;    function tstoreddef.OwnerHierarchyName: string;      var        tmp: tdef;      begin        tmp:=self;        result:='';        repeat          { can be not assigned in case of a forwarddef }          if assigned(tmp.owner) and             (tmp.owner.symtabletype in [ObjectSymtable,recordsymtable]) then            tmp:=tdef(tmp.owner.defowner)          else            break;          result:=tabstractrecorddef(tmp).objrealname^+'.'+result;        until tmp=nil;      end;    function tstoreddef.fullownerhierarchyname(skipprocparams:boolean): TSymStr;      var        lastowner: tsymtable;        tmp: tdef;        pno: tprocnameoptions;      begin{$ifdef symansistr}        if not skipprocparams and (_fullownerhierarchyname<>'') then          exit(_fullownerhierarchyname);{$else symansistr}        if not skipprocparams and assigned(_fullownerhierarchyname) then          exit(_fullownerhierarchyname^);{$endif symansistr}        { the def can only reside inside structured types or          procedures/functions/methods }        tmp:=self;        result:='';        repeat          lastowner:=tmp.owner;          { can be not assigned in case of a forwarddef }          if not assigned(lastowner) then            break          else            tmp:=tdef(lastowner.defowner);          if not assigned(tmp) then            break;          if tmp.typ in [recorddef,objectdef] then            result:=tabstractrecorddef(tmp).objrealname^+'.'+result          else            if tmp.typ=procdef then              begin                pno:=[pno_paranames,pno_proctypeoption];                if skipprocparams then                  include(pno,pno_noparams);                result:=tprocdef(tmp).customprocname(pno)+'.'+result;              end;        until tmp=nil;        { add the unit name }        if assigned(lastowner) and           assigned(lastowner.realname) then          result:=lastowner.realname^+'.'+result;        if not skipprocparams then          { don't store the name in this case }{$ifdef symansistr}          _fullownerhierarchyname:=result;{$else symansistr}          _fullownerhierarchyname:=stringdup(result);{$endif symansistr}      end;    function tstoreddef.in_currentunit: boolean;      var        st: tsymtable;      begin        st:=owner;        while not(st.symtabletype in [globalsymtable,staticsymtable]) do          st:=st.defowner.owner;        result:=st.iscurrentunit;      end;    function tstoreddef.getcopy : tstoreddef;      begin        Message(sym_e_cant_create_unique_type);        getcopy:=cerrordef.create;      end;    procedure tstoreddef.ppuwrite(ppufile:tcompilerppufile);      var        sizeleft,i : longint;        buf  : array[0..255] of byte;        oldintfcrc : boolean;      begin        if defid<0 then          internalerror(2015101401);        ppufile.putlongint(DefId);        ppufile.putderef(typesymderef);        ppufile.putset(tppuset2(defoptions));        oldintfcrc:=ppufile.do_crc;        ppufile.do_crc:=false;        ppufile.putset(tppuset1(defstates));        if df_genconstraint in defoptions then          genconstraintdata.ppuwrite(ppufile);        if [df_generic,df_specialization]*defoptions<>[] then          begin            if not assigned(genericparas) then              ppufile.putlongint(0)            else              begin                if not assigned(genericparaderefs) then                  internalerror(2014052305);                ppufile.putlongint(genericparas.count);                for i:=0 to genericparas.count-1 do                  begin                    ppufile.putstring(genericparas.nameofindex(i));                    ppufile.putderef(pderef(genericparaderefs[i])^);                  end;              end;          end;        if df_generic in defoptions then          begin            if assigned(generictokenbuf) then              begin                sizeleft:=generictokenbuf.size;                generictokenbuf.seek(0);              end            else              sizeleft:=0;            ppufile.putlongint(sizeleft);            while sizeleft>0 do              begin                if sizeleft>sizeof(buf) then                  i:=sizeof(buf)                else                  i:=sizeleft;                generictokenbuf.read(buf,i);                ppufile.putdata(buf,i);                dec(sizeleft,i);              end;          end;        ppufile.do_crc:=oldintfcrc;        if df_specialization in defoptions then          ppufile.putderef(genericdefderef);        trtti_attribute_list.ppuwrite(rtti_attribute_list,ppufile);      end;    procedure tstoreddef.ppuload_subentries(ppufile: tcompilerppufile);      begin        trtti_attribute_list.ppuload_subentries(rtti_attribute_list,ppufile);      end;    procedure tstoreddef.ppuwrite_subentries(ppufile: tcompilerppufile);      begin        trtti_attribute_list.ppuwrite_subentries(rtti_attribute_list,ppufile);      end;    procedure tstoreddef.buildderef;      var        i : longint;        sym : tsym;        symderef : pderef;      begin        if not registered then          register_def;        typesymderef.build(typesym);        genericdefderef.build(genericdef);        if assigned(rtti_attribute_list) then          rtti_attribute_list.buildderef;        if assigned(genconstraintdata) then          genconstraintdata.buildderef;        if assigned(genericparas) then          begin            if not assigned(genericparaderefs) then              genericparaderefs:=tfplist.create;            for i:=0 to genericparas.count-1 do              begin                sym:=tsym(genericparas.items[i]);                new(symderef);                symderef^.build(sym);                genericparaderefs.add(symderef);              end;          end;      end;    procedure tstoreddef.buildderefimpl;      begin      end;    procedure tstoreddef.deref;      var        symderef : pderef;        i : longint;      begin        typesym:=ttypesym(typesymderef.resolve);        if df_specialization in defoptions then          genericdef:=tstoreddef(genericdefderef.resolve);        if assigned(rtti_attribute_list) then          rtti_attribute_list.deref;        if assigned(genconstraintdata) then          genconstraintdata.deref;        if assigned(genericparas) then          begin            if not assigned(genericparaderefs) then              internalerror(2014052302);            if genericparas.count<>genericparaderefs.count then              internalerror(2014052303);            for i:=0 to genericparaderefs.count-1 do              begin                symderef:=pderef(genericparaderefs[i]);                genericparas.items[i]:=symderef^.resolve;              end;          end;      end;    procedure tstoreddef.derefimpl;      begin      end;    function tstoreddef.size : asizeint;      begin         size:=savesize;      end;    function tstoreddef.getvardef:longint;      begin        result:=varUndefined;      end;    function tstoreddef.alignment : shortint;      begin         { natural alignment by default }         alignment:=size_2_align(savesize);         { can happen if savesize = 0, e.g. for voiddef or           an empty record         }         if (alignment=0) then           alignment:=1;      end;    { returns true, if the definition can be published }    function tstoreddef.is_publishable : tpublishproperty;      begin         is_publishable:=pp_error;      end;    { needs an init table }    function tstoreddef.needs_inittable : boolean;      begin         needs_inittable:=false;      end;    function tstoreddef.has_non_trivial_init_child(check_parent:boolean):boolean;      begin        result:=false;      end;   function tstoreddef.is_intregable : boolean;{$ifndef cpuhighleveltarget}     var       recsize,temp: longint;{$endif cpuhighleveltarget}     begin        case typ of          orddef,          pointerdef,          enumdef,          classrefdef:            is_intregable:=true;          procvardef :            is_intregable:=tprocvardef(self).is_addressonly or (po_methodpointer in tprocvardef(self).procoptions);          objectdef:            is_intregable:=(is_implicit_pointer_object_type(self)) and not needs_inittable;          setdef:            is_intregable:=is_smallset(self);          arraydef:{$ifdef cpuhighleveltarget}            is_intregable:=false{$else cpuhighleveltarget}            is_intregable:=not(is_special_array(self)) and              (tarraydef(self).size<=8) and (tarraydef(self).size in [1,2,4,8]) and              tstoreddef(tarraydef(self).elementdef).is_intregable{$ifdef SUPPORT_MMX}              and not((cs_mmx in current_settings.localswitches) and                 is_mmx_able_array(self)){$endif SUPPORT_MMX}{$endif cpuhighleveltarget}              ;          recorddef:            begin{$ifdef cpuhighleveltarget}              is_intregable:=false;{$else cpuhighleveltarget}              recsize:=size;              is_intregable:=                ispowerof2(recsize,temp) and                ((recsize<=sizeof(aint)*2) and                 not trecorddef(self).contains_cross_aword_field and                 { records cannot go into registers on 16 bit targets for now }                 (sizeof(aint)>2) and                 not trecorddef(self).contains_float_field                ) and                not needs_inittable;{$endif cpuhighleveltarget}            end;          else           is_intregable:=false;        end;     end;   function tstoreddef.is_fpuregable : boolean;     begin{$ifdef x86}       result:=use_vectorfpu(self);{$else x86}       result:=(typ=floatdef) and not(cs_fp_emulation in current_settings.moduleswitches){$ifdef xtensa}         and (FPUXTENSA_SINGLE in fpu_capabilities[init_settings.fputype]) and (tfloatdef(self).floattype=s32real){$endif xtensa}{$ifdef arm}         and (((FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[init_settings.fputype]) and (tfloatdef(self).floattype=s32real)) or              (FPUARM_HAS_VFP_DOUBLE in fpu_capabilities[init_settings.fputype])){$endif arm}         ;{$endif x86}     end;   function tstoreddef.is_const_intregable : boolean;     begin       case typ of         stringdef:           result:=tstringdef(self).stringtype in [st_ansistring,st_unicodestring,st_widestring];         arraydef:           result:=is_dynamic_array(self);         objectdef:           result:=is_interface(self);         else           result:=false;       end;     end;   procedure tstoreddef.initgeneric;     begin       if assigned(generictokenbuf) then         internalerror(200512131);       generictokenbuf:=tdynamicarray.create(256);     end;   function tstoreddef.is_generic: boolean;     var       sym: tsym;       i: longint;     begin       result:=assigned(genericparas) and                 (genericparas.count>0) and                 (df_generic in defoptions);       if result then         { if any of the type parameters does *not* belong to as (meaning it was passed           in from outside) then we aren't a generic, but a specialization }         for i:=0 to genericparas.count-1 do           begin             sym:=tsym(genericparas[i]);             { sym must be either a type or const }             if not (sym.typ in [symconst.typesym,symconst.constsym]) then               internalerror(2014050903);             if (sym.owner.defowner<>self) or (sp_generic_unnamed_type in sym.symoptions) then               exit(false);             if (sym.typ=symconst.constsym) and (sp_generic_const in sym.symoptions) then               exit(false);           end;     end;   function tstoreddef.is_generic_param_const(index:integer):boolean;     begin       result:=tsym(genericparas[index]).typ=constsym;     end;   function tstoreddef.get_generic_param_def(index:integer):tdef;     begin       if tsym(genericparas[index]).typ=constsym then         result:=tconstsym(genericparas[index]).constdef       else         result:=ttypesym(genericparas[index]).typedef;     end;   function tstoreddef.is_specialization: boolean;     var       i : longint;       sym : tsym;     begin       result:=assigned(genericparas) and                 (genericparas.count>0) and                 (df_specialization in defoptions);       if result then         begin           { if at least one of the generic parameters is not owned by us (meaning it was             passed in from outside) then we have a specialization, otherwise we have a generic }           for i:=0 to genericparas.count-1 do             begin               sym:=tsym(genericparas[i]);               { sym must be either a type or const }               if not (sym.typ in [symconst.typesym,symconst.constsym]) then                 internalerror(2014050904);               if (sym.owner.defowner<>self) or (sp_generic_unnamed_type in sym.symoptions) then                 exit(true);               if (sym.typ=symconst.constsym) and (sp_generic_const in sym.symoptions) then                 exit(true);             end;           result:=false;         end;     end;   procedure tstoreddef.register_def;     var       gst : tgetsymtable;       st : tsymtable;     begin       if registered then         exit;       { Register in current_module }       if assigned(current_module) then         begin           exclude(defoptions,df_not_registered_no_free);           for gst:=low(tgetsymtable) to high(tgetsymtable) do             begin               st:=getsymtable(gst);               if assigned(st) then                 tstoredsymtable(st).register_children;             end;           if defid<defid_not_registered then             defid:=deflist_index           else             begin               current_module.deflist.Add(self);               defid:=current_module.deflist.Count-1;               registered_in_module:=current_module;             end;           maybe_put_in_symtable_stack;         end       else         DefId:=defid_registered_nost;     end;   procedure tstoreddef.maybe_put_in_symtable_stack;     var       insertstack: psymtablestackitem;     begin       if assigned(symtablestack) and          not assigned(self.owner) then         begin           insertstack:=symtablestack.stack;           { don't insert defs in exception symtables, as they are freed before             the module is compiled, so we can get crashes on high level targets             if they still need it while e.g. writing assembler code }           while assigned(insertstack) and                 (insertstack^.symtable.symtabletype in [exceptsymtable,withsymtable]) do             insertstack:=insertstack^.next;           if not assigned(insertstack) then             internalerror(200602044);           if insertstack^.symtable.sealed then             internalerror(2015022301);           insertstack^.symtable.insertdef(self);         end;     end;{****************************************************************************                               Tstringdef****************************************************************************}    constructor tstringdef.createshort(l: byte; doregister: boolean);      begin         inherited create(stringdef,doregister);         stringtype:=st_shortstring;         encoding:=0;         len:=l;      end;    constructor tstringdef.loadshort(ppufile:tcompilerppufile);      begin         inherited ppuload(stringdef,ppufile);         stringtype:=st_shortstring;         encoding:=0;         len:=ppufile.getbyte;         ppuload_platform(ppufile);      end;    constructor tstringdef.createlong(l: asizeint; doregister: boolean);      begin         inherited create(stringdef,doregister);         stringtype:=st_longstring;         encoding:=0;         len:=l;      end;    constructor tstringdef.loadlong(ppufile:tcompilerppufile);      begin         inherited ppuload(stringdef,ppufile);         stringtype:=st_longstring;         encoding:=0;         len:=ppufile.getasizeint;         ppuload_platform(ppufile);      end;    constructor tstringdef.createansi(aencoding: tstringencoding; doregister: boolean);      begin         inherited create(stringdef,doregister);         stringtype:=st_ansistring;         encoding:=aencoding;         len:=-1;      end;    constructor tstringdef.loadansi(ppufile:tcompilerppufile);      begin         inherited ppuload(stringdef,ppufile);         stringtype:=st_ansistring;         len:=ppufile.getasizeint;         encoding:=ppufile.getword;         ppuload_platform(ppufile);      end;    constructor tstringdef.createwide(doregister: boolean);      begin         inherited create(stringdef,doregister);         stringtype:=st_widestring;         if target_info.endian=endian_little then           encoding:=CP_UTF16LE         else           encoding:=CP_UTF16BE;         len:=-1;      end;    constructor tstringdef.loadwide(ppufile:tcompilerppufile);      begin         inherited ppuload(stringdef,ppufile);         stringtype:=st_widestring;         if target_info.endian=endian_little then           encoding:=CP_UTF16LE         else           encoding:=CP_UTF16BE;         len:=ppufile.getasizeint;         ppuload_platform(ppufile);      end;    constructor tstringdef.createunicode(doregister: boolean);      begin         inherited create(stringdef,doregister);         stringtype:=st_unicodestring;         if target_info.endian=endian_little then           encoding:=CP_UTF16LE         else           encoding:=CP_UTF16BE;         len:=-1;      end;    constructor tstringdef.loadunicode(ppufile:tcompilerppufile);      begin         inherited ppuload(stringdef,ppufile);         stringtype:=st_unicodestring;         len:=ppufile.getasizeint;         encoding:=ppufile.getword;         ppuload_platform(ppufile);      end;    function tstringdef.getcopy : tstoreddef;      begin        result:=cstringdef.create(typ,true);        result.typ:=stringdef;        tstringdef(result).stringtype:=stringtype;        tstringdef(result).encoding:=encoding;        tstringdef(result).len:=len;      end;    function tstringdef.stringtypname:string;      const        typname:array[tstringtype] of string[10]=(          'shortstr','longstr','ansistr','widestr','unicodestr'        );      begin        stringtypname:=typname[stringtype];      end;    procedure tstringdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         if stringtype=st_shortstring then           begin{$ifdef extdebug}            if len > 255 then internalerror(12122002);{$endif}            ppufile.putbyte(byte(len))           end         else           ppufile.putasizeint(len);         if stringtype in [st_ansistring,st_unicodestring] then           ppufile.putword(encoding);         case stringtype of            st_shortstring : writeentry(ppufile,ibshortstringdef);            st_longstring : writeentry(ppufile,iblongstringdef);            st_ansistring : writeentry(ppufile,ibansistringdef);            st_widestring : writeentry(ppufile,ibwidestringdef);            st_unicodestring : writeentry(ppufile,ibunicodestringdef);         end;      end;    function tstringdef.needs_inittable : boolean;      begin         needs_inittable:=stringtype in [st_ansistring,st_widestring,st_unicodestring];      end;    function tstringdef.GetTypeName : string;      const         names : array[tstringtype] of string[15] = (           'ShortString','LongString','AnsiString','WideString','UnicodeString');      begin         GetTypeName:=names[stringtype];         case stringtype of           st_ansistring,st_unicodestring:             GetTypeName:=GetTypeName+'('+tostr(encoding)+')';           st_shortstring:             GetTypeName:=GetTypeName+'['+tostr(len)+']';           else             ;         end;      end;    function tstringdef.getvardef : longint;      const        vardef : array[tstringtype] of longint = (          varUndefined,varUndefined,varString,varOleStr,varUString);      begin        result:=vardef[stringtype];      end;    function tstringdef.get_default_char_type: tdef;      begin        case stringtype of          st_shortstring,          st_longstring,          st_ansistring:            result:=cansichartype;          st_unicodestring,          st_widestring:            result:=cwidechartype;        end;      end;    function tstringdef.get_default_string_type: tdef;      begin        case stringtype of          st_shortstring:            result:=cshortstringtype;          { st_longstring is currently not supported but             when it is this case will need to be supplied }          st_longstring:            internalerror(2021040801);          st_ansistring:            result:=cansistringtype;          st_widestring:            result:=cwidestringtype;          st_unicodestring:            result:=cunicodestringtype;        end      end;    function tstringdef.alignment : shortint;      begin        case stringtype of          st_unicodestring,          st_widestring,          st_ansistring:            alignment:=voidpointertype.alignment;          st_longstring,          st_shortstring:              { char to string accesses byte 0 and 1 with one word access }            if (tf_requires_proper_alignment in target_info.flags) or              { macpas needs an alignment of 2 (MetroWerks compatible) }               (m_mac in current_settings.modeswitches) then              alignment:=size_2_align(2)            else              alignment:=size_2_align(1);        end;      end;    function tstringdef.getmangledparaname : TSymStr;      begin        getmangledparaname:='STRING';      end;    function tstringdef.is_publishable : tpublishproperty;      begin         is_publishable:=pp_publish;      end;    function tstringdef.size: asizeint;      begin        case stringtype of          st_shortstring:            Result:=len+1;          st_longstring,          st_ansistring,          st_widestring,          st_unicodestring:            Result:=voidpointertype.size;        end;      end;{****************************************************************************                                 TENUMDEF****************************************************************************}    constructor tenumdef.create;      begin         inherited create(enumdef,true);         minval:=0;         maxval:=0;         calcsavesize(current_settings.packenum);         has_jumps:=false;         basedef:=nil;         basedefderef.reset;         symtable:=tenumsymtable.create(self);      end;    constructor tenumdef.create_subrange(_basedef:tenumdef;_min,_max:asizeint);      begin         inherited create(enumdef,true);         minval:=_min;         maxval:=_max;         basedef:=_basedef;         calcsavesize(current_settings.packenum);         has_jumps:=false;         symtable:=basedef.symtable.getcopy;         include(defoptions, df_copied_def);       end;    constructor tenumdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(enumdef,ppufile);         minval:=ppufile.getaint;         maxval:=ppufile.getaint;         savesize:=ppufile.getaint;         has_jumps:=false;         if df_copied_def in defoptions then           begin             symtable:=nil;             ppufile.getderef(basedefderef);             ppuload_platform(ppufile);           end         else           begin             ppuload_platform(ppufile);             // create with nil defowner first to prevent values changes on insert             symtable:=tenumsymtable.create(nil);             tenumsymtable(symtable).ppuload(ppufile);             symtable.defowner:=self;           end;      end;    destructor tenumdef.destroy;      begin        symtable.free;        symtable:=nil;        inherited destroy;      end;    function tenumdef.getcopy : tstoreddef;      begin        if assigned(basedef) then          result:=cenumdef.create_subrange(basedef,minval,maxval)        else          begin            result:=cenumdef.create;            tenumdef(result).minval:=minval;            tenumdef(result).maxval:=maxval;            tenumdef(result).symtable.free;            tenumdef(result).symtable:=symtable.getcopy;            tenumdef(result).basedef:=self;          end;        tenumdef(result).has_jumps:=has_jumps;        tenumdef(result).basedefderef:=basedefderef;        include(tenumdef(result).defoptions,df_copied_def);      end;    procedure tenumdef.calcsavesize(packenum: shortint);      begin{$IFNDEF cpu64bitaddr} {$push}{$warnings off} {$ENDIF} //comparison always false warning        if (packenum=8) or (int64(min)<low(longint)) or (int64(max)>high(cardinal)) then         savesize:=8{$IFNDEF cpu64bitaddr} {$pop} {$ENDIF}        else{$IFDEF cpu16bitaddr} {$push}{$warnings off} {$ENDIF} //comparison always false warning         if (packenum=4) or (min<low(smallint)) or (max>high(word)) then          savesize:=4{$IFDEF cpu16bitaddr} {$pop} {$ENDIF}        else         if (packenum=2) or (min<low(shortint)) or (max>high(byte)) then          savesize:=2        else         savesize:=1;      end;    function tenumdef.packedbitsize: asizeint;      var        sizeval: tconstexprint;        power: longint;      begin        result := 0;        if (minval >= 0) and           (maxval <= 1) then          result := 1        else          begin            if (minval>=0) then              sizeval:=maxval            else             { don't count 0 twice, but take into account that range goes from -n-1..n }              sizeval:=(cutils.max(-minval,maxval+1)*2)-1;            { 256 must become 512 etc. }            nextpowerof2(sizeval+1,power);            result := power;          end;      end;    procedure tenumdef.setmax(_max:asizeint);      begin        maxval:=_max;        calcsavesize(current_settings.packenum);      end;    procedure tenumdef.setmin(_min:asizeint);      begin        minval:=_min;        calcsavesize(current_settings.packenum);      end;    function tenumdef.min:asizeint;      begin        min:=minval;      end;    function tenumdef.max:asizeint;      begin        max:=maxval;      end;    function tenumdef.getfirstsym: tsym;      var        i:integer;      begin        for i := 0 to symtable.SymList.Count - 1 do          begin            result:=tsym(symtable.SymList[i]);            if tenumsym(result).value=minval then              exit;          end;        result:=nil;      end;    function tenumdef.int2enumsym(l: asizeint): tsym;      var        i: longint;        sym: tsym;        bdef: tenumdef;      begin        result:=nil;        if (l<minval) or           (l>maxval) then          exit;        bdef:=getbasedef;        for i:=0 to bdef.symtable.symlist.count-1 do          begin            sym:=tsym(bdef.symtable.symlist[i]);            if (sym.typ=enumsym) and               (tenumsym(sym).value=l) then              begin                result:=sym;                exit;              end;          end;      end;    function tenumdef.getbasedef: tenumdef;      begin        if not assigned(basedef) then          result:=self        else          result:=basedef;      end;    procedure tenumdef.buildderef;      begin        inherited buildderef;        if df_copied_def in defoptions then          basedefderef.build(basedef)        else          tenumsymtable(symtable).buildderef;      end;    procedure tenumdef.deref;      begin        inherited deref;        if df_copied_def in defoptions then          begin            basedef:=tenumdef(basedefderef.resolve);            symtable:=basedef.symtable.getcopy;          end        else          tenumsymtable(symtable).deref(false);      end;    procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putaint(min);         ppufile.putaint(max);         ppufile.putaint(savesize);         if df_copied_def in defoptions then           ppufile.putderef(basedefderef);         writeentry(ppufile,ibenumdef);         if not (df_copied_def in defoptions) then           tenumsymtable(symtable).ppuwrite(ppufile);      end;    function tenumdef.is_publishable : tpublishproperty;      begin         if not has_jumps then           is_publishable:=pp_publish         else         if m_delphi in current_settings.modeswitches then           is_publishable:=pp_ignore         else           is_publishable:=pp_error;      end;    function tenumdef.GetTypeName : string;      begin         GetTypeName:='<enumeration type>';      end;{****************************************************************************                             TRTTI_ATTRIBUTE_LIST****************************************************************************}    constructor trtti_attribute.ppuload(ppufile: tcompilerppufile);      begin        ppufile.getderef(typesymderef);        ppufile.getderef(typeconstrderef);        setlength(paras,ppufile.getlongint);      end;    procedure trtti_attribute.ppuwrite(ppufile: tcompilerppufile);      begin        ppufile.putderef(typesymderef);        ppufile.putderef(typeconstrderef);        ppufile.putlongint(length(paras));      end;    procedure trtti_attribute.ppuload_subentries(ppufile: tcompilerppufile);      var        i : sizeint;      begin        for i:=0 to high(paras) do          paras[i]:=ppuloadnodetree(ppufile);      end;    procedure trtti_attribute.ppuwrite_subentries(ppufile: tcompilerppufile);      var        i : sizeint;      begin        for i:=0 to high(paras) do          ppuwritenodetree(ppufile,paras[i]);      end;    destructor trtti_attribute.destroy;      var        n : tnode;      begin        constructorcall.free;        for n in paras do          n.free;        inherited destroy;      end;    procedure trtti_attribute.buildderef;      var        i : sizeint;      begin        typesymderef.build(typesym);        typeconstrderef.build(typeconstr);        for i:=0 to high(paras) do          paras[i].buildderefimpl;      end;    procedure trtti_attribute.deref;      var        i : sizeint;      begin        typesym:=tsym(typesymderef.resolve);        typeconstr:=tdef(typeconstrderef.resolve);        for i:=0 to high(paras) do          paras[i].derefimpl;      end;    class procedure trtti_attribute_list.bind(var dangling,owned:trtti_attribute_list);      begin        if assigned(owned) then          internalerror(2019071001);        if not assigned(dangling) then          exit;        if dangling.is_bound then          internalerror(2019071002);        current_module.used_rtti_attrs.concatlistcopy(dangling.rtti_attributes);        dangling.is_bound:=true;        owned:=dangling;        dangling:=nil;      end;    procedure trtti_attribute_list.addattribute(atypesym:tsym;typeconstr:tdef;constructorcall:tnode;constref paras:array of tnode);      var        newattribute : trtti_attribute;        i : sizeint;      begin        if not assigned(rtti_attributes) then          rtti_attributes:=TFPObjectList.Create(true);        newattribute:=trtti_attribute.Create;        newattribute.typesym:=atypesym;        newattribute.typeconstr:=typeconstr;        newattribute.constructorcall:=constructorcall;        setlength(newattribute.paras,length(paras));        for i:=0 to high(paras) do          newattribute.paras[i]:=paras[i];        rtti_attributes.Add(newattribute);      end;    procedure trtti_attribute_list.addattribute(attr:trtti_attribute);      begin        if not assigned(rtti_attributes) then          rtti_attributes:=TFPObjectList.Create(true);        rtti_attributes.add(attr);      end;    destructor trtti_attribute_list.destroy;      begin        rtti_attributes.Free;        inherited destroy;      end;    function trtti_attribute_list.get_attribute_count:longint;      begin        if assigned(rtti_attributes) then          result:=rtti_attributes.Count        else          result:=0;      end;    procedure trtti_attribute_list.buildderef;      var        i : sizeint;      begin        if not assigned(rtti_attributes) then          exit;        for i:=0 to rtti_attributes.count-1 do          trtti_attribute(rtti_attributes[i]).buildderef;      end;    procedure trtti_attribute_list.deref;      var        i : sizeint;      begin        if not assigned(rtti_attributes) then          exit;        for i:=0 to rtti_attributes.count-1 do          trtti_attribute(rtti_attributes[i]).deref;      end;    class procedure trtti_attribute_list.ppuload_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);      var        i : sizeint;      begin        if assigned(attrlist) then          begin            if not assigned(attrlist.rtti_attributes) then              internalerror(2019071101);            for i:=0 to attrlist.rtti_attributes.count-1 do              trtti_attribute(attrlist.rtti_attributes[i]).ppuload_subentries(ppufile);          end;      end;    class procedure trtti_attribute_list.ppuwrite_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);      var        i : sizeint;      begin        if assigned(attrlist) and assigned(attrlist.rtti_attributes) then          begin            for i:=0 to attrlist.rtti_attributes.count-1 do              trtti_attribute(attrlist.rtti_attributes[i]).ppuwrite_subentries(ppufile);          end;      end;    class function trtti_attribute_list.ppuload(ppufile:tcompilerppufile):trtti_attribute_list;      var        cnt,i : longint;      begin        cnt:=ppufile.getlongint;        if cnt>0 then          begin            result:=trtti_attribute_list.create;            for i:=0 to cnt-1 do              result.addattribute(trtti_attribute.ppuload(ppufile));          end        else          result:=nil;      end;    class procedure trtti_attribute_list.ppuwrite(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);      var        i : longint;      begin        if assigned(attrlist) and assigned(attrlist.rtti_attributes) then          begin            ppufile.putlongint(attrlist.rtti_attributes.count);            for i:=0 to attrlist.rtti_attributes.count-1 do              trtti_attribute(attrlist.rtti_attributes[i]).ppuwrite(ppufile);          end        else          ppufile.putlongint(0);      end;{****************************************************************************                                 TORDDEF****************************************************************************}    constructor torddef.create(t : tordtype;v,b : TConstExprInt; doregister: boolean);      begin         inherited create(orddef,doregister);         low:=v;         high:=b;         ordtype:=t;         setsize;      end;    constructor torddef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(orddef,ppufile);         ordtype:=tordtype(ppufile.getbyte);         low:=ppufile.getexprint;         high:=ppufile.getexprint;         setsize;         ppuload_platform(ppufile);      end;    function torddef.getcopy : tstoreddef;      begin         result:=corddef.create(ordtype,low,high,true);         result.typ:=orddef;         torddef(result).low:=low;         torddef(result).high:=high;         torddef(result).ordtype:=ordtype;         torddef(result).savesize:=savesize;      end;    function torddef.alignment:shortint;      begin        if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_ios]) and           (ordtype in [s64bit,u64bit]) then          result := 4        else          result := inherited alignment;      end;    procedure torddef.setsize;      const        sizetbl : array[tordtype] of longint = (          0,          1,2,4,8,16,          1,2,4,8,16,          1,1,2,4,8,          1,2,4,8,          1,2,8,system.high(longint)        );      begin        savesize:=sizetbl[ordtype];        if savesize=system.high(longint) then          savesize:=packedbitsize div 8;      end;    function torddef.packedbitsize: asizeint;      var        sizeval: tconstexprint;        power: longint;      begin        result := 0;        if ordtype = uvoid then          exit;{$ifndef cpu64bitalu}        if (ordtype in [s64bit,u64bit]) then{$else not cpu64bitalu}        if ((ordtype = u64bit) and            (high > system.high(int64))) or           ((ordtype = s64bit) and            ((low <= (system.low(int64) div 2)) or             ((low < 0) and              (high > (system.high(int64) div 2))))) then{$endif cpu64bitalu}          result := 64        else if (            (low >= 0) and            (high <= 1)           ) or (             ordtype in [pasbool1,pasbool8,pasbool16,pasbool32,pasbool64,bool8bit,bool16bit,bool32bit,bool64bit]           ) then          result := 1        else          begin            if (low>=0) then              sizeval:=high            else              { don't count 0 twice, but take into account that range goes from -n-1..n }              sizeval:=(cutils.max(-low,high+1)*2)-1;            { 256 must become 512 etc. }            nextpowerof2(sizeval+1,power);            result := power;         end;      end;    function torddef.getvardef : longint;      const        basetype2vardef : array[tordtype] of longint = (          varUndefined,          varbyte,varword,varlongword,varqword,varUndefined,          varshortint,varsmallint,varinteger,varint64,varUndefined,          varboolean,varboolean,varboolean,varboolean,varboolean,          varboolean,varboolean,varUndefined,varUndefined,          varUndefined,varUndefined,varCurrency,varEmpty);      begin        result:=basetype2vardef[ordtype];        if result=varEmpty then          result:=basetype2vardef[range_to_basetype(low,high)];      end;    procedure torddef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(ordtype));         ppufile.putexprint(low);         ppufile.putexprint(high);         writeentry(ppufile,iborddef);      end;    function torddef.is_publishable : tpublishproperty;      begin         if ordtype<>uvoid then           is_publishable:=pp_publish         else           is_publishable:=pp_error;      end;    function torddef.GetTypeName : string;      const        names : array[tordtype] of string[20] = (          'untyped',          'Byte','Word','DWord','QWord','UInt128',          'ShortInt','SmallInt','LongInt','Int64','Int128',          'Boolean','Boolean8','Boolean16','Boolean32','Boolean64',          'ByteBool','WordBool','LongBool','QWordBool',          'AnsiChar','WideChar','Currency','CustomRange');      begin         GetTypeName:=names[ordtype];      end;{****************************************************************************                                TFLOATDEF****************************************************************************}    constructor tfloatdef.create(t: tfloattype; doregister: boolean);      begin         inherited create(floatdef,doregister);         floattype:=t;         setsize;      end;    constructor tfloatdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(floatdef,ppufile);         floattype:=tfloattype(ppufile.getbyte);         setsize;         ppuload_platform(ppufile);      end;    function tfloatdef.getcopy : tstoreddef;      begin         result:=cfloatdef.create(floattype,true);         result.typ:=floatdef;         tfloatdef(result).savesize:=savesize;      end;    function tfloatdef.alignment:shortint;      begin        if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_ios]) then          case floattype of            sc80real,            s80real: result:=16;            s64real,            s64currency,            s64comp : result:=4;            else              result := inherited alignment;          end        else          result := inherited alignment;      end;    function tfloatdef.structalignment: shortint;      begin        { aix is really annoying: the recommended scalar alignment for both          int64 and double is 64 bits, but in structs int64 has to be aligned          to 8 bytes and double to 4 bytes }        if (target_info.system in systems_aix) and           (floattype=s64real) then          result:=4        else          result:=alignment;      end;    procedure tfloatdef.setsize;      begin         case floattype of           s32real : savesize:=4;           s80real : savesize:=10;           sc80real:             if target_info.system in [system_i386_darwin,                  system_i386_iphonesim,system_x86_64_darwin,                  system_x86_64_iphonesim,                  system_x86_64_linux,system_x86_64_freebsd,                  system_x86_64_openbsd,system_x86_64_netbsd,                  system_x86_64_solaris,system_x86_64_embedded,                  system_x86_64_dragonfly,system_x86_64_haiku] then               savesize:=16             else               savesize:=12;           s64real,           s64currency,           s64comp : savesize:=8;         else           savesize:=0;         end;      end;    function tfloatdef.getvardef : longint;      const        floattype2vardef : array[tfloattype] of longint = (          varSingle,varDouble,varUndefined,varUndefined,          varUndefined,varCurrency,varUndefined);      begin        if (upper(typename)='TDATETIME') and          assigned(owner) and          assigned(owner.name) and          (owner.name^='SYSTEM') then          result:=varDate        else          result:=floattype2vardef[floattype];      end;    procedure tfloatdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(floattype));         writeentry(ppufile,ibfloatdef);      end;    function tfloatdef.is_publishable : tpublishproperty;      begin         is_publishable:=pp_publish;      end;    function tfloatdef.GetTypeName : string;      const        names : array[tfloattype] of string[20] = (          'Single','Double','Extended','CExtended','Comp','Currency','Float128');      begin         GetTypeName:=names[floattype];      end;{****************************************************************************                                TFILEDEF****************************************************************************}    constructor tfiledef.createtext;      begin         inherited create(filedef,true);         filetyp:=ft_text;         typedfiledef:=nil;         typedfiledefderef.reset;      end;    constructor tfiledef.createuntyped;      begin         inherited create(filedef,true);         filetyp:=ft_untyped;         typedfiledef:=nil;      end;    constructor tfiledef.createtyped(def:tdef);      begin         inherited create(filedef,true);         filetyp:=ft_typed;         typedfiledef:=def;      end;    constructor tfiledef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(filedef,ppufile);         filetyp:=tfiletyp(ppufile.getbyte);         if filetyp=ft_typed then           ppufile.getderef(typedfiledefderef)         else           typedfiledef:=nil;         ppuload_platform(ppufile);      end;    function tfiledef.getcopy : tstoreddef;      begin        case filetyp of          ft_typed:            result:=cfiledef.createtyped(typedfiledef);          ft_untyped:            result:=cfiledef.createuntyped;          ft_text:            result:=cfiledef.createtext;        end;      end;    procedure tfiledef.buildderef;      begin        inherited buildderef;        if filetyp=ft_typed then          typedfiledefderef.build(typedfiledef);      end;    procedure tfiledef.deref;      begin        inherited deref;        if filetyp=ft_typed then          typedfiledef:=tdef(typedfiledefderef.resolve);      end;    function  tfiledef.size:asizeint;      begin        if savesize=0 then          setsize;        size:=savesize;      end;    procedure tfiledef.setsize;      begin       case filetyp of         ft_text:           savesize:=search_system_type('TEXTREC').typedef.size;         ft_typed:           begin             savesize:=search_system_type('FILEREC').typedef.size;             { allocate put/get buffer in iso mode }             if m_isolike_io in current_settings.modeswitches then               inc(savesize,typedfiledef.size);           end;         ft_untyped:           savesize:=search_system_type('FILEREC').typedef.size;         end;      end;    function tfiledef.alignment: shortint;      begin        case filetyp of          ft_text:            result:=search_system_type('TEXTREC').typedef.alignment;          ft_typed,          ft_untyped:            result:=search_system_type('FILEREC').typedef.alignment;          end;      end;    procedure tfiledef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(filetyp));         if filetyp=ft_typed then           ppufile.putderef(typedfiledefderef);         writeentry(ppufile,ibfiledef);      end;    function tfiledef.GetTypeName : string;      begin         case filetyp of           ft_untyped:             GetTypeName:='File';           ft_typed:             GetTypeName:='File Of '+typedfiledef.typename;           ft_text:             GetTypeName:='Text'         end;      end;    function tfiledef.getmangledparaname : TSymStr;      begin         case filetyp of           ft_untyped:             getmangledparaname:='FILE';           ft_typed:             getmangledparaname:='FILE$OF$'+typedfiledef.mangledparaname;           ft_text:             getmangledparaname:='TEXT'         end;      end;{****************************************************************************                               TVARIANTDEF****************************************************************************}    constructor tvariantdef.create(v : tvarianttype);      begin         inherited create(variantdef,true);         varianttype:=v;         setsize;      end;    constructor tvariantdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(variantdef,ppufile);         varianttype:=tvarianttype(ppufile.getbyte);         setsize;         ppuload_platform(ppufile);      end;    function tvariantdef.getcopy : tstoreddef;      begin        result:=cvariantdef.create(varianttype);      end;    function tvariantdef.alignment: shortint;      begin        result:=search_system_type('TVARDATA').typedef.alignment;      end;    procedure tvariantdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(varianttype));         writeentry(ppufile,ibvariantdef);      end;    function tvariantdef.getvardef : longint;      begin        Result:=varVariant;      end;    procedure tvariantdef.setsize;      begin{$ifdef cpu64bitaddr}        savesize:=24;{$else cpu64bitaddr}        savesize:=16;{$endif cpu64bitaddr}      end;    function tvariantdef.GetTypeName : string;      begin         case varianttype of           vt_normalvariant:             GetTypeName:='Variant';           vt_olevariant:             GetTypeName:='OleVariant';         end;      end;    function tvariantdef.needs_inittable : boolean;      begin         needs_inittable:=true;      end;    function tvariantdef.is_publishable : tpublishproperty;      begin         is_publishable:=pp_publish;      end;{****************************************************************************                            TABSTRACtpointerdef****************************************************************************}    constructor tabstractpointerdef.create(dt:tdeftyp;def:tdef);      begin        inherited create(dt,true);        pointeddef:=def;        pointeddefderef.reset;        if df_generic in pointeddef.defoptions then          include(defoptions,df_generic);        if df_specialization in pointeddef.defoptions then          include(defoptions,df_specialization);      end;    constructor tabstractpointerdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);      begin         inherited ppuload(dt,ppufile);         ppufile.getderef(pointeddefderef);      end;    procedure tabstractpointerdef.buildderef;      begin        inherited buildderef;        pointeddefderef.build(pointeddef);      end;    procedure tabstractpointerdef.deref;      begin        inherited deref;        pointeddef:=tdef(pointeddefderef.resolve);      end;    function tabstractpointerdef.size: asizeint;      begin        Result:=voidpointertype.size;      end;    function tabstractpointerdef.alignment: shortint;      begin        alignment:=size_2_align(voidpointertype.size);      end;    procedure tabstractpointerdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putderef(pointeddefderef);      end;{****************************************************************************                               tpointerdef****************************************************************************}    constructor tpointerdef.create(def:tdef);      begin        inherited create(pointerdef,def);        has_pointer_math:=cs_pointermath in current_settings.localswitches;        if (df_specialization in tstoreddef(def).defoptions){$ifndef genericdef_for_nested}           { currently, nested procdefs of generic routines get df_specialization,             but no genericdef }           and assigned(tstoreddef(def).genericdef){$endif}           then          genericdef:=cpointerdef.getreusable(tstoreddef(def).genericdef);      end;    class function tpointerdef.getreusable(def: tdef): tpointerdef;      var        res: PHashSetItem;        oldsymtablestack: tsymtablestack;      begin        if not assigned(current_module) then          internalerror(2011071101);        res:=current_module.ptrdefs.FindOrAdd(@def,sizeof(def));        if not assigned(res^.Data) then          begin            { since these pointerdefs can be reused anywhere in the current              unit, add them to the global/staticsymtable (or local symtable              if they're a local def, because otherwise they'll be saved              to the ppu referencing a local symtable entry that doesn't              exist in the ppu) }            oldsymtablestack:=symtablestack;            { do not simply push/pop current_module.localsymtable, because              that can have side-effects (e.g., it removes helpers) }            symtablestack:=nil;            result:=cpointerdef.create(def);            setup_reusable_def(def,result,res,oldsymtablestack);            { res^.Data may still be nil -> don't overwrite result }            exit;          end;        result:=tpointerdef(res^.Data);      end;    class function tpointerdef.getreusable_no_free(def: tdef): tpointerdef;      begin        result:=getreusable(def);        if not result.is_registered then          include(result.defoptions,df_not_registered_no_free);      end;    function tpointerdef.size: asizeint;      begin        result:=sizeof(pint);      end;    constructor tpointerdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(pointerdef,ppufile);         has_pointer_math:=(ppufile.getbyte<>0);         ppuload_platform(ppufile);      end;    function tpointerdef.getcopy : tstoreddef;      begin        { don't use direct pointeddef if it is a forwarddef because in other case          one of them will be destroyed on forward type resolve and the second will          point to garbage }        if pointeddef.typ=forwarddef then          result:=cpointerdef.create(tforwarddef(pointeddef).getcopy)        else          result:=cpointerdef.create(pointeddef);        tpointerdef(result).has_pointer_math:=has_pointer_math;        tpointerdef(result).savesize:=savesize;      end;    procedure tpointerdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(has_pointer_math));         writeentry(ppufile,ibpointerdef);      end;    function tpointerdef.GetTypeName : string;      begin        { parameter types and the resultdef of a procvardef can contain a          pointer to this procvardef itself, resulting in endless recursion ->          use the typesym's name instead if it exists (if it doesn't, such as          for anynonymous procedure types in macpas/iso mode, then there cannot          be any recursive references to it either) }        if (pointeddef.typ<>procvardef) or           not assigned(pointeddef.typesym) then          GetTypeName:='^'+pointeddef.typename        else          GetTypeName:='^'+pointeddef.typesym.realname;      end;    function tpointerdef.pointer_arithmetic_int_type:tdef;      begin        result:=ptrsinttype;      end;    function tpointerdef.pointer_arithmetic_uint_type:tdef;      begin        result:=ptruinttype;      end;    function tpointerdef.pointer_subtraction_result_type:tdef;      begin        result:=ptrsinttype;      end;    function tpointerdef.compatible_with_pointerdef_size(ptr: tpointerdef): boolean;      begin        result:=true;      end;    function tpointerdef.converted_pointer_to_array_range_type:tdef;      begin        result:=ptrsinttype;      end;{****************************************************************************                              TCLASSREFDEF****************************************************************************}    constructor tclassrefdef.create(def:tdef);      begin         while (def.typ=objectdef) and tobjectdef(def).is_unique_objpasdef do           def:=tobjectdef(def).childof;         inherited create(classrefdef,def);         if df_specialization in tstoreddef(def).defoptions then           genericdef:=cclassrefdef.create(tstoreddef(def).genericdef);      end;    constructor tclassrefdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(classrefdef,ppufile);         ppuload_platform(ppufile);      end;    procedure tclassrefdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         writeentry(ppufile,ibclassrefdef);      end;    function tclassrefdef.getcopy:tstoreddef;      begin        if pointeddef.typ=forwarddef then          result:=cclassrefdef.create(tforwarddef(pointeddef).getcopy)        else          result:=cclassrefdef.create(pointeddef);      end;    function tclassrefdef.GetTypeName : string;      begin         GetTypeName:='Class Of '+pointeddef.typename;      end;    function tclassrefdef.is_publishable : tpublishproperty;      begin         is_publishable:=pp_publish;      end;    function tclassrefdef.rtti_mangledname(rt: trttitype): TSymStr;      begin        if (tobjectdef(pointeddef).objecttype<>odt_objcclass) then          result:=inherited rtti_mangledname(rt)        else          result:=tobjectdef(pointeddef).rtti_mangledname(objcmetartti);      end;    procedure tclassrefdef.register_created_object_type;      begin        tobjectdef(pointeddef).register_created_classref_type;      end;{***************************************************************************                                   TSETDEF***************************************************************************}    constructor tsetdef.create(def: tdef; low, high: asizeint; doregister: boolean);      var        setallocbits: aint;        packedsavesize: aint;        actual_setalloc: ShortInt;      begin         inherited create(setdef,doregister);         elementdef:=def;         elementdefderef.reset;         setmax:=high;         actual_setalloc:=current_settings.setalloc;{$if defined(cpu8bitalu) or defined(cpu16bitalu)}         if actual_setalloc=0 then           actual_setalloc:=1;{$endif}         if (actual_setalloc=0) then           begin             setbase:=0;             if (high<32) then               savesize:=Sizeof(longint)             else if (high<256) then               savesize:=32             else               savesize:=(high+7) div 8           end         else           begin             setallocbits:=actual_setalloc*8;             setbase:=low and not(setallocbits-1);             packedsavesize:=actual_setalloc*((((high+setallocbits)-setbase)) DIV setallocbits);             savesize:=packedsavesize;{$if not defined(cpu8bitalu) and not defined(cpu16bitalu)}             if savesize=3 then               savesize:=4;{$endif}           end;      end;    constructor tsetdef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(setdef,ppufile);         ppufile.getderef(elementdefderef);         savesize:=ppufile.getasizeint;         setbase:=ppufile.getasizeint;         setmax:=ppufile.getasizeint;         ppuload_platform(ppufile);      end;    function tsetdef.getcopy : tstoreddef;      begin        result:=csetdef.create(elementdef,setbase,setmax,true);        { the copy might have been created with a different setalloc setting }        tsetdef(result).savesize:=savesize;      end;    procedure tsetdef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putderef(elementdefderef);         ppufile.putasizeint(savesize);         ppufile.putasizeint(setbase);         ppufile.putasizeint(setmax);         writeentry(ppufile,ibsetdef);      end;    procedure tsetdef.buildderef;      begin        inherited buildderef;        elementdefderef.build(elementdef);      end;    procedure tsetdef.deref;      begin        inherited deref;        elementdef:=tdef(elementdefderef.resolve);      end;    function tsetdef.is_publishable : tpublishproperty;      begin         if savesize in [1,2,4] then           is_publishable:=pp_publish         else           is_publishable:=pp_error;      end;    function tsetdef.alignment: shortint;      begin        Result:=inherited;        if result>sizeof(aint) then          result:=sizeof(aint);      end;    function tsetdef.GetTypeName : string;      begin         if assigned(elementdef) then          GetTypeName:='Set Of '+elementdef.typename         else          GetTypeName:='Empty Set';      end;{***************************************************************************                                 TFORMALDEF***************************************************************************}    constructor tformaldef.create(Atyped:boolean);      begin         inherited create(formaldef,true);         typed:=Atyped;         savesize:=0;      end;    constructor tformaldef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(formaldef,ppufile);         typed:=boolean(ppufile.getbyte);         savesize:=0;         ppuload_platform(ppufile);      end;    procedure tformaldef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(typed));         writeentry(ppufile,ibformaldef);      end;    function tformaldef.GetTypeName : string;      begin         if typed then           GetTypeName:='<Typed formal type>'         else           GetTypeName:='<Formal type>';      end;{***************************************************************************                           TARRAYDEF***************************************************************************}    constructor tarraydef.create(l, h: asizeint; def: tdef);      begin         inherited create(arraydef,true);         lowrange:=l;         highrange:=h;         rangedef:=def;         rangedefderef.reset;         _elementdef:=nil;         _elementdefderef.reset;         arrayoptions:=[];         symtable:=tarraysymtable.create(self);      end;    constructor tarraydef.create_vector(l ,h: asizeint; def: tdef);      begin        self.create(l,h,def);        include(arrayoptions,ado_IsVector);      end;    constructor tarraydef.create_openarray;      begin        self.create(0,-1,sizesinttype);        include(arrayoptions,ado_OpenArray);      end;    class function tarraydef.getreusable_intern(def: tdef; elems: asizeint; const options: tarraydefoptions): tarraydef;      var        res: PHashSetItem;        oldsymtablestack: tsymtablestack;        arrdesc: packed record          def: tdef;          elecount: asizeint;          options: tarraydefoptions        end;      begin        if not assigned(current_module) then          internalerror(2011081301);        arrdesc.def:=def;        arrdesc.elecount:=elems;        arrdesc.options:=options;        res:=current_module.arraydefs.FindOrAdd(@arrdesc,sizeof(arrdesc));        if not assigned(res^.Data) then          begin            { since these pointerdefs can be reused anywhere in the current              unit, add them to the global/staticsymtable (or local symtable              if they're a local def, because otherwise they'll be saved              to the ppu referencing a local symtable entry that doesn't              exist in the ppu) }            oldsymtablestack:=symtablestack;            { do not simply push/pop current_module.localsymtable, because              that can have side-effects (e.g., it removes helpers) }            symtablestack:=nil;            result:=carraydef.create(0,elems-1,sizesinttype);            result.elementdef:=def;            result.arrayoptions:=options;            setup_reusable_def(def,result,res,oldsymtablestack);            { res^.Data may still be nil -> don't overwrite result }            exit;          end;        result:=tarraydef(res^.Data);      end;    class function tarraydef.getreusable(def: tdef; elems: asizeint): tarraydef;      begin        result:=getreusable_intern(def,elems,[]);      end;    class function tarraydef.getreusable_vector(def: tdef; elems: asizeint): tarraydef;      begin        result:=getreusable_intern(def,elems,[ado_IsVector]);      end;    class function tarraydef.getreusable_no_free(def: tdef; elems: asizeint): tarraydef;      begin        result:=getreusable(def,elems);        if not result.is_registered then          include(result.defoptions,df_not_registered_no_free);      end;    class function tarraydef.getreusable_no_free_vector(def: tdef; elems: asizeint): tarraydef;      begin        result:=getreusable_vector(def,elems);        if not result.is_registered then          include(result.defoptions,df_not_registered_no_free);      end;    destructor tarraydef.destroy;      begin        symtable.free;        symtable:=nil;        inherited;      end;    constructor tarraydef.create_from_pointer(def:tpointerdef);      begin         { divide by the element size and do -1 so the array will have a valid size,           further, the element size might be 0 e.g. for empty records, so use max(...,1)           to avoid a division by zero }         self.create(0,(high(asizeint) div max(def.pointeddef.size,1))-1,           def.converted_pointer_to_array_range_type);         arrayoptions:=[ado_IsConvertedPointer];         setelementdef(def.pointeddef);      end;    constructor tarraydef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(arraydef,ppufile);         { the addresses are calculated later }         ppufile.getderef(_elementdefderef);         ppufile.getderef(rangedefderef);         lowrange:=ppufile.getasizeint;         highrange:=ppufile.getasizeint;         ppufile.getset(tppuset2(arrayoptions));         ppuload_platform(ppufile);         symtable:=tarraysymtable.create(self);         tarraysymtable(symtable).ppuload(ppufile)      end;    function tarraydef.getcopy : tstoreddef;      begin        result:=carraydef.create(lowrange,highrange,rangedef);        tarraydef(result).arrayoptions:=arrayoptions;        tarraydef(result)._elementdef:=_elementdef;      end;    procedure tarraydef.buildderef;      begin        inherited buildderef;        tarraysymtable(symtable).buildderef;        _elementdefderef.build(_elementdef);        rangedefderef.build(rangedef);      end;    procedure tarraydef.deref;      begin        inherited deref;        tarraysymtable(symtable).deref(false);        _elementdef:=tdef(_elementdefderef.resolve);        rangedef:=tdef(rangedefderef.resolve);      end;    procedure tarraydef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         ppufile.putderef(_elementdefderef);         ppufile.putderef(rangedefderef);         ppufile.putasizeint(lowrange);         ppufile.putasizeint(highrange);         ppufile.putset(tppuset2(arrayoptions));         writeentry(ppufile,ibarraydef);         tarraysymtable(symtable).ppuwrite(ppufile);      end;    function tarraydef.elesize : asizeint;      begin        if (ado_IsBitPacked in arrayoptions) then          internalerror(2006080101);        if assigned(_elementdef) then          result:=_elementdef.size        else          result:=0;      end;    function tarraydef.elepackedbitsize : asizeint;      begin        if not(ado_IsBitPacked in arrayoptions) then          internalerror(2006080102);	if assigned(_elementdef) then          result:=_elementdef.packedbitsize	else	  result:=0;      end;    function tarraydef.elecount : asizeuint;      var        qhigh,qlow : qword;      begin        if ado_IsDynamicArray in arrayoptions then          begin            result:=0;            exit;          end;        { check whether the range might be larger than high(asizeint). Has          to include 0..high(sizeint), since that's high(sizeint)+1 elements }        if (highrange>=0) and (lowrange<=0) then          begin            qhigh:=highrange;            if lowrange=low(asizeint) then              qlow:=high(asizeint) + 1            else              qlow:=qword(-lowrange);            { prevent overflow, return 0 to indicate overflow }            if qhigh+qlow>qword(high(asizeint)-1) then              result:=0            else              result:=qhigh+qlow+1;          end        else          result:=int64(highrange)-lowrange+1;      end;    function tarraydef.size : asizeint;      var        cachedelecount : asizeuint;        cachedelesize : asizeint;      begin        if ado_IsDynamicArray in arrayoptions then          begin            size:=voidpointertype.size;            exit;          end;        { Tarraydef.size may never be called for an open array! }        if ado_OpenArray in arrayoptions then          internalerror(99080501);        if not (ado_IsBitPacked in arrayoptions) then          cachedelesize:=elesize        else          cachedelesize := elepackedbitsize;        cachedelecount:=elecount;        if (cachedelesize = 0) then          begin            size := 0;            exit;          end;        if (cachedelecount = 0) then          begin            if ado_isconststring in arrayoptions then              size := 0            else              size := -1;            exit;          end;        { prevent overflow, return -1 to indicate overflow }        { also make sure we don't need 64/128 bit arithmetic to calculate offsets }        if (cachedelecount > asizeuint(high(asizeint))) or           ((high(asizeint) div cachedelesize) < asizeint(cachedelecount)) or           { also lowrange*elesize must be < high(asizeint) to prevent overflow when             accessing the array, see ncgmem (PFV) }           ((high(asizeint) div cachedelesize) < abs(lowrange)) then          begin            result:=-1;            exit;          end;        result:=cachedelesize*asizeint(cachedelecount);        if (ado_IsBitPacked in arrayoptions) then          { can't just add 7 and divide by 8, because that may overflow }          result:=result div 8 + ord((result mod 8)<>0);{$ifdef cpu16bitaddr}        if result>65535 then          begin            result:=-1;            exit;          end;{$endif cpu16bitaddr}      end;    procedure tarraydef.setelementdef(def:tdef);      begin        _elementdef:=def;        if not(               (ado_IsDynamicArray in arrayoptions) or               (ado_IsConvertedPointer in arrayoptions) or               (ado_IsConstructor in arrayoptions) or               (ado_IsGeneric in arrayoptions) or               (highrange<lowrange)	      ) and           (size=-1) then          Message(sym_e_segment_too_large);      end;    function tarraydef.alignment : shortint;      begin        if ado_IsVector in arrayoptions then           alignment:=size         { alignment of dyn. arrays doesn't depend on the element size }         else if ado_IsDynamicArray in arrayoptions then           alignment:=voidpointertype.alignment         { alignment is the target alignment for the used load size }         else if (ado_IsBitPacked in arrayoptions) and            (elementdef.typ in [enumdef,orddef]) then           alignment:=cgsize_orddef(int_cgsize(packedbitsloadsize(elepackedbitsize))).alignment         { alignment is the alignment of the elements }         else           alignment:=elementdef.alignment      end;    function tarraydef.needs_inittable : boolean;      begin         needs_inittable:=(ado_IsDynamicArray in arrayoptions) or elementdef.needs_inittable;      end;    function tarraydef.needs_separate_initrtti : boolean;      begin        if ado_IsBitPacked in arrayoptions then          result:=false        else          result:=elementdef.needs_separate_initrtti;      end;    function tarraydef.GetTypeName : string;      begin         if (ado_IsConstString in arrayoptions) then           result:='Constant String'         else if (ado_isarrayofconst in arrayoptions) or                 (ado_isConstructor in arrayoptions) then           begin             if (ado_isvariant in arrayoptions) or ((highrange=-1) and (lowrange=0)) then               GetTypeName:='Array Of Const'             else               GetTypeName:='{Array Of Const/Constant Open} Array of '+elementdef.typename;           end         else if (ado_IsDynamicArray in arrayoptions) then           GetTypeName:='{Dynamic} Array Of '+elementdef.typename         else if (ado_OpenArray in arrayoptions) then           GetTypeName:='{Open} Array Of '+elementdef.typename         else           begin              result := '';              if (ado_IsBitPacked in arrayoptions) then                result:='BitPacked ';              if rangedef.typ=enumdef then                result:=result+'Array['+rangedef.typename+'] Of '+elementdef.typename              else                result:=result+'Array['+tostr(lowrange)+'..'+                  tostr(highrange)+'] Of '+elementdef.typename           end;      end;    function tarraydef.getmangledparaname : TSymStr;      begin         if ado_isarrayofconst in arrayoptions then          getmangledparaname:='array_of_const'         else          if ((highrange=-1) and (lowrange=0)) then           getmangledparaname:='array_of_'+elementdef.mangledparaname         else          internalerror(200204176);      end;    function tarraydef.is_publishable : tpublishproperty;      begin         if ado_IsDynamicArray in arrayoptions then           is_publishable:=pp_publish         else           is_publishable:=pp_error;      end;    function tarraydef.is_hwvector: boolean;      begin        result:=ado_IsVector in arrayoptions;      end;{***************************************************************************                              tabstractrecorddef***************************************************************************}    constructor tabstractrecorddef.create(const n:string; dt:tdeftyp;doregister:boolean);      begin        inherited create(dt,doregister);        objname:=stringdup(upper(n));        objrealname:=stringdup(n);        objectoptions:=[];        if assigned(current_module.namespace) then          begin            import_lib:=stringdup(current_module.namespace^);            replace(import_lib^,'.','/');          end;      end;    constructor tabstractrecorddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);      begin        inherited ppuload(dt,ppufile);        objrealname:=ppufile.getpshortstring;        objname:=stringdup(upper(objrealname^));        import_lib:=ppufile.getpshortstring;        { only used for external C++ classes and Java classes/records }        if (import_lib^='') then          stringdispose(import_lib);        ppufile.getset(tppuset4(objectoptions));      end;    procedure tabstractrecorddef.ppuwrite(ppufile: tcompilerppufile);      begin        inherited ppuwrite(ppufile);        ppufile.putstring(objrealname^);        if assigned(import_lib) then          ppufile.putstring(import_lib^)        else          ppufile.putstring('');        ppufile.putset(tppuset4(objectoptions));      end;    destructor tabstractrecorddef.destroy;      begin        stringdispose(objname);        stringdispose(objrealname);        stringdispose(import_lib);        tcinitcode.free;        inherited destroy;      end;    procedure tabstractrecorddef.buildderefimpl;      begin         inherited buildderefimpl;         if not (df_copied_def in defoptions) then           tstoredsymtable(symtable).buildderefimpl;      end;    procedure tabstractrecorddef.derefimpl;      begin        inherited derefimpl;        if not (df_copied_def in defoptions) then          tstoredsymtable(symtable).derefimpl(false);      end;    procedure tabstractrecorddef.check_forwards;      begin        { the defs of a copied def are defined for the original type only }        if not(df_copied_def in defoptions) then          tstoredsymtable(symtable).check_forwards;      end;    function tabstractrecorddef.find_procdef_bytype(pt:tproctypeoption): tprocdef;      var        i: longint;        sym: tsym;      begin        for i:=0 to symtable.SymList.Count-1 do          begin            sym:=tsym(symtable.SymList[i]);            if sym.typ=procsym then              begin                result:=tprocsym(sym).find_procdef_bytype(pt);                if assigned(result) then                  exit;              end;          end;          result:=nil;      end;    function tabstractrecorddef.GetSymtable(t:tGetSymtable):TSymtable;      begin        if t=gs_record then          GetSymtable:=symtable        else          GetSymtable:=nil;      end;    function tabstractrecorddef.is_packed:boolean;      begin        result:=tabstractrecordsymtable(symtable).is_packed;      end;    function tabstractrecorddef.RttiName: string;        function generate_full_paramname(maxlength:longint):string;          const            commacount : array[boolean] of longint = (0,1);          var            fullparas,            paramname : ansistring;            module : tmodule;            sym : tsym;            def : tdef;            i : longint;          begin            { we want at least enough space for an ellipsis }            if maxlength<3 then              internalerror(2014121203);            fullparas:='';            for i:=0 to genericparas.count-1 do              begin                sym:=tsym(genericparas[i]);                module:=find_module_from_symtable(sym.owner);                if not assigned(module) then                  internalerror(2014121202);                if not (sym.typ in [constsym,symconst.typesym]) then                  internalerror(2020042501);                if sym.typ=constsym then                  def:=tconstsym(sym).constdef                else                  def:=ttypesym(sym).typedef;                paramname:=module.realmodulename^;                if def.typ in [objectdef,recorddef] then                  paramname:=paramname+'.'+tabstractrecorddef(def).rttiname                else                  paramname:=paramname+'.'+def.typename;                if length(fullparas)+commacount[i>0]+length(paramname)>maxlength then                  begin                    if i>0 then                      fullparas:=fullparas+',...'                    else                      fullparas:=fullparas+'...';                    break;                  end;                { could we fit an ellipsis after this parameter if it should be too long? }                if (maxlength-(length(fullparas)+commacount[i>0]+length(paramname))<4) and (i<genericparas.count-1) then                  begin                    { then omit already this parameter }                    if i>0 then                      fullparas:=fullparas+',...'                    else                      fullparas:=fullparas+'...';                    break;                  end;                if i>0 then                  fullparas:=fullparas+',';                fullparas:=fullparas+paramname;              end;            result:=fullparas;          end;      var        nongeneric,        basename : string;        i,        remlength,        paramcount,        crcidx : longint;      begin        if rttistring='' then          begin            if is_specialization then              begin                rttistring:=OwnerHierarchyName;                { there should be two $ characters, one before the CRC and one before the count }                crcidx:=-1;                for i:=length(objrealname^) downto 1 do                  if objrealname^[i]='$' then                    begin                      crcidx:=i;                      break;                    end;                if crcidx<0 then                  internalerror(2014121201);                basename:=copy(objrealname^,1,crcidx-1);                split_generic_name(basename,nongeneric,paramcount);                rttistring:=rttistring+nongeneric+'<';                remlength:=255-length(rttistring)-1;                if remlength<4 then                  rttistring:=rttistring+'>'                else                  rttistring:=rttistring+generate_full_paramname(remlength)+'>';              end            else              if is_generic then                begin                  rttistring:=OwnerHierarchyName;                  split_generic_name(objrealname^,nongeneric,paramcount);                  rttistring:=rttistring+nongeneric+'<';                  { we don't want any ',' if there is only one parameter }                  for i:=0 to paramcount-0 do                    rttistring:=rttistring+',';                  rttistring:=rttistring+'>';                end              else                rttistring:=OwnerHierarchyName+objrealname^;          end;        result:=rttistring;      end;    function tabstractrecorddef.search_enumerator_get: tprocdef;      var        sym : tsym;        i : integer;        pd : tprocdef;        hashedid : THashedIDString;      begin        result:=nil;        hashedid.id:='GETENUMERATOR';        sym:=tsym(symtable.FindWithHash(hashedid));        if assigned(sym) and (sym.typ=procsym) then          begin            for i := 0 to Tprocsym(sym).ProcdefList.Count - 1 do            begin              pd := tprocdef(Tprocsym(sym).ProcdefList[i]);              if (pd.proctypeoption = potype_function) and                 (is_class_or_interface_or_object(pd.returndef) or is_record(pd.returndef)) and                 (pd.visibility >= vis_public) then              begin                result:=pd;                exit;              end;            end;          end;      end;    function tabstractrecorddef.search_enumerator_move: tprocdef;      var        sym : tsym;        i : integer;        pd : tprocdef;        hashedid : THashedIDString;      begin        result:=nil;        // first search for po_enumerator_movenext method modifier        // then search for public function MoveNext: Boolean        for i:=0 to symtable.SymList.Count-1 do          begin            sym:=TSym(symtable.SymList[i]);            if (sym.typ=procsym) then            begin              pd:=Tprocsym(sym).find_procdef_byoptions([po_enumerator_movenext]);              if assigned(pd) then                begin                  result:=pd;                  exit;                end;            end;          end;        hashedid.id:='MOVENEXT';        sym:=tsym(symtable.FindWithHash(hashedid));        if assigned(sym) and (sym.typ=procsym) then          begin            for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do            begin              pd := tprocdef(Tprocsym(sym).ProcdefList[i]);              if (pd.proctypeoption = potype_function) and                 is_boolean(pd.returndef) and                 (pd.minparacount = 0) and                 (pd.visibility >= vis_public) then              begin                result:=pd;                exit;              end;            end;          end;      end;    function tabstractrecorddef.search_enumerator_current: tsym;      var        sym: tsym;        i: integer;        hashedid : THashedIDString;      begin        result:=nil;        // first search for ppo_enumerator_current property modifier        // then search for public property Current        for i:=0 to symtable.SymList.Count-1 do          begin            sym:=TSym(symtable.SymList[i]);            if (sym.typ=propertysym) and (ppo_enumerator_current in tpropertysym(sym).propoptions) then            begin              result:=sym;              exit;            end;          end;        hashedid.id:='CURRENT';        sym:=tsym(symtable.FindWithHash(hashedid));        if assigned(sym) and (sym.typ=propertysym) and           (sym.visibility >= vis_public) and not tpropertysym(sym).propaccesslist[palt_read].empty then          begin            result:=sym;            exit;          end;      end;    function tabstractrecorddef.jvm_full_typename(with_package_name: boolean): string;      var        st: tsymtable;        enclosingdef: tdef;      begin        if typ=objectdef then          result:=tobjectdef(self).objextname^        else if assigned(typesym) then          result:=typesym.realname        { have to generate anonymous nested type in current unit/class/record }        else          internalerror(2011032601);        { in case of specializations, add some extras to prevent name conflicts          with nested classes }        if df_specialization in defoptions then          result:='$'+result+'$specialization$';        st:=owner;        while assigned(st) and              (st.symtabletype in [objectsymtable,recordsymtable,localsymtable]) do          begin            { nested classes are named as "OuterClass$InnerClass" }            enclosingdef:=tdef(st.defowner);            if enclosingdef.typ=procdef then              result:=result+tprocdef(enclosingdef).procsym.realname+'$$'+tostr(tprocdef(enclosingdef).procsym.symid)+'$'            else if enclosingdef.typ=objectdef then              result:=tobjectdef(enclosingdef).objextname^+'$'+result            else if assigned(enclosingdef.typesym) then              result:=enclosingdef.typesym.realname+'$'+result            else              internalerror(2011060305);            st:=enclosingdef.owner;          end;        if with_package_name and           assigned(import_lib) then          result:=import_lib^+'/'+result;      end;    function tabstractrecorddef.contains_float_field: boolean;      var        i : longint;      begin        result:=true;        for i:=0 to symtable.symlist.count-1 do          begin            if (tsym(symtable.symlist[i]).typ<>fieldvarsym) or               (sp_static in tsym(symtable.symlist[i]).symoptions) then              continue;            if assigned(tfieldvarsym(symtable.symlist[i]).vardef) then              begin                if tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).is_fpuregable then                  exit;                { search recursively }                if (tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).typ=recorddef) and                  (tabstractrecorddef(tfieldvarsym(symtable.symlist[i]).vardef).contains_float_field) then                  exit;              end;          end;        result:=false;      end;    function tabstractrecorddef.contains_cross_aword_field: boolean;      var        i : longint;        foffset, fsize: aword;      begin        result:=true;        for i:=0 to symtable.symlist.count-1 do          begin            if (tsym(symtable.symlist[i]).typ<>fieldvarsym) or               (sp_static in tsym(symtable.symlist[i]).symoptions) then              continue;            if assigned(tfieldvarsym(symtable.symlist[i]).vardef) then              begin                if is_packed then                  begin                    foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset;                    fsize:=tfieldvarsym(symtable.symlist[i]).vardef.packedbitsize;                  end                else                  begin                    foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset*8;                    fsize:=tfieldvarsym(symtable.symlist[i]).vardef.size*8;                  end;                if (fsize>0) and ((foffset div (sizeof(aword)*8)) <> ((foffset+fsize-1) div (sizeof(aword)*8))) then                  exit;                { search recursively }                if (tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).typ=recorddef) and                  (tabstractrecorddef(tfieldvarsym(symtable.symlist[i]).vardef).contains_cross_aword_field) then                  exit;              end;          end;        result:=false;      end;{$ifdef DEBUG_NODE_XML}    procedure tabstractrecorddef.XMLPrintDefData(var T: Text; Sym: TSym);      procedure WriteSymOptions(SourceSym: TSym);        var          i: TSymOption;          first: Boolean;        begin          First := True;          for i := Low(TSymOption) to High(TSymOption) do            if i in SourceSym.symoptions then              begin                if First then                  begin                    Write(T, '" symoptions="', i);                    First := False;                  end                else                  Write(T, ',', i)              end;        end;      var        List: TFPHashObjectList;        i: Integer;      begin        WriteLn(T, PrintNodeIndention, '<size>', size, '</size>');        if (alignment = structalignment) and (alignment = aggregatealignment) then          begin            { Straightforward and simple }            WriteLn(T, PrintNodeIndention, '<alignment>', alignment, '</alignment>');          end        else          begin            WriteLn(T, PrintNodeIndention, '<alignment>');            printnodeindent;            WriteLn(T, PrintNodeIndention, '<basic>', alignment, '</basic>');            if (structalignment <> alignment) then              WriteLn(T, PrintNodeIndention, '<struct>', structalignment, '</struct>');            if (aggregatealignment <> alignment) and (aggregatealignment <> structalignment) then              WriteLn(T, PrintNodeIndention, '<aggregate>', aggregatealignment, '</aggregate>');            printnodeunindent;            WriteLn(T, PrintNodeIndention, '</alignment>');          end;        { List the fields }        List := Symtable.SymList;        for i := 0 to List.Count - 1 do          case TSym(List[i]).typ of{            staticvarsym,localvarsym,paravarsym,fieldvarsym,            typesym,procsym,unitsym,}            constsym:              with TConstSym(List[i]) do                begin                  Write(T, PrintNodeIndention, '<const name="', RealName, '" pos="', fileinfo.line, ',', fileinfo.column);                  WriteSymOptions(TSym(List[i]));                  WriteLn(T, '">');                  PrintNodeIndent;                  XMLPrintConstData(T);                  PrintNodeUnindent;                  WriteLn(T, PrintNodeIndention, '</const>');                end; {            errorsym,syssym,labelsym,absolutevarsym,propertysym,            macrosym,namespacesym,undefinedsym,programparasym}            fieldvarsym:              with TFieldVarSym(List[i]) do                begin                  Write(T, PrintNodeIndention, '<field name="', RealName, '" pos="', fileinfo.line, ',', fileinfo.column);                  WriteSymOptions(TSym(List[i]));                  WriteLn(T, '">');                  PrintNodeIndent;                  XMLPrintFieldData(T);                  PrintNodeUnindent;                  WriteLn(T, PrintNodeIndention, '</field>');                end;            else              ;          end;      end;{$endif DEBUG_NODE_XML}{***************************************************************************                                  trecorddef***************************************************************************}    constructor trecorddef.create(const n:string; p:TSymtable);      begin         inherited create(n,recorddef,true);         symtable:=p;         { we can own the symtable only if nobody else owns a copy so far }         if symtable.refcount=1 then           symtable.defowner:=self;         isunion:=false;         cloneddefderef.reset;      end;    constructor trecorddef.create_internal(const n: string; packrecords, recordalignmin: shortint; where: tsymtable);      var        name : string;        pname : pshortstring;        oldsymtablestack: tsymtablestack;        ts: ttypesym;      begin        { construct name }        if n<>'' then          pname:=@n        else          begin            init_defid;            name:='$InternalRec'+unique_id_str;            pname:=@name;          end;        oldsymtablestack:=symtablestack;        { do not simply push/pop current_module.localsymtable, because          that can have side-effects (e.g., it removes helpers) }        symtablestack:=nil;        symtable:=trecordsymtable.create(pname^,packrecords,recordalignmin);        symtable.defowner:=self;        isunion:=false;        inherited create(pname^,recorddef,true);        where.insertdef(self);        { if we specified a name, then we'll probably want to look up the          type again by name too -> create typesym }        if n<>'' then          begin            ts:=ctypesym.create(n,self);            include(ts.symoptions,sp_internal);            { avoid hints about unused types (these may only be used for              typed constant data) }            ts.increfcount;            where.insertsym(ts);          end;        symtablestack:=oldsymtablestack;        { don't create RTTI for internal types, these are not exported }        defstates:=defstates+[ds_rtti_table_written,ds_init_table_written];        include(defoptions,df_internal);      end;    constructor trecorddef.create_global_internal(const n: string; packrecords, recordalignmin: shortint);      var        where : tsymtable;      begin        where:=current_module.localsymtable;        if not assigned(where) then          where:=current_module.globalsymtable;        create_internal(n,packrecords,recordalignmin,where);      end;    function trecorddef.add_field_by_def(const optionalname: TIDString; def: tdef): tsym;      var        sym: tfieldvarsym;        name: TIDString;        pname: ^TIDString;      begin        if optionalname='' then          begin            name:='$f'+tostr(trecordsymtable(symtable).symlist.count);            pname:=@name          end        else          pname:=@optionalname;        sym:=cfieldvarsym.create(pname^,vs_value,def,[]);        symtable.insertsym(sym);        trecordsymtable(symtable).addfield(sym,vis_hidden);        result:=sym;      end;    procedure trecorddef.add_fields_from_deflist(fieldtypes: tfplist);      var        i: longint;      begin        for i:=0 to fieldtypes.count-1 do          add_field_by_def('',tdef(fieldtypes[i]));      end;    constructor trecorddef.ppuload(ppufile:tcompilerppufile);      procedure readvariantrecdesc(var variantrecdesc : pvariantrecdesc);        var          i,j : longint;        begin         if ppufile.getbyte=1 then           begin             new(variantrecdesc);             ppufile.getderef(variantrecdesc^.variantselectorderef);             SetLength(variantrecdesc^.branches,ppufile.getasizeint);             for i:=0 to high(variantrecdesc^.branches) do               begin                 SetLength(variantrecdesc^.branches[i].values,ppufile.getasizeint);                 for j:=0 to high(variantrecdesc^.branches[i].values) do                   variantrecdesc^.branches[i].values[j]:=ppufile.getexprint;                 readvariantrecdesc(variantrecdesc^.branches[i].nestedvariant);               end;           end         else           variantrecdesc:=nil;        end;      begin         inherited ppuload(recorddef,ppufile);         if df_copied_def in defoptions then           begin             ppufile.getderef(cloneddefderef);             ppuload_platform(ppufile);           end         else           begin             symtable:=trecordsymtable.create(objrealname^,0,0);             trecordsymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);             trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte);             trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte);             trecordsymtable(symtable).usefieldalignment:=shortint(ppufile.getbyte);             trecordsymtable(symtable).recordalignmin:=shortint(ppufile.getbyte);             trecordsymtable(symtable).datasize:=ppufile.getasizeint;             trecordsymtable(symtable).paddingsize:=ppufile.getword;             ppufile.getset(tppuset1(trecordsymtable(symtable).managementoperators));             { position of ppuload_platform call must correspond               to position of writeentry in ppuwrite method }             ppuload_platform(ppufile);             trecordsymtable(symtable).ppuload(ppufile);             { the variantrecdesc is needed only for iso-like new statements new(prec,1,2,3 ...);               but because iso mode supports no units, there is no need to store the variantrecdesc               in the ppu             }             // readvariantrecdesc(variantrecdesc);             { requires usefieldalignment to be set }             symtable.defowner:=self;           end;         isunion:=false;      end;    destructor trecorddef.destroy;      procedure free_variantrecdesc(var variantrecdesc : pvariantrecdesc);        var          i : longint;        begin         while assigned(variantrecdesc) do           begin             for i:=0 to high(variantrecdesc^.branches) do               begin                 free_variantrecdesc(variantrecdesc^.branches[i].nestedvariant);                 SetLength(variantrecdesc^.branches[i].values,0);               end;             SetLength(variantrecdesc^.branches,0);             dispose(variantrecdesc);             variantrecdesc:=nil;           end;        end;      begin         if assigned(variantrecdesc) then           free_variantrecdesc(variantrecdesc);         if assigned(symtable) then           begin             symtable.free;             symtable:=nil;           end;         inherited destroy;      end;    function trecorddef.getcopy : tstoreddef;      begin        result:=crecorddef.create(objrealname^,symtable.getcopy);        trecorddef(result).isunion:=isunion;        include(trecorddef(result).defoptions,df_copied_def);        if assigned(tcinitcode) then          trecorddef(result).tcinitcode:=tcinitcode.getcopy;         if assigned(import_lib) then           trecorddef(result).import_lib:=stringdup(import_lib^);      end;    function trecorddef.needs_inittable : boolean;      begin        { each record with managed field or with any management operator needs          init table }        needs_inittable:=(trecordsymtable(symtable).managementoperators<>[]) or          trecordsymtable(symtable).needs_init_final      end;    function trecorddef.needs_separate_initrtti : boolean;      begin        result:=true;      end;    function trecorddef.has_non_trivial_init_child(check_parent:boolean):boolean;      begin        result:=trecordsymtable(symtable).has_non_trivial_init;      end;    procedure trecorddef.buildderef;      begin         inherited buildderef;         if df_copied_def in defoptions then           cloneddefderef.build(symtable.defowner)         else           tstoredsymtable(symtable).buildderef;      end;    procedure trecorddef.deref;      begin         inherited deref;         { now dereference the definitions }         if df_copied_def in defoptions then           begin             cloneddef:=trecorddef(cloneddefderef.resolve);             symtable:=cloneddef.symtable.getcopy;           end         else           tstoredsymtable(symtable).deref(false);         { internal types, only load from the system unit }         if assigned(owner) and            assigned(owner.name) and            (owner.name^='SYSTEM') then           begin             { TGUID  }             if not assigned(rec_tguid) and                (upper(typename)='TGUID') then               rec_tguid:=self             { JMP_BUF }             else if not assigned(rec_jmp_buf) and                (upper(typename)='JMP_BUF') then               rec_jmp_buf:=self             else if not assigned(rec_exceptaddr) and                (upper(typename)='TEXCEPTADDR') then               rec_exceptaddr:=self;           end;      end;    procedure trecorddef.ppuwrite(ppufile:tcompilerppufile);      procedure writevariantrecdesc(variantrecdesc : pvariantrecdesc);        var          i,j : longint;        begin         if assigned(variantrecdesc) then           begin             ppufile.putbyte(1);             ppufile.putderef(variantrecdesc^.variantselectorderef);             ppufile.putasizeint(length(variantrecdesc^.branches));             for i:=0 to high(variantrecdesc^.branches) do               begin                 ppufile.putasizeint(length(variantrecdesc^.branches[i].values));                 for j:=0 to high(variantrecdesc^.branches[i].values) do                   ppufile.putexprint(variantrecdesc^.branches[i].values[j]);                 writevariantrecdesc(variantrecdesc^.branches[i].nestedvariant);               end;           end         else           ppufile.putbyte(0);        end;      begin         inherited ppuwrite(ppufile);         if df_copied_def in defoptions then           ppufile.putderef(cloneddefderef)         else           begin             ppufile.putbyte(byte(trecordsymtable(symtable).fieldalignment));             ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment));             ppufile.putbyte(byte(trecordsymtable(symtable).padalignment));             ppufile.putbyte(byte(trecordsymtable(symtable).usefieldalignment));             ppufile.putbyte(byte(trecordsymtable(symtable).recordalignmin));             ppufile.putasizeint(trecordsymtable(symtable).datasize);             ppufile.putword(trecordsymtable(symtable).paddingsize);             ppufile.putset(tppuset1(trecordsymtable(symtable).managementoperators));             { the variantrecdesc is needed only for iso-like new statements new(prec,1,2,3 ...);               but because iso mode supports no units, there is no need to store the variantrecdesc               in the ppu             }             // writevariantrecdesc(variantrecdesc);           end;         writeentry(ppufile,ibrecorddef);         if not(df_copied_def in defoptions) then           trecordsymtable(symtable).ppuwrite(ppufile);      end;    function trecorddef.size:asizeint;      begin        result:=trecordsymtable(symtable).datasize;      end;    function trecorddef.alignment:shortint;      begin        alignment:=trecordsymtable(symtable).recordalignment;      end;    function trecorddef.padalignment:shortint;      begin        padalignment := trecordsymtable(symtable).padalignment;      end;    function trecorddef.GetTypeName : string;      begin         GetTypeName:='<record type>'      end;{$ifdef DEBUG_NODE_XML}    function TRecordDef.XMLPrintType: ansistring;      begin        Result := '<record>';      end;{$endif DEBUG_NODE_XML}{***************************************************************************                       TABSTRACTPROCDEF***************************************************************************}    constructor tabstractprocdef.create(dt:tdeftyp;level:byte;doregister:boolean);      begin         inherited create(dt,doregister);         parast:=tparasymtable.create(self,level);         paras:=nil;         minparacount:=0;         maxparacount:=0;         proctypeoption:=potype_none;         proccalloption:=pocall_none;         procoptions:=[];         returndef:=voidtype;         returndefderef.reset;         savesize:=sizeof(pint);         callerargareasize:=0;         calleeargareasize:=0;         has_paraloc_info:=callnoside;         funcretloc[callerside].init;         funcretloc[calleeside].init;         check_mark_as_nested;      end;    destructor tabstractprocdef.destroy;      begin         if assigned(paras) then           begin{$ifdef MEMDEBUG}             memprocpara.start;{$endif MEMDEBUG}             paras.free;             paras:=nil;{$ifdef MEMDEBUG}             memprocpara.stop;{$endif MEMDEBUG}          end;         if assigned(parast) then          begin{$ifdef MEMDEBUG}            memprocparast.start;{$endif MEMDEBUG}            parast.free;            parast:=nil;{$ifdef MEMDEBUG}            memprocparast.stop;{$endif MEMDEBUG}          end;         funcretloc[callerside].done;         funcretloc[calleeside].done;         inherited destroy;      end;    procedure tabstractprocdef.count_para(p:TObject;arg:pointer);      begin        if (tsym(p).typ<>paravarsym) then          exit;        inc(plongint(arg)^);        if not(vo_is_hidden_para in tparavarsym(p).varoptions) then         begin           if not assigned(tparavarsym(p).defaultconstsym) then             inc(minparacount);           inc(maxparacount);         end;      end;    procedure tabstractprocdef.insert_para(p:TObject;arg:pointer);      begin        if (tsym(p).typ<>paravarsym) then          exit;        paras.add(p);      end;    procedure tabstractprocdef.calcparas;      var        paracount : longint;      begin        { This can already be assigned when          we need to reresolve this unit (PFV) }        if assigned(paras) then          paras.free;        paras:=tparalist.create(false);        paracount:=0;        minparacount:=0;        maxparacount:=0;        parast.SymList.ForEachCall(@count_para,@paracount);        paras.capacity:=paracount;        { Insert parameters in table }        parast.SymList.ForEachCall(@insert_para,nil);        { Order parameters }        paras.sortparas;      end;    function tabstractprocdef.mangledprocparanames(oldlen : longint) : string;      var        hash  : qword;        hp   : TParavarsym;        hs   : TSymStr;        newlen,        i    : integer;      begin        result:='';        hp:=nil;        { add parameter types }        for i:=0 to paras.count-1 do         begin           hp:=tparavarsym(paras[i]);           if not(vo_is_hidden_para in hp.varoptions) then             result:=result+'$'+hp.vardef.mangledparaname;         end;        { add resultdef, add $$ as separator to make it unique from a          parameter separator }        if not is_void(returndef) then          result:=result+'$$'+returndef.mangledparaname;        newlen:=length(result)+oldlen;        { Replace with hash if the parameter line is very long }        if (newlen-oldlen>12) and           ((newlen>100) or (newlen-oldlen>64)) then          begin            hash:=0;            for i:=0 to paras.count-1 do              begin                hp:=tparavarsym(paras[i]);                if not(vo_is_hidden_para in hp.varoptions) then                  begin                    hs:=hp.vardef.mangledparaname;                    hash:=UpdateFnv64(hash,hs[1],length(hs));                  end;              end;            if not is_void(returndef) then              begin                { add a little prefix so that x(integer; integer) is different from x(integer):integer }                hs:='$$'+returndef.mangledparaname;                hash:=UpdateFnv64(hash,hs[1],length(hs));              end;            result:='$h'+Base64Mangle(hash);          end;      end;    procedure tabstractprocdef.buildderef;      begin         { released procdef? }         if not assigned(parast) then           exit;         inherited buildderef;         returndefderef.build(returndef);         if po_explicitparaloc in procoptions then           funcretloc[callerside].buildderef;         { parast }         tparasymtable(parast).buildderef;      end;    procedure tabstractprocdef.deref;      begin         inherited deref;         returndef:=tdef(returndefderef.resolve);         if po_explicitparaloc in procoptions then           begin             funcretloc[callerside].deref;             has_paraloc_info:=callerside;            end         else           begin             { deref is called after loading from a ppu, but also after another               unit has been reloaded/recompiled and all references must be               re-resolved. Since the funcretloc contains a reference to a tdef,               reset it so that we won't try to access the stale def }             funcretloc[callerside].init;             has_paraloc_info:=callnoside;           end;         { parast }         tparasymtable(parast).deref(false);         { recalculated parameters }         calcparas;      end;    constructor tabstractprocdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);      begin         inherited ppuload(dt,ppufile);         parast:=nil;         Paras:=nil;         minparacount:=0;         maxparacount:=0;         ppufile.getderef(returndefderef);         proctypeoption:=tproctypeoption(ppufile.getbyte);         proccalloption:=tproccalloption(ppufile.getbyte);         ppufile.getset(tppuset8(procoptions));         funcretloc[callerside].init;         if po_explicitparaloc in procoptions then           funcretloc[callerside].ppuload(ppufile);         savesize:=sizeof(pint);         if (po_explicitparaloc in procoptions) then           has_paraloc_info:=callerside;      end;    procedure tabstractprocdef.ppuwrite(ppufile:tcompilerppufile);      var        oldintfcrc : boolean;      begin         { released procdef? }         if not assigned(parast) then           exit;         inherited ppuwrite(ppufile);         ppufile.putderef(returndefderef);         oldintfcrc:=ppufile.do_interface_crc;         ppufile.do_interface_crc:=false;         ppufile.putbyte(ord(proctypeoption));         ppufile.putbyte(ord(proccalloption));         ppufile.putset(tppuset8(procoptions));         ppufile.do_interface_crc:=oldintfcrc;         if (po_explicitparaloc in procoptions) then           funcretloc[callerside].ppuwrite(ppufile);      end;    function tabstractprocdef.typename_paras(pno: tprocnameoptions) : ansistring;      var        hs,s  : ansistring;        hp    : TParavarsym;        hpc   : tconstsym;        first : boolean;        i,j   : integer;      begin        s:='';        first:=true;        for i:=0 to paras.count-1 do         begin           hp:=tparavarsym(paras[i]);           if not(vo_is_hidden_para in hp.varoptions) or              (pno_showhidden in pno) then            begin               if first then                begin                  s:=s+'(';                  first:=false;                end               else                s:=s+';';               if vo_is_hidden_para in hp.varoptions then                 s:=s+'<';               case hp.varspez of                 vs_var :                   s:=s+'var ';                 vs_const :                   s:=s+'const ';                 vs_out :                   s:=s+'out ';                 vs_constref :                   s:=s+'constref ';                 else                   ;               end;               if (pno_paranames in pno) then                 s:=s+hp.realname+':';               if hp.univpara then                 s:=s+'univ ';               if assigned(hp.vardef.typesym) then                 begin                   hs:=hp.vardef.typesym.realname;                   if hs[1]<>'$' then                     s:=s+hp.vardef.OwnerHierarchyName+hs                   else                     s:=s+hp.vardef.GetTypeName;                 end               else                 s:=s+hp.vardef.GetTypeName;               { default value }               if assigned(hp.defaultconstsym) then                begin                  hpc:=tconstsym(hp.defaultconstsym);                  hs:='';                  case hpc.consttyp of                    constwstring:                      begin                        if pcompilerwidestring(hpc.value.valueptr)^.len>0 then                          begin                            setlength(hs,pcompilerwidestring(hpc.value.valueptr)^.len);                            for j:=0 to pcompilerwidestring(hpc.value.valueptr)^.len-1 do                             begin                               if (ord(pcompilerwidestring(hpc.value.valueptr)^.data[j])<127) and                                  not(byte(pcompilerwidestring(hpc.value.valueptr)^.data[j]) in [0,10,13]) then                                 hs[j+1]:=char(pcompilerwidestring(hpc.value.valueptr)^.data[j])                               else                                 hs[j+1]:='.';                             end;                          end;                      end;                    conststring,                    constresourcestring :                      begin                        if hpc.value.len>0 then                          begin                            setLength(hs,hpc.value.len);                            { don't write past the end of hs if the constant                              is > 255 chars }                            move(hpc.value.valueptr^,hs[1],length(hs));                            { make sure that constant strings with newline chars                              don't create a linebreak in the assembler code,                              since comments are line-based. Also remove nulls                              because the comments are written as a pchar. }                            ReplaceCase(hs,#0,'.');                            ReplaceCase(hs,#10,'.');                            ReplaceCase(hs,#13,'.');                          end;                      end;                    constreal :                      str(pbestreal(hpc.value.valueptr)^,hs);                    constpointer :                      hs:=tostr(hpc.value.valueordptr);                    constord :                      begin                        if is_boolean(hpc.constdef) then                          begin                            if hpc.value.valueord<>0 then                             hs:='TRUE'                            else                             hs:='FALSE';                          end                        else                          hs:=tostr(hpc.value.valueord);                      end;                    constnil :                      hs:='nil';                    constset :                      hs:='<set>';                    constguid:                      hs:=guid2string(pguid(hpc.value.valueptr)^);                    constnone:                      internalerror(2019050704);                  end;                  if hs<>'' then                   s:=s+'=`'+hs+'`';                end;               if vo_is_hidden_para in hp.varoptions then                 s:=s+'>';             end;         end;        if not first then         s:=s+')';        if (po_varargs in procoptions) then         s:=s+';VarArgs';        typename_paras:=s;      end;    function tabstractprocdef.is_methodpointer:boolean;      begin        result:=false;      end;    function tabstractprocdef.is_addressonly:boolean;      begin        result:=true;      end;    function tabstractprocdef.no_self_node: boolean;      begin        Result:=([po_staticmethod,po_classmethod]<=procoptions)or                (proctypeoption in [potype_class_constructor,potype_class_destructor,potype_operator]);      end;    function tabstractprocdef.getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef;      var        j, nestinglevel: longint;        pvs, npvs: tparavarsym;      begin        nestinglevel:=parast.symtablelevel;        if newtyp=procdef then          begin            if (copytyp<>pc_bareproc) then              result:=cprocdef.create(nestinglevel,doregister)            else              result:=cprocdef.create(normal_function_level,doregister);            tprocdef(result).visibility:=vis_public;          end        else          begin            result:=cprocvardef.create(nestinglevel,true);          end;        tabstractprocdef(result).returndef:=returndef;        tabstractprocdef(result).returndefderef:=returndefderef;        pvs:=nil;        npvs:=nil;        if copytyp<>pc_normal_no_paras then          begin            for j:=0 to parast.symlist.count-1 do              begin                case tsym(parast.symlist[j]).typ of                  paravarsym:                    begin                      pvs:=tparavarsym(parast.symlist[j]);                      { in case of bare proc, don't copy self, vmt or framepointer                        parameters }                      if (copytyp in [pc_bareproc,pc_normal_no_hidden]) and                         (([vo_is_self,vo_is_vmt,vo_is_parentfp,vo_is_result,vo_is_funcret,vo_is_high_para]*pvs.varoptions)<>[]) then                        continue;                      if paraprefix='' then                        npvs:=cparavarsym.create(pvs.realname,pvs.paranr,pvs.varspez,                          pvs.vardef,pvs.varoptions)                      else if not(vo_is_high_para in pvs.varoptions) then                        npvs:=cparavarsym.create(paraprefix+pvs.realname,pvs.paranr,pvs.varspez,                          pvs.vardef,pvs.varoptions)                      else                        npvs:=cparavarsym.create('$high'+paraprefix+copy(pvs.name,5,length(pvs.name)),pvs.paranr,pvs.varspez,                          pvs.vardef,pvs.varoptions);                      npvs.defaultconstsym:=pvs.defaultconstsym;                      tabstractprocdef(result).parast.insertsym(npvs);                    end;                  constsym:                    begin                      // ignore, reuse original constym. Should also be duplicated                      // be safe though                    end;                  symconst.typesym:                    begin                      // reuse original, part of generic declaration                    end                  else                    internalerror(201160604);                  end;              end;          end;        tabstractprocdef(result).savesize:=savesize;        if (typ<>procvardef) and           (newtyp=procvardef) then          begin            { procvars can't be (class)constructures/destructors etc }            if proctypeoption=potype_constructor then              begin                tabstractprocdef(result).returndef:=tdef(owner.defowner);                if not(is_implicit_pointer_object_type(returndef) or                   (returndef.typ<>objectdef)) then                  tabstractprocdef(result).returndef:=cpointerdef.getreusable(tabstractprocdef(result).returndef);                tabstractprocdef(result).proctypeoption:=potype_function;              end            else if is_void(returndef) then              tabstractprocdef(result).proctypeoption:=potype_procedure            else              tabstractprocdef(result).proctypeoption:=potype_function;          end        else          tabstractprocdef(result).proctypeoption:=proctypeoption;        tabstractprocdef(result).proccalloption:=proccalloption;        tabstractprocdef(result).procoptions:=procoptions;        if (copytyp=pc_bareproc) then          tabstractprocdef(result).procoptions:=tabstractprocdef(result).procoptions*[po_explicitparaloc,po_hascallingconvention,po_varargs,po_iocheck,po_has_importname,po_has_importdll];        if newtyp=procvardef then          tabstractprocdef(result).procoptions:=tabstractprocdef(result).procoptions-[po_has_importname,po_has_importdll];        if copytyp=pc_address_only then          include(tabstractprocdef(result).procoptions,po_addressonly);        tabstractprocdef(result).callerargareasize:=callerargareasize;        tabstractprocdef(result).calleeargareasize:=calleeargareasize;        tabstractprocdef(result).maxparacount:=maxparacount;        tabstractprocdef(result).minparacount:=minparacount;        if po_explicitparaloc in procoptions then          tabstractprocdef(result).funcretloc[callerside]:=funcretloc[callerside].getcopy;        { recalculate parameter info }        tabstractprocdef(result).has_paraloc_info:=callnoside;{$ifdef m68k}        tabstractprocdef(result).exp_funcretloc:=exp_funcretloc;{$endif}        if (typ=procdef) and           (newtyp=procvardef) and           (owner.symtabletype in [ObjectSymtable,recordsymtable]) then          include(tprocvardef(result).procoptions,po_methodpointer);      end;    function tabstractprocdef.compatible_with_pointerdef_size(ptr: tpointerdef): boolean;      begin        result:=is_addressonly;      end;    procedure tabstractprocdef.check_mark_as_nested;      begin         { nested procvars require that nested functions use the Delphi-style           nested procedure calling convention }         if (parast.symtablelevel>normal_function_level) and            (m_nested_procvars in current_settings.modeswitches) then           include(procoptions,po_delphi_nested_cc);      end;    procedure tabstractprocdef.init_paraloc_info(side: tcallercallee);      begin        if (side in [callerside,callbothsides]) and           not(has_paraloc_info in [callerside,callbothsides]) then          begin            if not is_c_variadic(self) then              callerargareasize:=paramanager.create_paraloc_info(self,callerside)            else              callerargareasize:=paramanager.create_varargs_paraloc_info(self,callerside,nil);            if has_paraloc_info in [calleeside,callbothsides] then              has_paraloc_info:=callbothsides            else              has_paraloc_info:=callerside;          end;        if (side in [calleeside,callbothsides]) and           not(has_paraloc_info in [calleeside,callbothsides]) then          begin            if not is_c_variadic(self) then              calleeargareasize:=paramanager.create_paraloc_info(self,calleeside)            else              callerargareasize:=paramanager.create_varargs_paraloc_info(self,calleeside,nil);            if has_paraloc_info in [callerside,callbothsides] then              has_paraloc_info:=callbothsides            else              has_paraloc_info:=calleeside;          end;      end;    procedure tabstractprocdef.done_paraloc_info(side: tcallercallee);      var        i: longint;      begin        if (side in [callerside,callbothsides]) and           (has_paraloc_info in [callerside,callbothsides]) then          begin            funcretloc[callerside].done;            for i:=0 to paras.count-1 do              tparavarsym(paras[i]).paraloc[callerside].done;            if has_paraloc_info=callerside then              has_paraloc_info:=callnoside            else              has_paraloc_info:=calleeside;          end;        if (side in [calleeside,callbothsides]) and           (has_paraloc_info in [calleeside,callbothsides]) then          begin            funcretloc[calleeside].done;            for i:=0 to paras.count-1 do              tparavarsym(paras[i]).paraloc[calleeside].done;            if has_paraloc_info=calleeside then              has_paraloc_info:=callnoside            else              has_paraloc_info:=callerside;          end;      end;    function tabstractprocdef.stack_tainting_parameter(side: tcallercallee): boolean;      var        p: tparavarsym;        ploc: PCGParalocation;        i: longint;      begin        result:=false;        init_paraloc_info(side);        for i:=0 to parast.SymList.Count-1 do          if tsym(parast.SymList[i]).typ=paravarsym then            begin              p:=tparavarsym(parast.SymList[i]);              if not p.is_used then                continue;              { check if no parameter is located on the stack }              if (is_open_array(p.vardef) or                 is_array_of_const(p.vardef)) and (p.varspez=vs_value) then                begin                  result:=true;                  exit;                end;              ploc:=p.paraloc[side].location;              while assigned(ploc) do                begin                  if (ploc^.loc=LOC_REFERENCE) then                    begin                      result:=true;                      exit                    end;                  ploc:=ploc^.next;                end;            end;      end;    function tabstractprocdef.is_pushleftright: boolean;      begin        result:=false;      end;    function tabstractprocdef.address_type: tdef;      begin        result:=voidcodepointertype;      end;    function tabstractprocdef.ofs_address_type:tdef;      begin        result:=address_type;      end;    procedure tabstractprocdef.declared_far;      begin        Message1(parser_w_proc_directive_ignored,'FAR');      end;    procedure tabstractprocdef.declared_near;      begin        Message1(parser_w_proc_directive_ignored,'NEAR');      end;    function tabstractprocdef.generate_safecall_wrapper: boolean;      begin{$ifdef SUPPORT_SAFECALL}        result:=          (proccalloption=pocall_safecall) and          not(po_assembler in procoptions) and          (tf_safecall_exceptions in target_info.flags);{$else SUPPORT_SAFECALL}        result:=false;{$endif}      end;    function tabstractprocdef.is_generic_param(def:tdef): boolean;      begin        if def.typ=undefineddef then          result:=def.owner=self.parast        else if def.typ=objectdef then          result:=(def.owner=self.parast) and (tstoreddef(def).genconstraintdata<>nil)        else          result:=false;      end;    function tabstractprocdef.wpo_may_create_instance(optionalmethodpointer: tnode): boolean;      begin        result:=          (proctypeoption=potype_constructor) or          ((typ=procdef) and           ((not assigned(optionalmethodpointer) and             is_class(tdef(owner.defowner))) or            (assigned(optionalmethodpointer) and             ((optionalmethodpointer.resultdef.typ=classrefdef) or              (optionalmethodpointer.nodetype=typen)))) and           (tprocdef(self).procsym.Name='NEWINSTANCE'))      end;{***************************************************************************                                  TPROCDEF***************************************************************************}    function tprocdef.getparentfpsym: tsym;      begin        if not assigned(_parentfpsym) then          begin            _parentfpsym:=tsym(parast.Find('parentfp'));            if not assigned(_parentfpsym) then              internalerror(200309281);          end;        result:=_parentfpsym;      end;    function tprocdef.Getis_implemented: boolean;      begin        result:=not assigned(implprocdefinfo) or implprocdefinfo^.is_implemented;      end;    procedure tprocdef.Setis_implemented(AValue: boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2020062101);        implprocdefinfo^.is_implemented:=AValue;      end;    function tprocdef.getwas_anonymous:boolean;      begin        result:=assigned(implprocdefinfo) and implprocdefinfo^.was_anonymous;      end;    procedure tprocdef.setwas_anonymous(avalue:boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2022020502);        implprocdefinfo^.was_anonymous:=avalue;      end;    function tprocdef.gethas_capturer:boolean;      begin        result:=assigned(implprocdefinfo) and implprocdefinfo^.has_capturer;      end;    procedure tprocdef.sethas_capturer(avalue:boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2022020503);        implprocdefinfo^.has_capturer:=avalue;      end;    function tprocdef.Getcapturedsyms:tfplist;      begin        if not assigned(implprocdefinfo) then          result:=nil        else          result:=implprocdefinfo^.capturedsyms;      end;    function tprocdef.store_localst: boolean;      begin        result:=has_inlininginfo or (df_generic in defoptions);      end;    function tprocdef.GetResultName: PShortString;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010301);        result:=implprocdefinfo^.resultname;      end;    procedure tprocdef.SetResultName(AValue: PShortString);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010302);        implprocdefinfo^.resultname:=AValue;      end;    function tprocdef.GetParentFPInitBlock: tnode;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010303);        result:=implprocdefinfo^.parentfpinitblock;      end;    function tprocdef.GetParentFPStruct: tsym;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010304);        result:=implprocdefinfo^.parentfpstruct;      end;    function tprocdef.GetParentFPStructPtrType: tdef;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010305);        result:=implprocdefinfo^.parentfpstructptrtype;      end;    procedure tprocdef.SetParentFPInitBlock(AValue: tnode);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010306);        implprocdefinfo^.parentfpinitblock:=AValue;      end;    function tprocdef.Getprocendtai: tai;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010307);        result:=implprocdefinfo^.procendtai;      end;    function tprocdef.Getprocstarttai: tai;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010308);        result:=implprocdefinfo^.procstarttai;      end;    procedure tprocdef.Setprocendtai(AValue: tai);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010309);        implprocdefinfo^.procendtai:=AValue;      end;    function tprocdef.Getskpara: pointer;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010310);        result:=implprocdefinfo^.skpara;      end;    procedure tprocdef.Setskpara(AValue: pointer);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010311);        implprocdefinfo^.skpara:=AValue;      end;    function tprocdef.Getpersonality: tprocdef;      begin        if not assigned(implprocdefinfo) then          internalerror(2016121704);         result:=implprocdefinfo^.personality;      end;    procedure tprocdef.Setpersonality(AValue: tprocdef);      begin        if not assigned(implprocdefinfo) then          internalerror(2016121705);        implprocdefinfo^.personality:=AValue;      end;    function tprocdef.Getforwarddef: boolean;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010312);        result:=implprocdefinfo^.forwarddef;      end;    function tprocdef.Gethasforward: boolean;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010313);        result:=implprocdefinfo^.hasforward;      end;    function tprocdef.Getinterfacedef: boolean;      begin        if not assigned(implprocdefinfo) then          internalerror(2014010314);        result:=implprocdefinfo^.interfacedef;      end;    procedure tprocdef.Setforwarddef(AValue: boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010315);        implprocdefinfo^.forwarddef:=AValue;      end;    procedure tprocdef.Sethasforward(AValue: boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010316);        implprocdefinfo^.hasforward:=AValue;      end;    function tprocdef.GetIsEmpty: boolean;      begin        result:=pio_empty in implprocoptions;      end;    procedure tprocdef.SetIsEmpty(AValue: boolean);      begin        if AValue then          include(implprocoptions,pio_empty)        else          exclude(implprocoptions,pio_empty);      end;    function tprocdef.GetHasInliningInfo: boolean;      begin        result:=pio_has_inlininginfo in implprocoptions;      end;    procedure tprocdef.SetHasInliningInfo(AValue: boolean);      begin        if AValue then          include(implprocoptions,pio_has_inlininginfo)        else          exclude(implprocoptions,pio_has_inlininginfo);      end;    procedure tprocdef.Setinterfacedef(AValue: boolean);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010317);        implprocdefinfo^.interfacedef:=AValue;      end;    procedure tprocdef.Setprocstarttai(AValue: tai);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010318);        implprocdefinfo^.procstarttai:=AValue;      end;    procedure tprocdef.SetParentFPStruct(AValue: tsym);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010319);        implprocdefinfo^.parentfpstruct:=AValue;      end;    procedure tprocdef.SetParentFPStructPtrType(AValue: tdef);      begin        if not assigned(implprocdefinfo) then          internalerror(2014010320);        implprocdefinfo^.parentfpstructptrtype:=AValue;      end;    constructor tprocdef.create(level:byte;doregister:boolean);      begin         inherited create(procdef,level,doregister);         implprocdefinfo:=allocmem(sizeof(implprocdefinfo^));         localst:=tlocalsymtable.create(self,parast.symtablelevel);{$ifdef symansistr}         _mangledname:='';{$else symansistr}         _mangledname:=nil;{$endif symansistr}{$ifndef DISABLE_FAST_OVERLOAD_PATCH}         seenmarker := nil;{$endif}         fileinfo:=current_filepos;         extnumber:=$ffff;         aliasnames:=TCmdStrList.create;         funcretsym:=nil;         funcretsymderef.reset;         procsymderef.reset;         forwarddef:=true;         interfacedef:=false;         hasforward:=false;         struct := nil;         structderef.reset;         import_dll:=nil;         import_name:=nil;         import_nr:=0;         inlininginfo:=nil;         deprecatedmsg:=nil;         genericdecltokenbuf:=nil;         if cs_opt_fastmath in current_settings.optimizerswitches then           include(implprocoptions, pio_fastmath);      end;    constructor tprocdef.ppuload(ppufile:tcompilerppufile);      var        i,aliasnamescount,sizeleft : longint;        level : byte;        buf : array[0..255] of byte;      begin         inherited ppuload(procdef,ppufile);{$ifdef symansistr}         if po_has_mangledname in procoptions then           _mangledname:=ppufile.getansistring         else           _mangledname:='';{$else symansistr}         if po_has_mangledname in procoptions then          _mangledname:=ppufile.getpshortstring         else          _mangledname:=nil;{$endif symansistr}         extnumber:=ppufile.getword;         level:=ppufile.getbyte;         ppufile.getderef(structderef);         ppufile.getderef(procsymderef);         ppufile.getposinfo(fileinfo);         visibility:=tvisibility(ppufile.getbyte);         ppufile.getset(tppuset2(symoptions));         if sp_has_deprecated_msg in symoptions then           deprecatedmsg:=ppufile.getpshortstring         else           deprecatedmsg:=nil;         { import stuff }         if po_has_importdll in procoptions then           import_dll:=ppufile.getpshortstring         else           import_dll:=nil;         if po_has_importname in procoptions then           import_name:=ppufile.getpshortstring         else           import_name:=nil;         import_nr:=ppufile.getword;         if (po_msgint in procoptions) then           messageinf.i:=ppufile.getlongint;         if (po_msgstr in procoptions) then           messageinf.str:=ppufile.getpshortstring;         if (po_dispid in procoptions) then           dispid:=ppufile.getlongint;         { inline stuff }         ppufile.getset(tppuset1(implprocoptions));         if has_inlininginfo then           begin             ppufile.getderef(funcretsymderef);             new(inlininginfo);             ppufile.getset(tppuset4(inlininginfo^.flags));           end         else           begin             inlininginfo:=nil;             funcretsym:=nil;           end;         aliasnames:=TCmdStrList.create;         { count alias names }         aliasnamescount:=ppufile.getbyte;         for i:=1 to aliasnamescount do           aliasnames.insert(ppufile.getstring);         { load the token stream containing the declaration }         sizeleft:=ppufile.getlongint;         if sizeleft>0 then           begin             init_genericdecl;             while sizeleft>0 do               begin                 if sizeleft>sizeof(buf) then                   i:=sizeof(buf)                 else                   i:=sizeleft;                 ppufile.getdata(buf,i);                 genericdecltokenbuf.write(buf,i);                 dec(sizeleft,i);               end;           end;         ppuload_platform(ppufile);         { load para symtable }         parast:=tparasymtable.create(self,level);         tparasymtable(parast).ppuload(ppufile);         { load local symtable }         if store_localst then          begin            localst:=tlocalsymtable.create(self,level);            tlocalsymtable(localst).ppuload(ppufile);          end         else          localst:=nil;         { inline stuff }         if has_inlininginfo then           inlininginfo^.code:=ppuloadnodetree(ppufile);         { default values for no persistent data }         if (cs_link_deffile in current_settings.globalswitches) and            (tf_need_export in target_info.flags) and            (po_exports in procoptions) then           deffile.AddExport(mangledname);         { Disable po_has_inlining until the derefimpl is done }         has_inlininginfo:=false;      end;    destructor tprocdef.destroy;      begin         aliasnames.free;         aliasnames:=nil;         if assigned(localst) and           (localst.symtabletype<>staticsymtable) then          begin{$ifdef MEMDEBUG}            memproclocalst.start;{$endif MEMDEBUG}            localst.free;            localst:=nil;{$ifdef MEMDEBUG}            memproclocalst.start;{$endif MEMDEBUG}          end;         if assigned(inlininginfo) then          begin{$ifdef MEMDEBUG}            memprocnodetree.start;{$endif MEMDEBUG}            tnode(inlininginfo^.code).free;{$ifdef MEMDEBUG}            memprocnodetree.start;{$endif MEMDEBUG}            dispose(inlininginfo);            inlininginfo:=nil;          end;         freeimplprocdefinfo;         genericdecltokenbuf.free;         genericdecltokenbuf:=nil;         stringdispose(import_dll);         stringdispose(import_name);         stringdispose(deprecatedmsg);         if (po_msgstr in procoptions) then           stringdispose(messageinf.str);{$ifndef symansistr}         if assigned(_mangledname) then          begin{$ifdef MEMDEBUG}            memmanglednames.start;{$endif MEMDEBUG}            stringdispose(_mangledname);{$ifdef MEMDEBUG}            memmanglednames.stop;{$endif MEMDEBUG}          end;{$endif symansistr}         inherited destroy;      end;    procedure tprocdef.freeimplprocdefinfo;      var        i : longint;      begin        if assigned(implprocdefinfo) then          begin            stringdispose(implprocdefinfo^.resultname);            if assigned(implprocdefinfo^.capturedsyms) then              begin                for i:=0 to implprocdefinfo^.capturedsyms.count-1 do                  dispose(pcapturedsyminfo(implprocdefinfo^.capturedsyms[i]));              end;            implprocdefinfo^.capturedsyms.free;            implprocdefinfo^.capturedsyms:=nil;            freemem(implprocdefinfo);            implprocdefinfo:=nil;          end;      end;    procedure tprocdef.ppuwrite(ppufile:tcompilerppufile);      var        oldintfcrc : boolean;        aliasnamescount,i,sizeleft : longint;        item : TCmdStrListItem;        buf : array[0..255] of byte;      begin         { released procdef? }         if not assigned(parast) then           exit;         inherited ppuwrite(ppufile);{$ifdef symansistr}         if po_has_mangledname in procoptions then           ppufile.putansistring(_mangledname);{$else symansistr}         if po_has_mangledname in procoptions then          ppufile.putstring(_mangledname^);{$endif symansistr}         ppufile.putword(extnumber);         ppufile.putbyte(parast.symtablelevel);         ppufile.putderef(structderef);         ppufile.putderef(procsymderef);         ppufile.putposinfo(fileinfo);         ppufile.putbyte(byte(visibility));         ppufile.putset(tppuset2(symoptions));         if sp_has_deprecated_msg in symoptions then           ppufile.putstring(deprecatedmsg^);         { import }         if po_has_importdll in procoptions then           ppufile.putstring(import_dll^);         if po_has_importname in procoptions then           ppufile.putstring(import_name^);         ppufile.putword(import_nr);         if (po_msgint in procoptions) then           ppufile.putlongint(messageinf.i);         if (po_msgstr in procoptions) then           ppufile.putstring(messageinf.str^);         if (po_dispid in procoptions) then           ppufile.putlongint(dispid);         { inline stuff }         oldintfcrc:=ppufile.do_crc;         ppufile.do_crc:=false;         ppufile.putset(tppuset1(implprocoptions));         if has_inlininginfo then           begin             ppufile.putderef(funcretsymderef);             ppufile.putset(tppuset4(inlininginfo^.flags));           end;         { count alias names }         aliasnamescount:=0;         item:=TCmdStrListItem(aliasnames.first);         while assigned(item) do           begin             inc(aliasnamescount);             item:=TCmdStrListItem(item.next);           end;         if aliasnamescount>255 then           internalerror(200711021);         ppufile.putbyte(aliasnamescount);         item:=TCmdStrListItem(aliasnames.first);         while assigned(item) do          begin            ppufile.putstring(item.str);            item:=TCmdStrListItem(item.next);          end;         ppufile.do_crc:=oldintfcrc;         { generic tokens for the declaration }         if assigned(genericdecltokenbuf) and (genericdecltokenbuf.size>0) then           begin             sizeleft:=genericdecltokenbuf.size;             genericdecltokenbuf.seek(0);             ppufile.putlongint(sizeleft);             while sizeleft>0 do               begin                 if sizeleft>sizeof(buf) then                   i:=sizeof(buf)                 else                   i:=sizeleft;                 genericdecltokenbuf.read(buf,i);                 ppufile.putdata(buf,i);                 dec(sizeleft,i);               end;           end         else           ppufile.putlongint(0);         { write this entry }         writeentry(ppufile,ibprocdef);         { Save the para symtable, this is taken from the interface }         tparasymtable(parast).ppuwrite(ppufile);         { save localsymtable for inline procedures or when local           browser info is requested, this has no influence on the crc }         if store_localst and not ppufile.crc_only then          begin            oldintfcrc:=ppufile.do_crc;            ppufile.do_crc:=false;            tlocalsymtable(localst).ppuwrite(ppufile);            ppufile.do_crc:=oldintfcrc;          end;         { node tree for inlining }         oldintfcrc:=ppufile.do_crc;         ppufile.do_crc:=false;         if has_inlininginfo then           ppuwritenodetree(ppufile,inlininginfo^.code);         ppufile.do_crc:=oldintfcrc;      end;    function tprocdef.fullprocname(showhidden:boolean):string;      var        pno: tprocnameoptions;      begin        pno:=[];        if showhidden then          include(pno,pno_showhidden);        result:=customprocname(pno);      end;    function tprocdef.customprocname(pno: tprocnameoptions):ansistring;      var        s, hs, rn : ansistring;        t : ttoken;	module : tmodule;        syssym : tsyssym;      begin{$ifdef EXTDEBUG}        include(pno,pno_showhidden);{$endif EXTDEBUG}        s:='';        rn:='';        if proctypeoption=potype_operator then          begin            for t:=NOTOKEN to last_overloaded do              if procsym.realname='$'+overloaded_names[t] then                begin                  s:='operator ';                  if (pno_ownername in pno) and                     assigned(struct) then                    s:=s+struct.RttiName+'.';                  s:=s+arraytokeninfo[t].str;                  if not (pno_noparams in pno) then                    s:=s+typename_paras(pno);                  break;                end;          end        else          begin            if (po_classmethod in procoptions) and               not(pno_noclassmarker in pno) then              s:='class ';            case proctypeoption of              potype_constructor,              potype_class_constructor:                s:=s+'constructor ';              potype_class_destructor,              potype_destructor:                s:=s+'destructor ';              else                if (pno_proctypeoption in pno) and not (po_anonymous in procoptions) then                  begin                   if assigned(returndef) and                     not(is_void(returndef)) then                     s:=s+'function '                   else                     s:=s+'procedure ';                  end;            end;            if (pno_ownername in pno) and               (owner.symtabletype in [recordsymtable,objectsymtable]) then              s:=s+tabstractrecorddef(owner.defowner).RttiName+'.';            if (po_compilerproc in procoptions) and (extnumber<>$ffff) then              begin                syssym:=tsyssym.find_by_number(extnumber);                if not assigned(syssym) then                  internalerror(2016060305);                rn:=syssym.realname;              end            else if po_anonymous in procoptions then              begin                s:=s+'anonymous ';                if assigned(returndef) and                  not(is_void(returndef)) then                  s:=s+'function'                else                  s:=s+'procedure';              end            else if pno_prettynames in pno then              rn:=procsym.prettyname            else              rn:=procsym.RealName;            if (pno_noleadingdollar in pno) and               (rn[1]='$') then              delete(rn,1,1);            s:=s+rn;            if not (pno_noparams in pno) then              s:=s+typename_paras(pno);          end;        if not(proctypeoption in [potype_constructor,potype_destructor,             potype_class_constructor,potype_class_destructor]) and           assigned(returndef) and           not(is_void(returndef)) then          begin            if assigned(returndef.typesym) then              begin                module:=find_module_from_symtable(returndef.typesym.owner);		if module <> current_module then                  s:=s+':'+module.realmodulename^+'.'                else	          s:=s+':';                if pno_prettynames in pno then                  hs:=returndef.typesym.prettyname                else                  hs:=returndef.typesym.realname;                if hs[1]<>'$' then                  s:=s+returndef.OwnerHierarchyName+hs                else                  s:=s+returndef.GetTypeName;              end            else              s:=s+':'+returndef.GetTypeName;	  end;        if not (po_anonymous in procoptions) then          if assigned(owner) and (owner.symtabletype=localsymtable) then            s:=s+' is nested'          else if po_is_block in procoptions then            s:=s+' is block';        s:=s+';';        if po_far in procoptions then          s:=s+' far;';        { forced calling convention? }        if (po_hascallingconvention in procoptions) then          s:=s+' '+ProcCallOptionStr[proccalloption]+';';        if (po_staticmethod in procoptions) and           not (proctypeoption in [potype_class_constructor,potype_class_destructor]) then          s:=s+' Static;';        if pno_mangledname in pno then          s:=s+' -- mangled name: '+mangledname;        customprocname:=s;      end;    function tprocdef.is_methodpointer:boolean;      begin        { don't check assigned(_class), that's also the case for nested          procedures inside methods }        result:=(owner.symtabletype in [recordsymtable,ObjectSymtable]) and not no_self_node;      end;    function tprocdef.is_addressonly:boolean;      begin        result:=assigned(owner) and                not is_methodpointer and                (not(m_nested_procvars in current_settings.modeswitches) or                 not is_nested_pd(self)) and                 (                   not (po_anonymous in procoptions) or                   not assigned(capturedsyms) or                   (capturedsyms.count=0)                 );      end;    procedure tprocdef.make_external;      begin        include(procoptions,po_external);        forwarddef:=false;      end;    procedure tprocdef.init_genericdecl;      begin        if assigned(genericdecltokenbuf) then          internalerror(2015061901);        genericdecltokenbuf:=tdynamicarray.create(256);      end;    function tprocdef.get_funcretsym_info(out ressym: tsym; out resdef: tdef): boolean;      begin        result:=false;        if proctypeoption=potype_constructor then          begin            result:=true;            ressym:=tsym(parast.Find('self'));            resdef:=tabstractnormalvarsym(ressym).vardef;            { and TP-style constructors return a pointer to self }            if is_object(resdef) then              resdef:=cpointerdef.getreusable(resdef);          end        else if (proccalloption=pocall_safecall) and           (tf_safecall_exceptions in target_info.flags) then          begin            result:=true;            ressym:=tsym(localst.Find('safecallresult'));            resdef:=tabstractnormalvarsym(ressym).vardef;          end        else if not is_void(returndef) then          begin            result:=true;            ressym:=funcretsym;            resdef:=tabstractnormalvarsym(ressym).vardef;          end;      end;    function tprocdef.get_safecall_funcretsym_info(out ressym: tsym; out resdef: tdef): boolean;      begin        result:=false;        if (proctypeoption<>potype_constructor) and           (proccalloption=pocall_safecall) and           (tf_safecall_exceptions in target_info.flags) then          begin            result:=true;            ressym:=tsym(localst.Find('safecallresult'));            resdef:=tabstractnormalvarsym(ressym).vardef;          end      end;    procedure tprocdef.add_captured_sym(sym:tsym;const filepos:tfileposinfo);      var        i : longint;        capturedsym : pcapturedsyminfo;      begin        if not assigned(implprocdefinfo) then          internalerror(2021052601);        if not assigned(implprocdefinfo^.capturedsyms) then          implprocdefinfo^.capturedsyms:=tfplist.create;        for i:=0 to implprocdefinfo^.capturedsyms.count-1 do          begin            capturedsym:=pcapturedsyminfo(implprocdefinfo^.capturedsyms[i]);            if capturedsym^.sym=sym then              exit;          end;        new(capturedsym);        capturedsym^.sym:=sym;        capturedsym^.fileinfo:=filepos;        implprocdefinfo^.capturedsyms.add(capturedsym);      end;    function tprocdef.has_alias_name(const s: TSymStr): boolean;      var        item : TCmdStrListItem;      begin        result:=true;        if mangledname=s then          exit;        item:=TCmdStrListItem(aliasnames.first);        while assigned(item) do          begin            if item.str=s then              exit;            item:=TCmdStrListItem(item.next);          end;        result:=false;      end;    function tprocdef.GetSymtable(t:tGetSymtable):TSymtable;      begin        case t of          gs_local :            GetSymtable:=localst;          gs_para :            GetSymtable:=parast;          else            GetSymtable:=nil;        end;      end;    function tprocdef.getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef;      var        j : longint;      begin        result:=inherited;        if newtyp=procvardef then          begin            { create new paralist }            tprocvardef(result).calcparas;            exit;          end;        { don't copy mangled name, can be different }        tprocdef(result).messageinf:=messageinf;        tprocdef(result).dispid:=dispid;        if po_msgstr in procoptions then          tprocdef(result).messageinf.str:=stringdup(messageinf.str^);        tprocdef(result).symoptions:=symoptions;        if assigned(deprecatedmsg) then          tprocdef(result).deprecatedmsg:=stringdup(deprecatedmsg^);        { will have to be associated with appropriate procsym }        tprocdef(result).procsym:=nil;        { don't create aliases for bare copies, nor copy the funcretsym as          the function result parameter will be inserted again if necessary          (e.g. if the calling convention is changed) }        if not(copytyp in [pc_bareproc,pc_normal_no_hidden]) then          begin            tprocdef(result).aliasnames.concatListcopy(aliasnames);            if assigned(funcretsym) then              begin                if funcretsym.owner=parast then                  begin                    j:=parast.symlist.indexof(funcretsym);                    if j<0 then                      internalerror(2011040606);                    tprocdef(result).funcretsym:=tsym(tprocdef(result).parast.symlist[j]);                  end                else if funcretsym.owner=localst then                  begin                    { nothing to do, will be inserted for the new procdef while                      parsing its body (by pdecsub.insert_funcret_local) }                  end                else                  internalerror(2011040605);              end;          end;        { will have to be associated with a new struct }        tprocdef(result).struct:=nil;        if assigned(implprocdefinfo) then          begin            if assigned(resultname) then              tprocdef(result).resultname:=stringdup(resultname^);            tprocdef(result).synthetickind:=synthetickind;          end;        if assigned(import_dll) then          tprocdef(result).import_dll:=stringdup(import_dll^);        if assigned(import_name) then          tprocdef(result).import_name:=stringdup(import_name^);        tprocdef(result).import_nr:=import_nr;        tprocdef(result).extnumber:=$ffff;        tprocdef(result).visibility:=visibility;        { we need a separate implementation for the copied def }        tprocdef(result).forwarddef:=true;        tprocdef(result).interfacedef:=true;        { create new paralist }        tprocdef(result).calcparas;      end;    function tprocdef.getcopy: tstoreddef;      begin        result:=getcopyas(procdef,pc_normal,'',true);      end;    procedure tprocdef.buildderef;      begin         inherited buildderef;         structderef.build(struct);         { procsym that originaly defined this definition, should be in the           same symtable }         procsymderef.build(procsym);      end;    procedure tprocdef.buildderefimpl;      begin         inherited buildderefimpl;         { Localst is not available for main/unit init }         if store_localst and assigned(localst) then           begin             tlocalsymtable(localst).buildderef;             tlocalsymtable(localst).buildderefimpl;           end;         { inline tree }         if has_inlininginfo then           begin             funcretsymderef.build(funcretsym);             inlininginfo^.code.buildderefimpl;           end;      end;    procedure tprocdef.deref;      begin         inherited deref;         struct:=tabstractrecorddef(structderef.resolve);         { procsym that originaly defined this definition, should be in the           same symtable }         procsym:=tprocsym(procsymderef.resolve);      end;    procedure tprocdef.derefimpl;      begin         { Enable has_inlininginfo when the inlininginfo           structure is available. The has_inlininginfo was disabled           after the load, since the data was invalid }         if assigned(inlininginfo) then           has_inlininginfo:=true;         { Locals }         if store_localst and assigned(localst) then           begin             tlocalsymtable(localst).deref(false);             tlocalsymtable(localst).derefimpl(false);           end;        { Inline }        if has_inlininginfo then          begin            inlininginfo^.code.derefimpl;            { funcretsym, this is always located in the localst }            funcretsym:=tsym(funcretsymderef.resolve);          end        else          begin            { safety }            { Not safe! A unit may be reresolved after its interface has been              parsed but before its implementation has been parsed, and in that              case the funcretsym is still required!            funcretsym:=nil; }          end;      end;    function tprocdef.GetTypeName : string;      begin         GetTypeName := FullProcName(false);      end;    function tprocdef.mangledname : TSymStr;      begin{$ifdef symansistr}        if _mangledname='' then          begin            result:=defaultmangledname;            _mangledname:=result;          end        else          result:=_mangledname;{$else symansistr}        if not assigned(_mangledname) then          begin            result:=defaultmangledname;            _mangledname:=stringdup(mangledname);          end        else          result:=_mangledname^;{$endif symansistr}      end;    function tprocdef.defaultmangledname: TSymStr;      var        n : TSymStr;      begin        n:=procsym.name;        { make sure that the mangled names of these overloadable methods types is          unique even if it's made lowercase (e.g. for section names) }        if proctypeoption in [potype_operator,potype_class_constructor,potype_class_destructor] then          n:='$'+n;        { we need to use the symtable where the procsym is inserted,          because that is visible to the world }        defaultmangledname:=make_mangledname('',procsym.owner,n);        defaultmangledname:=defaultmangledname+mangledprocparanames(Length(defaultmangledname))      end;    function tprocdef.cplusplusmangledname : TSymStr;      function getcppparaname(p : tdef) : TSymStr;        const{$ifdef NAMEMANGLING_GCC2}           ordtype2str : array[tordtype] of string[2] = (             '',             'Uc','Us','Ui','Us','',             'Sc','s','i','x','',             'b','b','b','b','b','b',             'c','w','x');{$else NAMEMANGLING_GCC2}           ordtype2str : array[tordtype] of string[1] = (             'v',             'h','t','j','y','',             'a','s','i','x','',             'b','b','b','b','b',             'b','b','b','b',             'c','w','x','C');           floattype2str : array[tfloattype] of string[1] = (             'f','d','e','e',             'd','d','g');{$endif NAMEMANGLING_GCC2}        var           s : TSymStr;        begin           case p.typ of              orddef:                begin                  s:=ordtype2str[torddef(p).ordtype];                  if s='C' then                    s:=ordtype2str[range_to_basetype(torddef(p).low,torddef(p).high)];                end;              pointerdef:                s:='P'+getcppparaname(tpointerdef(p).pointeddef);{$ifndef NAMEMANGLING_GCC2}              floatdef:                s:=floattype2str[tfloatdef(p).floattype];{$endif NAMEMANGLING_GCC2}              else                internalerror(2103001);           end;           getcppparaname:=s;        end;      var         s,s2 : TSymStr;         hp   : TParavarsym;         i    : integer;      begin{$ifdef NAMEMANGLING_GCC2}        { outdated gcc 2.x name mangling scheme }         s := procsym.realname;         if procsym.owner.symtabletype=ObjectSymtable then           begin              s2:=upper(tobjectdef(procsym.owner.defowner).objrealname^);              case proctypeoption of                 potype_destructor:                   s:='_$_'+tostr(length(s2))+s2;                 potype_constructor:                   s:='___'+tostr(length(s2))+s2;                 else                   s:='_'+s+'__'+tostr(length(s2))+s2;              end;           end         else s:=s+'__';         s:=s+'F';         { concat modifiers }         { !!!!! }         { now we handle the parameters }         if maxparacount>0 then           begin             for i:=0 to paras.count-1 do               begin                 hp:=tparavarsym(paras[i]);                 { no hidden parameters form part of a C++ mangled name:                     a) self is not included                     b) there are no "high" or other hidden parameters                 }                 if vo_is_hidden_para in hp.varoptions then                   continue;                 s2:=getcppparaname(hp.vardef);                 if hp.varspez in [vs_var,vs_out] then                   s2:='R'+s2;                 s:=s+s2;               end;           end         else           s:=s+'v';         cplusplusmangledname:=s;{$else NAMEMANGLING_GCC2}         { gcc 3.x and 4.x name mangling scheme }         { see http://www.codesourcery.com/public/cxx-abi/abi.html#mangling }         if procsym.owner.symtabletype=ObjectSymtable then           begin             s:='_ZN';             s2:=tobjectdef(procsym.owner.defowner).objextname^;             s:=s+tostr(length(s2))+s2;             case proctypeoption of                potype_constructor:                  s:=s+'C1';                potype_destructor:                  s:=s+'D1';                else                  s:=s+tostr(length(procsym.realname))+procsym.realname;             end;             s:=s+'E';           end         else           s:=procsym.realname;         { now we handle the parameters }         if maxparacount>0 then           begin             for i:=0 to paras.count-1 do               begin                 hp:=tparavarsym(paras[i]);                 { no hidden parameters form part of a C++ mangled name:                     a) self is not included                     b) there are no "high" or other hidden parameters                 }                 if vo_is_hidden_para in hp.varoptions then                   continue;                 s2:=getcppparaname(hp.vardef);                 if hp.varspez in [vs_var,vs_out] then                   s2:='R'+s2;                 s:=s+s2;               end;           end         else           s:=s+'v';         cplusplusmangledname:=s;{$endif NAMEMANGLING_GCC2}      end;    function  tprocdef.objcmangledname : TSymStr;      var        manglednamelen: longint;        iscatmethod   : boolean;      begin        if not (po_msgstr in procoptions) then          internalerror(2009030901);        { we may very well need longer strings to handle these... }        manglednamelen:=length(tobjectdef(procsym.owner.defowner).objextname^)+          length('+"[ ]"')+length(messageinf.str^);        iscatmethod:=oo_is_classhelper in tobjectdef(procsym.owner.defowner).objectoptions;        if (iscatmethod) then          inc(manglednamelen,length(tobjectdef(procsym.owner.defowner).childof.objextname^)+length('()'));        if manglednamelen>255 then          Message1(parser_e_objc_message_name_too_long,messageinf.str^);        if not(po_classmethod in procoptions) then          result:='"-['        else          result:='"+[';        { quotes are necessary because the +/- otherwise confuse the assembler          into expecting a number        }        if iscatmethod then          result:=result+tobjectdef(procsym.owner.defowner).childof.objextname^+'(';        result:=result+tobjectdef(procsym.owner.defowner).objextname^;        if iscatmethod then          result:=result+')';        result:=result+' '+messageinf.str^+']"';      end;    procedure tprocdef.setmangledname(const s : TSymStr);      begin        { This is not allowed anymore, the forward declaration          already needs to create the correct mangledname, no changes          afterwards are allowed (PFV) }        { Exception: interface definitions in mode macpas, since in that }        {   case no reference to the old name can exist yet (JM)         }{$ifdef symansistr}        if _mangledname<>'' then          if ((m_mac in current_settings.modeswitches) and              (interfacedef)) then            _mangledname:=''          else            internalerror(200411171);{$else symansistr}        if assigned(_mangledname) then          if ((m_mac in current_settings.modeswitches) and              (interfacedef)) then            stringdispose(_mangledname)          else            internalerror(200411171);{$endif symansistr}{$ifdef jvm}        { this routine can be called for compilerproces. can't set mangled          name since it must be calculated, but it uses import_name when set          -> set that one }        import_name:=stringdup(s);        include(procoptions,po_has_importname);        include(procoptions,po_has_mangledname);{$else}  {$ifdef symansistr}        _mangledname:=s;  {$else symansistr}        _mangledname:=stringdup(s);  {$endif symansistr}{$endif jvm}        include(procoptions,po_has_mangledname);      end;    function tprocdef.needsglobalasmsym: boolean;      begin        result:=          (cs_profile in current_settings.moduleswitches) or          { smart linking using a library requires to promote            all non-nested procedures to AB_GLOBAL            otherwise you get undefined symbol error at linking            for msdos  target with -CX option for instance }          (create_smartlink_library and not is_nested_pd(self)) or          (po_global in procoptions);    end;    procedure tprocdef.setcompilerprocname;      begin        procsym.realname:='$'+lower(procsym.name);      end;{***************************************************************************                                 TPROCVARDEF***************************************************************************}    constructor tprocvardef.create(level:byte;doregister:boolean);      begin         inherited create(procvardef,level,doregister);      end;    class function tprocvardef.getreusableprocaddr(def: tabstractprocdef; copytyp: tcacheableproccopytyp): tprocvardef;      var        res: PHashSetItem;        oldsymtablestack: tsymtablestack;        key: packed record          def: tabstractprocdef;          copytyp: tcacheableproccopytyp;        end;      begin        if not assigned(current_module) then          internalerror(2011081302);        key.def:=def;        key.copytyp:=copytyp;        res:=current_module.procaddrdefs.FindOrAdd(@key,sizeof(key));        if not assigned(res^.Data) then          begin            { since these pointerdefs can be reused anywhere in the current              unit, add them to the global/staticsymtable (or local symtable              if they're a local def, because otherwise they'll be saved              to the ppu referencing a local symtable entry that doesn't              exist in the ppu) }            oldsymtablestack:=symtablestack;            { do not simply push/pop current_module.localsymtable, because              that can have side-effects (e.g., it removes helpers) }            symtablestack:=nil;            result:=tprocvardef(def.getcopyas(procvardef,copytyp,'',true));            setup_reusable_def(def,result,res,oldsymtablestack);            { res^.Data may still be nil -> don't overwrite result }            exit;          end;        result:=tprocvardef(res^.Data);      end;    class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;      begin        result:=getreusableprocaddr(def,pc_address_only);        if not result.is_registered then          include(result.defoptions,df_not_registered_no_free);      end;    constructor tprocvardef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(procvardef,ppufile);         { load para symtable }         parast:=tparasymtable.create(self,ppufile.getbyte);         ppuload_platform(ppufile);         tparasymtable(parast).ppuload(ppufile);      end;    function tprocvardef.getcopy : tstoreddef;      var        i : tcallercallee;        j : longint;      begin        result:=cprocvardef.create(parast.symtablelevel,true);        tprocvardef(result).returndef:=returndef;        tprocvardef(result).returndefderef:=returndefderef;        tprocvardef(result).parast:=parast.getcopy;        tprocvardef(result).savesize:=savesize;        { create paralist copy }        calcparas;        tprocvardef(result).paras:=tparalist.create(false);        tprocvardef(result).paras.count:=paras.count;        for j:=0 to paras.count-1 do          tprocvardef(result).paras[j]:=paras[j];        tprocvardef(result).proctypeoption:=proctypeoption;        tprocvardef(result).proccalloption:=proccalloption;        tprocvardef(result).procoptions:=procoptions;        tprocvardef(result).callerargareasize:=callerargareasize;        tprocvardef(result).calleeargareasize:=calleeargareasize;        tprocvardef(result).maxparacount:=maxparacount;        tprocvardef(result).minparacount:=minparacount;        for i:=low(funcretloc) to high(funcretloc) do          tprocvardef(result).funcretloc[i]:=funcretloc[i].getcopy;        tprocvardef(result).has_paraloc_info:=has_paraloc_info;{$ifdef m68k}        tprocvardef(result).exp_funcretloc:=exp_funcretloc;{$endif}      end;    procedure tprocvardef.ppuwrite(ppufile:tcompilerppufile);      begin        inherited ppuwrite(ppufile);        { Save the para symtable level (necessary to distinguish nested          procvars) }        ppufile.putbyte(parast.symtablelevel);        { Write this entry }        writeentry(ppufile,ibprocvardef);        { Save the para symtable, this is taken from the interface }        tparasymtable(parast).ppuwrite(ppufile);      end;    function tprocvardef.GetSymtable(t:tGetSymtable):TSymtable;      begin        case t of          gs_para :            GetSymtable:=parast;          else            GetSymtable:=nil;        end;      end;    function tprocvardef.size : asizeint;      begin         { we return false for is_addressonly for a block (because it's not a           simple pointer to a function), but they are handled as implicit           pointers to a datastructure that contains everything ->           voidpointertype.size instead of voidcodepointertype.size }         if po_is_block in procoptions then           size:=voidpointertype.size         else if not is_addressonly then           begin             if is_nested_pd(self) then               size:=voidcodepointertype.size+parentfpvoidpointertype.size             else               size:=voidcodepointertype.size+voidpointertype.size;           end         else           size:=voidcodepointertype.size;      end;    function tprocvardef.is_methodpointer:boolean;      begin        result:=(po_methodpointer in procoptions);      end;    function tprocvardef.is_addressonly:boolean;      begin        result:=((not(po_methodpointer in procoptions) or (po_staticmethod in procoptions)) and                 not(po_is_block in procoptions) and                 not is_nested_pd(self)) or                (po_addressonly in procoptions);      end;    function tprocvardef.getmangledparaname:TSymStr;      begin        if not(po_methodpointer in procoptions) then          if not is_nested_pd(self) then            result:='procvar'          else            { we need the manglednames here, because nestedprocvars can be anonymous, e.g.              having not a type name or not an unique one, see webtbs/tw27515.pp              Further, use $_ ... _$ delimiters to avoid ambiguous names, see webtbs/tw27515.pp }            result:='$_nestedprovar'+mangledprocparanames(0)+'_$'        else          result:='procvarofobj'      end;    function tprocvardef.getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string;doregister:boolean): tstoreddef;      begin        result:=inherited;        tabstractprocdef(result).calcparas;      end;    function tprocvardef.is_publishable : tpublishproperty;      begin         if po_methodpointer in procoptions then           is_publishable:=pp_publish         else           is_publishable:=pp_error;      end;    function tprocvardef.GetTypeName : string;      var        s: string;        pno : tprocnameoptions;      begin{$ifdef EXTDEBUG}         pno:=[pno_showhidden];{$else EXTDEBUG}         pno:=[];{$endif EXTDEBUG}         s:='<';         if po_is_block in procoptions then           s := s+'reference to'         else if po_classmethod in procoptions then           s := s+'class method type of'         else           if po_addressonly in procoptions then             s := s+'address of'           else             s := s+'procedure variable type of';         if assigned(returndef) and            (returndef<>voidtype) then           s:=s+' function'+typename_paras(pno)+':'+returndef.GetTypeName         else           s:=s+' procedure'+typename_paras(pno);         if po_methodpointer in procoptions then           s := s+' of object';         if is_nested_pd(self) then           s := s+' is nested';         if po_far in procoptions then           s := s+';far';         GetTypeName := s+';'+ProcCallOptionStr[proccalloption]+'>';      end;{***************************************************************************                              TOBJECTDEF***************************************************************************}   constructor tobjectdef.create(ot:tobjecttyp;const n:string;c:tobjectdef;doregister:boolean);     begin        inherited create(n,objectdef,doregister);        fcurrent_dispid:=0;        objecttype:=ot;        childof:=nil;        childofderef.reset;        vmt_fieldderef.reset;        extendeddefderef.reset;        cloneddefderef.reset;        if objecttype=odt_helper then          owner.includeoption(sto_has_helper);        symtable:=tObjectSymtable.create(self,n,current_settings.packrecords,          current_settings.alignment.recordalignmin);        { create space for vmt !! }        vmtentries:=TFPList.Create;        set_parent(c);        if objecttype in [odt_interfacecorba,odt_interfacecom,odt_dispinterface] then          prepareguid;        { setup implemented interfaces }        if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_objccategory,odt_javaclass,odt_interfacejava] then          ImplementedInterfaces:=TFPObjectList.Create(true)        else          ImplementedInterfaces:=nil;        writing_class_record_dbginfo:=false;     end;    constructor tobjectdef.ppuload(ppufile:tcompilerppufile);      var         i,         implintfcount : longint;         d, getterd : tderef;         ImplIntf : TImplementedInterface;         vmtentry : pvmtentry;      begin         inherited ppuload(objectdef,ppufile);         objecttype:=tobjecttyp(ppufile.getbyte);         helpertype:=thelpertype(ppufile.getbyte);         objextname:=ppufile.getpshortstring;         { only used for external Objective-C classes/protocols }         if (objextname^='') then           stringdispose(objextname);         symtable:=tObjectSymtable.create(self,objrealname^,0,0);         tObjectSymtable(symtable).datasize:=ppufile.getasizeint;         tObjectSymtable(symtable).paddingsize:=ppufile.getword;         tObjectSymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);         tObjectSymtable(symtable).recordalignment:=shortint(ppufile.getbyte);         tObjectSymtable(symtable).recordalignmin:=shortint(ppufile.getbyte);         ppufile.getderef(vmt_fieldderef);         ppufile.getderef(childofderef);         { load guid }         iidstr:=nil;         if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then           begin              new(iidguid);              ppufile.getguid(iidguid^);              iidstr:=ppufile.getpshortstring;           end;         abstractcnt:=ppufile.getlongint;         if objecttype=odt_helper then           ppufile.getderef(extendeddefderef);         vmtentries:=TFPList.Create;         vmtentries.count:=ppufile.getlongint;         for i:=0 to vmtentries.count-1 do           begin             ppufile.getderef(d);             new(vmtentry);             vmtentry^.procdef:=nil;             vmtentry^.procdefderef:=d;             vmtentry^.visibility:=tvisibility(ppufile.getbyte);             vmtentries[i]:=vmtentry;           end;         { load implemented interfaces }         if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_objccategory,odt_javaclass,odt_interfacejava] then           begin             ImplementedInterfaces:=TFPObjectList.Create(true);             implintfcount:=ppufile.getlongint;             for i:=0 to implintfcount-1 do               begin                 ppufile.getderef(d);                 ppufile.getderef(getterd);                 ImplIntf:=TImplementedInterface.Create_deref(d,getterd);                 ImplIntf.IOffset:=ppufile.getlongint;                 byte(ImplIntf.IType):=ppufile.getbyte;                 ImplementedInterfaces.Add(ImplIntf);               end;           end         else           ImplementedInterfaces:=nil;         if df_copied_def in defoptions then           begin             ppufile.getderef(cloneddefderef);             ppuload_platform(ppufile);           end         else           begin             ppuload_platform(ppufile);             tObjectSymtable(symtable).ppuload(ppufile);           end;         { handles the predefined class tobject  }         { the last TOBJECT which is loaded gets }         { it !                                  }         { but do this only from a unit that's   }         { marked as system unit to avoid some   }         { equally named user's type to override }         { the internal types!                   }         if mf_system_unit in current_module.moduleflags then           begin             if (childof=nil) and                (objecttype in [odt_class,odt_javaclass]) and                (objname^='TOBJECT') then               class_tobject:=self;             if (childof=nil) and                (objecttype=odt_interfacecom) then                if (objname^='IUNKNOWN') then                  interface_iunknown:=self                else                if (objname^='IDISPATCH') then                  interface_idispatch:=self;             if (objecttype=odt_javaclass) and                not(oo_is_formal in objectoptions) then               begin                 if (objname^='JLOBJECT') then                   java_jlobject:=self                 else if (objname^='JLTHROWABLE') then                   java_jlthrowable:=self                 else if (objname^='FPCBASERECORDTYPE') then                   java_fpcbaserecordtype:=self                 else if (objname^='JLSTRING') then                   java_jlstring:=self                 else if (objname^='ANSISTRINGCLASS') then                   java_ansistring:=self                 else if (objname^='SHORTSTRINGCLASS') then                   java_shortstring:=self                 else if (objname^='JLENUM') then                   java_jlenum:=self                 else if (objname^='JUENUMSET') then                   java_juenumset:=self                 else if (objname^='FPCBITSET') then                   java_jubitset:=self                 else if (objname^='FPCBASEPROCVARTYPE') then                   java_procvarbase:=self;               end;           end;         if (childof=nil) and            (objecttype=odt_objcclass) and            (objname^='PROTOCOL') then           objc_protocoltype:=self;         writing_class_record_dbginfo:=false;       end;    destructor tobjectdef.destroy;      var        i: longint;      begin         if assigned(symtable) then           begin             symtable.free;             symtable:=nil;           end;         stringdispose(objextname);         stringdispose(iidstr);         if assigned(ImplementedInterfaces) then           begin             ImplementedInterfaces.free;             ImplementedInterfaces:=nil;           end;         if assigned(iidguid) then           begin             dispose(iidguid);             iidguid:=nil;           end;         if assigned(vmtentries) then           begin             for i:=0 to vmtentries.count-1 do               dispose(pvmtentry(vmtentries[i]));             vmtentries.free;             vmtentries:=nil;           end;         if assigned(vmcallstaticinfo) then           begin             freemem(vmcallstaticinfo);             vmcallstaticinfo:=nil;           end;         inherited destroy;      end;    function tobjectdef.getcopy : tstoreddef;      var        i : longint;      begin        result:=cobjectdef.create(objecttype,objrealname^,childof,true);        { the constructor allocates a symtable which we release to avoid memory leaks }        tobjectdef(result).symtable.free;        tobjectdef(result).symtable:=symtable.getcopy;        if assigned(objextname) then          tobjectdef(result).objextname:=stringdup(objextname^);        if assigned(import_lib) then          tobjectdef(result).import_lib:=stringdup(import_lib^);        tobjectdef(result).objectoptions:=objectoptions;        include(tobjectdef(result).defoptions,df_copied_def);        tobjectdef(result).extendeddef:=extendeddef;        if assigned(tcinitcode) then          tobjectdef(result).tcinitcode:=tcinitcode.getcopy;        tobjectdef(result).vmt_field:=vmt_field;        if assigned(iidguid) then          begin            new(tobjectdef(result).iidguid);            move(iidguid^,tobjectdef(result).iidguid^,sizeof(iidguid^));          end;        if assigned(iidstr) then          tobjectdef(result).iidstr:=stringdup(iidstr^);        tobjectdef(result).abstractcnt:=abstractcnt;        if assigned(ImplementedInterfaces) then          begin            for i:=0 to ImplementedInterfaces.count-1 do              tobjectdef(result).ImplementedInterfaces.Add(TImplementedInterface(ImplementedInterfaces[i]).Getcopy);          end;        tobjectdef(result).copyvmtentries(self);      end;    procedure tobjectdef.ppuwrite(ppufile:tcompilerppufile);      var         i : longint;         vmtentry : pvmtentry;         ImplIntf : TImplementedInterface;         old_do_indirect_crc: boolean;      begin         { if class1 in unit A changes, and class2 in unit B inherits from it           (so unit B uses unit A), then unit B with class2 will be recompiled.           However, if there is also a class3 in unit C that only depends on           unit B, then unit C will not be recompiled because nothing changed           to the interface of unit B. Nevertheless, unit C can indirectly           depend on unit A via derefs, and these must be updated -> the           indirect crc keeps track of such changes. }         old_do_indirect_crc:=ppufile.do_indirect_crc;         ppufile.do_indirect_crc:=true;         inherited ppuwrite(ppufile);         ppufile.putbyte(byte(objecttype));         ppufile.putbyte(byte(helpertype));         if assigned(objextname) then           ppufile.putstring(objextname^)         else           ppufile.putstring('');         ppufile.putasizeint(tObjectSymtable(symtable).datasize);         ppufile.putword(tObjectSymtable(symtable).paddingsize);         ppufile.putbyte(byte(tObjectSymtable(symtable).fieldalignment));         ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignment));         ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignmin));         ppufile.putderef(vmt_fieldderef);         ppufile.putderef(childofderef);         if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then           begin              ppufile.putguid(iidguid^);              ppufile.putstring(iidstr^);           end;         ppufile.putlongint(abstractcnt);         if objecttype=odt_helper then           ppufile.putderef(extendeddefderef);         ppufile.putlongint(vmtentries.count);         for i:=0 to vmtentries.count-1 do           begin             vmtentry:=pvmtentry(vmtentries[i]);             ppufile.putderef(vmtentry^.procdefderef);             ppufile.putbyte(byte(vmtentry^.visibility));           end;         if assigned(ImplementedInterfaces) then           begin             ppufile.putlongint(ImplementedInterfaces.Count);             for i:=0 to ImplementedInterfaces.Count-1 do               begin                 ImplIntf:=TImplementedInterface(ImplementedInterfaces[i]);                 ppufile.putderef(ImplIntf.intfdefderef);                 ppufile.putderef(ImplIntf.ImplementsGetterDeref);                 ppufile.putlongint(ImplIntf.Ioffset);                 ppufile.putbyte(byte(ImplIntf.IType));               end;           end;         if df_copied_def in defoptions then           ppufile.putderef(cloneddefderef);         writeentry(ppufile,ibobjectdef);         if not(df_copied_def in defoptions) then           tObjectSymtable(symtable).ppuwrite(ppufile);         ppufile.do_indirect_crc:=old_do_indirect_crc;      end;    function tobjectdef.GetTypeName:string;      begin        { in this case we will go in endless recursion, because then  }        { there is no tsym associated yet with the def. It can occur  }        { (tests/webtbf/tw4757.pp), so for now give a generic name    }        { instead of the actual type name                             }        if not assigned(typesym) then          result:='<Currently Parsed Class>'        else          result:=typesymbolprettyname;      end;    procedure tobjectdef.buildderef;      var         i : longint;         vmtentry : pvmtentry;      begin         inherited buildderef;         vmt_fieldderef.build(vmt_field);         childofderef.build(childof);         if df_copied_def in defoptions then           cloneddefderef.build(symtable.defowner)         else           tstoredsymtable(symtable).buildderef;         if objecttype=odt_helper then           extendeddefderef.build(extendeddef);         for i:=0 to vmtentries.count-1 do           begin             vmtentry:=pvmtentry(vmtentries[i]);             vmtentry^.procdefderef.build(vmtentry^.procdef);           end;         if assigned(ImplementedInterfaces) then           begin             for i:=0 to ImplementedInterfaces.count-1 do               TImplementedInterface(ImplementedInterfaces[i]).buildderef;           end;      end;    procedure tobjectdef.deref;      var         i : longint;         vmtentry : pvmtentry;      begin         inherited deref;         vmt_field:=tsym(vmt_fieldderef.resolve);         childof:=tobjectdef(childofderef.resolve);         if df_copied_def in defoptions then           begin             cloneddef:=tobjectdef(cloneddefderef.resolve);             symtable:=cloneddef.symtable.getcopy;           end         else           tstoredsymtable(symtable).deref(false);         if objecttype=odt_helper then           extendeddef:=tdef(extendeddefderef.resolve);         for i:=0 to vmtentries.count-1 do           begin             vmtentry:=pvmtentry(vmtentries[i]);             vmtentry^.procdef:=tprocdef(vmtentry^.procdefderef.resolve);           end;         if assigned(ImplementedInterfaces) then           begin             for i:=0 to ImplementedInterfaces.count-1 do               TImplementedInterface(ImplementedInterfaces[i]).deref;           end;      end;    procedure create_class_helper_for_procdef(def: tobject; arg: pointer);      var        pd: tprocdef absolute def;        st: tsymtable;        psym: tsym;        nname: TIDString;      begin        if (tdef(def).typ<>procdef) then          exit;        { pd.owner = objcclass symtable -> defowner = objcclassdef ->          owner = symtable in which objcclassdef is defined        }        st:=pd.owner.defowner.owner;        nname:=class_helper_prefix+tprocsym(pd.procsym).name;        { check for an existing procsym with our special name }        psym:=tsym(st.find(nname));        if not assigned(psym) then          begin            psym:=cprocsym.create(nname);            { avoid warning about this symbol being unused }            psym.IncRefCount;            { don't check for duplicates:               a) we checked above               b) in case we are in the implementation section of a unit, this                  will also check for this symbol in the interface section                  (since you normally cannot have symbols with the same name                   both interface and implementation), and it's possible to                   have class helpers for the same class in the interface and                   in the implementation, and they cannot be merged since only                   the once in the interface must be saved to the ppu/visible                   from other units }            st.insertsym(psym,false);          end        else if (psym.typ<>procsym) then          internalerror(2009111501);        { add ourselves to this special procsym }        tprocsym(psym).procdeflist.add(def);      end;    procedure tobjectdef.derefimpl;      begin         inherited derefimpl;         { the procdefs are not owned by the class helper procsyms, so they           are not stored/restored either -> re-add them here }         if (objecttype in [odt_objcclass,odt_objcprotocol]) or            (oo_is_classhelper in objectoptions) then           symtable.DefList.ForEachCall(@create_class_helper_for_procdef,nil);      end;    procedure tobjectdef.copyvmtentries(objdef:tobjectdef);      var        i : longint;        vmtentry : pvmtentry;      begin        if vmtentries.count<>0 then          internalerror(2019081401);        vmtentries.count:=objdef.vmtentries.count;        for i:=0 to objdef.vmtentries.count-1 do          begin            new(vmtentry);            vmtentry^:=pvmtentry(objdef.vmtentries[i])^;            vmtentries[i]:=vmtentry;          end;       end;    function tobjectdef.getparentdef:tdef;      begin{ TODO: Remove getparentdef hack}        { With 2 forward declared classes with the child class before the          parent class the child class is written earlier to the ppu. Leaving it          possible to have a reference to the parent class for property overriding,          but the parent class still has the childof not resolved yet (PFV) }        if childof=nil then          childof:=tobjectdef(childofderef.resolve);        result:=childof;      end;    procedure tobjectdef.prepareguid;      begin        { set up guid }        if not assigned(iidguid) then         begin            new(iidguid);            fillchar(iidguid^,sizeof(iidguid^),0); { default null guid }         end;        { setup iidstring }        if not assigned(iidstr) then          iidstr:=stringdup(''); { default is empty string }      end;    procedure tobjectdef.set_parent( c : tobjectdef);      begin        if assigned(childof) then          exit;        childof:=c;        if not assigned(c) then          exit;        { inherit options and status }        objectoptions:=objectoptions+(c.objectoptions*inherited_objectoptions);        { initially has the same number of abstract methods as the parent }        abstractcnt:=c.abstractcnt;        { add the data of the anchestor class/object }        if (objecttype in [odt_class,odt_object,odt_objcclass,odt_javaclass]) then          begin            tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize+tObjectSymtable(c.symtable).datasize;            { inherit recordalignment }            tObjectSymtable(symtable).recordalignment:=tObjectSymtable(c.symtable).recordalignment;            { if both the parent and this record use C-alignment, also inherit              the current field alignment }            if (tObjectSymtable(c.symtable).usefieldalignment=C_alignment) and               (tObjectSymtable(symtable).usefieldalignment=C_alignment) then              tObjectSymtable(symtable).fieldalignment:=tObjectSymtable(c.symtable).fieldalignment;            { the padding is not inherited for Objective-C classes (maybe not              for cppclass either?) }            if objecttype=odt_objcclass then              tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-tObjectSymtable(c.symtable).paddingsize;            if (oo_has_vmt in objectoptions) and               (oo_has_vmt in c.objectoptions) then              tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-sizeof(pint);            { if parent has a vmt field then the offset is the same for the child PM }            if (oo_has_vmt in c.objectoptions) or is_class(self) then              begin                vmt_field:=c.vmt_field;                include(objectoptions,oo_has_vmt);              end;          end;      end;   procedure tobjectdef.insertvmt;     begin        if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then          exit;        if (oo_has_vmt in objectoptions) then          internalerror(2020100816)        else          begin             tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,                 tObjectSymtable(symtable).fieldalignment);             if (tf_requires_proper_alignment in target_info.flags) then               begin                 { Align VMT pointer and whole object instance if target CPU requires alignment. }                 tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,sizeof(pint));                 tObjectSymtable(symtable).alignrecord(tObjectSymtable(symtable).datasize,sizeof(pint));               end;             vmt_field:=cfieldvarsym.create('_vptr$'+objname^,vs_value,voidpointertype,[]);             hidesym(vmt_field);             tObjectSymtable(symtable).insertsym(vmt_field);             tObjectSymtable(symtable).addfield(tfieldvarsym(vmt_field),vis_hidden);             include(objectoptions,oo_has_vmt);          end;     end;   function tobjectdef.vmt_offset: asizeint;     begin        if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then          result:=0        else if (tObjectSymtable(symtable).usefieldalignment<>bit_alignment) then          result:=tfieldvarsym(vmt_field).fieldoffset        else          result:=tfieldvarsym(vmt_field).fieldoffset div 8;     end;   procedure tobjectdef.check_forwards;     begin        if not(objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcprotocol,odt_interfacejava]) then          inherited;        if (oo_is_forward in objectoptions) then          begin             { ok, in future, the forward can be resolved }             Message1(sym_e_class_forward_not_resolved,objrealname^);             exclude(objectoptions,oo_is_forward);          end;     end;   function tobjectdef.find_destructor: tprocdef;     var       objdef: tobjectdef;     begin        objdef:=self;        while assigned(objdef) do          begin            result:=objdef.find_procdef_bytype(potype_destructor);            if assigned(result) then              exit;            objdef:=objdef.childof;          end;        result:=nil;     end;    function tobjectdef.implements_any_interfaces: boolean;      begin        result := (ImplementedInterfaces.Count > 0) or          (assigned(childof) and childof.implements_any_interfaces);      end;    function tobjectdef.register_implemented_interface(intfdef:tobjectdef;useguid:boolean):timplementedinterface;      begin        { allocate the GUID only if the class implements at least one interface }        if useguid then          prepareguid;        result:=timplementedinterface.create(intfdef);        ImplementedInterfaces.Add(result);      end;    function tobjectdef.size : asizeint;      begin        if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava] then          result:=voidpointertype.size        else          result:=tObjectSymtable(symtable).datasize;      end;    function tobjectdef.alignment:shortint;      begin        if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava] then          alignment:=voidpointertype.alignment        else          alignment:=tObjectSymtable(symtable).recordalignment;      end;    function tobjectdef.vmtmethodoffset(index:longint):longint;      begin        { for offset of methods for classes, see rtl/inc/objpash.inc }        case objecttype of        odt_class:          { the +2*sizeof(pint) is size and -size }          vmtmethodoffset:=index*voidcodepointertype.size+10*voidpointertype.size+2*sizeof(pint);        odt_helper,        odt_objcclass,        odt_objcprotocol:          vmtmethodoffset:=0;        odt_interfacecom,odt_interfacecorba,odt_dispinterface:          vmtmethodoffset:=index*voidcodepointertype.size;        odt_javaclass,        odt_interfacejava:          { invalid }          vmtmethodoffset:=-1;        else          { the +2*sizeof(pint) is size and -size }{$ifdef WITHDMT}          vmtmethodoffset:=index*voidcodepointertype.size+2*voidpointertype.size+2*sizeof(pint);{$else WITHDMT}          vmtmethodoffset:=index*voidcodepointertype.size+1*voidpointertype.size+2*sizeof(pint);{$endif WITHDMT}        end;      end;    function tobjectdef.vmt_mangledname : TSymStr;      begin        if not(oo_has_vmt in objectoptions) then          Message1(parser_n_object_has_no_vmt,objrealname^);        if not is_unique_objpasdef then          vmt_mangledname:=make_mangledname('VMT',owner,objname^)        else          vmt_mangledname:=childof.vmt_mangledname;      end;    function tobjectdef.vmt_def: trecorddef;      var        where: tsymtable;        vmttypesym: tsymentry;      begin        if not is_unique_objpasdef then          begin            vmttypesym:=symtable.Find('vmtdef');            if not assigned(vmttypesym) or               (vmttypesym.typ<>symconst.typesym) or               (ttypesym(vmttypesym).typedef.typ<>recorddef) then              internalerror(2015052501);            result:=trecorddef(ttypesym(vmttypesym).typedef);          end        else          result:=childof.vmt_def;      end;    function tobjectdef.needs_inittable : boolean;      var        hp : tobjectdef;      begin         case objecttype of            odt_helper,            odt_class :              needs_inittable:=false;            odt_dispinterface,            odt_interfacecom:              needs_inittable:=true;            odt_interfacecorba:              begin                hp:=childof;                while assigned(hp) do                  begin                    if hp=interface_iunknown then                      begin                        needs_inittable:=true;                        exit;                      end;                    hp:=hp.childof;                  end;                needs_inittable:=false;              end;            odt_object:              needs_inittable:=                tObjectSymtable(symtable).needs_init_final or                (assigned(childof) and                 childof.needs_inittable);            odt_cppclass,            odt_objcclass,            odt_objcprotocol,            odt_javaclass,            odt_interfacejava:              needs_inittable:=false;            else              internalerror(200108267);         end;      end;    function tobjectdef.needs_separate_initrtti : boolean;      begin        result:=not (objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface]);      end;    function tobjectdef.has_non_trivial_init_child(check_parent:boolean):boolean;      begin        if objecttype in [odt_class,odt_object] then          begin            result:=tobjectsymtable(symtable).has_non_trivial_init or                      (check_parent and assigned(childof) and childof.has_non_trivial_init_child(true));          end        else          result:=false;      end;    function tobjectdef.rtti_mangledname(rt: trttitype): TSymStr;      begin        if not(objecttype in [odt_objcclass,odt_objcprotocol]) then          begin            if not is_unique_objpasdef then              result:=inherited rtti_mangledname(rt)            else              result:=childof.rtti_mangledname(rt)          end        else          begin            { necessary in case of a dynamic array of nsobject, or              if an nsobject field appears in a record that needs              init/finalisation }            if rt=initrtti then              begin                result:=voidpointertype.rtti_mangledname(rt);                exit;              end;            if not(target_info.system in systems_objc_nfabi) then              begin                result:=target_asm.labelprefix;                case objecttype of                  odt_objcclass:                    begin                      case rt of                        objcclassrtti:                          if not(oo_is_classhelper in objectoptions) then                            result:=result+'_OBJC_CLASS_'                          else                            result:=result+'_OBJC_CATEGORY_';                        objcmetartti:                          if not(oo_is_classhelper in objectoptions) then                            result:=result+'_OBJC_METACLASS_'                          else                            internalerror(2009111511);                        else                         internalerror(2009092302);                      end;                    end;                  odt_objcprotocol:                    result:=result+'_OBJC_PROTOCOL_';                  else                   ;                end;              end            else              begin                case objecttype of                  odt_objcclass:                    begin                      if (oo_is_classhelper in objectoptions) and                         (rt<>objcclassrtti) then                        internalerror(2009111512);                      case rt of                        objcclassrtti:                          if not(oo_is_classhelper in objectoptions) then                            result:='_OBJC_CLASS_$_'                          else                            result:='_OBJC_$_CATEGORY_';                        objcmetartti:                          result:='_OBJC_METACLASS_$_';                        objcclassrortti:                          result:=lower(target_asm.labelprefix)+'_OBJC_CLASS_RO_$_';                        objcmetarortti:                          result:=lower(target_asm.labelprefix)+'_OBJC_METACLASS_RO_$_';                        else                         internalerror(2009092303);                      end;                    end;                  odt_objcprotocol:                    begin                      result:=lower(target_asm.labelprefix);                      case rt of                        objcclassrtti:                          result:=result+'_OBJC_PROTOCOL_$_';                        objcmetartti:                          result:=result+'_OBJC_LABEL_PROTOCOL_$_';                        else                          internalerror(2009092501);                      end;                    end;                  else                    internalerror(2013113005);                end;              end;            result:=result+objextname^;          end;      end;    function tobjectdef.is_unique_objpasdef: boolean;        begin          result:=            (df_unique in defoptions) and            is_class_or_interface_or_dispinterface(self)        end;    function tobjectdef.members_need_inittable : boolean;      begin        members_need_inittable:=tObjectSymtable(symtable).needs_init_final or                                  has_non_trivial_init_child(true);      end;    function tobjectdef.is_publishable : tpublishproperty;      begin         if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface] then           is_publishable:=pp_publish         else           is_publishable:=pp_error;      end;    function tobjectdef.get_next_dispid: longint;      begin        inc(fcurrent_dispid);        result:=fcurrent_dispid;      end;    function tobjectdef.search_enumerator_get: tprocdef;      begin        result:=inherited;        if not assigned(result) and assigned(childof) then          result:=childof.search_enumerator_get;      end;    function tobjectdef.search_enumerator_move: tprocdef;      begin        result:=inherited;        if not assigned(result) and assigned(childof) then          result:=childof.search_enumerator_move;      end;    function tobjectdef.search_enumerator_current: tsym;      begin        result:=inherited;        if not assigned(result) and assigned(childof) then          result:=childof.search_enumerator_current;      end;    procedure tobjectdef.register_created_classref_type;      begin        if not classref_created_in_current_module then          begin            classref_created_in_current_module:=true;            current_module.wpoinfo.addcreatedobjtypeforclassref(self);          end;      end;    procedure tobjectdef.register_created_object_type;      begin        if not created_in_current_module then          begin            created_in_current_module:=true;            current_module.wpoinfo.addcreatedobjtype(self);          end;      end;    procedure tobjectdef.register_maybe_created_object_type;      begin        { if we know it has been created for sure, no need          to also record that it maybe can be created in          this module        }        if not (created_in_current_module) and           not (maybe_created_in_current_module) then          begin            maybe_created_in_current_module:=true;            current_module.wpoinfo.addmaybecreatedbyclassref(self);          end;      end;    procedure tobjectdef.register_vmt_call(index: longint);      begin        if (is_object(self) or is_class(self)) then          current_module.wpoinfo.addcalledvmtentry(self,index);      end;    procedure check_and_finish_msg(data: tobject; arg: pointer);      var        def: tdef absolute data;        pd: tprocdef absolute data;        i,        paracount: longint;      begin        if (def.typ=procdef) then          begin            { add all messages also under a dummy name to the symtable in              which the objcclass/protocol/category is declared, so they can              be called via id.<name>            }            create_class_helper_for_procdef(pd,nil);            { we have to wait until now to set the mangled name because it              depends on the (possibly external) class name, which is defined              at the very end.  }            if not(po_msgstr in pd.procoptions) then              begin                CGMessagePos(pd.fileinfo,parser_e_objc_requires_msgstr);                { recover to avoid internalerror later on }                include(pd.procoptions,po_msgstr);                pd.messageinf.str:=stringdup('MissingDeclaration');              end;            { Mangled name is already set in case this is a copy of              another type.  }            if not(po_has_mangledname in pd.procoptions) then              begin                { check whether the number of formal parameters is correct,                  and whether they have valid Objective-C types }                paracount:=0;                for i:=1 to length(pd.messageinf.str^) do                  if pd.messageinf.str^[i]=':' then                    inc(paracount);                for i:=0 to pd.paras.count-1 do                  if not(vo_is_hidden_para in tparavarsym(pd.paras[i]).varoptions) and                     not is_array_of_const(tparavarsym(pd.paras[i]).vardef) then                    dec(paracount);                if (paracount<>0) then                  MessagePos(pd.fileinfo,sym_e_objc_para_mismatch);                pd.setmangledname(pd.objcmangledname);              end            else              { all checks already done }              exit;            if not(oo_is_external in pd.struct.objectoptions) then              begin                if (po_varargs in pd.procoptions) then                  MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external)                else                  begin                    { check for "array of const" parameters }                    for i:=0 to pd.parast.symlist.count-1 do                      begin                        if (tsym(pd.parast.symlist[i]).typ=paravarsym) and                           is_array_of_const(tparavarsym(pd.parast.symlist[i]).vardef) then                          MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external);                      end;                  end;              end;          end;      end;    procedure mark_private_fields_used(data: tobject; arg: pointer);      var        sym: tsym absolute data;      begin        if (sym.typ=fieldvarsym) and           (tfieldvarsym(sym).visibility in [vis_private,vis_strictprivate]) then          sym.IncRefCount;      end;    procedure tobjectdef.finish_objc_data;      begin        self.symtable.DefList.foreachcall(@check_and_finish_msg,nil);        if (oo_is_external in objectoptions) then          self.symtable.SymList.ForEachCall(@mark_private_fields_used,nil);      end;    procedure verify_objc_vardef(data: tobject; arg: pointer);      var        sym: tabstractvarsym absolute data;        res: pboolean absolute arg;        founderrordef: tdef;      begin        if not(tsym(data).typ in [paravarsym,fieldvarsym]) then          exit;        if (sym.typ=paravarsym) and           ((vo_is_hidden_para in tparavarsym(sym).varoptions) or            is_array_of_const(tparavarsym(sym).vardef)) then          exit;        if not objcchecktype(sym.vardef,founderrordef) then          begin            MessagePos1(sym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);            res^:=false;          end;      end;    procedure verify_objc_procdef_paras(data: tobject; arg: pointer);      var        def: tdef absolute data;        res: pboolean absolute arg;        founderrordef: tdef;      begin        if (def.typ<>procdef) then          exit;        { check parameter types for validity }        tprocdef(def).paras.foreachcall(@verify_objc_vardef,arg);        { check the result type for validity }        if not objcchecktype(tprocdef(def).returndef,founderrordef) then          begin            MessagePos1(tprocdef(def).funcretsym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);            res^:=false;          end;      end;    function tobjectdef.check_objc_types: boolean;      begin        { done in separate step from finish_objc_data, because when          finish_objc_data is called, not all forwarddefs have been resolved          yet and we need to know all types here }        result:=true;        self.symtable.symlist.foreachcall(@verify_objc_vardef,@result);        self.symtable.deflist.foreachcall(@verify_objc_procdef_paras,@result);      end;    procedure do_cpp_import_info(data: tobject; arg: pointer);      var        def: tdef absolute data;        pd: tprocdef absolute data;      begin        if (def.typ=procdef) then          begin            pd.setmangledname(target_info.Cprefix+pd.cplusplusmangledname);            if (oo_is_external in pd.struct.objectoptions) then              begin                { copied from psub.read_proc }                if assigned(tobjectdef(pd.struct).import_lib) then                   current_module.AddExternalImport(tobjectdef(pd.struct).import_lib^,pd.mangledname,pd.mangledname,0,false,false)                 else                   begin                     { add import name to external list for DLL scanning }                     if tf_has_dllscanner in target_info.flags then                       current_module.dllscannerinputlist.Add(pd.mangledname,pd);                   end;              end;          end;      end;    procedure tobjectdef.finish_cpp_data;      begin        self.symtable.DefList.ForEachCall(@do_cpp_import_info,nil);      end;{$ifdef DEBUG_NODE_XML}    function TObjectDef.XMLPrintType: ansistring;      begin        if (oo_is_forward in objectoptions) then          Result := '<class prototype>'        else          Result := '<class>';      end;    procedure TObjectDef.XMLPrintDefInfo(var T: Text; Sym: TSym);      var        i: TObjectOption;        first: Boolean;      begin        inherited XMLPrintDefInfo(T, Sym);        First := True;        for i := Low(TObjectOption) to High(TObjectOption) do          if i in objectoptions then            begin              if First then                begin                  Write(T, ' objectoptions="', i);                  First := False;                end              else                Write(T, ',', i)            end;        if not first then          Write(T, '"');      end;    procedure TObjectDef.XMLPrintDefData(var T: Text; Sym: TSym);      begin        { There's nothing useful yet if the type is only forward-declared }        if not (oo_is_forward in objectoptions) then          begin            if Assigned(childof) then              WriteLn(T, printnodeindention, '<ancestor>', SanitiseXMLString(childof.typesym.RealName), '</ancestor>');            inherited XMLPrintDefData(T, Sym);          end;      end;{$endif DEBUG_NODE_XML}{****************************************************************************                             TImplementedInterface****************************************************************************}    function TImplementedInterface.GetIOffset: longint;      begin        if (fIOffset=-1) and           (IType in [etFieldValue,etFieldValueClass]) then          result:=tfieldvarsym(ImplementsField).fieldoffset        else          result:=fIOffset;      end;    constructor TImplementedInterface.create(aintf: tobjectdef);      begin        inherited create;        intfdef:=aintf;        intfdefderef.reset;        IOffset:=-1;        IType:=etStandard;        NameMappings:=nil;        procdefs:=nil;      end;    constructor TImplementedInterface.create_deref(intfd,getterd:tderef);      begin        inherited create;        intfdef:=nil;        intfdefderef:=intfd;        ImplementsGetterDeref:=getterd;        IOffset:=-1;        IType:=etStandard;        NameMappings:=nil;        procdefs:=nil;      end;    destructor  TImplementedInterface.destroy;      var        i : longint;        mappedname : pshortstring;      begin        if assigned(NameMappings) then          begin            for i:=0 to NameMappings.Count-1 do              begin                mappedname:=pshortstring(NameMappings[i]);                stringdispose(mappedname);              end;            NameMappings.free;            NameMappings:=nil;          end;        if assigned(procdefs) then          begin            procdefs.free;            procdefs:=nil;          end;        inherited destroy;      end;    procedure TImplementedInterface.buildderef;      begin        intfdefderef.build(intfdef);        ImplementsGetterDeref.build(ImplementsGetter);      end;    procedure TImplementedInterface.deref;      begin        intfdef:=tobjectdef(intfdefderef.resolve);        ImplementsGetter:=tsym(ImplementsGetterDeref.resolve);      end;    procedure TImplementedInterface.AddMapping(const origname,newname: string);      begin        if not assigned(NameMappings) then          NameMappings:=TFPHashList.Create;        NameMappings.Add(origname,stringdup(newname));      end;    function TImplementedInterface.GetMapping(const origname: string):string;      var        mappedname : pshortstring;      begin        result:='';        if not assigned(NameMappings) then          exit;        mappedname:=PShortstring(NameMappings.Find(origname));        if assigned(mappedname) then          result:=mappedname^;      end;    procedure TImplementedInterface.AddImplProc(pd:tprocdef);      begin        if not assigned(procdefs) then          procdefs:=TFPObjectList.Create(false);        { duplicate entries must be stored, because multiple }        { interfaces can declare methods with the same name  }        { and all of these get their own VMT entry           }        procdefs.Add(pd);      end;    function TImplementedInterface.IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;      var        i : longint;      begin        result:=false;        { interfaces being implemented through delegation are not mergable (FK) }        if (IType<>etStandard) or (MergingIntf.IType<>etStandard) or not(assigned(ProcDefs)) or not(assigned(MergingIntf.ProcDefs)) then          exit;        weight:=0;        { empty interface is mergeable }        if ProcDefs.Count=0 then          begin            result:=true;            exit;          end;        { The interface to merge must at least the number of          procedures of this interface }        if MergingIntf.ProcDefs.Count<ProcDefs.Count then          exit;        for i:=0 to ProcDefs.Count-1 do          begin            if MergingIntf.ProcDefs[i]<>ProcDefs[i] then              exit;          end;        weight:=ProcDefs.Count;        result:=true;      end;    function TImplementedInterface.getcopy:TImplementedInterface;      begin        Result:=TImplementedInterface.Create(nil);        { 1) the procdefs list will be freed once for each copy          2) since the procdefs list owns its elements, those will also be freed for each copy          3) idem for the name mappings        }        { warning: this is completely wrong on so many levels...        Move(pointer(self)^,pointer(result)^,InstanceSize);        We need to make clean copies of the different fields        this is not implemented yet, and thus we generate an internal        error instead PM 2011-06-14 }        internalerror(2011061401);      end;{****************************************************************************                                TFORWARDDEF****************************************************************************}   constructor tforwarddef.create(const s:string;const pos:tfileposinfo);     begin        inherited create(forwarddef,true);        tosymname:=stringdup(s);        forwardpos:=pos;     end;    function tforwarddef.GetTypeName:string;      begin        GetTypeName:='unresolved forward to '+tosymname^;      end;    destructor tforwarddef.destroy;      begin        stringdispose(tosymname);        inherited destroy;      end;    function tforwarddef.getcopy:tstoreddef;      begin        result:=cforwarddef.create(tosymname^, forwardpos);      end;{****************************************************************************                               TUNDEFINEDDEF****************************************************************************}   constructor tundefineddef.create(doregister:boolean);     begin        inherited create(undefineddef,doregister);     end;    constructor tundefineddef.ppuload(ppufile:tcompilerppufile);      begin         inherited ppuload(undefineddef,ppufile);         ppuload_platform(ppufile);      end;    function tundefineddef.GetTypeName:string;      begin        GetTypeName:='<undefined type>';      end;    procedure tundefineddef.ppuwrite(ppufile:tcompilerppufile);      begin         inherited ppuwrite(ppufile);         writeentry(ppufile,ibundefineddef);      end;{****************************************************************************                                  TERRORDEF****************************************************************************}    constructor terrordef.create;      begin        inherited create(errordef,true);        { prevent consecutive faults }        savesize:=1;      end;    procedure terrordef.ppuwrite(ppufile:tcompilerppufile);      begin        { Can't write errordefs to ppu }        internalerror(200411063);      end;    function terrordef.GetTypeName:string;      begin        GetTypeName:='<erroneous type>';      end;    function terrordef.getmangledparaname:TSymStr;      begin        getmangledparaname:='error';      end;{****************************************************************************                           Definition Helpers****************************************************************************}    function is_interfacecom(def: tdef): boolean;      begin        is_interfacecom:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_interfacecom);      end;    function is_interfacecom_or_dispinterface(def: tdef): boolean;      begin        is_interfacecom_or_dispinterface:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_interfacecom,odt_dispinterface]);      end;    function is_any_interface_kind(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          ((tobjectdef(def).objecttype in [odt_interfacecom,odt_dispinterface,odt_interfacecorba,odt_interfacejava,odt_objcprotocol]) or           is_objccategory(def));      end;    function is_interfacecorba(def: tdef): boolean;      begin        is_interfacecorba:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_interfacecorba);      end;    function is_interface(def: tdef): boolean;      begin        is_interface:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_interfacecom,odt_interfacecorba]);      end;    function is_dispinterface(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_dispinterface);      end;    function is_class(def: tdef): boolean;      begin        is_class:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_class);      end;    function is_object(def: tdef): boolean;      begin        is_object:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_object);      end;    function is_cppclass(def: tdef): boolean;      begin        is_cppclass:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_cppclass);      end;    function is_objcclass(def: tdef): boolean;      begin        is_objcclass:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_objcclass);      end;    function is_objectpascal_helper(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_helper);      end;    function is_objcclassref(def: tdef): boolean;      begin        is_objcclassref:=          assigned(def) and          (def.typ=classrefdef) and          is_objcclass(tclassrefdef(def).pointeddef);      end;    function is_objcprotocol(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_objcprotocol);      end;    function is_objccategory(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          { if used as a forward type }          ((tobjectdef(def).objecttype=odt_objccategory) or          { if used as after it has been resolved }           ((tobjectdef(def).objecttype=odt_objcclass) and            (oo_is_classhelper in tobjectdef(def).objectoptions)));      end;    function is_objc_class_or_protocol(def: tdef): boolean;      begin         result:=           assigned(def) and           (def.typ=objectdef) and           (tobjectdef(def).objecttype in [odt_objcclass,odt_objcprotocol]);      end;    function is_objc_protocol_or_category(def: tdef): boolean;      begin         result:=           assigned(def) and           (def.typ=objectdef) and           ((tobjectdef(def).objecttype = odt_objcprotocol) or            ((tobjectdef(def).objecttype = odt_objcclass) and             (oo_is_classhelper in tobjectdef(def).objectoptions)));      end;    function is_classhelper(def: tdef): boolean;      begin         result:=           is_objectpascal_helper(def) or           is_objccategory(def);      end;    function is_class_or_interface(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba]);      end;    function is_class_or_interface_or_objc(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_objcclass,odt_objcprotocol]);      end;    function is_class_or_interface_or_objc_or_java(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava]);      end;    function is_class_or_interface_or_dispinterface_or_objc_or_java(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava]);      end;    function is_class_or_interface_or_object(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_object]);      end;    function is_class_or_interface_or_dispinterface(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface]);      end;    function is_implicit_pointer_object_type(def: tdef): boolean;      begin        result:=          assigned(def) and          (((def.typ=objectdef) and            (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava])) or           ((target_info.system in systems_jvm) and            (def.typ=recorddef)));      end;    function is_implicit_array_pointer(def: tdef): boolean;      begin        result:=is_dynamic_array(def) or is_dynamicstring(def);      end;    function is_class_or_object(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_class,odt_object]);      end;    function is_record(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=recorddef);      end;    function is_javaclass(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_javaclass);      end;    function is_javaclassref(def: tdef): boolean;      begin        is_javaclassref:=          assigned(def) and          (def.typ=classrefdef) and          is_javaclass(tclassrefdef(def).pointeddef);      end;    function is_javainterface(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype=odt_interfacejava);      end;    function is_java_class_or_interface(def: tdef): boolean;      begin        result:=          assigned(def) and          (def.typ=objectdef) and          (tobjectdef(def).objecttype in [odt_javaclass,odt_interfacejava]);      end;    procedure loadobjctypes;      begin        objc_metaclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_CLASS',true).typedef);        objc_superclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_SUPER',true).typedef);        objc_idtype:=tpointerdef(search_named_unit_globaltype('OBJC','ID',true).typedef);        objc_seltype:=tpointerdef(search_named_unit_globaltype('OBJC','SEL',true).typedef);        objc_objecttype:=trecorddef(search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef);      end;    procedure maybeloadcocoatypes;      var        tsym: ttypesym;        cocoaunit: string[15];      begin        if assigned(objc_fastenumeration) then          exit;        if not(target_info.system in [system_arm_ios,system_i386_iphonesim,system_aarch64_ios,system_x86_64_iphonesim,system_aarch64_iphonesim]) then          cocoaunit:='COCOAALL'        else          cocoaunit:='IPHONEALL';        tsym:=search_named_unit_globaltype(cocoaunit,'NSFASTENUMERATIONPROTOCOL',false);        if assigned(tsym) then          objc_fastenumeration:=tobjectdef(tsym.typedef)        else          objc_fastenumeration:=nil;        tsym:=search_named_unit_globaltype(cocoaunit,'NSFASTENUMERATIONSTATE',false);        if assigned(tsym) then          objc_fastenumerationstate:=trecorddef(tsym.typedef)        else          objc_fastenumerationstate:=nil;      end;    function use_vectorfpu(def : tdef) : boolean;      begin{$ifdef x86}{$define use_vectorfpuimplemented}        use_vectorfpu:=(is_single(def) and (current_settings.fputype in sse_singlescalar)) or          (is_double(def) and (current_settings.fputype in sse_doublescalar));{$endif x86}{$ifdef arm}{$define use_vectorfpuimplemented}        use_vectorfpu:=FPUARM_HAS_VFP_EXTENSION in fpu_capabilities[current_settings.fputype];{$endif arm}{$ifdef aarch64}{$define use_vectorfpuimplemented}        use_vectorfpu:=true;{$endif aarch64}{$ifndef use_vectorfpuimplemented}        use_vectorfpu:=false;{$endif}      end;end.
 |