symdef.pas 291 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689
  1. {
  2. Symbol table implementation for the definitions
  3. Copyright (c) 1998-2005 by Florian Klaempfl, Pierre Muller
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit symdef;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,widestr,
  23. { global }
  24. globtype,globals,tokens,constexp,
  25. { symtable }
  26. symconst,symbase,symtype,
  27. { node }
  28. node,
  29. { aasm }
  30. aasmtai,
  31. cpuinfo,
  32. cgbase,
  33. parabase
  34. ;
  35. type
  36. {************************************************
  37. TDef
  38. ************************************************}
  39. tgenericconstraintdata=class
  40. interfaces : tfpobjectlist;
  41. interfacesderef : tfplist;
  42. flags : tgenericconstraintflags;
  43. constructor create;
  44. destructor destroy;override;
  45. procedure ppuload(ppufile:tcompilerppufile);
  46. procedure ppuwrite(ppufile:tcompilerppufile);
  47. procedure buildderef;
  48. procedure deref;
  49. end;
  50. { trtti_attribute_list }
  51. trtti_attribute = class
  52. typesym : tsym;
  53. typesymderef : tderef;
  54. typeconstr : tdef;
  55. typeconstrderef : tderef;
  56. { these two are not stored in PPU }
  57. constructorcall : tnode;
  58. constructorpd : tdef;
  59. paras : array of tnode;
  60. constructor ppuload(ppufile:tcompilerppufile);
  61. procedure ppuwrite(ppufile:tcompilerppufile);
  62. procedure ppuload_subentries(ppufile:tcompilerppufile);
  63. procedure ppuwrite_subentries(ppufile:tcompilerppufile);
  64. destructor destroy;override;
  65. procedure buildderef;
  66. procedure deref;
  67. end;
  68. trtti_attribute_list = class
  69. rtti_attributes : TFPObjectList;
  70. { if the attribute list is bound to a def or symbol }
  71. is_bound : Boolean;
  72. class procedure bind(var dangling,owned:trtti_attribute_list);
  73. procedure addattribute(atypesym:tsym;typeconstr:tdef;constructorcall:tnode;constref paras:array of tnode);
  74. procedure addattribute(attr:trtti_attribute);
  75. destructor destroy; override;
  76. function get_attribute_count:longint;
  77. procedure buildderef;
  78. procedure deref;
  79. class function ppuload(ppufile:tcompilerppufile):trtti_attribute_list;
  80. class procedure ppuwrite(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  81. class procedure ppuload_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  82. class procedure ppuwrite_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  83. end;
  84. { tstoreddef }
  85. tstoreddef = class(tdef)
  86. private
  87. {$ifdef symansistr}
  88. _fullownerhierarchyname : ansistring;
  89. {$else symansistr}
  90. _fullownerhierarchyname : pshortstring;
  91. {$endif symansistr}
  92. procedure writeentry(ppufile: tcompilerppufile; ibnr: byte);
  93. protected
  94. typesymderef : tderef;
  95. procedure ppuwrite_platform(ppufile:tcompilerppufile);virtual;
  96. procedure ppuload_platform(ppufile:tcompilerppufile);virtual;
  97. { a (possibly) reusable def is always created on the basis of another
  98. def, and contains a reference to this other def. If this other
  99. def is in a non-persistent symboltable, the new def cannot actually
  100. be safely reused everywhere in the current module. This routine
  101. abtracts that checking, and also restores the symtable stack
  102. (which had to be reset before creating the new def, so that the new
  103. def did not automatically get added to its top) }
  104. class procedure setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);
  105. public
  106. {$ifdef EXTDEBUG}
  107. fileinfo : tfileposinfo;
  108. {$endif}
  109. { generic support }
  110. genericdef : tstoreddef;
  111. genericdefderef : tderef;
  112. generictokenbuf : tdynamicarray;
  113. { this list contains references to the symbols that make up the
  114. generic parameters; the symbols are not owned by this list
  115. Note: this list is allocated on demand! }
  116. genericparas : tfphashobjectlist;
  117. genericparaderefs : tfplist;
  118. { contains additional data if this def is a generic constraint
  119. Note: this class is allocated on demand! }
  120. genconstraintdata : tgenericconstraintdata;
  121. { this is Nil if the def has no RTTI attributes }
  122. rtti_attribute_list : trtti_attribute_list;
  123. constructor create(dt:tdeftyp;doregister:boolean);
  124. constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  125. destructor destroy;override;
  126. function getcopy : tstoreddef;virtual;
  127. procedure ppuwrite(ppufile:tcompilerppufile);virtual;
  128. { this is called directly after ppuload }
  129. procedure ppuload_subentries(ppufile:tcompilerppufile);virtual;
  130. { this is called directly after ppuwrite }
  131. procedure ppuwrite_subentries(ppufile:tcompilerppufile);virtual;
  132. procedure buildderef;override;
  133. procedure buildderefimpl;override;
  134. procedure deref;override;
  135. procedure derefimpl;override;
  136. function size:asizeint;override;
  137. function getvardef:longint;override;
  138. function alignment:shortint;override;
  139. function is_publishable : boolean;override;
  140. function needs_inittable : boolean;override;
  141. function has_non_trivial_init_child(check_parent:boolean):boolean;override;
  142. function rtti_mangledname(rt:trttitype):TSymStr;override;
  143. function OwnerHierarchyName: string; override;
  144. function fullownerhierarchyname(skipprocparams:boolean):TSymStr;override;
  145. function needs_separate_initrtti:boolean;override;
  146. function in_currentunit: boolean;
  147. { regvars }
  148. function is_intregable : boolean;
  149. function is_fpuregable : boolean;
  150. { def can be put into a register if it is const/immutable }
  151. function is_const_intregable : boolean;
  152. { generics }
  153. procedure initgeneric;
  154. { this function can be used to determine whether a def is really a
  155. generic declaration or just a normal type declared inside another
  156. generic }
  157. function is_generic:boolean;
  158. { same as above for specializations }
  159. function is_specialization:boolean;
  160. { registers this def in the unit's deflist; no-op if already registered }
  161. procedure register_def; override;
  162. { add the def to the top of the symtable stack if it's not yet owned
  163. by another symtable }
  164. procedure maybe_put_in_symtable_stack;
  165. private
  166. savesize : asizeuint;
  167. end;
  168. tfiletyp = (ft_text,ft_typed,ft_untyped);
  169. tfiledef = class(tstoreddef)
  170. filetyp : tfiletyp;
  171. typedfiledef : tdef;
  172. typedfiledefderef : tderef;
  173. constructor createtext;virtual;
  174. constructor createuntyped;virtual;
  175. constructor createtyped(def : tdef);virtual;
  176. constructor ppuload(ppufile:tcompilerppufile);
  177. function getcopy : tstoreddef;override;
  178. { do not override this routine in platform-specific subclasses,
  179. override ppuwrite_platform instead }
  180. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  181. procedure buildderef;override;
  182. procedure deref;override;
  183. function GetTypeName:string;override;
  184. function getmangledparaname:TSymStr;override;
  185. function size:asizeint;override;
  186. procedure setsize;
  187. function alignment: shortint; override;
  188. end;
  189. tfiledefclass = class of tfiledef;
  190. tvariantdef = class(tstoreddef)
  191. varianttype : tvarianttype;
  192. constructor create(v : tvarianttype);virtual;
  193. constructor ppuload(ppufile:tcompilerppufile);
  194. function getcopy : tstoreddef;override;
  195. function GetTypeName:string;override;
  196. { do not override this routine in platform-specific subclasses,
  197. override ppuwrite_platform instead }
  198. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  199. function getvardef:longint;override;
  200. procedure setsize;
  201. function is_publishable : boolean;override;
  202. function needs_inittable : boolean;override;
  203. end;
  204. tvariantdefclass = class of tvariantdef;
  205. tformaldef = class(tstoreddef)
  206. typed:boolean;
  207. constructor create(Atyped:boolean);virtual;
  208. constructor ppuload(ppufile:tcompilerppufile);
  209. { do not override this routine in platform-specific subclasses,
  210. override ppuwrite_platform instead }
  211. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  212. function GetTypeName:string;override;
  213. end;
  214. tformaldefclass = class of tformaldef;
  215. tforwarddef = class(tstoreddef)
  216. tosymname : pshortstring;
  217. forwardpos : tfileposinfo;
  218. constructor create(const s:string;const pos:tfileposinfo);virtual;
  219. destructor destroy;override;
  220. function getcopy:tstoreddef;override;
  221. function GetTypeName:string;override;
  222. end;
  223. tforwarddefclass = class of tforwarddef;
  224. tundefineddef = class(tstoreddef)
  225. constructor create(doregister:boolean);virtual;
  226. constructor ppuload(ppufile:tcompilerppufile);
  227. { do not override this routine in platform-specific subclasses,
  228. override ppuwrite_platform instead }
  229. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  230. function GetTypeName:string;override;
  231. end;
  232. tundefineddefclass = class of tundefineddef;
  233. terrordef = class(tstoreddef)
  234. constructor create;virtual;
  235. { do not override this routine in platform-specific subclasses,
  236. override ppuwrite_platform instead }
  237. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  238. function GetTypeName:string;override;
  239. function getmangledparaname : TSymStr;override;
  240. end;
  241. terrordefclass = class of terrordef;
  242. tabstractpointerdef = class(tstoreddef)
  243. pointeddef : tdef;
  244. pointeddefderef : tderef;
  245. constructor create(dt:tdeftyp;def:tdef);
  246. constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  247. procedure ppuwrite(ppufile:tcompilerppufile);override;
  248. procedure buildderef;override;
  249. procedure deref;override;
  250. function size:asizeint;override;
  251. function alignment:shortint;override;
  252. end;
  253. tpointerdef = class(tabstractpointerdef)
  254. has_pointer_math : boolean;
  255. constructor create(def:tdef);virtual;
  256. { returns a pointerdef for def, reusing an existing one in case it
  257. exists in the current module }
  258. class function getreusable(def: tdef): tpointerdef; virtual;
  259. { same as above, but in case the def must never be freed after the
  260. current module has been compiled -- even if the def was not written
  261. to the ppu file (for defs in para locations, as we don't reset them
  262. so we don't have to recalculate them all the time) }
  263. class function getreusable_no_free(def: tdef): tpointerdef;
  264. function size:asizeint;override;
  265. function getcopy:tstoreddef;override;
  266. constructor ppuload(ppufile:tcompilerppufile);
  267. { do not override this routine in platform-specific subclasses,
  268. override ppuwrite_platform instead }
  269. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  270. function GetTypeName:string;override;
  271. {# returns the appropriate int type for pointer arithmetic with the given pointer type.
  272. When adding or subtracting a number to/from a pointer, this function returns the
  273. int type to which that number has to be converted, before the operation can be performed.
  274. Normally, this is sinttype, except on i8086, where it takes into account the
  275. special i8086 pointer types (near, far, huge). }
  276. function pointer_arithmetic_int_type:tdef;virtual;
  277. {# the unsigned version of pointer_arithmetic_int_type. Used with inc/dec. }
  278. function pointer_arithmetic_uint_type:tdef;virtual;
  279. {# returns the int type produced when subtracting two pointers of the given type.
  280. Normally, this is sinttype, except on i8086, where it takes into account the
  281. special i8086 pointer types (near, far, huge). }
  282. function pointer_subtraction_result_type:tdef;virtual;
  283. function compatible_with_pointerdef_size(ptr: tpointerdef): boolean; virtual;
  284. {# the integer index type used to convert the pointer to array (i.e. denotes int_type in: ptr[int_type]) }
  285. function converted_pointer_to_array_range_type:tdef;virtual;
  286. end;
  287. tpointerdefclass = class of tpointerdef;
  288. tprocdef = class;
  289. tabstractrecorddef= class(tstoreddef)
  290. private
  291. rttistring : string;
  292. public
  293. objname,
  294. objrealname : PShortString;
  295. { for C++ classes: name of the library this class is imported from }
  296. { for Java classes/records: package name }
  297. import_lib : PShortString;
  298. symtable : TSymtable;
  299. cloneddef : tabstractrecorddef;
  300. cloneddefderef : tderef;
  301. objectoptions : tobjectoptions;
  302. { for targets that initialise typed constants via explicit assignments
  303. instead of by generating an initialised data sectino }
  304. tcinitcode : tnode;
  305. constructor create(const n:string; dt:tdeftyp;doregister:boolean);
  306. constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  307. procedure ppuwrite(ppufile:tcompilerppufile);override;
  308. destructor destroy; override;
  309. procedure buildderefimpl;override;
  310. procedure derefimpl;override;
  311. procedure check_forwards; virtual;
  312. function find_procdef_bytype(pt:tproctypeoption): tprocdef;
  313. function GetSymtable(t:tGetSymtable):TSymtable;override;
  314. function is_packed:boolean;
  315. function RttiName: string;
  316. { enumerator support }
  317. function search_enumerator_get: tprocdef; virtual;
  318. function search_enumerator_move: tprocdef; virtual;
  319. function search_enumerator_current: tsym; virtual;
  320. { JVM }
  321. function jvm_full_typename(with_package_name: boolean): string;
  322. { check if the symtable contains a float field }
  323. function contains_float_field : boolean;
  324. { check if the symtable contains a field that spans an aword boundary }
  325. function contains_cross_aword_field: boolean;
  326. end;
  327. pvariantrecdesc = ^tvariantrecdesc;
  328. tvariantrecbranch = record
  329. { we store only single values here and no ranges because tvariantrecdesc is only needed in iso mode
  330. which does not support range expressions in variant record definitions }
  331. values : array of Tconstexprint;
  332. nestedvariant : pvariantrecdesc;
  333. end;
  334. ppvariantrecdesc = ^pvariantrecdesc;
  335. tvariantrecdesc = record
  336. variantselector : tsym;
  337. variantselectorderef : tderef;
  338. branches : array of tvariantrecbranch;
  339. end;
  340. trecorddef = class(tabstractrecorddef)
  341. public
  342. variantrecdesc : pvariantrecdesc;
  343. isunion : boolean;
  344. constructor create(const n:string; p:TSymtable);virtual;
  345. constructor create_global_internal(n: string; packrecords, recordalignmin, maxCrecordalign: shortint); virtual;
  346. function add_field_by_def(const optionalname: TIDString; def: tdef): tsym;
  347. procedure add_fields_from_deflist(fieldtypes: tfplist);
  348. constructor ppuload(ppufile:tcompilerppufile);
  349. destructor destroy;override;
  350. function getcopy : tstoreddef;override;
  351. { do not override this routine in platform-specific subclasses,
  352. override ppuwrite_platform instead }
  353. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  354. procedure buildderef;override;
  355. procedure deref;override;
  356. function size:asizeint;override;
  357. function alignment : shortint;override;
  358. function padalignment: shortint;
  359. function GetTypeName:string;override;
  360. { debug }
  361. function needs_inittable : boolean;override;
  362. function needs_separate_initrtti:boolean;override;
  363. function has_non_trivial_init_child(check_parent:boolean):boolean;override;
  364. end;
  365. trecorddefclass = class of trecorddef;
  366. tobjectdef = class;
  367. { TImplementedInterface }
  368. TImplementedInterface = class
  369. private
  370. fIOffset : longint;
  371. function GetIOffset: longint;
  372. public
  373. IntfDef : tobjectdef;
  374. IntfDefDeref : tderef;
  375. IType : tinterfaceentrytype;
  376. VtblImplIntf : TImplementedInterface;
  377. NameMappings : TFPHashList;
  378. ProcDefs : TFPObjectList;
  379. ImplementsGetter : tsym;
  380. ImplementsGetterDeref : tderef;
  381. ImplementsField : tsym;
  382. constructor create(aintf: tobjectdef);virtual;
  383. constructor create_deref(intfd,getterd:tderef);virtual;
  384. destructor destroy; override;
  385. function getcopy:TImplementedInterface;
  386. procedure buildderef;
  387. procedure deref;
  388. procedure AddMapping(const origname, newname: string);
  389. function GetMapping(const origname: string):string;
  390. procedure AddImplProc(pd:tprocdef);
  391. function IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;
  392. property IOffset: longint read GetIOffset write fIOffset;
  393. end;
  394. timplementedinterfaceclass = class of timplementedinterface;
  395. { tvmtentry }
  396. tvmtentry = record
  397. procdef : tprocdef;
  398. procdefderef : tderef;
  399. visibility : tvisibility;
  400. end;
  401. pvmtentry = ^tvmtentry;
  402. { tobjectdef }
  403. tvmcallstatic = (vmcs_default, vmcs_yes, vmcs_no, vmcs_unreachable);
  404. pmvcallstaticinfo = ^tmvcallstaticinfo;
  405. tmvcallstaticinfo = array[0..1024*1024-1] of tvmcallstatic;
  406. tobjectdef = class(tabstractrecorddef)
  407. private
  408. fcurrent_dispid: longint;
  409. public
  410. childof : tobjectdef;
  411. childofderef : tderef;
  412. { for Object Pascal helpers }
  413. extendeddef : tdef;
  414. extendeddefderef: tderef;
  415. helpertype : thelpertype;
  416. { for Objective-C: protocols and classes can have the same name there }
  417. objextname : pshortstring;
  418. { to be able to have a variable vmt position }
  419. { and no vmt field for objects without virtuals }
  420. vmtentries : TFPList;
  421. vmcallstaticinfo : pmvcallstaticinfo;
  422. vmt_field : tsym;
  423. vmt_fieldderef : tderef;
  424. iidguid : pguid;
  425. iidstr : pshortstring;
  426. { store implemented interfaces defs and name mappings }
  427. ImplementedInterfaces : TFPObjectList;
  428. { number of abstract methods (used by JVM target to determine whether
  429. or not the class should be marked as abstract: must be done if 1 or
  430. more abstract methods) }
  431. abstractcnt : longint;
  432. writing_class_record_dbginfo,
  433. { a class of this type has been created in this module }
  434. created_in_current_module,
  435. { a loadvmtnode for this class has been created in this
  436. module, so if a classrefdef variable of this or a parent
  437. class is used somewhere to instantiate a class, then this
  438. class may be instantiated
  439. }
  440. maybe_created_in_current_module,
  441. { a "class of" this particular class has been created in
  442. this module
  443. }
  444. classref_created_in_current_module : boolean;
  445. objecttype : tobjecttyp;
  446. constructor create(ot:tobjecttyp;const n:string;c:tobjectdef;doregister:boolean);virtual;
  447. constructor ppuload(ppufile:tcompilerppufile);
  448. destructor destroy;override;
  449. function getcopy : tstoreddef;override;
  450. { do not override this routine in platform-specific subclasses,
  451. override ppuwrite_platform instead }
  452. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  453. function GetTypeName:string;override;
  454. procedure buildderef;override;
  455. procedure deref;override;
  456. procedure derefimpl;override;
  457. procedure resetvmtentries;
  458. procedure copyvmtentries(objdef:tobjectdef);
  459. function getparentdef:tdef;override;
  460. function size : asizeint;override;
  461. function alignment:shortint;override;
  462. function vmtmethodoffset(index:longint):longint;
  463. function members_need_inittable : boolean;
  464. { this should be called when this class implements an interface }
  465. procedure prepareguid;
  466. function is_publishable : boolean;override;
  467. function needs_inittable : boolean;override;
  468. function needs_separate_initrtti : boolean;override;
  469. function has_non_trivial_init_child(check_parent:boolean):boolean;override;
  470. function rtti_mangledname(rt:trttitype):TSymStr;override;
  471. function vmt_mangledname : TSymStr;
  472. function vmt_def: trecorddef;
  473. procedure check_forwards; override;
  474. procedure insertvmt;
  475. function vmt_offset: asizeint;
  476. procedure set_parent(c : tobjectdef);
  477. function find_destructor: tprocdef;
  478. function implements_any_interfaces: boolean;
  479. { dispinterface support }
  480. function get_next_dispid: longint;
  481. { enumerator support }
  482. function search_enumerator_get: tprocdef; override;
  483. function search_enumerator_move: tprocdef; override;
  484. function search_enumerator_current: tsym; override;
  485. { WPO }
  486. procedure register_created_object_type;override;
  487. procedure register_maybe_created_object_type;
  488. procedure register_created_classref_type;
  489. procedure register_vmt_call(index:longint);
  490. { ObjC }
  491. procedure finish_objc_data;
  492. function check_objc_types: boolean;
  493. { C++ }
  494. procedure finish_cpp_data;
  495. end;
  496. tobjectdefclass = class of tobjectdef;
  497. tclassrefdef = class(tabstractpointerdef)
  498. constructor create(def:tdef);virtual;
  499. constructor ppuload(ppufile:tcompilerppufile);
  500. { do not override this routine in platform-specific subclasses,
  501. override ppuwrite_platform instead }
  502. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  503. function getcopy:tstoreddef;override;
  504. function GetTypeName:string;override;
  505. function is_publishable : boolean;override;
  506. function rtti_mangledname(rt:trttitype):TSymStr;override;
  507. procedure register_created_object_type;override;
  508. end;
  509. tclassrefdefclass = class of tclassrefdef;
  510. tarraydef = class(tstoreddef)
  511. lowrange,
  512. highrange : asizeint;
  513. rangedef : tdef;
  514. rangedefderef : tderef;
  515. arrayoptions : tarraydefoptions;
  516. symtable : TSymtable;
  517. protected
  518. _elementdef : tdef;
  519. _elementdefderef : tderef;
  520. procedure setelementdef(def:tdef);
  521. public
  522. function elesize : asizeint;
  523. function elepackedbitsize : asizeint;
  524. function elecount : asizeuint;
  525. constructor create_from_pointer(def:tpointerdef);virtual;
  526. constructor create(l,h:asizeint;def:tdef);virtual;
  527. constructor create_openarray;virtual;
  528. class function getreusable(def: tdef; elems: asizeint): tarraydef; virtual;
  529. { same as above, but in case the def must never be freed after the
  530. current module has been compiled -- even if the def was not written
  531. to the ppu file (for defs in para locations, as we don't reset them
  532. so we don't have to recalculate them all the time) }
  533. class function getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
  534. constructor ppuload(ppufile:tcompilerppufile);
  535. destructor destroy; override;
  536. function getcopy : tstoreddef;override;
  537. { do not override this routine in platform-specific subclasses,
  538. override ppuwrite_platform instead }
  539. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  540. function GetTypeName:string;override;
  541. function getmangledparaname : TSymStr;override;
  542. procedure buildderef;override;
  543. procedure deref;override;
  544. function size : asizeint;override;
  545. function alignment : shortint;override;
  546. { returns the label of the range check string }
  547. function needs_inittable : boolean;override;
  548. function needs_separate_initrtti : boolean;override;
  549. property elementdef : tdef read _elementdef write setelementdef;
  550. function is_publishable : boolean;override;
  551. end;
  552. tarraydefclass = class of tarraydef;
  553. torddef = class(tstoreddef)
  554. low,high : TConstExprInt;
  555. ordtype : tordtype;
  556. constructor create(t : tordtype;v,b : TConstExprInt; doregister: boolean);virtual;
  557. constructor ppuload(ppufile:tcompilerppufile);
  558. function getcopy : tstoreddef;override;
  559. { do not override this routine in platform-specific subclasses,
  560. override ppuwrite_platform instead }
  561. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  562. function is_publishable : boolean;override;
  563. function GetTypeName:string;override;
  564. function alignment:shortint;override;
  565. procedure setsize;
  566. function packedbitsize: asizeint; override;
  567. function getvardef : longint;override;
  568. end;
  569. torddefclass = class of torddef;
  570. tfloatdef = class(tstoreddef)
  571. floattype : tfloattype;
  572. constructor create(t: tfloattype; doregister: boolean);virtual;
  573. constructor ppuload(ppufile:tcompilerppufile);
  574. function getcopy : tstoreddef;override;
  575. { do not override this routine in platform-specific subclasses,
  576. override ppuwrite_platform instead }
  577. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  578. function GetTypeName:string;override;
  579. function is_publishable : boolean;override;
  580. function alignment:shortint;override;
  581. function structalignment: shortint;override;
  582. procedure setsize;
  583. function getvardef:longint;override;
  584. end;
  585. tfloatdefclass = class of tfloatdef;
  586. { tabstractprocdef }
  587. tprocnameoption = (pno_showhidden, pno_proctypeoption, pno_paranames,
  588. pno_ownername, pno_noclassmarker, pno_noleadingdollar,
  589. pno_mangledname, pno_noparams);
  590. tprocnameoptions = set of tprocnameoption;
  591. tproccopytyp = (pc_normal,
  592. { everything except for hidden parameters }
  593. pc_normal_no_hidden,
  594. { always creates a top-level function, removes all
  595. special parameters (self, vmt, parentfp, ...) }
  596. pc_bareproc,
  597. { creates a procvardef describing only the code pointer
  598. of a method/netsted function/... }
  599. pc_address_only
  600. );
  601. tabstractprocdef = class(tstoreddef)
  602. { saves a definition to the return type }
  603. returndef : tdef;
  604. returndefderef : tderef;
  605. parast : TSymtable;
  606. paras : tparalist;
  607. proctypeoption : tproctypeoption;
  608. proccalloption : tproccalloption;
  609. procoptions : tprocoptions;
  610. callerargareasize,
  611. calleeargareasize: pint;
  612. {$ifdef m68k}
  613. exp_funcretloc : tregister; { explicit funcretloc for AmigaOS }
  614. {$endif}
  615. funcretloc : array[callerside..calleeside] of TCGPara;
  616. has_paraloc_info : tcallercallee; { paraloc info is available }
  617. { number of user visible parameters }
  618. maxparacount,
  619. minparacount : byte;
  620. constructor create(dt:tdeftyp;level:byte;doregister:boolean);
  621. constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  622. destructor destroy;override;
  623. procedure ppuwrite(ppufile:tcompilerppufile);override;
  624. procedure buildderef;override;
  625. procedure deref;override;
  626. procedure calcparas;
  627. function mangledprocparanames(oldlen : longint) : string;
  628. function typename_paras(pno: tprocnameoptions): ansistring;
  629. function is_methodpointer:boolean;virtual;
  630. function is_addressonly:boolean;virtual;
  631. function no_self_node:boolean;
  632. { get either a copy as a procdef or procvardef }
  633. function getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string): tstoreddef; virtual;
  634. function compatible_with_pointerdef_size(ptr: tpointerdef): boolean; virtual;
  635. procedure check_mark_as_nested;
  636. procedure init_paraloc_info(side: tcallercallee);
  637. procedure done_paraloc_info(side: tcallercallee);
  638. function stack_tainting_parameter(side: tcallercallee): boolean;
  639. function is_pushleftright: boolean;virtual;
  640. function address_type:tdef;virtual;
  641. { address type, generated for ofs() }
  642. function ofs_address_type:tdef;virtual;
  643. procedure declared_far;virtual;
  644. procedure declared_near;virtual;
  645. private
  646. procedure count_para(p:TObject;arg:pointer);
  647. procedure insert_para(p:TObject;arg:pointer);
  648. end;
  649. tprocvardef = class(tabstractprocdef)
  650. constructor create(level:byte);virtual;
  651. { returns a procvardef that represents the address of a proc(var)def }
  652. class function getreusableprocaddr(def: tabstractprocdef): tprocvardef; virtual;
  653. { same as above, but in case the def must never be freed after the
  654. current module has been compiled -- even if the def was not written
  655. to the ppu file (for defs in para locations, as we don't reset them
  656. so we don't have to recalculate them all the time) }
  657. class function getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
  658. constructor ppuload(ppufile:tcompilerppufile);
  659. function getcopy : tstoreddef;override;
  660. { do not override this routine in platform-specific subclasses,
  661. override ppuwrite_platform instead }
  662. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  663. function GetSymtable(t:tGetSymtable):TSymtable;override;
  664. function size : asizeint;override;
  665. function GetTypeName:string;override;
  666. function is_publishable : boolean;override;
  667. function is_methodpointer:boolean;override;
  668. function is_addressonly:boolean;override;
  669. function getmangledparaname:TSymStr;override;
  670. function getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string): tstoreddef; override;
  671. end;
  672. tprocvardefclass = class of tprocvardef;
  673. tmessageinf = record
  674. case integer of
  675. 0 : (str : pshortstring);
  676. 1 : (i : longint);
  677. end;
  678. tinlininginfo = record
  679. { node tree }
  680. code : tnode;
  681. flags : tprocinfoflags;
  682. end;
  683. pinlininginfo = ^tinlininginfo;
  684. {$ifdef oldregvars}
  685. { register variables }
  686. pregvarinfo = ^tregvarinfo;
  687. tregvarinfo = record
  688. regvars : array[1..maxvarregs] of tsym;
  689. regvars_para : array[1..maxvarregs] of boolean;
  690. regvars_refs : array[1..maxvarregs] of longint;
  691. fpuregvars : array[1..maxfpuvarregs] of tsym;
  692. fpuregvars_para : array[1..maxfpuvarregs] of boolean;
  693. fpuregvars_refs : array[1..maxfpuvarregs] of longint;
  694. end;
  695. {$endif oldregvars}
  696. timplprocdefinfo = record
  697. resultname : pshortstring;
  698. parentfpstruct: tsym;
  699. parentfpstructptrtype: tdef;
  700. parentfpinitblock: tnode;
  701. procstarttai,
  702. procendtai : tai;
  703. skpara: pointer;
  704. personality: tprocdef;
  705. forwarddef,
  706. interfacedef : boolean;
  707. hasforward : boolean;
  708. end;
  709. pimplprocdefinfo = ^timplprocdefinfo;
  710. { tprocdef }
  711. tprocdef = class(tabstractprocdef)
  712. protected
  713. {$ifdef symansistr}
  714. _mangledname : ansistring;
  715. {$else symansistr}
  716. _mangledname : pshortstring;
  717. {$endif}
  718. { information that is only required until the implementation of the
  719. procdef has been handled }
  720. implprocdefinfo : pimplprocdefinfo;
  721. function GetResultName: PShortString;
  722. procedure SetResultName(AValue: PShortString);
  723. function GetParentFPStruct: tsym;
  724. procedure SetParentFPStruct(AValue: tsym);
  725. function GetParentFPStructPtrType: tdef;
  726. procedure SetParentFPStructPtrType(AValue: tdef);
  727. function GetParentFPInitBlock: tnode;
  728. procedure SetParentFPInitBlock(AValue: tnode);
  729. function Getprocstarttai: tai;
  730. procedure Setprocstarttai(AValue: tai);
  731. function Getprocendtai: tai;
  732. procedure Setprocendtai(AValue: tai);
  733. function Getskpara: pointer;
  734. procedure Setskpara(AValue: pointer);
  735. function Getpersonality: tprocdef;
  736. procedure Setpersonality(AValue: tprocdef);
  737. function Getforwarddef: boolean;
  738. procedure Setforwarddef(AValue: boolean);
  739. function Getinterfacedef: boolean;
  740. procedure Setinterfacedef(AValue: boolean);virtual;
  741. function Gethasforward: boolean;
  742. procedure Sethasforward(AValue: boolean);
  743. function GetIsEmpty: boolean;
  744. procedure SetIsEmpty(AValue: boolean);
  745. function GetHasInliningInfo: boolean;
  746. procedure SetHasInliningInfo(AValue: boolean);
  747. public
  748. messageinf : tmessageinf;
  749. dispid : longint;
  750. {$ifndef EXTDEBUG}
  751. { where is this function defined and what were the symbol
  752. flags, needed here because there
  753. is only one symbol for all overloaded functions
  754. EXTDEBUG has fileinfo in tdef (PFV) }
  755. fileinfo : tfileposinfo;
  756. {$endif}
  757. symoptions : tsymoptions;
  758. deprecatedmsg : pshortstring;
  759. { generic support }
  760. genericdecltokenbuf : tdynamicarray;
  761. { symbol owning this definition }
  762. procsym : tsym;
  763. procsymderef : tderef;
  764. { alias names }
  765. aliasnames : TCmdStrList;
  766. { symtables }
  767. localst : TSymtable;
  768. funcretsym : tsym;
  769. funcretsymderef : tderef;
  770. struct : tabstractrecorddef;
  771. structderef : tderef;
  772. implprocoptions: timplprocoptions;
  773. { import info }
  774. import_dll,
  775. import_name : pshortstring;
  776. { info for inlining the subroutine, if this pointer is nil,
  777. the procedure can't be inlined }
  778. inlininginfo : pinlininginfo;
  779. {$ifdef oldregvars}
  780. regvarinfo: pregvarinfo;
  781. {$endif oldregvars}
  782. import_nr : word;
  783. extnumber : word;
  784. { set to a value different from tsk_none in case this procdef is for
  785. a routine that has to be internally generated by the compiler }
  786. synthetickind: tsynthetickind;
  787. visibility : tvisibility;
  788. constructor create(level:byte;doregister:boolean);virtual;
  789. constructor ppuload(ppufile:tcompilerppufile);
  790. destructor destroy;override;
  791. procedure freeimplprocdefinfo;
  792. { do not override this routine in platform-specific subclasses,
  793. override ppuwrite_platform instead }
  794. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  795. procedure buildderef;override;
  796. procedure buildderefimpl;override;
  797. procedure deref;override;
  798. procedure derefimpl;override;
  799. function GetSymtable(t:tGetSymtable):TSymtable;override;
  800. { warnings:
  801. * the symtablestack top has to be the symtable to which the copy
  802. should be added
  803. * getcopy does not create a finished/ready-to-use procdef; it
  804. needs to be finalised afterwards by calling
  805. symcreat.finish_copied_procdef() afterwards
  806. }
  807. function getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string): tstoreddef; override;
  808. function getcopy: tstoreddef; override;
  809. function GetTypeName : string;override;
  810. function mangledname : TSymStr; virtual;
  811. procedure setmangledname(const s : TSymStr);
  812. function needsglobalasmsym: boolean;
  813. procedure setcompilerprocname;
  814. function fullprocname(showhidden:boolean):string;
  815. function customprocname(pno: tprocnameoptions):ansistring;
  816. function defaultmangledname: TSymStr;
  817. function cplusplusmangledname : TSymStr;
  818. function objcmangledname : TSymStr;
  819. function is_methodpointer:boolean;override;
  820. function is_addressonly:boolean;override;
  821. procedure make_external;
  822. procedure init_genericdecl;
  823. function getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean; virtual;
  824. { returns whether the mangled name or any of its aliases is equal to
  825. s }
  826. function has_alias_name(const s: TSymStr):boolean;
  827. { aliases to fields only required when a function is implemented in
  828. the current unit }
  829. property resultname: PShortString read GetResultName write SetResultName;
  830. { temporary reference to structure containing copies of all local
  831. variables and parameters accessed by nested routines; reference to
  832. this structure is passed as "parent frame pointer" on targets that
  833. lack this concept (at least JVM and LLVM); no need to save to/
  834. restore from ppu, since nested routines are always in the same
  835. unit }
  836. property parentfpstruct: tsym read GetParentFPStruct write SetParentFPStruct;
  837. { pointer to parentfpstruct's type (not yet valid during parsing, so
  838. cannot be used for $parentfp parameter) (no need to save to ppu) }
  839. property parentfpstructptrtype: tdef read GetParentFPStructPtrType write SetParentFPStructPtrType;
  840. { code to copy the parameters accessed from nested routines into the
  841. parentfpstruct (no need to save to ppu) }
  842. property parentfpinitblock: tnode read GetParentFPInitBlock write SetParentFPInitBlock;
  843. { First/last assembler symbol/instruction in aasmoutput list.
  844. Note: initialised after compiling the code for the procdef, but
  845. not saved to/restored from ppu. Used when inserting debug info }
  846. property procstarttai: tai read Getprocstarttai write Setprocstarttai;
  847. property procendtai: tai read Getprocendtai write Setprocendtai;
  848. { optional parameter for the synthetic routine generation logic }
  849. property skpara: pointer read Getskpara write Setskpara;
  850. { ABI-conformant exception handling personality function }
  851. property personality: tprocdef read Getpersonality write Setpersonality;
  852. { true, if the procedure is only declared
  853. (forward procedure) }
  854. property forwarddef: boolean read Getforwarddef write Setforwarddef;
  855. { true if the procedure is declared in the interface }
  856. property interfacedef: boolean read Getinterfacedef write Setinterfacedef;
  857. { true if the procedure has a forward declaration }
  858. property hasforward: boolean read Gethasforward write Sethasforward;
  859. { true if the routine's body is empty }
  860. property isempty: boolean read GetIsEmpty write SetIsEmpty;
  861. { true if all information required to inline this routine is available }
  862. property has_inlininginfo: boolean read GetHasInliningInfo write SetHasInliningInfo;
  863. end;
  864. tprocdefclass = class of tprocdef;
  865. { single linked list of overloaded procs }
  866. pprocdeflist = ^tprocdeflist;
  867. tprocdeflist = record
  868. def : tprocdef;
  869. defderef : tderef;
  870. next : pprocdeflist;
  871. end;
  872. tstringdef = class(tstoreddef)
  873. encoding : tstringencoding;
  874. stringtype : tstringtype;
  875. len : asizeint;
  876. constructor createshort(l: byte; doregister: boolean);virtual;
  877. constructor loadshort(ppufile:tcompilerppufile);
  878. constructor createlong(l: asizeint; doregister: boolean);virtual;
  879. constructor loadlong(ppufile:tcompilerppufile);
  880. constructor createansi(aencoding: tstringencoding; doregister: boolean);virtual;
  881. constructor loadansi(ppufile:tcompilerppufile);
  882. constructor createwide(doregister: boolean);virtual;
  883. constructor loadwide(ppufile:tcompilerppufile);
  884. constructor createunicode(doregister: boolean);virtual;
  885. constructor loadunicode(ppufile:tcompilerppufile);virtual;
  886. function getcopy : tstoreddef;override;
  887. function stringtypname:string;
  888. { do not override this routine in platform-specific subclasses,
  889. override ppuwrite_platform instead }
  890. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  891. function GetTypeName:string;override;
  892. function getmangledparaname:TSymStr;override;
  893. function is_publishable : boolean;override;
  894. function size:asizeint;override;
  895. function alignment : shortint;override;
  896. function needs_inittable : boolean;override;
  897. function getvardef:longint;override;
  898. end;
  899. tstringdefclass = class of tstringdef;
  900. { tenumdef }
  901. tenumdef = class(tstoreddef)
  902. minval,
  903. maxval : asizeint;
  904. basedef : tenumdef;
  905. basedefderef : tderef;
  906. symtable : TSymtable;
  907. has_jumps : boolean;
  908. constructor create;virtual;
  909. constructor create_subrange(_basedef:tenumdef;_min,_max:asizeint);virtual;
  910. constructor ppuload(ppufile:tcompilerppufile);
  911. destructor destroy;override;
  912. function getcopy : tstoreddef;override;
  913. { do not override this routine in platform-specific subclasses,
  914. override ppuwrite_platform instead }
  915. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  916. procedure buildderef;override;
  917. procedure deref;override;
  918. function GetTypeName:string;override;
  919. function is_publishable : boolean;override;
  920. procedure calcsavesize(packenum: shortint);
  921. function packedbitsize: asizeint; override;
  922. procedure setmax(_max:asizeint);
  923. procedure setmin(_min:asizeint);
  924. function min:asizeint;
  925. function max:asizeint;
  926. function getfirstsym:tsym;
  927. function int2enumsym(l: asizeint): tsym;
  928. { returns basedef if assigned, otherwise self }
  929. function getbasedef: tenumdef;
  930. end;
  931. tenumdefclass = class of tenumdef;
  932. tsetdef = class(tstoreddef)
  933. elementdef : tdef;
  934. elementdefderef : tderef;
  935. setbase,
  936. setmax : asizeint;
  937. constructor create(def: tdef; low, high: asizeint; doregister: boolean);virtual;
  938. constructor ppuload(ppufile:tcompilerppufile);
  939. function getcopy : tstoreddef;override;
  940. { do not override this routine in platform-specific subclasses,
  941. override ppuwrite_platform instead }
  942. procedure ppuwrite(ppufile:tcompilerppufile);override;final;
  943. procedure buildderef;override;
  944. procedure deref;override;
  945. function GetTypeName:string;override;
  946. function is_publishable : boolean;override;
  947. function alignment: shortint; override;
  948. end;
  949. tsetdefclass = class of tsetdef;
  950. tgenericdummyentry = class
  951. dummysym : tsym;
  952. resolvedsym : tsym;
  953. end;
  954. tdefawaresymtablestack = class(TSymtablestack)
  955. private
  956. procedure add_helpers_and_generics(st:tsymtable;addgenerics:boolean);
  957. procedure remove_helpers_and_generics(st:tsymtable);inline;
  958. procedure remove_helpers(st:tsymtable);
  959. procedure remove_generics(st:tsymtable);
  960. procedure pushcommon(st:tsymtable);inline;
  961. public
  962. procedure push(st: TSymtable); override;
  963. procedure pushafter(st,afterst:TSymtable); override;
  964. procedure pop(st: TSymtable); override;
  965. end;
  966. var
  967. current_structdef: tabstractrecorddef; { used for private functions check !! }
  968. current_genericdef: tstoreddef; { used to reject declaration of generic class inside generic class }
  969. current_specializedef: tstoreddef; { used to implement usage of generic class in itself }
  970. cfiledef: tfiledefclass;
  971. cvariantdef: tvariantdefclass;
  972. cformaldef: tformaldefclass;
  973. cforwarddef: tforwarddefclass;
  974. cundefineddef: tundefineddefclass;
  975. cerrordef: terrordefclass;
  976. cpointerdef: tpointerdefclass;
  977. crecorddef: trecorddefclass;
  978. cimplementedinterface: timplementedinterfaceclass;
  979. cobjectdef: tobjectdefclass;
  980. cclassrefdef: tclassrefdefclass;
  981. carraydef: tarraydefclass;
  982. corddef: torddefclass;
  983. cfloatdef: tfloatdefclass;
  984. cprocvardef: tprocvardefclass;
  985. cprocdef: tprocdefclass;
  986. cstringdef: tstringdefclass;
  987. cenumdef: tenumdefclass;
  988. csetdef: tsetdefclass;
  989. { default types }
  990. generrordef, { error in definition }
  991. voidpointertype, { pointer for Void-pointeddef }
  992. charpointertype, { pointer for Char-pointeddef }
  993. widecharpointertype, { pointer for WideChar-pointeddef }
  994. voidcodepointertype, { pointer to code; corresponds to System.CodePointer }
  995. voidstackpointertype, { the pointer type used for accessing parameters and local vars on the stack }
  996. parentfpvoidpointertype, { void pointer with the size of the hidden parentfp parameter, passed to nested functions }
  997. {$ifdef x86}
  998. voidnearpointertype,
  999. voidnearcspointertype,
  1000. voidneardspointertype,
  1001. voidnearsspointertype,
  1002. voidnearespointertype,
  1003. voidnearfspointertype,
  1004. voidneargspointertype,
  1005. {$ifdef i8086}
  1006. voidfarpointertype,
  1007. voidhugepointertype,
  1008. charnearpointertype,
  1009. charfarpointertype,
  1010. charhugepointertype,
  1011. bytefarpointertype, { used for Mem[] }
  1012. wordfarpointertype, { used for MemW[] }
  1013. longintfarpointertype, { used for MemL[] }
  1014. {$endif i8086}
  1015. {$endif x86}
  1016. cundefinedtype,
  1017. cformaltype, { unique formal definition }
  1018. ctypedformaltype, { unique typed formal definition }
  1019. voidtype, { Void (procedure) }
  1020. cansichartype, { Char }
  1021. cwidechartype, { WideChar }
  1022. pasbool1type, { boolean type }
  1023. pasbool8type,
  1024. pasbool16type,
  1025. pasbool32type,
  1026. pasbool64type,
  1027. bool8type,
  1028. bool16type,
  1029. bool32type,
  1030. bool64type, { implement me }
  1031. {$ifdef llvm}
  1032. llvmbool1type, { LLVM i1 type }
  1033. {$endif llvm}
  1034. u8inttype, { 8-Bit unsigned integer }
  1035. s8inttype, { 8-Bit signed integer }
  1036. u16inttype, { 16-Bit unsigned integer }
  1037. s16inttype, { 16-Bit signed integer }
  1038. u24inttype, { 24-Bit unsigned integer }
  1039. s24inttype, { 24-Bit signed integer }
  1040. u32inttype, { 32-Bit unsigned integer }
  1041. s32inttype, { 32-Bit signed integer }
  1042. u40inttype, { 40-Bit unsigned integer }
  1043. s40inttype, { 40-Bit signed integer }
  1044. u48inttype, { 48-Bit unsigned integer }
  1045. s48inttype, { 48-Bit signed integer }
  1046. u56inttype, { 56-Bit unsigned integer }
  1047. s56inttype, { 56-Bit signed integer }
  1048. u64inttype, { 64-bit unsigned integer }
  1049. s64inttype, { 64-bit signed integer }
  1050. u128inttype, { 128-bit unsigned integer }
  1051. s128inttype, { 128-bit signed integer }
  1052. s32floattype, { 32 bit floating point number }
  1053. s64floattype, { 64 bit floating point number }
  1054. s80floattype, { 80 bit floating point number }
  1055. sc80floattype, { 80 bit floating point number but stored like in C }
  1056. s64currencytype, { pointer to a currency type }
  1057. cshortstringtype, { pointer to type of short string const }
  1058. clongstringtype, { pointer to type of long string const }
  1059. cansistringtype, { pointer to type of ansi string const }
  1060. cwidestringtype, { pointer to type of wide string const }
  1061. cunicodestringtype,
  1062. openshortstringtype, { pointer to type of an open shortstring,
  1063. needed for readln() }
  1064. openchararraytype, { pointer to type of an open array of char,
  1065. needed for readln() }
  1066. cfiletype, { get the same definition for all file }
  1067. { used for stabs }
  1068. methodpointertype, { typecasting of methodpointers to extract self }
  1069. nestedprocpointertype, { typecasting of nestedprocpointers to extract parentfp }
  1070. hresultdef,
  1071. typekindtype, { def of TTypeKind for correct handling of GetTypeKind parameters }
  1072. { we use only one variant def for every variant class }
  1073. cvarianttype,
  1074. colevarianttype,
  1075. { default integer type, normally s32inttype on 32 bit systems and s64bittype on 64 bit systems }
  1076. sinttype,
  1077. uinttype,
  1078. { integer types corresponding to OS_SINT/OS_INT }
  1079. ossinttype,
  1080. osuinttype,
  1081. { integer types corresponding to the ALU size, sizeof(aint) and the ALUSInt/ALUUInt types in the system unit }
  1082. alusinttype,
  1083. aluuinttype,
  1084. { integer types corresponding to SizeInt and SizeUInt for the target platform }
  1085. sizeuinttype,
  1086. sizesinttype,
  1087. { unsigned and signed ord type with the same size as a pointer }
  1088. ptruinttype,
  1089. ptrsinttype,
  1090. { unsigned and signed ord type with the same size as a codepointer }
  1091. codeptruinttype,
  1092. codeptrsinttype,
  1093. { several types to simulate more or less C++ objects for GDB }
  1094. vmttype,
  1095. vmtarraytype,
  1096. pvmttype : tdef; { type of classrefs, used for stabs }
  1097. { pointer to the anchestor of all classes }
  1098. class_tobject : tobjectdef;
  1099. { pointer to the base type for custom attributes }
  1100. class_tcustomattribute : tobjectdef;
  1101. { pointer to the ancestor of all COM interfaces }
  1102. interface_iunknown : tobjectdef;
  1103. { pointer to the ancestor of all dispinterfaces }
  1104. interface_idispatch : tobjectdef;
  1105. { pointer to the TGUID type
  1106. of all interfaces }
  1107. rec_tguid : trecorddef;
  1108. { jump buffer type, used by setjmp }
  1109. rec_jmp_buf : trecorddef;
  1110. { system.texceptaddr type, used by fpc_pushexceptaddr }
  1111. rec_exceptaddr: trecorddef;
  1112. { Objective-C base types }
  1113. objc_metaclasstype,
  1114. objc_superclasstype,
  1115. objc_idtype,
  1116. objc_seltype : tpointerdef;
  1117. objc_objecttype : trecorddef;
  1118. { base type of @protocol(protocolname) Objective-C statements }
  1119. objc_protocoltype : tobjectdef;
  1120. { helper types for for-in "fast enumeration" support in Objective-C 2.0 }
  1121. objc_fastenumeration : tobjectdef;
  1122. objc_fastenumerationstate : trecorddef;
  1123. {$ifdef llvm}
  1124. { llvm types }
  1125. { a unique def to identify any kind of metadata }
  1126. llvm_metadatatype : tdef;
  1127. {$endif llvm}
  1128. { Java base types }
  1129. { java.lang.Object }
  1130. java_jlobject : tobjectdef;
  1131. { java.lang.Throwable }
  1132. java_jlthrowable : tobjectdef;
  1133. { FPC base type for records }
  1134. java_fpcbaserecordtype : tobjectdef;
  1135. { java.lang.String }
  1136. java_jlstring : tobjectdef;
  1137. { java.lang.Enum }
  1138. java_jlenum : tobjectdef;
  1139. { java.util.EnumSet }
  1140. java_juenumset : tobjectdef;
  1141. { java.util.BitSet }
  1142. java_jubitset : tobjectdef;
  1143. { FPC java implementation of ansistrings }
  1144. java_ansistring : tobjectdef;
  1145. { FPC java implementation of shortstrings }
  1146. java_shortstring : tobjectdef;
  1147. { FPC java procvar base class }
  1148. java_procvarbase : tobjectdef;
  1149. function make_mangledname(const typeprefix:TSymStr;st:TSymtable;const suffix:TSymStr):TSymStr;
  1150. function make_dllmangledname(const dllname,importname:TSymStr;
  1151. import_nr : word; pco : tproccalloption):TSymStr;
  1152. { should be in the types unit, but the types unit uses the node stuff :( }
  1153. function is_interfacecom(def: tdef): boolean;
  1154. function is_interfacecom_or_dispinterface(def: tdef): boolean;
  1155. function is_any_interface_kind(def: tdef): boolean;
  1156. function is_interfacecorba(def: tdef): boolean;
  1157. function is_interface(def: tdef): boolean;
  1158. function is_dispinterface(def: tdef): boolean;
  1159. function is_object(def: tdef): boolean;
  1160. function is_class(def: tdef): boolean;
  1161. function is_cppclass(def: tdef): boolean;
  1162. function is_objectpascal_helper(def: tdef): boolean;
  1163. function is_objcclass(def: tdef): boolean;
  1164. function is_objcclassref(def: tdef): boolean;
  1165. function is_objcprotocol(def: tdef): boolean;
  1166. function is_objccategory(def: tdef): boolean;
  1167. function is_objc_class_or_protocol(def: tdef): boolean;
  1168. function is_objc_protocol_or_category(def: tdef): boolean;
  1169. function is_classhelper(def: tdef): boolean;
  1170. function is_class_or_interface(def: tdef): boolean;
  1171. function is_class_or_interface_or_objc(def: tdef): boolean;
  1172. function is_class_or_interface_or_objc_or_java(def: tdef): boolean;
  1173. function is_class_or_interface_or_dispinterface_or_objc_or_java(def: tdef): boolean;
  1174. function is_class_or_interface_or_object(def: tdef): boolean;
  1175. function is_class_or_interface_or_dispinterface(def: tdef): boolean;
  1176. function is_implicit_pointer_object_type(def: tdef): boolean;
  1177. { returns true, if def is a type which is an implicit pointer to an array (dyn. array or dyn. string) }
  1178. function is_implicit_array_pointer(def: tdef): boolean;
  1179. function is_class_or_object(def: tdef): boolean;
  1180. function is_record(def: tdef): boolean;
  1181. function is_javaclass(def: tdef): boolean;
  1182. function is_javaclassref(def: tdef): boolean;
  1183. function is_javainterface(def: tdef): boolean;
  1184. function is_java_class_or_interface(def: tdef): boolean;
  1185. procedure loadobjctypes;
  1186. procedure maybeloadcocoatypes;
  1187. function use_vectorfpu(def : tdef) : boolean;
  1188. function getansistringcodepage:tstringencoding; inline;
  1189. function getansistringdef:tstringdef;
  1190. function getparaencoding(def:tdef):tstringencoding; inline;
  1191. function get_threadvar_record(def: tdef; out index_field, non_mt_data_field: tsym): trecorddef;
  1192. function get_recorddef(prefix:tinternaltypeprefix;const fields:array of tdef; packrecords:shortint): trecorddef;
  1193. { get a table def of the form
  1194. record
  1195. count: countdef;
  1196. elements: array[0..count-1] of elementdef
  1197. end;
  1198. Returns both the outer record and the inner arraydef
  1199. }
  1200. procedure get_tabledef(prefix:tinternaltypeprefix;countdef,elementdef:tdef;count:longint;packrecords:shortint;out recdef:trecorddef;out arrdef:tarraydef);
  1201. implementation
  1202. uses
  1203. SysUtils,
  1204. cutils,
  1205. { global }
  1206. verbose,
  1207. { target }
  1208. systems,paramgr,
  1209. { symtable }
  1210. symsym,symtable,defutil,objcdef,
  1211. { parser }
  1212. pgenutil,
  1213. { module }
  1214. fmodule,
  1215. { other }
  1216. aasmbase,
  1217. gendef,
  1218. fpccrc,
  1219. entfile
  1220. ;
  1221. {****************************************************************************
  1222. Helpers
  1223. ****************************************************************************}
  1224. function getansistringcodepage:tstringencoding; inline;
  1225. begin
  1226. if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then
  1227. result:=current_settings.sourcecodepage
  1228. else
  1229. result:=0;
  1230. end;
  1231. function getansistringdef:tstringdef;
  1232. var
  1233. symtable:tsymtable;
  1234. oldstack : tsymtablestack;
  1235. begin
  1236. { if a codepage is explicitly defined in this mudule we need to return
  1237. a replacement for ansistring def }
  1238. if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then
  1239. begin
  1240. if not assigned(current_module) then
  1241. internalerror(2011101301);
  1242. { codepage can be redeclared only once per unit so we don't need a list of
  1243. redefined ansistring but only one pointer }
  1244. if not assigned(current_module.ansistrdef) then
  1245. begin
  1246. { if we did not create it yet we need to do this now }
  1247. if current_module.in_interface then
  1248. symtable:=current_module.globalsymtable
  1249. else
  1250. symtable:=current_module.localsymtable;
  1251. { create a temporary stack as it's not good (TM) to mess around
  1252. with the order if the unit contains generics or helpers; don't
  1253. use a def aware symtablestack though }
  1254. oldstack:=symtablestack;
  1255. symtablestack:=tsymtablestack.create;
  1256. symtablestack.push(symtable);
  1257. current_module.ansistrdef:=cstringdef.createansi(current_settings.sourcecodepage,true);
  1258. symtablestack.pop(symtable);
  1259. symtablestack.free;
  1260. symtablestack:=oldstack;
  1261. end;
  1262. result:=tstringdef(current_module.ansistrdef);
  1263. end
  1264. else
  1265. result:=tstringdef(cansistringtype);
  1266. end;
  1267. function getparaencoding(def:tdef):tstringencoding; inline;
  1268. begin
  1269. { don't pass CP_NONE encoding to internal functions
  1270. they expect 0 encoding instead
  1271. exception: result of string concatenation, because if you pass the
  1272. result of a string concatenation to a rawbytestring, the result of
  1273. that concatenation shouldn't be converted to defaultsystemcodepage
  1274. if all strings have the same type }
  1275. result:=tstringdef(def).encoding;
  1276. if result=globals.CP_NONE then
  1277. result:=0
  1278. end;
  1279. function get_threadvar_record(def: tdef; out index_field, non_mt_data_field: tsym): trecorddef;
  1280. var
  1281. typ: ttypesym;
  1282. name: string;
  1283. begin
  1284. name:=internaltypeprefixName[itp_threadvar_record]+def.unique_id_str;
  1285. typ:=try_search_current_module_type(name);
  1286. if assigned(typ) then
  1287. begin
  1288. result:=trecorddef(ttypesym(typ).typedef);
  1289. index_field:=tsym(result.symtable.symlist[0]);
  1290. non_mt_data_field:=tsym(result.symtable.symlist[1]);
  1291. exit;
  1292. end;
  1293. { set recordalinmin to sizeof(pint), so the second field gets put at
  1294. offset = sizeof(pint) as expected }
  1295. result:=crecorddef.create_global_internal(
  1296. name,sizeof(pint),sizeof(pint),
  1297. init_settings.alignment.maxCrecordalign);
  1298. {$ifdef cpu16bitaddr}
  1299. index_field:=result.add_field_by_def('',u16inttype);
  1300. {$else cpu16bitaddr}
  1301. index_field:=result.add_field_by_def('',u32inttype);
  1302. {$endif cpu16bitaddr}
  1303. non_mt_data_field:=result.add_field_by_def('',def);
  1304. { no need to add alignment padding, we won't create arrays of these }
  1305. end;
  1306. function get_recorddef(prefix:tinternaltypeprefix; const fields:array of tdef; packrecords:shortint): trecorddef;
  1307. var
  1308. fieldlist: tfplist;
  1309. srsym: tsym;
  1310. srsymtable: tsymtable;
  1311. i: longint;
  1312. name : TIDString;
  1313. begin
  1314. name:=copy(internaltypeprefixName[prefix],2,length(internaltypeprefixName[prefix]));
  1315. if searchsym_type(name,srsym,srsymtable) then
  1316. begin
  1317. result:=trecorddef(ttypesym(srsym).typedef);
  1318. exit
  1319. end;
  1320. { also always search in the current module (symtables are popped for
  1321. RTTI related code already) }
  1322. if searchsym_in_module(pointer(current_module),name,srsym,srsymtable) then
  1323. begin
  1324. result:=trecorddef(ttypesym(srsym).typedef);
  1325. exit;
  1326. end;
  1327. fieldlist:=tfplist.create;
  1328. for i:=low(fields) to high(fields) do
  1329. fieldlist.add(fields[i]);
  1330. result:=crecorddef.create_global_internal(internaltypeprefixName[prefix],packrecords,
  1331. targetinfos[target_info.system]^.alignment.recordalignmin,
  1332. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1333. result.add_fields_from_deflist(fieldlist);
  1334. fieldlist.free;
  1335. end;
  1336. procedure get_tabledef(prefix:tinternaltypeprefix;countdef,elementdef:tdef;count:longint;packrecords:shortint;out recdef:trecorddef;out arrdef:tarraydef);
  1337. var
  1338. fields: tfplist;
  1339. name: TIDString;
  1340. srsym: tsym;
  1341. srsymtable: tsymtable;
  1342. begin
  1343. { already created a message string table with this number of elements
  1344. in this unit -> reuse the def }
  1345. name:=internaltypeprefixName[prefix]+tostr(count);
  1346. if searchsym_type(copy(name,2,length(name)),srsym,srsymtable) then
  1347. begin
  1348. recdef:=trecorddef(ttypesym(srsym).typedef);
  1349. arrdef:=tarraydef(trecordsymtable(recdef.symtable).findfieldbyoffset(countdef.size).vardef);
  1350. exit
  1351. end;
  1352. { also always search in the current module (symtables are popped for
  1353. RTTI related code already) }
  1354. if searchsym_in_module(pointer(current_module),copy(name,2,length(name)),srsym,srsymtable) then
  1355. begin
  1356. recdef:=trecorddef(ttypesym(srsym).typedef);
  1357. arrdef:=tarraydef(trecordsymtable(recdef.symtable).findfieldbyoffset(countdef.size).vardef);
  1358. exit;
  1359. end;
  1360. recdef:=crecorddef.create_global_internal(name,packrecords,
  1361. targetinfos[target_info.system]^.alignment.recordalignmin,
  1362. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1363. fields:=tfplist.create;
  1364. fields.add(countdef);
  1365. if count>0 then
  1366. begin
  1367. arrdef:=carraydef.create(0,count-1,sizeuinttype);
  1368. arrdef.elementdef:=elementdef;
  1369. fields.add(arrdef);
  1370. end
  1371. else
  1372. arrdef:=nil;
  1373. recdef.add_fields_from_deflist(fields);
  1374. fields.free;
  1375. end;
  1376. function make_mangledname(const typeprefix:TSymStr;st:TSymtable;const suffix:TSymStr):TSymStr;
  1377. var
  1378. s,
  1379. prefix : TSymStr;
  1380. crc : dword;
  1381. begin
  1382. prefix:='';
  1383. if not assigned(st) then
  1384. internalerror(200204212);
  1385. { sub procedures }
  1386. while (st.symtabletype in [localsymtable,parasymtable]) do
  1387. begin
  1388. if st.defowner.typ<>procdef then
  1389. internalerror(200204173);
  1390. { Add the full mangledname of procedure to prevent
  1391. conflicts with 2 overloads having both a nested procedure
  1392. with the same name, see tb0314 (PFV) }
  1393. s:=tprocdef(st.defowner).procsym.name;
  1394. s:=s+tprocdef(st.defowner).mangledprocparanames(Length(s));
  1395. if prefix<>'' then
  1396. prefix:=s+'_'+prefix
  1397. else
  1398. prefix:=s;
  1399. if length(prefix)>100 then
  1400. begin
  1401. crc:=0;
  1402. crc:=UpdateCrc32(crc,prefix[1],length(prefix));
  1403. prefix:='$CRC'+hexstr(crc,8);
  1404. end;
  1405. st:=st.defowner.owner;
  1406. end;
  1407. { object/classes symtable, nested type definitions in classes require the while loop }
  1408. while st.symtabletype in [ObjectSymtable,recordsymtable] do
  1409. begin
  1410. if not (st.defowner.typ in [objectdef,recorddef]) then
  1411. internalerror(200204174);
  1412. prefix:=tabstractrecorddef(st.defowner).objname^+'_$_'+prefix;
  1413. st:=st.defowner.owner;
  1414. end;
  1415. { symtable must now be static or global }
  1416. if not(st.symtabletype in [staticsymtable,globalsymtable]) then
  1417. internalerror(200204175);
  1418. { The mangled name is made out of at most 4 parts:
  1419. 1) Optional typeprefix given as first parameter
  1420. with '_$' appended if not empty
  1421. 2) Unit name or 'P$'+program name (never empty)
  1422. 3) optional prefix variable that contains a unique
  1423. name for the local symbol table (prepended with '$_$'
  1424. if not empty)
  1425. 4) suffix as given as third parameter,
  1426. also optional (i.e. can be empty)
  1427. prepended by '_$$_' if not empty }
  1428. result:='';
  1429. if typeprefix<>'' then
  1430. result:=result+typeprefix+'_$';
  1431. { Add P$ for program, which can have the same name as
  1432. a unit }
  1433. if (TSymtable(main_module.localsymtable)=st) and
  1434. (not main_module.is_unit) then
  1435. result:=result+'P$'+st.name^
  1436. else
  1437. result:=result+st.name^;
  1438. if prefix<>'' then
  1439. result:=result+'$_$'+prefix;
  1440. if suffix<>'' then
  1441. result:=result+'_$$_'+suffix;
  1442. { the Darwin assembler assumes that all symbols starting with 'L' are local }
  1443. { Further, the Mac OS X 10.5 linker does not consider symbols which do not }
  1444. { start with '_' as regular symbols (it does not generate N_GSYM entries }
  1445. { those in the debug map, leading to troubles with dsymutil). So always }
  1446. { add an underscore on darwin. }
  1447. if (target_info.system in systems_darwin) then
  1448. result := '_' + result;
  1449. end;
  1450. function make_dllmangledname(const dllname,importname:TSymStr;import_nr : word; pco : tproccalloption):TSymStr;
  1451. var
  1452. crc : cardinal;
  1453. i : longint;
  1454. use_crc : boolean;
  1455. dllprefix : TSymStr;
  1456. begin
  1457. if (target_info.system in (systems_all_windows + systems_nativent +
  1458. [system_i386_emx, system_i386_os2]))
  1459. and (dllname <> '') then
  1460. begin
  1461. dllprefix:=lower(ExtractFileName(dllname));
  1462. { Remove .dll suffix if present }
  1463. if copy(dllprefix,length(dllprefix)-3,length(dllprefix))='.dll' then
  1464. dllprefix:=copy(dllprefix,1,length(dllprefix)-4);
  1465. use_crc:=false;
  1466. for i:=1 to length(dllprefix) do
  1467. if not (dllprefix[i] in ['a'..'z','A'..'Z','_','0'..'9']) then
  1468. begin
  1469. use_crc:=true;
  1470. break;
  1471. end;
  1472. if use_crc then
  1473. begin
  1474. crc:=0;
  1475. crc:=UpdateCrc32(crc,dllprefix[1],length(dllprefix));
  1476. dllprefix:='_$dll$crc$'+hexstr(crc,8)+'$';
  1477. end
  1478. else
  1479. dllprefix:='_$dll$'+dllprefix+'$';
  1480. if importname<>'' then
  1481. result:=dllprefix+importname
  1482. else
  1483. result:=dllprefix+'_index_'+tostr(import_nr);
  1484. { Replace ? and @ in import name, since GNU AS does not allow these characters in symbol names. }
  1485. { This allows to import VC++ mangled names from DLLs. }
  1486. { Do not perform replacement, if external symbol is not imported from DLL. }
  1487. if (dllname<>'') then
  1488. begin
  1489. Replace(result,'?','__q$$');
  1490. {$ifdef arm}
  1491. { @ symbol is not allowed in ARM assembler only }
  1492. Replace(result,'@','__a$$');
  1493. {$endif arm}
  1494. end;
  1495. end
  1496. else
  1497. begin
  1498. if importname<>'' then
  1499. begin
  1500. if not(pco in [pocall_cdecl,pocall_cppdecl]) then
  1501. result:=importname
  1502. else
  1503. result:=target_info.Cprefix+importname;
  1504. end
  1505. else
  1506. result:='_index_'+tostr(import_nr);
  1507. end;
  1508. end;
  1509. {****************************************************************************
  1510. TDEFAWARESYMTABLESTACK
  1511. (symtablestack descendant that does some special actions on
  1512. the pushed/popped symtables)
  1513. ****************************************************************************}
  1514. procedure tdefawaresymtablestack.add_helpers_and_generics(st:tsymtable;addgenerics:boolean);
  1515. var
  1516. i: integer;
  1517. s: string;
  1518. list: TFPObjectList;
  1519. def: tdef;
  1520. sym : tsym;
  1521. begin
  1522. { search the symtable from first to last; the helper to use will be the
  1523. last one in the list }
  1524. for i:=0 to st.symlist.count-1 do
  1525. begin
  1526. sym:=tsym(st.symlist[i]);
  1527. if not (sym.typ in [typesym,procsym]) then
  1528. continue;
  1529. if sym.typ=typesym then
  1530. def:=ttypesym(st.SymList[i]).typedef
  1531. else
  1532. def:=nil;
  1533. if is_objectpascal_helper(def) then
  1534. begin
  1535. s:=generate_objectpascal_helper_key(tobjectdef(def).extendeddef);
  1536. Message1(sym_d_adding_helper_for,s);
  1537. list:=TFPObjectList(current_module.extendeddefs.Find(s));
  1538. if not assigned(list) then
  1539. begin
  1540. list:=TFPObjectList.Create(false);
  1541. current_module.extendeddefs.Add(s,list);
  1542. end;
  1543. list.Add(def);
  1544. end
  1545. else
  1546. begin
  1547. if addgenerics then
  1548. add_generic_dummysym(sym);
  1549. { add nested helpers as well }
  1550. if assigned(def) and
  1551. (def.typ in [recorddef,objectdef]) and
  1552. (sto_has_helper in tabstractrecorddef(def).symtable.tableoptions) then
  1553. add_helpers_and_generics(tabstractrecorddef(def).symtable,false);
  1554. end;
  1555. end;
  1556. end;
  1557. procedure tdefawaresymtablestack.remove_helpers_and_generics(st:tsymtable);
  1558. begin
  1559. if sto_has_helper in st.tableoptions then
  1560. remove_helpers(st);
  1561. if sto_has_generic in st.tableoptions then
  1562. remove_generics(st);
  1563. end;
  1564. procedure tdefawaresymtablestack.remove_helpers(st:TSymtable);
  1565. var
  1566. i, j: integer;
  1567. tmpst: TSymtable;
  1568. list: TFPObjectList;
  1569. begin
  1570. for i:=current_module.extendeddefs.count-1 downto 0 do
  1571. begin
  1572. list:=TFPObjectList(current_module.extendeddefs[i]);
  1573. for j:=list.count-1 downto 0 do
  1574. begin
  1575. if not (list[j] is tobjectdef) then
  1576. Internalerror(2011031501);
  1577. tmpst:=tobjectdef(list[j]).owner;
  1578. repeat
  1579. if tmpst=st then
  1580. begin
  1581. list.delete(j);
  1582. break;
  1583. end
  1584. else
  1585. begin
  1586. if assigned(tmpst.defowner) then
  1587. tmpst:=tmpst.defowner.owner
  1588. else
  1589. tmpst:=nil;
  1590. end;
  1591. until not assigned(tmpst) or (tmpst.symtabletype in [globalsymtable,staticsymtable]);
  1592. end;
  1593. if list.count=0 then
  1594. current_module.extendeddefs.delete(i);
  1595. end;
  1596. end;
  1597. procedure tdefawaresymtablestack.remove_generics(st:tsymtable);
  1598. var
  1599. i,j : longint;
  1600. entry : tgenericdummyentry;
  1601. list : tfpobjectlist;
  1602. begin
  1603. for i:=current_module.genericdummysyms.count-1 downto 0 do
  1604. begin
  1605. list:=tfpobjectlist(current_module.genericdummysyms[i]);
  1606. if not assigned(list) then
  1607. continue;
  1608. for j:=list.count-1 downto 0 do
  1609. begin
  1610. entry:=tgenericdummyentry(list[j]);
  1611. if entry.dummysym.owner=st then
  1612. list.delete(j);
  1613. end;
  1614. if list.count=0 then
  1615. current_module.genericdummysyms.delete(i);
  1616. end;
  1617. end;
  1618. procedure tdefawaresymtablestack.pushcommon(st:tsymtable);
  1619. begin
  1620. if (sto_has_generic in st.tableoptions) or
  1621. (
  1622. (st.symtabletype in [globalsymtable,staticsymtable]) and
  1623. (sto_has_helper in st.tableoptions)
  1624. ) then
  1625. { nested helpers will be added as well }
  1626. add_helpers_and_generics(st,true);
  1627. end;
  1628. procedure tdefawaresymtablestack.push(st: TSymtable);
  1629. begin
  1630. pushcommon(st);
  1631. inherited push(st);
  1632. end;
  1633. procedure tdefawaresymtablestack.pushafter(st,afterst:TSymtable);
  1634. begin
  1635. pushcommon(st);
  1636. inherited pushafter(st,afterst);
  1637. end;
  1638. procedure tdefawaresymtablestack.pop(st: TSymtable);
  1639. begin
  1640. inherited pop(st);
  1641. if (sto_has_generic in st.tableoptions) or
  1642. (
  1643. (st.symtabletype in [globalsymtable,staticsymtable]) and
  1644. (sto_has_helper in st.tableoptions)
  1645. ) then
  1646. { nested helpers will be removed as well }
  1647. remove_helpers_and_generics(st);
  1648. end;
  1649. {****************************************************************************
  1650. TDEF (base class for definitions)
  1651. ****************************************************************************}
  1652. constructor tgenericconstraintdata.create;
  1653. begin
  1654. interfaces:=tfpobjectlist.create(false);
  1655. interfacesderef:=tfplist.create;
  1656. end;
  1657. destructor tgenericconstraintdata.destroy;
  1658. var
  1659. i : longint;
  1660. begin
  1661. for i:=0 to interfacesderef.count-1 do
  1662. dispose(pderef(interfacesderef[i]));
  1663. interfacesderef.free;
  1664. interfaces.free;
  1665. inherited destroy;
  1666. end;
  1667. procedure tgenericconstraintdata.ppuload(ppufile: tcompilerppufile);
  1668. var
  1669. cnt,i : longint;
  1670. intfderef : pderef;
  1671. begin
  1672. ppufile.getsmallset(flags);
  1673. cnt:=ppufile.getlongint;
  1674. for i:=0 to cnt-1 do
  1675. begin
  1676. new(intfderef);
  1677. ppufile.getderef(intfderef^);
  1678. interfacesderef.add(intfderef);
  1679. end;
  1680. end;
  1681. procedure tgenericconstraintdata.ppuwrite(ppufile: tcompilerppufile);
  1682. var
  1683. i : longint;
  1684. begin
  1685. ppufile.putsmallset(flags);
  1686. ppufile.putlongint(interfacesderef.count);
  1687. for i:=0 to interfacesderef.count-1 do
  1688. ppufile.putderef(pderef(interfacesderef[i])^);
  1689. end;
  1690. procedure tgenericconstraintdata.buildderef;
  1691. var
  1692. intfderef : pderef;
  1693. i : longint;
  1694. begin
  1695. for i:=0 to interfaces.count-1 do
  1696. begin
  1697. new(intfderef);
  1698. intfderef^.build(tobjectdef(interfaces[i]));
  1699. interfacesderef.add(intfderef);
  1700. end;
  1701. end;
  1702. procedure tgenericconstraintdata.deref;
  1703. var
  1704. i : longint;
  1705. begin
  1706. for i:=0 to interfacesderef.count-1 do
  1707. interfaces.add(pderef(interfacesderef[i])^.resolve);
  1708. end;
  1709. procedure tstoreddef.writeentry(ppufile: tcompilerppufile; ibnr: byte);
  1710. begin
  1711. ppuwrite_platform(ppufile);
  1712. ppufile.writeentry(ibnr);
  1713. end;
  1714. procedure tstoreddef.ppuwrite_platform(ppufile: tcompilerppufile);
  1715. begin
  1716. { by default: do nothing }
  1717. end;
  1718. procedure tstoreddef.ppuload_platform(ppufile: tcompilerppufile);
  1719. begin
  1720. { by default: do nothing }
  1721. end;
  1722. class procedure tstoreddef.setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);
  1723. var
  1724. reusablesymtab: tsymtable;
  1725. begin
  1726. { must not yet belong to a symtable }
  1727. if assigned(newdef.owner) then
  1728. internalerror(2015111503);
  1729. reusablesymtab:=origdef.getreusablesymtab;
  1730. res^.Data:=newdef;
  1731. reusablesymtab.insertdef(newdef);
  1732. symtablestack:=oldsymtablestack;
  1733. end;
  1734. constructor tstoreddef.create(dt:tdeftyp;doregister:boolean);
  1735. begin
  1736. inherited create(dt);
  1737. savesize := 0;
  1738. {$ifdef EXTDEBUG}
  1739. fileinfo := current_filepos;
  1740. {$endif}
  1741. generictokenbuf:=nil;
  1742. genericdef:=nil;
  1743. typesymderef.reset;
  1744. genericdefderef.reset;
  1745. { Don't register forwarddefs, they are disposed at the
  1746. end of an type block }
  1747. if (dt=forwarddef) then
  1748. exit;
  1749. { Register in symtable stack }
  1750. if doregister then
  1751. begin
  1752. { immediately register interface defs, as they will always be
  1753. written to the ppu, their defid inlfuences the interface crc and
  1754. if we wait, depending on e.g. compiler defines they may get a
  1755. different defid (e.g. when a function is called, its procdef is
  1756. registered, so depending on whether or not, or when, an interface
  1757. procedure is called in the implementation, that may change its
  1758. defid otherwise) }
  1759. if assigned(current_module) and
  1760. current_module.in_interface then
  1761. register_def
  1762. else
  1763. maybe_put_in_symtable_stack;
  1764. end;
  1765. end;
  1766. destructor tstoreddef.destroy;
  1767. var
  1768. i : longint;
  1769. begin
  1770. { Direct calls are not allowed, use symtable.deletedef() }
  1771. if assigned(owner) then
  1772. internalerror(200612311);
  1773. if assigned(generictokenbuf) then
  1774. begin
  1775. generictokenbuf.free;
  1776. generictokenbuf:=nil;
  1777. end;
  1778. rtti_attribute_list.free;
  1779. genericparas.free;
  1780. if assigned(genericparaderefs) then
  1781. for i:=0 to genericparaderefs.count-1 do
  1782. dispose(pderef(genericparaderefs[i]));
  1783. genericparaderefs.free;
  1784. genconstraintdata.free;
  1785. {$ifndef symansistr}
  1786. stringdispose(_fullownerhierarchyname);
  1787. {$endif not symansistr}
  1788. inherited destroy;
  1789. end;
  1790. constructor tstoreddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  1791. var
  1792. sizeleft,i,cnt : longint;
  1793. buf : array[0..255] of byte;
  1794. symderef : pderef;
  1795. begin
  1796. inherited create(dt);
  1797. DefId:=ppufile.getlongint;
  1798. current_module.deflist[DefId]:=self;
  1799. {$ifdef EXTDEBUG}
  1800. fillchar(fileinfo,sizeof(fileinfo),0);
  1801. {$endif}
  1802. { load }
  1803. ppufile.getderef(typesymderef);
  1804. ppufile.getsmallset(defoptions);
  1805. ppufile.getsmallset(defstates);
  1806. if df_genconstraint in defoptions then
  1807. begin
  1808. genconstraintdata:=tgenericconstraintdata.create;
  1809. genconstraintdata.ppuload(ppufile);
  1810. end;
  1811. if [df_generic,df_specialization]*defoptions<>[] then
  1812. begin
  1813. cnt:=ppufile.getlongint;
  1814. if cnt>0 then
  1815. begin
  1816. genericparas:=tfphashobjectlist.create(false);
  1817. genericparaderefs:=tfplist.create;
  1818. for i:=0 to cnt-1 do
  1819. begin
  1820. genericparas.add(ppufile.getstring,nil);
  1821. New(symderef);
  1822. ppufile.getderef(symderef^);
  1823. genericparaderefs.add(symderef);
  1824. end;
  1825. end;
  1826. end;
  1827. if df_generic in defoptions then
  1828. begin
  1829. sizeleft:=ppufile.getlongint;
  1830. initgeneric;
  1831. while sizeleft>0 do
  1832. begin
  1833. if sizeleft>sizeof(buf) then
  1834. i:=sizeof(buf)
  1835. else
  1836. i:=sizeleft;
  1837. ppufile.getdata(buf,i);
  1838. generictokenbuf.write(buf,i);
  1839. dec(sizeleft,i);
  1840. end;
  1841. end;
  1842. if df_specialization in defoptions then
  1843. ppufile.getderef(genericdefderef);
  1844. rtti_attribute_list:=trtti_attribute_list.ppuload(ppufile);
  1845. end;
  1846. function tstoreddef.needs_separate_initrtti:boolean;
  1847. begin
  1848. result:=false;
  1849. end;
  1850. function tstoreddef.rtti_mangledname(rt : trttitype) : TSymStr;
  1851. var
  1852. prefix : string[4];
  1853. begin
  1854. if (rt=fullrtti) or (not needs_separate_initrtti) then
  1855. begin
  1856. prefix:='RTTI';
  1857. include(defstates,ds_rtti_table_used);
  1858. end
  1859. else
  1860. begin
  1861. prefix:='INIT';
  1862. include(defstates,ds_init_table_used);
  1863. end;
  1864. if assigned(typesym) and
  1865. (owner.symtabletype in [staticsymtable,globalsymtable]) then
  1866. result:=make_mangledname(prefix,typesym.owner,typesym.name)
  1867. else
  1868. result:=make_mangledname(prefix,findunitsymtable(owner),'def'+unique_id_str)
  1869. end;
  1870. function tstoreddef.OwnerHierarchyName: string;
  1871. var
  1872. tmp: tdef;
  1873. begin
  1874. tmp:=self;
  1875. result:='';
  1876. repeat
  1877. { can be not assigned in case of a forwarddef }
  1878. if assigned(tmp.owner) and
  1879. (tmp.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
  1880. tmp:=tdef(tmp.owner.defowner)
  1881. else
  1882. break;
  1883. result:=tabstractrecorddef(tmp).objrealname^+'.'+result;
  1884. until tmp=nil;
  1885. end;
  1886. function tstoreddef.fullownerhierarchyname(skipprocparams:boolean): TSymStr;
  1887. var
  1888. lastowner: tsymtable;
  1889. tmp: tdef;
  1890. pno: tprocnameoptions;
  1891. begin
  1892. {$ifdef symansistr}
  1893. if not skipprocparams and (_fullownerhierarchyname<>'') then
  1894. exit(_fullownerhierarchyname);
  1895. {$else symansistr}
  1896. if not skipprocparams and assigned(_fullownerhierarchyname) then
  1897. exit(_fullownerhierarchyname^);
  1898. {$endif symansistr}
  1899. { the def can only reside inside structured types or
  1900. procedures/functions/methods }
  1901. tmp:=self;
  1902. result:='';
  1903. repeat
  1904. lastowner:=tmp.owner;
  1905. { can be not assigned in case of a forwarddef }
  1906. if not assigned(lastowner) then
  1907. break
  1908. else
  1909. tmp:=tdef(lastowner.defowner);
  1910. if not assigned(tmp) then
  1911. break;
  1912. if tmp.typ in [recorddef,objectdef] then
  1913. result:=tabstractrecorddef(tmp).objrealname^+'.'+result
  1914. else
  1915. if tmp.typ=procdef then
  1916. begin
  1917. pno:=[pno_paranames,pno_proctypeoption];
  1918. if skipprocparams then
  1919. include(pno,pno_noparams);
  1920. result:=tprocdef(tmp).customprocname(pno)+'.'+result;
  1921. end;
  1922. until tmp=nil;
  1923. { add the unit name }
  1924. if assigned(lastowner) and
  1925. assigned(lastowner.realname) then
  1926. result:=lastowner.realname^+'.'+result;
  1927. if not skipprocparams then
  1928. { don't store the name in this case }
  1929. {$ifdef symansistr}
  1930. _fullownerhierarchyname:=result;
  1931. {$else symansistr}
  1932. _fullownerhierarchyname:=stringdup(result);
  1933. {$endif symansistr}
  1934. end;
  1935. function tstoreddef.in_currentunit: boolean;
  1936. var
  1937. st: tsymtable;
  1938. begin
  1939. st:=owner;
  1940. while not(st.symtabletype in [globalsymtable,staticsymtable]) do
  1941. st:=st.defowner.owner;
  1942. result:=st.iscurrentunit;
  1943. end;
  1944. function tstoreddef.getcopy : tstoreddef;
  1945. begin
  1946. Message(sym_e_cant_create_unique_type);
  1947. getcopy:=cerrordef.create;
  1948. end;
  1949. procedure tstoreddef.ppuwrite(ppufile:tcompilerppufile);
  1950. var
  1951. sizeleft,i : longint;
  1952. buf : array[0..255] of byte;
  1953. oldintfcrc : boolean;
  1954. begin
  1955. if defid<0 then
  1956. internalerror(2015101401);
  1957. ppufile.putlongint(DefId);
  1958. ppufile.putderef(typesymderef);
  1959. ppufile.putsmallset(defoptions);
  1960. oldintfcrc:=ppufile.do_crc;
  1961. ppufile.do_crc:=false;
  1962. ppufile.putsmallset(defstates);
  1963. if df_genconstraint in defoptions then
  1964. genconstraintdata.ppuwrite(ppufile);
  1965. if [df_generic,df_specialization]*defoptions<>[] then
  1966. begin
  1967. if not assigned(genericparas) then
  1968. ppufile.putlongint(0)
  1969. else
  1970. begin
  1971. if not assigned(genericparaderefs) then
  1972. internalerror(2014052305);
  1973. ppufile.putlongint(genericparas.count);
  1974. for i:=0 to genericparas.count-1 do
  1975. begin
  1976. ppufile.putstring(genericparas.nameofindex(i));
  1977. ppufile.putderef(pderef(genericparaderefs[i])^);
  1978. end;
  1979. end;
  1980. end;
  1981. if df_generic in defoptions then
  1982. begin
  1983. if assigned(generictokenbuf) then
  1984. begin
  1985. sizeleft:=generictokenbuf.size;
  1986. generictokenbuf.seek(0);
  1987. end
  1988. else
  1989. sizeleft:=0;
  1990. ppufile.putlongint(sizeleft);
  1991. while sizeleft>0 do
  1992. begin
  1993. if sizeleft>sizeof(buf) then
  1994. i:=sizeof(buf)
  1995. else
  1996. i:=sizeleft;
  1997. generictokenbuf.read(buf,i);
  1998. ppufile.putdata(buf,i);
  1999. dec(sizeleft,i);
  2000. end;
  2001. end;
  2002. ppufile.do_crc:=oldintfcrc;
  2003. if df_specialization in defoptions then
  2004. ppufile.putderef(genericdefderef);
  2005. trtti_attribute_list.ppuwrite(rtti_attribute_list,ppufile);
  2006. end;
  2007. procedure tstoreddef.ppuload_subentries(ppufile: tcompilerppufile);
  2008. begin
  2009. trtti_attribute_list.ppuload_subentries(rtti_attribute_list,ppufile);
  2010. end;
  2011. procedure tstoreddef.ppuwrite_subentries(ppufile: tcompilerppufile);
  2012. begin
  2013. trtti_attribute_list.ppuwrite_subentries(rtti_attribute_list,ppufile);
  2014. end;
  2015. procedure tstoreddef.buildderef;
  2016. var
  2017. i : longint;
  2018. sym : tsym;
  2019. symderef : pderef;
  2020. begin
  2021. if not registered then
  2022. register_def;
  2023. typesymderef.build(typesym);
  2024. genericdefderef.build(genericdef);
  2025. if assigned(rtti_attribute_list) then
  2026. rtti_attribute_list.buildderef;
  2027. if assigned(genconstraintdata) then
  2028. genconstraintdata.buildderef;
  2029. if assigned(genericparas) then
  2030. begin
  2031. if not assigned(genericparaderefs) then
  2032. genericparaderefs:=tfplist.create;
  2033. for i:=0 to genericparas.count-1 do
  2034. begin
  2035. sym:=tsym(genericparas.items[i]);
  2036. new(symderef);
  2037. symderef^.build(sym);
  2038. genericparaderefs.add(symderef);
  2039. end;
  2040. end;
  2041. end;
  2042. procedure tstoreddef.buildderefimpl;
  2043. begin
  2044. end;
  2045. procedure tstoreddef.deref;
  2046. var
  2047. symderef : pderef;
  2048. i : longint;
  2049. begin
  2050. typesym:=ttypesym(typesymderef.resolve);
  2051. if df_specialization in defoptions then
  2052. genericdef:=tstoreddef(genericdefderef.resolve);
  2053. if assigned(rtti_attribute_list) then
  2054. rtti_attribute_list.deref;
  2055. if assigned(genconstraintdata) then
  2056. genconstraintdata.deref;
  2057. if assigned(genericparas) then
  2058. begin
  2059. if not assigned(genericparaderefs) then
  2060. internalerror(2014052302);
  2061. if genericparas.count<>genericparaderefs.count then
  2062. internalerror(2014052303);
  2063. for i:=0 to genericparaderefs.count-1 do
  2064. begin
  2065. symderef:=pderef(genericparaderefs[i]);
  2066. genericparas.items[i]:=symderef^.resolve;
  2067. end;
  2068. end;
  2069. end;
  2070. procedure tstoreddef.derefimpl;
  2071. begin
  2072. end;
  2073. function tstoreddef.size : asizeint;
  2074. begin
  2075. size:=savesize;
  2076. end;
  2077. function tstoreddef.getvardef:longint;
  2078. begin
  2079. result:=varUndefined;
  2080. end;
  2081. function tstoreddef.alignment : shortint;
  2082. begin
  2083. { natural alignment by default }
  2084. alignment:=size_2_align(savesize);
  2085. { can happen if savesize = 0, e.g. for voiddef or
  2086. an empty record
  2087. }
  2088. if (alignment=0) then
  2089. alignment:=1;
  2090. end;
  2091. { returns true, if the definition can be published }
  2092. function tstoreddef.is_publishable : boolean;
  2093. begin
  2094. is_publishable:=false;
  2095. end;
  2096. { needs an init table }
  2097. function tstoreddef.needs_inittable : boolean;
  2098. begin
  2099. needs_inittable:=false;
  2100. end;
  2101. function tstoreddef.has_non_trivial_init_child(check_parent:boolean):boolean;
  2102. begin
  2103. result:=false;
  2104. end;
  2105. function tstoreddef.is_intregable : boolean;
  2106. var
  2107. recsize,temp: longint;
  2108. begin
  2109. case typ of
  2110. orddef,
  2111. pointerdef,
  2112. enumdef,
  2113. classrefdef:
  2114. is_intregable:=true;
  2115. procvardef :
  2116. is_intregable:=tprocvardef(self).is_addressonly or (po_methodpointer in tprocvardef(self).procoptions);
  2117. objectdef:
  2118. is_intregable:=(is_implicit_pointer_object_type(self)) and not needs_inittable;
  2119. setdef:
  2120. is_intregable:=is_smallset(self);
  2121. arraydef:
  2122. {$ifdef cpuhighleveltarget}
  2123. is_intregable:=false
  2124. {$else cpuhighleveltarget}
  2125. is_intregable:=not(is_special_array(self)) and
  2126. (tarraydef(self).size in [1,2,4,8]) and tstoreddef(tarraydef(self).elementdef).is_intregable
  2127. {$ifdef SUPPORT_MMX}
  2128. and not((cs_mmx in current_settings.localswitches) and
  2129. is_mmx_able_array(self))
  2130. {$endif SUPPORT_MMX}
  2131. {$endif cpuhighleveltarget}
  2132. ;
  2133. recorddef:
  2134. begin
  2135. {$ifdef cpuhighleveltarget}
  2136. is_intregable:=false;
  2137. {$else cpuhighleveltarget}
  2138. recsize:=size;
  2139. is_intregable:=
  2140. ispowerof2(recsize,temp) and
  2141. ((recsize<=sizeof(aint)*2) and
  2142. not trecorddef(self).contains_cross_aword_field and
  2143. { records cannot go into registers on 16 bit targets for now }
  2144. (sizeof(aint)>2) and
  2145. (not trecorddef(self).contains_float_field) or
  2146. (recsize <= sizeof(aint))
  2147. ) and
  2148. not needs_inittable;
  2149. {$endif cpuhighleveltarget}
  2150. end;
  2151. else
  2152. is_intregable:=false;
  2153. end;
  2154. end;
  2155. function tstoreddef.is_fpuregable : boolean;
  2156. begin
  2157. {$ifdef x86}
  2158. result:=use_vectorfpu(self);
  2159. {$else x86}
  2160. result:=(typ=floatdef) and not(cs_fp_emulation in current_settings.moduleswitches);
  2161. {$endif x86}
  2162. end;
  2163. function tstoreddef.is_const_intregable : boolean;
  2164. begin
  2165. case typ of
  2166. stringdef:
  2167. result:=tstringdef(self).stringtype in [st_ansistring,st_unicodestring,st_widestring];
  2168. arraydef:
  2169. result:=is_dynamic_array(self);
  2170. objectdef:
  2171. result:=is_interface(self);
  2172. else
  2173. result:=false;
  2174. end;
  2175. end;
  2176. procedure tstoreddef.initgeneric;
  2177. begin
  2178. if assigned(generictokenbuf) then
  2179. internalerror(200512131);
  2180. generictokenbuf:=tdynamicarray.create(256);
  2181. end;
  2182. function tstoreddef.is_generic: boolean;
  2183. var
  2184. sym: tsym;
  2185. i: longint;
  2186. begin
  2187. result:=assigned(genericparas) and
  2188. (genericparas.count>0) and
  2189. (df_generic in defoptions);
  2190. if result then
  2191. { if any of the type parameters does *not* belong to as (meaning it was passed
  2192. in from outside) then we aren't a generic, but a specialization }
  2193. for i:=0 to genericparas.count-1 do
  2194. begin
  2195. sym:=tsym(genericparas[i]);
  2196. if sym.typ<>symconst.typesym then
  2197. internalerror(2014050903);
  2198. if sym.owner.defowner<>self then
  2199. exit(false);
  2200. end;
  2201. end;
  2202. function tstoreddef.is_specialization: boolean;
  2203. var
  2204. i : longint;
  2205. sym : tsym;
  2206. begin
  2207. result:=assigned(genericparas) and
  2208. (genericparas.count>0) and
  2209. (df_specialization in defoptions);
  2210. if result then
  2211. begin
  2212. { if at least one of the generic parameters is not owned by us (meaning it was
  2213. passed in from outside) then we have a specialization, otherwise we have a generic }
  2214. for i:=0 to genericparas.count-1 do
  2215. begin
  2216. sym:=tsym(genericparas[i]);
  2217. if sym.typ<>symconst.typesym then
  2218. internalerror(2014050904);
  2219. if sym.owner.defowner<>self then
  2220. exit(true);
  2221. end;
  2222. result:=false;
  2223. end;
  2224. end;
  2225. procedure tstoreddef.register_def;
  2226. var
  2227. gst : tgetsymtable;
  2228. st : tsymtable;
  2229. begin
  2230. if registered then
  2231. exit;
  2232. { Register in current_module }
  2233. if assigned(current_module) then
  2234. begin
  2235. exclude(defoptions,df_not_registered_no_free);
  2236. for gst:=low(tgetsymtable) to high(tgetsymtable) do
  2237. begin
  2238. st:=getsymtable(gst);
  2239. if assigned(st) then
  2240. tstoredsymtable(st).register_children;
  2241. end;
  2242. if defid<defid_not_registered then
  2243. defid:=deflist_index
  2244. else
  2245. begin
  2246. current_module.deflist.Add(self);
  2247. defid:=current_module.deflist.Count-1;
  2248. end;
  2249. maybe_put_in_symtable_stack;
  2250. end
  2251. else
  2252. DefId:=defid_registered_nost;
  2253. end;
  2254. procedure tstoreddef.maybe_put_in_symtable_stack;
  2255. var
  2256. insertstack: psymtablestackitem;
  2257. begin
  2258. if assigned(symtablestack) and
  2259. not assigned(self.owner) then
  2260. begin
  2261. insertstack:=symtablestack.stack;
  2262. { don't insert defs in exception symtables, as they are freed before
  2263. the module is compiled, so we can get crashes on high level targets
  2264. if they still need it while e.g. writing assembler code }
  2265. while assigned(insertstack) and
  2266. (insertstack^.symtable.symtabletype in [stt_exceptsymtable,withsymtable]) do
  2267. insertstack:=insertstack^.next;
  2268. if not assigned(insertstack) then
  2269. internalerror(200602044);
  2270. if insertstack^.symtable.sealed then
  2271. internalerror(2015022301);
  2272. insertstack^.symtable.insertdef(self);
  2273. end;
  2274. end;
  2275. {****************************************************************************
  2276. Tstringdef
  2277. ****************************************************************************}
  2278. constructor tstringdef.createshort(l: byte; doregister: boolean);
  2279. begin
  2280. inherited create(stringdef,doregister);
  2281. stringtype:=st_shortstring;
  2282. encoding:=0;
  2283. len:=l;
  2284. end;
  2285. constructor tstringdef.loadshort(ppufile:tcompilerppufile);
  2286. begin
  2287. inherited ppuload(stringdef,ppufile);
  2288. stringtype:=st_shortstring;
  2289. encoding:=0;
  2290. len:=ppufile.getbyte;
  2291. ppuload_platform(ppufile);
  2292. end;
  2293. constructor tstringdef.createlong(l: asizeint; doregister: boolean);
  2294. begin
  2295. inherited create(stringdef,doregister);
  2296. stringtype:=st_longstring;
  2297. encoding:=0;
  2298. len:=l;
  2299. end;
  2300. constructor tstringdef.loadlong(ppufile:tcompilerppufile);
  2301. begin
  2302. inherited ppuload(stringdef,ppufile);
  2303. stringtype:=st_longstring;
  2304. encoding:=0;
  2305. len:=ppufile.getasizeint;
  2306. ppuload_platform(ppufile);
  2307. end;
  2308. constructor tstringdef.createansi(aencoding: tstringencoding; doregister: boolean);
  2309. begin
  2310. inherited create(stringdef,doregister);
  2311. stringtype:=st_ansistring;
  2312. encoding:=aencoding;
  2313. len:=-1;
  2314. end;
  2315. constructor tstringdef.loadansi(ppufile:tcompilerppufile);
  2316. begin
  2317. inherited ppuload(stringdef,ppufile);
  2318. stringtype:=st_ansistring;
  2319. len:=ppufile.getasizeint;
  2320. encoding:=ppufile.getword;
  2321. ppuload_platform(ppufile);
  2322. end;
  2323. constructor tstringdef.createwide(doregister: boolean);
  2324. begin
  2325. inherited create(stringdef,doregister);
  2326. stringtype:=st_widestring;
  2327. if target_info.endian=endian_little then
  2328. encoding:=CP_UTF16LE
  2329. else
  2330. encoding:=CP_UTF16BE;
  2331. len:=-1;
  2332. end;
  2333. constructor tstringdef.loadwide(ppufile:tcompilerppufile);
  2334. begin
  2335. inherited ppuload(stringdef,ppufile);
  2336. stringtype:=st_widestring;
  2337. if target_info.endian=endian_little then
  2338. encoding:=CP_UTF16LE
  2339. else
  2340. encoding:=CP_UTF16BE;
  2341. len:=ppufile.getasizeint;
  2342. ppuload_platform(ppufile);
  2343. end;
  2344. constructor tstringdef.createunicode(doregister: boolean);
  2345. begin
  2346. inherited create(stringdef,doregister);
  2347. stringtype:=st_unicodestring;
  2348. if target_info.endian=endian_little then
  2349. encoding:=CP_UTF16LE
  2350. else
  2351. encoding:=CP_UTF16BE;
  2352. len:=-1;
  2353. end;
  2354. constructor tstringdef.loadunicode(ppufile:tcompilerppufile);
  2355. begin
  2356. inherited ppuload(stringdef,ppufile);
  2357. stringtype:=st_unicodestring;
  2358. len:=ppufile.getasizeint;
  2359. encoding:=ppufile.getword;
  2360. ppuload_platform(ppufile);
  2361. end;
  2362. function tstringdef.getcopy : tstoreddef;
  2363. begin
  2364. result:=cstringdef.create(typ,true);
  2365. result.typ:=stringdef;
  2366. tstringdef(result).stringtype:=stringtype;
  2367. tstringdef(result).encoding:=encoding;
  2368. tstringdef(result).len:=len;
  2369. end;
  2370. function tstringdef.stringtypname:string;
  2371. const
  2372. typname:array[tstringtype] of string[10]=(
  2373. 'shortstr','longstr','ansistr','widestr','unicodestr'
  2374. );
  2375. begin
  2376. stringtypname:=typname[stringtype];
  2377. end;
  2378. procedure tstringdef.ppuwrite(ppufile:tcompilerppufile);
  2379. begin
  2380. inherited ppuwrite(ppufile);
  2381. if stringtype=st_shortstring then
  2382. begin
  2383. {$ifdef extdebug}
  2384. if len > 255 then internalerror(12122002);
  2385. {$endif}
  2386. ppufile.putbyte(byte(len))
  2387. end
  2388. else
  2389. ppufile.putasizeint(len);
  2390. if stringtype in [st_ansistring,st_unicodestring] then
  2391. ppufile.putword(encoding);
  2392. case stringtype of
  2393. st_shortstring : writeentry(ppufile,ibshortstringdef);
  2394. st_longstring : writeentry(ppufile,iblongstringdef);
  2395. st_ansistring : writeentry(ppufile,ibansistringdef);
  2396. st_widestring : writeentry(ppufile,ibwidestringdef);
  2397. st_unicodestring : writeentry(ppufile,ibunicodestringdef);
  2398. end;
  2399. end;
  2400. function tstringdef.needs_inittable : boolean;
  2401. begin
  2402. needs_inittable:=stringtype in [st_ansistring,st_widestring,st_unicodestring];
  2403. end;
  2404. function tstringdef.GetTypeName : string;
  2405. const
  2406. names : array[tstringtype] of string[15] = (
  2407. 'ShortString','LongString','AnsiString','WideString','UnicodeString');
  2408. begin
  2409. GetTypeName:=names[stringtype];
  2410. end;
  2411. function tstringdef.getvardef : longint;
  2412. const
  2413. vardef : array[tstringtype] of longint = (
  2414. varUndefined,varUndefined,varString,varOleStr,varUString);
  2415. begin
  2416. result:=vardef[stringtype];
  2417. end;
  2418. function tstringdef.alignment : shortint;
  2419. begin
  2420. case stringtype of
  2421. st_unicodestring,
  2422. st_widestring,
  2423. st_ansistring:
  2424. alignment:=voidpointertype.alignment;
  2425. st_longstring,
  2426. st_shortstring:
  2427. { char to string accesses byte 0 and 1 with one word access }
  2428. if (tf_requires_proper_alignment in target_info.flags) or
  2429. { macpas needs an alignment of 2 (MetroWerks compatible) }
  2430. (m_mac in current_settings.modeswitches) then
  2431. alignment:=size_2_align(2)
  2432. else
  2433. alignment:=size_2_align(1);
  2434. end;
  2435. end;
  2436. function tstringdef.getmangledparaname : TSymStr;
  2437. begin
  2438. getmangledparaname:='STRING';
  2439. end;
  2440. function tstringdef.is_publishable : boolean;
  2441. begin
  2442. is_publishable:=true;
  2443. end;
  2444. function tstringdef.size: asizeint;
  2445. begin
  2446. case stringtype of
  2447. st_shortstring:
  2448. Result:=len+1;
  2449. st_longstring,
  2450. st_ansistring,
  2451. st_widestring,
  2452. st_unicodestring:
  2453. Result:=voidpointertype.size;
  2454. end;
  2455. end;
  2456. {****************************************************************************
  2457. TENUMDEF
  2458. ****************************************************************************}
  2459. constructor tenumdef.create;
  2460. begin
  2461. inherited create(enumdef,true);
  2462. minval:=0;
  2463. maxval:=0;
  2464. calcsavesize(current_settings.packenum);
  2465. has_jumps:=false;
  2466. basedef:=nil;
  2467. basedefderef.reset;
  2468. symtable:=tenumsymtable.create(self);
  2469. end;
  2470. constructor tenumdef.create_subrange(_basedef:tenumdef;_min,_max:asizeint);
  2471. begin
  2472. inherited create(enumdef,true);
  2473. minval:=_min;
  2474. maxval:=_max;
  2475. basedef:=_basedef;
  2476. calcsavesize(current_settings.packenum);
  2477. has_jumps:=false;
  2478. symtable:=basedef.symtable.getcopy;
  2479. include(defoptions, df_copied_def);
  2480. end;
  2481. constructor tenumdef.ppuload(ppufile:tcompilerppufile);
  2482. begin
  2483. inherited ppuload(enumdef,ppufile);
  2484. minval:=ppufile.getaint;
  2485. maxval:=ppufile.getaint;
  2486. savesize:=ppufile.getaint;
  2487. has_jumps:=false;
  2488. if df_copied_def in defoptions then
  2489. begin
  2490. symtable:=nil;
  2491. ppufile.getderef(basedefderef);
  2492. ppuload_platform(ppufile);
  2493. end
  2494. else
  2495. begin
  2496. ppuload_platform(ppufile);
  2497. // create with nil defowner first to prevent values changes on insert
  2498. symtable:=tenumsymtable.create(nil);
  2499. tenumsymtable(symtable).ppuload(ppufile);
  2500. symtable.defowner:=self;
  2501. end;
  2502. end;
  2503. destructor tenumdef.destroy;
  2504. begin
  2505. symtable.free;
  2506. symtable:=nil;
  2507. inherited destroy;
  2508. end;
  2509. function tenumdef.getcopy : tstoreddef;
  2510. begin
  2511. if assigned(basedef) then
  2512. result:=cenumdef.create_subrange(basedef,minval,maxval)
  2513. else
  2514. begin
  2515. result:=cenumdef.create;
  2516. tenumdef(result).minval:=minval;
  2517. tenumdef(result).maxval:=maxval;
  2518. tenumdef(result).symtable.free;
  2519. tenumdef(result).symtable:=symtable.getcopy;
  2520. tenumdef(result).basedef:=self;
  2521. end;
  2522. tenumdef(result).has_jumps:=has_jumps;
  2523. tenumdef(result).basedefderef:=basedefderef;
  2524. include(tenumdef(result).defoptions,df_copied_def);
  2525. end;
  2526. procedure tenumdef.calcsavesize(packenum: shortint);
  2527. begin
  2528. {$IFNDEF cpu64bitaddr} {$push}{$warnings off} {$ENDIF} //comparison always false warning
  2529. if (packenum=8) or (int64(min)<low(longint)) or (int64(max)>high(cardinal)) then
  2530. savesize:=8
  2531. {$IFNDEF cpu64bitaddr} {$pop} {$ENDIF}
  2532. else
  2533. {$IFDEF cpu16bitaddr} {$push}{$warnings off} {$ENDIF} //comparison always false warning
  2534. if (packenum=4) or (min<low(smallint)) or (max>high(word)) then
  2535. savesize:=4
  2536. {$IFDEF cpu16bitaddr} {$pop} {$ENDIF}
  2537. else
  2538. if (packenum=2) or (min<low(shortint)) or (max>high(byte)) then
  2539. savesize:=2
  2540. else
  2541. savesize:=1;
  2542. end;
  2543. function tenumdef.packedbitsize: asizeint;
  2544. var
  2545. sizeval: tconstexprint;
  2546. power: longint;
  2547. begin
  2548. result := 0;
  2549. if (minval >= 0) and
  2550. (maxval <= 1) then
  2551. result := 1
  2552. else
  2553. begin
  2554. if (minval>=0) then
  2555. sizeval:=maxval
  2556. else
  2557. { don't count 0 twice, but take into account that range goes from -n-1..n }
  2558. sizeval:=(cutils.max(-minval,maxval+1)*2)-1;
  2559. { 256 must become 512 etc. }
  2560. nextpowerof2(sizeval+1,power);
  2561. result := power;
  2562. end;
  2563. end;
  2564. procedure tenumdef.setmax(_max:asizeint);
  2565. begin
  2566. maxval:=_max;
  2567. calcsavesize(current_settings.packenum);
  2568. end;
  2569. procedure tenumdef.setmin(_min:asizeint);
  2570. begin
  2571. minval:=_min;
  2572. calcsavesize(current_settings.packenum);
  2573. end;
  2574. function tenumdef.min:asizeint;
  2575. begin
  2576. min:=minval;
  2577. end;
  2578. function tenumdef.max:asizeint;
  2579. begin
  2580. max:=maxval;
  2581. end;
  2582. function tenumdef.getfirstsym: tsym;
  2583. var
  2584. i:integer;
  2585. begin
  2586. for i := 0 to symtable.SymList.Count - 1 do
  2587. begin
  2588. result:=tsym(symtable.SymList[i]);
  2589. if tenumsym(result).value=minval then
  2590. exit;
  2591. end;
  2592. result:=nil;
  2593. end;
  2594. function tenumdef.int2enumsym(l: asizeint): tsym;
  2595. var
  2596. i: longint;
  2597. sym: tsym;
  2598. bdef: tenumdef;
  2599. begin
  2600. result:=nil;
  2601. if (l<minval) or
  2602. (l>maxval) then
  2603. exit;
  2604. bdef:=getbasedef;
  2605. for i:=0 to bdef.symtable.symlist.count-1 do
  2606. begin
  2607. sym:=tsym(bdef.symtable.symlist[i]);
  2608. if (sym.typ=enumsym) and
  2609. (tenumsym(sym).value=l) then
  2610. begin
  2611. result:=sym;
  2612. exit;
  2613. end;
  2614. end;
  2615. end;
  2616. function tenumdef.getbasedef: tenumdef;
  2617. begin
  2618. if not assigned(basedef) then
  2619. result:=self
  2620. else
  2621. result:=basedef;
  2622. end;
  2623. procedure tenumdef.buildderef;
  2624. begin
  2625. inherited buildderef;
  2626. if df_copied_def in defoptions then
  2627. basedefderef.build(basedef)
  2628. else
  2629. tenumsymtable(symtable).buildderef;
  2630. end;
  2631. procedure tenumdef.deref;
  2632. begin
  2633. inherited deref;
  2634. if df_copied_def in defoptions then
  2635. begin
  2636. basedef:=tenumdef(basedefderef.resolve);
  2637. symtable:=basedef.symtable.getcopy;
  2638. end
  2639. else
  2640. tenumsymtable(symtable).deref(false);
  2641. end;
  2642. procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);
  2643. begin
  2644. inherited ppuwrite(ppufile);
  2645. ppufile.putaint(min);
  2646. ppufile.putaint(max);
  2647. ppufile.putaint(savesize);
  2648. if df_copied_def in defoptions then
  2649. ppufile.putderef(basedefderef);
  2650. writeentry(ppufile,ibenumdef);
  2651. if not (df_copied_def in defoptions) then
  2652. tenumsymtable(symtable).ppuwrite(ppufile);
  2653. end;
  2654. function tenumdef.is_publishable : boolean;
  2655. begin
  2656. is_publishable:=true;
  2657. end;
  2658. function tenumdef.GetTypeName : string;
  2659. begin
  2660. GetTypeName:='<enumeration type>';
  2661. end;
  2662. {****************************************************************************
  2663. TRTTI_ATTRIBUTE_LIST
  2664. ****************************************************************************}
  2665. constructor trtti_attribute.ppuload(ppufile: tcompilerppufile);
  2666. begin
  2667. ppufile.getderef(typesymderef);
  2668. ppufile.getderef(typeconstrderef);
  2669. setlength(paras,ppufile.getlongint);
  2670. end;
  2671. procedure trtti_attribute.ppuwrite(ppufile: tcompilerppufile);
  2672. begin
  2673. ppufile.putderef(typesymderef);
  2674. ppufile.putderef(typeconstrderef);
  2675. ppufile.putlongint(length(paras));
  2676. end;
  2677. procedure trtti_attribute.ppuload_subentries(ppufile: tcompilerppufile);
  2678. var
  2679. i : sizeint;
  2680. begin
  2681. for i:=0 to high(paras) do
  2682. paras[i]:=ppuloadnodetree(ppufile);
  2683. end;
  2684. procedure trtti_attribute.ppuwrite_subentries(ppufile: tcompilerppufile);
  2685. var
  2686. i : sizeint;
  2687. begin
  2688. for i:=0 to high(paras) do
  2689. ppuwritenodetree(ppufile,paras[i]);
  2690. end;
  2691. destructor trtti_attribute.destroy;
  2692. var
  2693. n : tnode;
  2694. begin
  2695. constructorcall.free;
  2696. for n in paras do
  2697. n.free;
  2698. inherited destroy;
  2699. end;
  2700. procedure trtti_attribute.buildderef;
  2701. var
  2702. i : sizeint;
  2703. begin
  2704. typesymderef.build(typesym);
  2705. typeconstrderef.build(typeconstr);
  2706. for i:=0 to high(paras) do
  2707. paras[i].buildderefimpl;
  2708. end;
  2709. procedure trtti_attribute.deref;
  2710. var
  2711. i : sizeint;
  2712. begin
  2713. typesym:=tsym(typesymderef.resolve);
  2714. typeconstr:=tdef(typeconstrderef.resolve);
  2715. for i:=0 to high(paras) do
  2716. paras[i].derefimpl;
  2717. end;
  2718. class procedure trtti_attribute_list.bind(var dangling,owned:trtti_attribute_list);
  2719. begin
  2720. if assigned(owned) then
  2721. internalerror(2019071001);
  2722. if not assigned(dangling) then
  2723. exit;
  2724. if dangling.is_bound then
  2725. internalerror(2019071002);
  2726. current_module.used_rtti_attrs.concatlistcopy(dangling.rtti_attributes);
  2727. dangling.is_bound:=true;
  2728. owned:=dangling;
  2729. dangling:=nil;
  2730. end;
  2731. procedure trtti_attribute_list.addattribute(atypesym:tsym;typeconstr:tdef;constructorcall:tnode;constref paras:array of tnode);
  2732. var
  2733. newattribute : trtti_attribute;
  2734. i : sizeint;
  2735. begin
  2736. if not assigned(rtti_attributes) then
  2737. rtti_attributes:=TFPObjectList.Create(true);
  2738. newattribute:=trtti_attribute.Create;
  2739. newattribute.typesym:=atypesym;
  2740. newattribute.typeconstr:=typeconstr;
  2741. newattribute.constructorcall:=constructorcall;
  2742. setlength(newattribute.paras,length(paras));
  2743. for i:=0 to high(paras) do
  2744. newattribute.paras[i]:=paras[i];
  2745. rtti_attributes.Add(newattribute);
  2746. end;
  2747. procedure trtti_attribute_list.addattribute(attr:trtti_attribute);
  2748. begin
  2749. if not assigned(rtti_attributes) then
  2750. rtti_attributes:=TFPObjectList.Create(true);
  2751. rtti_attributes.add(attr);
  2752. end;
  2753. destructor trtti_attribute_list.destroy;
  2754. begin
  2755. rtti_attributes.Free;
  2756. inherited destroy;
  2757. end;
  2758. function trtti_attribute_list.get_attribute_count:longint;
  2759. begin
  2760. if assigned(rtti_attributes) then
  2761. result:=rtti_attributes.Count
  2762. else
  2763. result:=0;
  2764. end;
  2765. procedure trtti_attribute_list.buildderef;
  2766. var
  2767. i : sizeint;
  2768. begin
  2769. if not assigned(rtti_attributes) then
  2770. exit;
  2771. for i:=0 to rtti_attributes.count-1 do
  2772. trtti_attribute(rtti_attributes[i]).buildderef;
  2773. end;
  2774. procedure trtti_attribute_list.deref;
  2775. var
  2776. i : sizeint;
  2777. begin
  2778. if not assigned(rtti_attributes) then
  2779. exit;
  2780. for i:=0 to rtti_attributes.count-1 do
  2781. trtti_attribute(rtti_attributes[i]).deref;
  2782. end;
  2783. class procedure trtti_attribute_list.ppuload_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  2784. var
  2785. i : sizeint;
  2786. begin
  2787. if assigned(attrlist) then
  2788. begin
  2789. if not assigned(attrlist.rtti_attributes) then
  2790. internalerror(2019071101);
  2791. for i:=0 to attrlist.rtti_attributes.count-1 do
  2792. trtti_attribute(attrlist.rtti_attributes[i]).ppuload_subentries(ppufile);
  2793. end;
  2794. end;
  2795. class procedure trtti_attribute_list.ppuwrite_subentries(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  2796. var
  2797. i : sizeint;
  2798. begin
  2799. if assigned(attrlist) and assigned(attrlist.rtti_attributes) then
  2800. begin
  2801. for i:=0 to attrlist.rtti_attributes.count-1 do
  2802. trtti_attribute(attrlist.rtti_attributes[i]).ppuwrite_subentries(ppufile);
  2803. end;
  2804. end;
  2805. class function trtti_attribute_list.ppuload(ppufile:tcompilerppufile):trtti_attribute_list;
  2806. var
  2807. cnt,i : longint;
  2808. begin
  2809. cnt:=ppufile.getlongint;
  2810. if cnt>0 then
  2811. begin
  2812. result:=trtti_attribute_list.create;
  2813. for i:=0 to cnt-1 do
  2814. result.addattribute(trtti_attribute.ppuload(ppufile));
  2815. end
  2816. else
  2817. result:=nil;
  2818. end;
  2819. class procedure trtti_attribute_list.ppuwrite(attrlist:trtti_attribute_list;ppufile:tcompilerppufile);
  2820. var
  2821. i : longint;
  2822. begin
  2823. if assigned(attrlist) and assigned(attrlist.rtti_attributes) then
  2824. begin
  2825. ppufile.putlongint(attrlist.rtti_attributes.count);
  2826. for i:=0 to attrlist.rtti_attributes.count-1 do
  2827. trtti_attribute(attrlist.rtti_attributes[i]).ppuwrite(ppufile);
  2828. end
  2829. else
  2830. ppufile.putlongint(0);
  2831. end;
  2832. {****************************************************************************
  2833. TORDDEF
  2834. ****************************************************************************}
  2835. constructor torddef.create(t : tordtype;v,b : TConstExprInt; doregister: boolean);
  2836. begin
  2837. inherited create(orddef,doregister);
  2838. low:=v;
  2839. high:=b;
  2840. ordtype:=t;
  2841. setsize;
  2842. end;
  2843. constructor torddef.ppuload(ppufile:tcompilerppufile);
  2844. begin
  2845. inherited ppuload(orddef,ppufile);
  2846. ordtype:=tordtype(ppufile.getbyte);
  2847. low:=ppufile.getexprint;
  2848. high:=ppufile.getexprint;
  2849. setsize;
  2850. ppuload_platform(ppufile);
  2851. end;
  2852. function torddef.getcopy : tstoreddef;
  2853. begin
  2854. result:=corddef.create(ordtype,low,high,true);
  2855. result.typ:=orddef;
  2856. torddef(result).low:=low;
  2857. torddef(result).high:=high;
  2858. torddef(result).ordtype:=ordtype;
  2859. torddef(result).savesize:=savesize;
  2860. end;
  2861. function torddef.alignment:shortint;
  2862. begin
  2863. if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_darwin]) and
  2864. (ordtype in [s64bit,u64bit]) then
  2865. result := 4
  2866. else
  2867. result := inherited alignment;
  2868. end;
  2869. procedure torddef.setsize;
  2870. const
  2871. sizetbl : array[tordtype] of longint = (
  2872. 0,
  2873. 1,2,4,8,16,
  2874. 1,2,4,8,16,
  2875. 1,1,2,4,8,
  2876. 1,2,4,8,
  2877. 1,2,8,system.high(longint)
  2878. );
  2879. begin
  2880. savesize:=sizetbl[ordtype];
  2881. if savesize=system.high(longint) then
  2882. savesize:=packedbitsize div 8;
  2883. end;
  2884. function torddef.packedbitsize: asizeint;
  2885. var
  2886. sizeval: tconstexprint;
  2887. power: longint;
  2888. begin
  2889. result := 0;
  2890. if ordtype = uvoid then
  2891. exit;
  2892. {$ifndef cpu64bitalu}
  2893. if (ordtype in [s64bit,u64bit]) then
  2894. {$else not cpu64bitalu}
  2895. if (ordtype = u64bit) or
  2896. ((ordtype = s64bit) and
  2897. ((low <= (system.low(int64) div 2)) or
  2898. (high > (system.high(int64) div 2)))) then
  2899. {$endif cpu64bitalu}
  2900. result := 64
  2901. else if (
  2902. (low >= 0) and
  2903. (high <= 1)
  2904. ) or (
  2905. ordtype in [pasbool1,pasbool8,pasbool16,pasbool32,pasbool64,bool8bit,bool16bit,bool32bit,bool64bit]
  2906. ) then
  2907. result := 1
  2908. else
  2909. begin
  2910. if (low>=0) then
  2911. sizeval:=high
  2912. else
  2913. { don't count 0 twice, but take into account that range goes from -n-1..n }
  2914. sizeval:=(cutils.max(-low,high+1)*2)-1;
  2915. { 256 must become 512 etc. }
  2916. nextpowerof2(sizeval+1,power);
  2917. result := power;
  2918. end;
  2919. end;
  2920. function torddef.getvardef : longint;
  2921. const
  2922. basetype2vardef : array[tordtype] of longint = (
  2923. varUndefined,
  2924. varbyte,varword,varlongword,varqword,varUndefined,
  2925. varshortint,varsmallint,varinteger,varint64,varUndefined,
  2926. varboolean,varboolean,varboolean,varboolean,varboolean,
  2927. varboolean,varboolean,varUndefined,varUndefined,
  2928. varUndefined,varUndefined,varCurrency,varEmpty);
  2929. begin
  2930. result:=basetype2vardef[ordtype];
  2931. if result=varEmpty then
  2932. result:=basetype2vardef[range_to_basetype(low,high)];
  2933. end;
  2934. procedure torddef.ppuwrite(ppufile:tcompilerppufile);
  2935. begin
  2936. inherited ppuwrite(ppufile);
  2937. ppufile.putbyte(byte(ordtype));
  2938. ppufile.putexprint(low);
  2939. ppufile.putexprint(high);
  2940. writeentry(ppufile,iborddef);
  2941. end;
  2942. function torddef.is_publishable : boolean;
  2943. begin
  2944. is_publishable:=(ordtype<>uvoid);
  2945. end;
  2946. function torddef.GetTypeName : string;
  2947. const
  2948. names : array[tordtype] of string[20] = (
  2949. 'untyped',
  2950. 'Byte','Word','DWord','QWord','UInt128',
  2951. 'ShortInt','SmallInt','LongInt','Int64','Int128',
  2952. 'Boolean','Boolean8','Boolean16','Boolean32','Boolean64',
  2953. 'ByteBool','WordBool','LongBool','QWordBool',
  2954. 'Char','WideChar','Currency','CustomRange');
  2955. begin
  2956. GetTypeName:=names[ordtype];
  2957. end;
  2958. {****************************************************************************
  2959. TFLOATDEF
  2960. ****************************************************************************}
  2961. constructor tfloatdef.create(t: tfloattype; doregister: boolean);
  2962. begin
  2963. inherited create(floatdef,doregister);
  2964. floattype:=t;
  2965. setsize;
  2966. end;
  2967. constructor tfloatdef.ppuload(ppufile:tcompilerppufile);
  2968. begin
  2969. inherited ppuload(floatdef,ppufile);
  2970. floattype:=tfloattype(ppufile.getbyte);
  2971. setsize;
  2972. ppuload_platform(ppufile);
  2973. end;
  2974. function tfloatdef.getcopy : tstoreddef;
  2975. begin
  2976. result:=cfloatdef.create(floattype,true);
  2977. result.typ:=floatdef;
  2978. tfloatdef(result).savesize:=savesize;
  2979. end;
  2980. function tfloatdef.alignment:shortint;
  2981. begin
  2982. if (target_info.system in [system_i386_darwin,system_i386_iphonesim,system_arm_darwin]) then
  2983. case floattype of
  2984. sc80real,
  2985. s80real: result:=16;
  2986. s64real,
  2987. s64currency,
  2988. s64comp : result:=4;
  2989. else
  2990. result := inherited alignment;
  2991. end
  2992. else
  2993. result := inherited alignment;
  2994. end;
  2995. function tfloatdef.structalignment: shortint;
  2996. begin
  2997. { aix is really annoying: the recommended scalar alignment for both
  2998. int64 and double is 64 bits, but in structs int64 has to be aligned
  2999. to 8 bytes and double to 4 bytes }
  3000. if (target_info.system in systems_aix) and
  3001. (floattype=s64real) then
  3002. result:=4
  3003. else
  3004. result:=alignment;
  3005. end;
  3006. procedure tfloatdef.setsize;
  3007. begin
  3008. case floattype of
  3009. s32real : savesize:=4;
  3010. s80real : savesize:=10;
  3011. sc80real:
  3012. if target_info.system in [system_i386_darwin,
  3013. system_i386_iphonesim,system_x86_64_darwin,
  3014. system_x86_64_iphonesim,
  3015. system_x86_64_linux,system_x86_64_freebsd,
  3016. system_x86_64_openbsd,system_x86_64_netbsd,
  3017. system_x86_64_solaris,system_x86_64_embedded,
  3018. system_x86_64_dragonfly,system_x86_64_haiku] then
  3019. savesize:=16
  3020. else
  3021. savesize:=12;
  3022. s64real,
  3023. s64currency,
  3024. s64comp : savesize:=8;
  3025. else
  3026. savesize:=0;
  3027. end;
  3028. end;
  3029. function tfloatdef.getvardef : longint;
  3030. const
  3031. floattype2vardef : array[tfloattype] of longint = (
  3032. varSingle,varDouble,varUndefined,varUndefined,
  3033. varUndefined,varCurrency,varUndefined);
  3034. begin
  3035. if (upper(typename)='TDATETIME') and
  3036. assigned(owner) and
  3037. assigned(owner.name) and
  3038. (owner.name^='SYSTEM') then
  3039. result:=varDate
  3040. else
  3041. result:=floattype2vardef[floattype];
  3042. end;
  3043. procedure tfloatdef.ppuwrite(ppufile:tcompilerppufile);
  3044. begin
  3045. inherited ppuwrite(ppufile);
  3046. ppufile.putbyte(byte(floattype));
  3047. writeentry(ppufile,ibfloatdef);
  3048. end;
  3049. function tfloatdef.is_publishable : boolean;
  3050. begin
  3051. is_publishable:=true;
  3052. end;
  3053. function tfloatdef.GetTypeName : string;
  3054. const
  3055. names : array[tfloattype] of string[20] = (
  3056. 'Single','Double','Extended','CExtended','Comp','Currency','Float128');
  3057. begin
  3058. GetTypeName:=names[floattype];
  3059. end;
  3060. {****************************************************************************
  3061. TFILEDEF
  3062. ****************************************************************************}
  3063. constructor tfiledef.createtext;
  3064. begin
  3065. inherited create(filedef,true);
  3066. filetyp:=ft_text;
  3067. typedfiledef:=nil;
  3068. typedfiledefderef.reset;
  3069. end;
  3070. constructor tfiledef.createuntyped;
  3071. begin
  3072. inherited create(filedef,true);
  3073. filetyp:=ft_untyped;
  3074. typedfiledef:=nil;
  3075. end;
  3076. constructor tfiledef.createtyped(def:tdef);
  3077. begin
  3078. inherited create(filedef,true);
  3079. filetyp:=ft_typed;
  3080. typedfiledef:=def;
  3081. end;
  3082. constructor tfiledef.ppuload(ppufile:tcompilerppufile);
  3083. begin
  3084. inherited ppuload(filedef,ppufile);
  3085. filetyp:=tfiletyp(ppufile.getbyte);
  3086. if filetyp=ft_typed then
  3087. ppufile.getderef(typedfiledefderef)
  3088. else
  3089. typedfiledef:=nil;
  3090. ppuload_platform(ppufile);
  3091. end;
  3092. function tfiledef.getcopy : tstoreddef;
  3093. begin
  3094. case filetyp of
  3095. ft_typed:
  3096. result:=cfiledef.createtyped(typedfiledef);
  3097. ft_untyped:
  3098. result:=cfiledef.createuntyped;
  3099. ft_text:
  3100. result:=cfiledef.createtext;
  3101. end;
  3102. end;
  3103. procedure tfiledef.buildderef;
  3104. begin
  3105. inherited buildderef;
  3106. if filetyp=ft_typed then
  3107. typedfiledefderef.build(typedfiledef);
  3108. end;
  3109. procedure tfiledef.deref;
  3110. begin
  3111. inherited deref;
  3112. if filetyp=ft_typed then
  3113. typedfiledef:=tdef(typedfiledefderef.resolve);
  3114. end;
  3115. function tfiledef.size:asizeint;
  3116. begin
  3117. if savesize=0 then
  3118. setsize;
  3119. size:=savesize;
  3120. end;
  3121. procedure tfiledef.setsize;
  3122. begin
  3123. case filetyp of
  3124. ft_text:
  3125. savesize:=search_system_type('TEXTREC').typedef.size;
  3126. ft_typed:
  3127. begin
  3128. savesize:=search_system_type('FILEREC').typedef.size;
  3129. { allocate put/get buffer in iso mode }
  3130. if m_isolike_io in current_settings.modeswitches then
  3131. inc(savesize,typedfiledef.size);
  3132. end;
  3133. ft_untyped:
  3134. savesize:=search_system_type('FILEREC').typedef.size;
  3135. end;
  3136. end;
  3137. function tfiledef.alignment: shortint;
  3138. begin
  3139. case filetyp of
  3140. ft_text:
  3141. result:=search_system_type('TEXTREC').typedef.alignment;
  3142. ft_typed,
  3143. ft_untyped:
  3144. result:=search_system_type('FILEREC').typedef.alignment;
  3145. end;
  3146. end;
  3147. procedure tfiledef.ppuwrite(ppufile:tcompilerppufile);
  3148. begin
  3149. inherited ppuwrite(ppufile);
  3150. ppufile.putbyte(byte(filetyp));
  3151. if filetyp=ft_typed then
  3152. ppufile.putderef(typedfiledefderef);
  3153. writeentry(ppufile,ibfiledef);
  3154. end;
  3155. function tfiledef.GetTypeName : string;
  3156. begin
  3157. case filetyp of
  3158. ft_untyped:
  3159. GetTypeName:='File';
  3160. ft_typed:
  3161. GetTypeName:='File Of '+typedfiledef.typename;
  3162. ft_text:
  3163. GetTypeName:='Text'
  3164. end;
  3165. end;
  3166. function tfiledef.getmangledparaname : TSymStr;
  3167. begin
  3168. case filetyp of
  3169. ft_untyped:
  3170. getmangledparaname:='FILE';
  3171. ft_typed:
  3172. getmangledparaname:='FILE$OF$'+typedfiledef.mangledparaname;
  3173. ft_text:
  3174. getmangledparaname:='TEXT'
  3175. end;
  3176. end;
  3177. {****************************************************************************
  3178. TVARIANTDEF
  3179. ****************************************************************************}
  3180. constructor tvariantdef.create(v : tvarianttype);
  3181. begin
  3182. inherited create(variantdef,true);
  3183. varianttype:=v;
  3184. setsize;
  3185. end;
  3186. constructor tvariantdef.ppuload(ppufile:tcompilerppufile);
  3187. begin
  3188. inherited ppuload(variantdef,ppufile);
  3189. varianttype:=tvarianttype(ppufile.getbyte);
  3190. setsize;
  3191. ppuload_platform(ppufile);
  3192. end;
  3193. function tvariantdef.getcopy : tstoreddef;
  3194. begin
  3195. result:=cvariantdef.create(varianttype);
  3196. end;
  3197. procedure tvariantdef.ppuwrite(ppufile:tcompilerppufile);
  3198. begin
  3199. inherited ppuwrite(ppufile);
  3200. ppufile.putbyte(byte(varianttype));
  3201. writeentry(ppufile,ibvariantdef);
  3202. end;
  3203. function tvariantdef.getvardef : longint;
  3204. begin
  3205. Result:=varVariant;
  3206. end;
  3207. procedure tvariantdef.setsize;
  3208. begin
  3209. {$ifdef cpu64bitaddr}
  3210. savesize:=24;
  3211. {$else cpu64bitaddr}
  3212. savesize:=16;
  3213. {$endif cpu64bitaddr}
  3214. end;
  3215. function tvariantdef.GetTypeName : string;
  3216. begin
  3217. case varianttype of
  3218. vt_normalvariant:
  3219. GetTypeName:='Variant';
  3220. vt_olevariant:
  3221. GetTypeName:='OleVariant';
  3222. end;
  3223. end;
  3224. function tvariantdef.needs_inittable : boolean;
  3225. begin
  3226. needs_inittable:=true;
  3227. end;
  3228. function tvariantdef.is_publishable : boolean;
  3229. begin
  3230. is_publishable:=true;
  3231. end;
  3232. {****************************************************************************
  3233. TABSTRACtpointerdef
  3234. ****************************************************************************}
  3235. constructor tabstractpointerdef.create(dt:tdeftyp;def:tdef);
  3236. begin
  3237. inherited create(dt,true);
  3238. pointeddef:=def;
  3239. pointeddefderef.reset;
  3240. if df_generic in pointeddef.defoptions then
  3241. include(defoptions,df_generic);
  3242. if df_specialization in pointeddef.defoptions then
  3243. include(defoptions,df_specialization);
  3244. end;
  3245. constructor tabstractpointerdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  3246. begin
  3247. inherited ppuload(dt,ppufile);
  3248. ppufile.getderef(pointeddefderef);
  3249. end;
  3250. procedure tabstractpointerdef.buildderef;
  3251. begin
  3252. inherited buildderef;
  3253. pointeddefderef.build(pointeddef);
  3254. end;
  3255. procedure tabstractpointerdef.deref;
  3256. begin
  3257. inherited deref;
  3258. pointeddef:=tdef(pointeddefderef.resolve);
  3259. end;
  3260. function tabstractpointerdef.size: asizeint;
  3261. begin
  3262. Result:=voidpointertype.size;
  3263. end;
  3264. function tabstractpointerdef.alignment: shortint;
  3265. begin
  3266. alignment:=size_2_align(voidpointertype.size);
  3267. end;
  3268. procedure tabstractpointerdef.ppuwrite(ppufile:tcompilerppufile);
  3269. begin
  3270. inherited ppuwrite(ppufile);
  3271. ppufile.putderef(pointeddefderef);
  3272. end;
  3273. {****************************************************************************
  3274. tpointerdef
  3275. ****************************************************************************}
  3276. constructor tpointerdef.create(def:tdef);
  3277. begin
  3278. inherited create(pointerdef,def);
  3279. has_pointer_math:=cs_pointermath in current_settings.localswitches;
  3280. if (df_specialization in tstoreddef(def).defoptions)
  3281. {$ifndef genericdef_for_nested}
  3282. { currently, nested procdefs of generic routines get df_specialisation,
  3283. but no genericdef }
  3284. and assigned(tstoreddef(def).genericdef)
  3285. {$endif}
  3286. then
  3287. genericdef:=cpointerdef.getreusable(tstoreddef(def).genericdef);
  3288. end;
  3289. class function tpointerdef.getreusable(def: tdef): tpointerdef;
  3290. var
  3291. res: PHashSetItem;
  3292. oldsymtablestack: tsymtablestack;
  3293. begin
  3294. if not assigned(current_module) then
  3295. internalerror(2011071101);
  3296. res:=current_module.ptrdefs.FindOrAdd(@def,sizeof(def));
  3297. if not assigned(res^.Data) then
  3298. begin
  3299. { since these pointerdefs can be reused anywhere in the current
  3300. unit, add them to the global/staticsymtable (or local symtable
  3301. if they're a local def, because otherwise they'll be saved
  3302. to the ppu referencing a local symtable entry that doesn't
  3303. exist in the ppu) }
  3304. oldsymtablestack:=symtablestack;
  3305. { do not simply push/pop current_module.localsymtable, because
  3306. that can have side-effects (e.g., it removes helpers) }
  3307. symtablestack:=nil;
  3308. result:=cpointerdef.create(def);
  3309. setup_reusable_def(def,result,res,oldsymtablestack);
  3310. { res^.Data may still be nil -> don't overwrite result }
  3311. exit;
  3312. end;
  3313. result:=tpointerdef(res^.Data);
  3314. end;
  3315. class function tpointerdef.getreusable_no_free(def: tdef): tpointerdef;
  3316. begin
  3317. result:=getreusable(def);
  3318. if not result.is_registered then
  3319. include(result.defoptions,df_not_registered_no_free);
  3320. end;
  3321. function tpointerdef.size: asizeint;
  3322. begin
  3323. result:=sizeof(pint);
  3324. end;
  3325. constructor tpointerdef.ppuload(ppufile:tcompilerppufile);
  3326. begin
  3327. inherited ppuload(pointerdef,ppufile);
  3328. has_pointer_math:=(ppufile.getbyte<>0);
  3329. ppuload_platform(ppufile);
  3330. end;
  3331. function tpointerdef.getcopy : tstoreddef;
  3332. begin
  3333. { don't use direct pointeddef if it is a forwarddef because in other case
  3334. one of them will be destroyed on forward type resolve and the second will
  3335. point to garbage }
  3336. if pointeddef.typ=forwarddef then
  3337. result:=cpointerdef.create(tforwarddef(pointeddef).getcopy)
  3338. else
  3339. result:=cpointerdef.create(pointeddef);
  3340. tpointerdef(result).has_pointer_math:=has_pointer_math;
  3341. tpointerdef(result).savesize:=savesize;
  3342. end;
  3343. procedure tpointerdef.ppuwrite(ppufile:tcompilerppufile);
  3344. begin
  3345. inherited ppuwrite(ppufile);
  3346. ppufile.putbyte(byte(has_pointer_math));
  3347. writeentry(ppufile,ibpointerdef);
  3348. end;
  3349. function tpointerdef.GetTypeName : string;
  3350. begin
  3351. { parameter types and the resultdef of a procvardef can contain a
  3352. pointer to this procvardef itself, resulting in endless recursion ->
  3353. use the typesym's name instead if it exists (if it doesn't, such as
  3354. for anynonymous procedure types in macpas/iso mode, then there cannot
  3355. be any recursive references to it either) }
  3356. if (pointeddef.typ<>procvardef) or
  3357. not assigned(pointeddef.typesym) then
  3358. GetTypeName:='^'+pointeddef.typename
  3359. else
  3360. GetTypeName:='^'+pointeddef.typesym.realname;
  3361. end;
  3362. function tpointerdef.pointer_arithmetic_int_type:tdef;
  3363. begin
  3364. result:=ptrsinttype;
  3365. end;
  3366. function tpointerdef.pointer_arithmetic_uint_type:tdef;
  3367. begin
  3368. result:=ptruinttype;
  3369. end;
  3370. function tpointerdef.pointer_subtraction_result_type:tdef;
  3371. begin
  3372. result:=ptrsinttype;
  3373. end;
  3374. function tpointerdef.compatible_with_pointerdef_size(ptr: tpointerdef): boolean;
  3375. begin
  3376. result:=true;
  3377. end;
  3378. function tpointerdef.converted_pointer_to_array_range_type:tdef;
  3379. begin
  3380. result:=ptrsinttype;
  3381. end;
  3382. {****************************************************************************
  3383. TCLASSREFDEF
  3384. ****************************************************************************}
  3385. constructor tclassrefdef.create(def:tdef);
  3386. begin
  3387. inherited create(classrefdef,def);
  3388. if df_specialization in tstoreddef(def).defoptions then
  3389. genericdef:=cclassrefdef.create(tstoreddef(def).genericdef);
  3390. end;
  3391. constructor tclassrefdef.ppuload(ppufile:tcompilerppufile);
  3392. begin
  3393. inherited ppuload(classrefdef,ppufile);
  3394. ppuload_platform(ppufile);
  3395. end;
  3396. procedure tclassrefdef.ppuwrite(ppufile:tcompilerppufile);
  3397. begin
  3398. inherited ppuwrite(ppufile);
  3399. writeentry(ppufile,ibclassrefdef);
  3400. end;
  3401. function tclassrefdef.getcopy:tstoreddef;
  3402. begin
  3403. if pointeddef.typ=forwarddef then
  3404. result:=cclassrefdef.create(tforwarddef(pointeddef).getcopy)
  3405. else
  3406. result:=cclassrefdef.create(pointeddef);
  3407. end;
  3408. function tclassrefdef.GetTypeName : string;
  3409. begin
  3410. GetTypeName:='Class Of '+pointeddef.typename;
  3411. end;
  3412. function tclassrefdef.is_publishable : boolean;
  3413. begin
  3414. result:=true;
  3415. end;
  3416. function tclassrefdef.rtti_mangledname(rt: trttitype): TSymStr;
  3417. begin
  3418. if (tobjectdef(pointeddef).objecttype<>odt_objcclass) then
  3419. result:=inherited rtti_mangledname(rt)
  3420. else
  3421. result:=tobjectdef(pointeddef).rtti_mangledname(objcmetartti);
  3422. end;
  3423. procedure tclassrefdef.register_created_object_type;
  3424. begin
  3425. tobjectdef(pointeddef).register_created_classref_type;
  3426. end;
  3427. {***************************************************************************
  3428. TSETDEF
  3429. ***************************************************************************}
  3430. constructor tsetdef.create(def: tdef; low, high: asizeint; doregister: boolean);
  3431. var
  3432. setallocbits: aint;
  3433. packedsavesize: aint;
  3434. actual_setalloc: ShortInt;
  3435. begin
  3436. inherited create(setdef,doregister);
  3437. elementdef:=def;
  3438. elementdefderef.reset;
  3439. setmax:=high;
  3440. actual_setalloc:=current_settings.setalloc;
  3441. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  3442. if actual_setalloc=0 then
  3443. actual_setalloc:=1;
  3444. {$endif}
  3445. if (actual_setalloc=0) then
  3446. begin
  3447. setbase:=0;
  3448. if (high<32) then
  3449. savesize:=Sizeof(longint)
  3450. else if (high<256) then
  3451. savesize:=32
  3452. else
  3453. savesize:=(high+7) div 8
  3454. end
  3455. else
  3456. begin
  3457. setallocbits:=actual_setalloc*8;
  3458. setbase:=low and not(setallocbits-1);
  3459. packedsavesize:=actual_setalloc*((((high+setallocbits)-setbase)) DIV setallocbits);
  3460. savesize:=packedsavesize;
  3461. {$if not defined(cpu8bitalu) and not defined(cpu16bitalu)}
  3462. if savesize=3 then
  3463. savesize:=4;
  3464. {$endif}
  3465. end;
  3466. end;
  3467. constructor tsetdef.ppuload(ppufile:tcompilerppufile);
  3468. begin
  3469. inherited ppuload(setdef,ppufile);
  3470. ppufile.getderef(elementdefderef);
  3471. savesize:=ppufile.getasizeint;
  3472. setbase:=ppufile.getasizeint;
  3473. setmax:=ppufile.getasizeint;
  3474. ppuload_platform(ppufile);
  3475. end;
  3476. function tsetdef.getcopy : tstoreddef;
  3477. begin
  3478. result:=csetdef.create(elementdef,setbase,setmax,true);
  3479. { the copy might have been created with a different setalloc setting }
  3480. tsetdef(result).savesize:=savesize;
  3481. end;
  3482. procedure tsetdef.ppuwrite(ppufile:tcompilerppufile);
  3483. begin
  3484. inherited ppuwrite(ppufile);
  3485. ppufile.putderef(elementdefderef);
  3486. ppufile.putasizeint(savesize);
  3487. ppufile.putasizeint(setbase);
  3488. ppufile.putasizeint(setmax);
  3489. writeentry(ppufile,ibsetdef);
  3490. end;
  3491. procedure tsetdef.buildderef;
  3492. begin
  3493. inherited buildderef;
  3494. elementdefderef.build(elementdef);
  3495. end;
  3496. procedure tsetdef.deref;
  3497. begin
  3498. inherited deref;
  3499. elementdef:=tdef(elementdefderef.resolve);
  3500. end;
  3501. function tsetdef.is_publishable : boolean;
  3502. begin
  3503. is_publishable:=savesize in [1,2,4];
  3504. end;
  3505. function tsetdef.alignment: shortint;
  3506. begin
  3507. Result:=inherited;
  3508. if result>sizeof(aint) then
  3509. result:=sizeof(aint);
  3510. end;
  3511. function tsetdef.GetTypeName : string;
  3512. begin
  3513. if assigned(elementdef) then
  3514. GetTypeName:='Set Of '+elementdef.typename
  3515. else
  3516. GetTypeName:='Empty Set';
  3517. end;
  3518. {***************************************************************************
  3519. TFORMALDEF
  3520. ***************************************************************************}
  3521. constructor tformaldef.create(Atyped:boolean);
  3522. begin
  3523. inherited create(formaldef,true);
  3524. typed:=Atyped;
  3525. savesize:=0;
  3526. end;
  3527. constructor tformaldef.ppuload(ppufile:tcompilerppufile);
  3528. begin
  3529. inherited ppuload(formaldef,ppufile);
  3530. typed:=boolean(ppufile.getbyte);
  3531. savesize:=0;
  3532. ppuload_platform(ppufile);
  3533. end;
  3534. procedure tformaldef.ppuwrite(ppufile:tcompilerppufile);
  3535. begin
  3536. inherited ppuwrite(ppufile);
  3537. ppufile.putbyte(byte(typed));
  3538. writeentry(ppufile,ibformaldef);
  3539. end;
  3540. function tformaldef.GetTypeName : string;
  3541. begin
  3542. if typed then
  3543. GetTypeName:='<Typed formal type>'
  3544. else
  3545. GetTypeName:='<Formal type>';
  3546. end;
  3547. {***************************************************************************
  3548. TARRAYDEF
  3549. ***************************************************************************}
  3550. constructor tarraydef.create(l,h:asizeint;def:tdef);
  3551. begin
  3552. inherited create(arraydef,true);
  3553. lowrange:=l;
  3554. highrange:=h;
  3555. rangedef:=def;
  3556. rangedefderef.reset;
  3557. _elementdef:=nil;
  3558. _elementdefderef.reset;
  3559. arrayoptions:=[];
  3560. symtable:=tarraysymtable.create(self);
  3561. end;
  3562. constructor tarraydef.create_openarray;
  3563. begin
  3564. self.create(0,-1,sizesinttype)
  3565. end;
  3566. class function tarraydef.getreusable(def: tdef; elems: asizeint): tarraydef;
  3567. var
  3568. res: PHashSetItem;
  3569. oldsymtablestack: tsymtablestack;
  3570. arrdesc: packed record
  3571. def: tdef;
  3572. elecount: asizeint;
  3573. end;
  3574. begin
  3575. if not assigned(current_module) then
  3576. internalerror(2011081301);
  3577. arrdesc.def:=def;
  3578. arrdesc.elecount:=elems;
  3579. res:=current_module.arraydefs.FindOrAdd(@arrdesc,sizeof(arrdesc));
  3580. if not assigned(res^.Data) then
  3581. begin
  3582. { since these pointerdefs can be reused anywhere in the current
  3583. unit, add them to the global/staticsymtable (or local symtable
  3584. if they're a local def, because otherwise they'll be saved
  3585. to the ppu referencing a local symtable entry that doesn't
  3586. exist in the ppu) }
  3587. oldsymtablestack:=symtablestack;
  3588. { do not simply push/pop current_module.localsymtable, because
  3589. that can have side-effects (e.g., it removes helpers) }
  3590. symtablestack:=nil;
  3591. result:=carraydef.create(0,elems-1,sizesinttype);
  3592. result.elementdef:=def;
  3593. setup_reusable_def(def,result,res,oldsymtablestack);
  3594. { res^.Data may still be nil -> don't overwrite result }
  3595. exit;
  3596. end;
  3597. result:=tarraydef(res^.Data);
  3598. end;
  3599. class function tarraydef.getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
  3600. begin
  3601. result:=getreusable(def,elems);
  3602. if not result.is_registered then
  3603. include(result.defoptions,df_not_registered_no_free);
  3604. end;
  3605. destructor tarraydef.destroy;
  3606. begin
  3607. symtable.free;
  3608. symtable:=nil;
  3609. inherited;
  3610. end;
  3611. constructor tarraydef.create_from_pointer(def:tpointerdef);
  3612. begin
  3613. { divide by the element size and do -1 so the array will have a valid size,
  3614. further, the element size might be 0 e.g. for empty records, so use max(...,1)
  3615. to avoid a division by zero }
  3616. self.create(0,(high(asizeint) div max(def.pointeddef.size,1))-1,
  3617. def.converted_pointer_to_array_range_type);
  3618. arrayoptions:=[ado_IsConvertedPointer];
  3619. setelementdef(def.pointeddef);
  3620. end;
  3621. constructor tarraydef.ppuload(ppufile:tcompilerppufile);
  3622. begin
  3623. inherited ppuload(arraydef,ppufile);
  3624. { the addresses are calculated later }
  3625. ppufile.getderef(_elementdefderef);
  3626. ppufile.getderef(rangedefderef);
  3627. lowrange:=ppufile.getasizeint;
  3628. highrange:=ppufile.getasizeint;
  3629. ppufile.getsmallset(arrayoptions);
  3630. ppuload_platform(ppufile);
  3631. symtable:=tarraysymtable.create(self);
  3632. tarraysymtable(symtable).ppuload(ppufile)
  3633. end;
  3634. function tarraydef.getcopy : tstoreddef;
  3635. begin
  3636. result:=carraydef.create(lowrange,highrange,rangedef);
  3637. tarraydef(result).arrayoptions:=arrayoptions;
  3638. tarraydef(result)._elementdef:=_elementdef;
  3639. end;
  3640. procedure tarraydef.buildderef;
  3641. begin
  3642. inherited buildderef;
  3643. tarraysymtable(symtable).buildderef;
  3644. _elementdefderef.build(_elementdef);
  3645. rangedefderef.build(rangedef);
  3646. end;
  3647. procedure tarraydef.deref;
  3648. begin
  3649. inherited deref;
  3650. tarraysymtable(symtable).deref(false);
  3651. _elementdef:=tdef(_elementdefderef.resolve);
  3652. rangedef:=tdef(rangedefderef.resolve);
  3653. end;
  3654. procedure tarraydef.ppuwrite(ppufile:tcompilerppufile);
  3655. begin
  3656. inherited ppuwrite(ppufile);
  3657. ppufile.putderef(_elementdefderef);
  3658. ppufile.putderef(rangedefderef);
  3659. ppufile.putasizeint(lowrange);
  3660. ppufile.putasizeint(highrange);
  3661. ppufile.putsmallset(arrayoptions);
  3662. writeentry(ppufile,ibarraydef);
  3663. tarraysymtable(symtable).ppuwrite(ppufile);
  3664. end;
  3665. function tarraydef.elesize : asizeint;
  3666. begin
  3667. if (ado_IsBitPacked in arrayoptions) then
  3668. internalerror(2006080101);
  3669. if assigned(_elementdef) then
  3670. result:=_elementdef.size
  3671. else
  3672. result:=0;
  3673. end;
  3674. function tarraydef.elepackedbitsize : asizeint;
  3675. begin
  3676. if not(ado_IsBitPacked in arrayoptions) then
  3677. internalerror(2006080102);
  3678. if assigned(_elementdef) then
  3679. result:=_elementdef.packedbitsize
  3680. else
  3681. result:=0;
  3682. end;
  3683. function tarraydef.elecount : asizeuint;
  3684. var
  3685. qhigh,qlow : qword;
  3686. begin
  3687. if ado_IsDynamicArray in arrayoptions then
  3688. begin
  3689. result:=0;
  3690. exit;
  3691. end;
  3692. if (highrange>0) and (lowrange<0) then
  3693. begin
  3694. qhigh:=highrange;
  3695. qlow:=qword(-lowrange);
  3696. { prevent overflow, return 0 to indicate overflow }
  3697. if qhigh+qlow>qword(high(asizeint)-1) then
  3698. result:=0
  3699. else
  3700. result:=qhigh+qlow+1;
  3701. end
  3702. else
  3703. result:=int64(highrange)-lowrange+1;
  3704. end;
  3705. function tarraydef.size : asizeint;
  3706. var
  3707. cachedelecount : asizeuint;
  3708. cachedelesize : asizeint;
  3709. begin
  3710. if ado_IsDynamicArray in arrayoptions then
  3711. begin
  3712. size:=voidpointertype.size;
  3713. exit;
  3714. end;
  3715. { Tarraydef.size may never be called for an open array! }
  3716. if highrange<lowrange then
  3717. internalerror(99080501);
  3718. if not (ado_IsBitPacked in arrayoptions) then
  3719. cachedelesize:=elesize
  3720. else
  3721. cachedelesize := elepackedbitsize;
  3722. cachedelecount:=elecount;
  3723. if (cachedelesize = 0) then
  3724. begin
  3725. size := 0;
  3726. exit;
  3727. end;
  3728. if (cachedelecount = 0) then
  3729. begin
  3730. size := -1;
  3731. exit;
  3732. end;
  3733. { prevent overflow, return -1 to indicate overflow }
  3734. { also make sure we don't need 64/128 bit arithmetic to calculate offsets }
  3735. if (cachedelecount > asizeuint(high(asizeint))) or
  3736. ((high(asizeint) div cachedelesize) < asizeint(cachedelecount)) or
  3737. { also lowrange*elesize must be < high(asizeint) to prevent overflow when
  3738. accessing the array, see ncgmem (PFV) }
  3739. ((high(asizeint) div cachedelesize) < abs(lowrange)) then
  3740. begin
  3741. result:=-1;
  3742. exit;
  3743. end;
  3744. result:=cachedelesize*asizeint(cachedelecount);
  3745. if (ado_IsBitPacked in arrayoptions) then
  3746. { can't just add 7 and divide by 8, because that may overflow }
  3747. result:=result div 8 + ord((result mod 8)<>0);
  3748. {$ifdef cpu16bitaddr}
  3749. if result>65535 then
  3750. begin
  3751. result:=-1;
  3752. exit;
  3753. end;
  3754. {$endif cpu16bitaddr}
  3755. end;
  3756. procedure tarraydef.setelementdef(def:tdef);
  3757. begin
  3758. _elementdef:=def;
  3759. if not(
  3760. (ado_IsDynamicArray in arrayoptions) or
  3761. (ado_IsConvertedPointer in arrayoptions) or
  3762. (ado_IsConstructor in arrayoptions) or
  3763. (highrange<lowrange)
  3764. ) and
  3765. (size=-1) then
  3766. Message(sym_e_segment_too_large);
  3767. end;
  3768. function tarraydef.alignment : shortint;
  3769. begin
  3770. { alignment of dyn. arrays doesn't depend on the element size }
  3771. if (ado_IsDynamicArray in arrayoptions) then
  3772. alignment:=voidpointertype.alignment
  3773. { alignment is the target alignment for the used load size }
  3774. else if (ado_IsBitPacked in arrayoptions) and
  3775. (elementdef.typ in [enumdef,orddef]) then
  3776. alignment:=cgsize_orddef(int_cgsize(packedbitsloadsize(elepackedbitsize))).alignment
  3777. { alignment is the alignment of the elements }
  3778. else
  3779. alignment:=elementdef.alignment
  3780. end;
  3781. function tarraydef.needs_inittable : boolean;
  3782. begin
  3783. needs_inittable:=(ado_IsDynamicArray in arrayoptions) or elementdef.needs_inittable;
  3784. end;
  3785. function tarraydef.needs_separate_initrtti : boolean;
  3786. begin
  3787. if ado_IsBitPacked in arrayoptions then
  3788. result:=false
  3789. else
  3790. result:=elementdef.needs_separate_initrtti;
  3791. end;
  3792. function tarraydef.GetTypeName : string;
  3793. begin
  3794. if (ado_IsConstString in arrayoptions) then
  3795. result:='Constant String'
  3796. else if (ado_isarrayofconst in arrayoptions) or
  3797. (ado_isConstructor in arrayoptions) then
  3798. begin
  3799. if (ado_isvariant in arrayoptions) or ((highrange=-1) and (lowrange=0)) then
  3800. GetTypeName:='Array Of Const'
  3801. else
  3802. GetTypeName:='{Array Of Const/Constant Open} Array of '+elementdef.typename;
  3803. end
  3804. else if (ado_IsDynamicArray in arrayoptions) then
  3805. GetTypeName:='{Dynamic} Array Of '+elementdef.typename
  3806. else if ((highrange=-1) and (lowrange=0)) then
  3807. GetTypeName:='{Open} Array Of '+elementdef.typename
  3808. else
  3809. begin
  3810. result := '';
  3811. if (ado_IsBitPacked in arrayoptions) then
  3812. result:='BitPacked ';
  3813. if rangedef.typ=enumdef then
  3814. result:=result+'Array['+rangedef.typename+'] Of '+elementdef.typename
  3815. else
  3816. result:=result+'Array['+tostr(lowrange)+'..'+
  3817. tostr(highrange)+'] Of '+elementdef.typename
  3818. end;
  3819. end;
  3820. function tarraydef.getmangledparaname : TSymStr;
  3821. begin
  3822. if ado_isarrayofconst in arrayoptions then
  3823. getmangledparaname:='array_of_const'
  3824. else
  3825. if ((highrange=-1) and (lowrange=0)) then
  3826. getmangledparaname:='array_of_'+elementdef.mangledparaname
  3827. else
  3828. internalerror(200204176);
  3829. end;
  3830. function tarraydef.is_publishable : boolean;
  3831. begin
  3832. Result:=ado_IsDynamicArray in arrayoptions;
  3833. end;
  3834. {***************************************************************************
  3835. tabstractrecorddef
  3836. ***************************************************************************}
  3837. constructor tabstractrecorddef.create(const n:string; dt:tdeftyp;doregister:boolean);
  3838. begin
  3839. inherited create(dt,doregister);
  3840. objname:=stringdup(upper(n));
  3841. objrealname:=stringdup(n);
  3842. objectoptions:=[];
  3843. if assigned(current_module.namespace) then
  3844. begin
  3845. import_lib:=stringdup(current_module.namespace^);
  3846. replace(import_lib^,'.','/');
  3847. end;
  3848. end;
  3849. constructor tabstractrecorddef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  3850. begin
  3851. inherited ppuload(dt,ppufile);
  3852. objrealname:=ppufile.getpshortstring;
  3853. objname:=stringdup(upper(objrealname^));
  3854. import_lib:=ppufile.getpshortstring;
  3855. { only used for external C++ classes and Java classes/records }
  3856. if (import_lib^='') then
  3857. stringdispose(import_lib);
  3858. ppufile.getsmallset(objectoptions);
  3859. end;
  3860. procedure tabstractrecorddef.ppuwrite(ppufile: tcompilerppufile);
  3861. begin
  3862. inherited ppuwrite(ppufile);
  3863. ppufile.putstring(objrealname^);
  3864. if assigned(import_lib) then
  3865. ppufile.putstring(import_lib^)
  3866. else
  3867. ppufile.putstring('');
  3868. ppufile.putsmallset(objectoptions);
  3869. end;
  3870. destructor tabstractrecorddef.destroy;
  3871. begin
  3872. stringdispose(objname);
  3873. stringdispose(objrealname);
  3874. stringdispose(import_lib);
  3875. tcinitcode.free;
  3876. inherited destroy;
  3877. end;
  3878. procedure tabstractrecorddef.buildderefimpl;
  3879. begin
  3880. inherited buildderefimpl;
  3881. if not (df_copied_def in defoptions) then
  3882. tstoredsymtable(symtable).buildderefimpl;
  3883. end;
  3884. procedure tabstractrecorddef.derefimpl;
  3885. begin
  3886. inherited derefimpl;
  3887. if not (df_copied_def in defoptions) then
  3888. tstoredsymtable(symtable).derefimpl(false);
  3889. end;
  3890. procedure tabstractrecorddef.check_forwards;
  3891. begin
  3892. { the defs of a copied def are defined for the original type only }
  3893. if not(df_copied_def in defoptions) then
  3894. tstoredsymtable(symtable).check_forwards;
  3895. end;
  3896. function tabstractrecorddef.find_procdef_bytype(pt:tproctypeoption): tprocdef;
  3897. var
  3898. i: longint;
  3899. sym: tsym;
  3900. begin
  3901. for i:=0 to symtable.SymList.Count-1 do
  3902. begin
  3903. sym:=tsym(symtable.SymList[i]);
  3904. if sym.typ=procsym then
  3905. begin
  3906. result:=tprocsym(sym).find_procdef_bytype(pt);
  3907. if assigned(result) then
  3908. exit;
  3909. end;
  3910. end;
  3911. result:=nil;
  3912. end;
  3913. function tabstractrecorddef.GetSymtable(t:tGetSymtable):TSymtable;
  3914. begin
  3915. if t=gs_record then
  3916. GetSymtable:=symtable
  3917. else
  3918. GetSymtable:=nil;
  3919. end;
  3920. function tabstractrecorddef.is_packed:boolean;
  3921. begin
  3922. result:=tabstractrecordsymtable(symtable).is_packed;
  3923. end;
  3924. function tabstractrecorddef.RttiName: string;
  3925. function generate_full_paramname(maxlength:longint):string;
  3926. const
  3927. commacount : array[boolean] of longint = (0,1);
  3928. var
  3929. fullparas,
  3930. paramname : ansistring;
  3931. module : tmodule;
  3932. sym : ttypesym;
  3933. i : longint;
  3934. begin
  3935. { we want at least enough space for an ellipsis }
  3936. if maxlength<3 then
  3937. internalerror(2014121203);
  3938. fullparas:='';
  3939. for i:=0 to genericparas.count-1 do
  3940. begin
  3941. sym:=ttypesym(genericparas[i]);
  3942. module:=find_module_from_symtable(sym.owner);
  3943. if not assigned(module) then
  3944. internalerror(2014121202);
  3945. paramname:=module.realmodulename^;
  3946. if sym.typedef.typ in [objectdef,recorddef] then
  3947. paramname:=paramname+'.'+tabstractrecorddef(sym.typedef).rttiname
  3948. else
  3949. paramname:=paramname+'.'+sym.typedef.typename;
  3950. if length(fullparas)+commacount[i>0]+length(paramname)>maxlength then
  3951. begin
  3952. if i>0 then
  3953. fullparas:=fullparas+',...'
  3954. else
  3955. fullparas:=fullparas+'...';
  3956. break;
  3957. end;
  3958. { could we fit an ellipsis after this parameter if it should be too long? }
  3959. if (maxlength-(length(fullparas)+commacount[i>0]+length(paramname))<4) and (i<genericparas.count-1) then
  3960. begin
  3961. { then omit already this parameter }
  3962. if i>0 then
  3963. fullparas:=fullparas+',...'
  3964. else
  3965. fullparas:=fullparas+'...';
  3966. break;
  3967. end;
  3968. if i>0 then
  3969. fullparas:=fullparas+',';
  3970. fullparas:=fullparas+paramname;
  3971. end;
  3972. result:=fullparas;
  3973. end;
  3974. var
  3975. nongeneric,
  3976. basename : string;
  3977. i,
  3978. remlength,
  3979. paramcount,
  3980. crcidx : longint;
  3981. begin
  3982. if rttistring='' then
  3983. begin
  3984. if is_specialization then
  3985. begin
  3986. rttistring:=OwnerHierarchyName;
  3987. { there should be two $ characters, one before the CRC and one before the count }
  3988. crcidx:=-1;
  3989. for i:=length(objrealname^) downto 1 do
  3990. if objrealname^[i]='$' then
  3991. begin
  3992. crcidx:=i;
  3993. break;
  3994. end;
  3995. if crcidx<0 then
  3996. internalerror(2014121201);
  3997. basename:=copy(objrealname^,1,crcidx-1);
  3998. split_generic_name(basename,nongeneric,paramcount);
  3999. rttistring:=rttistring+nongeneric+'<';
  4000. remlength:=255-length(rttistring)-1;
  4001. if remlength<4 then
  4002. rttistring:=rttistring+'>'
  4003. else
  4004. rttistring:=rttistring+generate_full_paramname(remlength)+'>';
  4005. end
  4006. else
  4007. if is_generic then
  4008. begin
  4009. rttistring:=OwnerHierarchyName;
  4010. split_generic_name(objrealname^,nongeneric,paramcount);
  4011. rttistring:=rttistring+nongeneric+'<';
  4012. { we don't want any ',' if there is only one parameter }
  4013. for i:=0 to paramcount-0 do
  4014. rttistring:=rttistring+',';
  4015. rttistring:=rttistring+'>';
  4016. end
  4017. else
  4018. rttistring:=OwnerHierarchyName+objrealname^;
  4019. end;
  4020. result:=rttistring;
  4021. end;
  4022. function tabstractrecorddef.search_enumerator_get: tprocdef;
  4023. var
  4024. sym : tsym;
  4025. i : integer;
  4026. pd : tprocdef;
  4027. hashedid : THashedIDString;
  4028. begin
  4029. result:=nil;
  4030. hashedid.id:='GETENUMERATOR';
  4031. sym:=tsym(symtable.FindWithHash(hashedid));
  4032. if assigned(sym) and (sym.typ=procsym) then
  4033. begin
  4034. for i := 0 to Tprocsym(sym).ProcdefList.Count - 1 do
  4035. begin
  4036. pd := tprocdef(Tprocsym(sym).ProcdefList[i]);
  4037. if (pd.proctypeoption = potype_function) and
  4038. (is_class_or_interface_or_object(pd.returndef) or is_record(pd.returndef)) and
  4039. (pd.visibility >= vis_public) then
  4040. begin
  4041. result:=pd;
  4042. exit;
  4043. end;
  4044. end;
  4045. end;
  4046. end;
  4047. function tabstractrecorddef.search_enumerator_move: tprocdef;
  4048. var
  4049. sym : tsym;
  4050. i : integer;
  4051. pd : tprocdef;
  4052. hashedid : THashedIDString;
  4053. begin
  4054. result:=nil;
  4055. // first search for po_enumerator_movenext method modifier
  4056. // then search for public function MoveNext: Boolean
  4057. for i:=0 to symtable.SymList.Count-1 do
  4058. begin
  4059. sym:=TSym(symtable.SymList[i]);
  4060. if (sym.typ=procsym) then
  4061. begin
  4062. pd:=Tprocsym(sym).find_procdef_byoptions([po_enumerator_movenext]);
  4063. if assigned(pd) then
  4064. begin
  4065. result:=pd;
  4066. exit;
  4067. end;
  4068. end;
  4069. end;
  4070. hashedid.id:='MOVENEXT';
  4071. sym:=tsym(symtable.FindWithHash(hashedid));
  4072. if assigned(sym) and (sym.typ=procsym) then
  4073. begin
  4074. for i:=0 to Tprocsym(sym).ProcdefList.Count-1 do
  4075. begin
  4076. pd := tprocdef(Tprocsym(sym).ProcdefList[i]);
  4077. if (pd.proctypeoption = potype_function) and
  4078. is_boolean(pd.returndef) and
  4079. (pd.minparacount = 0) and
  4080. (pd.visibility >= vis_public) then
  4081. begin
  4082. result:=pd;
  4083. exit;
  4084. end;
  4085. end;
  4086. end;
  4087. end;
  4088. function tabstractrecorddef.search_enumerator_current: tsym;
  4089. var
  4090. sym: tsym;
  4091. i: integer;
  4092. hashedid : THashedIDString;
  4093. begin
  4094. result:=nil;
  4095. // first search for ppo_enumerator_current property modifier
  4096. // then search for public property Current
  4097. for i:=0 to symtable.SymList.Count-1 do
  4098. begin
  4099. sym:=TSym(symtable.SymList[i]);
  4100. if (sym.typ=propertysym) and (ppo_enumerator_current in tpropertysym(sym).propoptions) then
  4101. begin
  4102. result:=sym;
  4103. exit;
  4104. end;
  4105. end;
  4106. hashedid.id:='CURRENT';
  4107. sym:=tsym(symtable.FindWithHash(hashedid));
  4108. if assigned(sym) and (sym.typ=propertysym) and
  4109. (sym.visibility >= vis_public) and not tpropertysym(sym).propaccesslist[palt_read].empty then
  4110. begin
  4111. result:=sym;
  4112. exit;
  4113. end;
  4114. end;
  4115. function tabstractrecorddef.jvm_full_typename(with_package_name: boolean): string;
  4116. var
  4117. st: tsymtable;
  4118. enclosingdef: tdef;
  4119. begin
  4120. if typ=objectdef then
  4121. result:=tobjectdef(self).objextname^
  4122. else if assigned(typesym) then
  4123. result:=typesym.realname
  4124. { have to generate anonymous nested type in current unit/class/record }
  4125. else
  4126. internalerror(2011032601);
  4127. { in case of specializations, add some extras to prevent name conflicts
  4128. with nested classes }
  4129. if df_specialization in defoptions then
  4130. result:='$'+result+'$specialization$';
  4131. st:=owner;
  4132. while assigned(st) and
  4133. (st.symtabletype in [objectsymtable,recordsymtable,localsymtable]) do
  4134. begin
  4135. { nested classes are named as "OuterClass$InnerClass" }
  4136. enclosingdef:=tdef(st.defowner);
  4137. if enclosingdef.typ=procdef then
  4138. result:=result+tprocdef(enclosingdef).procsym.realname+'$$'+tostr(tprocdef(enclosingdef).procsym.symid)+'$'
  4139. else if enclosingdef.typ=objectdef then
  4140. result:=tobjectdef(enclosingdef).objextname^+'$'+result
  4141. else if assigned(enclosingdef.typesym) then
  4142. result:=enclosingdef.typesym.realname+'$'+result
  4143. else
  4144. internalerror(2011060305);
  4145. st:=enclosingdef.owner;
  4146. end;
  4147. if with_package_name and
  4148. assigned(import_lib) then
  4149. result:=import_lib^+'/'+result;
  4150. end;
  4151. function tabstractrecorddef.contains_float_field: boolean;
  4152. var
  4153. i : longint;
  4154. begin
  4155. result:=true;
  4156. for i:=0 to symtable.symlist.count-1 do
  4157. begin
  4158. if (tsym(symtable.symlist[i]).typ<>fieldvarsym) or
  4159. (sp_static in tsym(symtable.symlist[i]).symoptions) then
  4160. continue;
  4161. if assigned(tfieldvarsym(symtable.symlist[i]).vardef) then
  4162. begin
  4163. if tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).is_fpuregable then
  4164. exit;
  4165. { search recursively }
  4166. if (tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).typ=recorddef) and
  4167. (tabstractrecorddef(tfieldvarsym(symtable.symlist[i]).vardef).contains_float_field) then
  4168. exit;
  4169. end;
  4170. end;
  4171. result:=false;
  4172. end;
  4173. function tabstractrecorddef.contains_cross_aword_field: boolean;
  4174. var
  4175. i : longint;
  4176. foffset, fsize: aword;
  4177. begin
  4178. result:=true;
  4179. for i:=0 to symtable.symlist.count-1 do
  4180. begin
  4181. if (tsym(symtable.symlist[i]).typ<>fieldvarsym) or
  4182. (sp_static in tsym(symtable.symlist[i]).symoptions) then
  4183. continue;
  4184. if assigned(tfieldvarsym(symtable.symlist[i]).vardef) then
  4185. begin
  4186. if is_packed then
  4187. begin
  4188. foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset;
  4189. fsize:=tfieldvarsym(symtable.symlist[i]).vardef.packedbitsize;
  4190. end
  4191. else
  4192. begin
  4193. foffset:=tfieldvarsym(symtable.symlist[i]).fieldoffset*8;
  4194. fsize:=tfieldvarsym(symtable.symlist[i]).vardef.size*8;
  4195. end;
  4196. if (fsize>0) and ((foffset div (sizeof(aword)*8)) <> ((foffset+fsize-1) div (sizeof(aword)*8))) then
  4197. exit;
  4198. { search recursively }
  4199. if (tstoreddef(tfieldvarsym(symtable.symlist[i]).vardef).typ=recorddef) and
  4200. (tabstractrecorddef(tfieldvarsym(symtable.symlist[i]).vardef).contains_cross_aword_field) then
  4201. exit;
  4202. end;
  4203. end;
  4204. result:=false;
  4205. end;
  4206. {***************************************************************************
  4207. trecorddef
  4208. ***************************************************************************}
  4209. constructor trecorddef.create(const n:string; p:TSymtable);
  4210. begin
  4211. inherited create(n,recorddef,true);
  4212. symtable:=p;
  4213. { we can own the symtable only if nobody else owns a copy so far }
  4214. if symtable.refcount=1 then
  4215. symtable.defowner:=self;
  4216. isunion:=false;
  4217. cloneddefderef.reset;
  4218. end;
  4219. constructor trecorddef.create_global_internal(n: string; packrecords, recordalignmin, maxCrecordalign: shortint);
  4220. var
  4221. oldsymtablestack: tsymtablestack;
  4222. ts: ttypesym;
  4223. definedname: boolean;
  4224. begin
  4225. { construct name }
  4226. definedname:=n<>'';
  4227. if not definedname then
  4228. n:='$InternalRec'+tostr(current_module.deflist.count);
  4229. oldsymtablestack:=symtablestack;
  4230. { do not simply push/pop current_module.localsymtable, because
  4231. that can have side-effects (e.g., it removes helpers) }
  4232. symtablestack:=nil;
  4233. symtable:=trecordsymtable.create(n,packrecords,recordalignmin,maxCrecordalign);
  4234. symtable.defowner:=self;
  4235. isunion:=false;
  4236. inherited create(n,recorddef,true);
  4237. { if we specified a name, then we'll probably want to look up the
  4238. type again by name too -> create typesym }
  4239. ts:=nil;
  4240. if definedname then
  4241. begin
  4242. ts:=ctypesym.create(n,self,true);
  4243. { avoid hints about unused types (these may only be used for
  4244. typed constant data) }
  4245. ts.increfcount;
  4246. end;
  4247. if assigned(current_module.localsymtable) then
  4248. begin
  4249. current_module.localsymtable.insertdef(self);
  4250. if definedname then
  4251. current_module.localsymtable.insert(ts);
  4252. end
  4253. else
  4254. begin
  4255. current_module.globalsymtable.insertdef(self);
  4256. if definedname then
  4257. current_module.globalsymtable.insert(ts);
  4258. end;
  4259. symtablestack:=oldsymtablestack;
  4260. { don't create RTTI for internal types, these are not exported }
  4261. defstates:=defstates+[ds_rtti_table_written,ds_init_table_written];
  4262. include(defoptions,df_internal);
  4263. end;
  4264. function trecorddef.add_field_by_def(const optionalname: TIDString; def: tdef): tsym;
  4265. var
  4266. sym: tfieldvarsym;
  4267. name: TIDString;
  4268. pname: ^TIDString;
  4269. begin
  4270. if optionalname='' then
  4271. begin
  4272. name:='$f'+tostr(trecordsymtable(symtable).symlist.count);
  4273. pname:=@name
  4274. end
  4275. else
  4276. pname:=@optionalname;
  4277. sym:=cfieldvarsym.create(pname^,vs_value,def,[],true);
  4278. symtable.insert(sym);
  4279. trecordsymtable(symtable).addfield(sym,vis_hidden);
  4280. result:=sym;
  4281. end;
  4282. procedure trecorddef.add_fields_from_deflist(fieldtypes: tfplist);
  4283. var
  4284. i: longint;
  4285. begin
  4286. for i:=0 to fieldtypes.count-1 do
  4287. add_field_by_def('',tdef(fieldtypes[i]));
  4288. end;
  4289. constructor trecorddef.ppuload(ppufile:tcompilerppufile);
  4290. procedure readvariantrecdesc(var variantrecdesc : pvariantrecdesc);
  4291. var
  4292. i,j : longint;
  4293. begin
  4294. if ppufile.getbyte=1 then
  4295. begin
  4296. new(variantrecdesc);
  4297. ppufile.getderef(variantrecdesc^.variantselectorderef);
  4298. SetLength(variantrecdesc^.branches,ppufile.getasizeint);
  4299. for i:=0 to high(variantrecdesc^.branches) do
  4300. begin
  4301. SetLength(variantrecdesc^.branches[i].values,ppufile.getasizeint);
  4302. for j:=0 to high(variantrecdesc^.branches[i].values) do
  4303. variantrecdesc^.branches[i].values[j]:=ppufile.getexprint;
  4304. readvariantrecdesc(variantrecdesc^.branches[i].nestedvariant);
  4305. end;
  4306. end
  4307. else
  4308. variantrecdesc:=nil;
  4309. end;
  4310. begin
  4311. inherited ppuload(recorddef,ppufile);
  4312. if df_copied_def in defoptions then
  4313. begin
  4314. ppufile.getderef(cloneddefderef);
  4315. ppuload_platform(ppufile);
  4316. end
  4317. else
  4318. begin
  4319. symtable:=trecordsymtable.create(objrealname^,0,0,0);
  4320. trecordsymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
  4321. trecordsymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
  4322. trecordsymtable(symtable).padalignment:=shortint(ppufile.getbyte);
  4323. trecordsymtable(symtable).usefieldalignment:=shortint(ppufile.getbyte);
  4324. trecordsymtable(symtable).recordalignmin:=shortint(ppufile.getbyte);
  4325. trecordsymtable(symtable).datasize:=ppufile.getasizeint;
  4326. trecordsymtable(symtable).paddingsize:=ppufile.getword;
  4327. ppufile.getsmallset(trecordsymtable(symtable).managementoperators);
  4328. { position of ppuload_platform call must correspond
  4329. to position of writeentry in ppuwrite method }
  4330. ppuload_platform(ppufile);
  4331. trecordsymtable(symtable).ppuload(ppufile);
  4332. { the variantrecdesc is needed only for iso-like new statements new(prec,1,2,3 ...);
  4333. but because iso mode supports no units, there is no need to store the variantrecdesc
  4334. in the ppu
  4335. }
  4336. // readvariantrecdesc(variantrecdesc);
  4337. { requires usefieldalignment to be set }
  4338. symtable.defowner:=self;
  4339. end;
  4340. isunion:=false;
  4341. end;
  4342. destructor trecorddef.destroy;
  4343. procedure free_variantrecdesc(var variantrecdesc : pvariantrecdesc);
  4344. var
  4345. i : longint;
  4346. begin
  4347. while assigned(variantrecdesc) do
  4348. begin
  4349. for i:=0 to high(variantrecdesc^.branches) do
  4350. begin
  4351. free_variantrecdesc(variantrecdesc^.branches[i].nestedvariant);
  4352. SetLength(variantrecdesc^.branches[i].values,0);
  4353. end;
  4354. SetLength(variantrecdesc^.branches,0);
  4355. dispose(variantrecdesc);
  4356. variantrecdesc:=nil;
  4357. end;
  4358. end;
  4359. begin
  4360. if assigned(variantrecdesc) then
  4361. free_variantrecdesc(variantrecdesc);
  4362. if assigned(symtable) then
  4363. begin
  4364. symtable.free;
  4365. symtable:=nil;
  4366. end;
  4367. inherited destroy;
  4368. end;
  4369. function trecorddef.getcopy : tstoreddef;
  4370. begin
  4371. result:=crecorddef.create(objrealname^,symtable.getcopy);
  4372. trecorddef(result).isunion:=isunion;
  4373. include(trecorddef(result).defoptions,df_copied_def);
  4374. if assigned(tcinitcode) then
  4375. trecorddef(result).tcinitcode:=tcinitcode.getcopy;
  4376. if assigned(import_lib) then
  4377. trecorddef(result).import_lib:=stringdup(import_lib^);
  4378. end;
  4379. function trecorddef.needs_inittable : boolean;
  4380. begin
  4381. { each record with managed field or with any management operator needs
  4382. init table }
  4383. needs_inittable:=(trecordsymtable(symtable).managementoperators<>[]) or
  4384. trecordsymtable(symtable).needs_init_final
  4385. end;
  4386. function trecorddef.needs_separate_initrtti : boolean;
  4387. begin
  4388. result:=true;
  4389. end;
  4390. function trecorddef.has_non_trivial_init_child(check_parent:boolean):boolean;
  4391. begin
  4392. result:=trecordsymtable(symtable).has_non_trivial_init;
  4393. end;
  4394. procedure trecorddef.buildderef;
  4395. begin
  4396. inherited buildderef;
  4397. if df_copied_def in defoptions then
  4398. cloneddefderef.build(symtable.defowner)
  4399. else
  4400. tstoredsymtable(symtable).buildderef;
  4401. end;
  4402. procedure trecorddef.deref;
  4403. begin
  4404. inherited deref;
  4405. { now dereference the definitions }
  4406. if df_copied_def in defoptions then
  4407. begin
  4408. cloneddef:=trecorddef(cloneddefderef.resolve);
  4409. symtable:=cloneddef.symtable.getcopy;
  4410. end
  4411. else
  4412. tstoredsymtable(symtable).deref(false);
  4413. { internal types, only load from the system unit }
  4414. if assigned(owner) and
  4415. assigned(owner.name) and
  4416. (owner.name^='SYSTEM') then
  4417. begin
  4418. { TGUID }
  4419. if not assigned(rec_tguid) and
  4420. (upper(typename)='TGUID') then
  4421. rec_tguid:=self
  4422. { JMP_BUF }
  4423. else if not assigned(rec_jmp_buf) and
  4424. (upper(typename)='JMP_BUF') then
  4425. rec_jmp_buf:=self
  4426. else if not assigned(rec_exceptaddr) and
  4427. (upper(typename)='TEXCEPTADDR') then
  4428. rec_exceptaddr:=self;
  4429. end;
  4430. end;
  4431. procedure trecorddef.ppuwrite(ppufile:tcompilerppufile);
  4432. procedure writevariantrecdesc(variantrecdesc : pvariantrecdesc);
  4433. var
  4434. i,j : longint;
  4435. begin
  4436. if assigned(variantrecdesc) then
  4437. begin
  4438. ppufile.putbyte(1);
  4439. ppufile.putderef(variantrecdesc^.variantselectorderef);
  4440. ppufile.putasizeint(length(variantrecdesc^.branches));
  4441. for i:=0 to high(variantrecdesc^.branches) do
  4442. begin
  4443. ppufile.putasizeint(length(variantrecdesc^.branches[i].values));
  4444. for j:=0 to high(variantrecdesc^.branches[i].values) do
  4445. ppufile.putexprint(variantrecdesc^.branches[i].values[j]);
  4446. writevariantrecdesc(variantrecdesc^.branches[i].nestedvariant);
  4447. end;
  4448. end
  4449. else
  4450. ppufile.putbyte(0);
  4451. end;
  4452. begin
  4453. inherited ppuwrite(ppufile);
  4454. if df_copied_def in defoptions then
  4455. ppufile.putderef(cloneddefderef)
  4456. else
  4457. begin
  4458. ppufile.putbyte(byte(trecordsymtable(symtable).fieldalignment));
  4459. ppufile.putbyte(byte(trecordsymtable(symtable).recordalignment));
  4460. ppufile.putbyte(byte(trecordsymtable(symtable).padalignment));
  4461. ppufile.putbyte(byte(trecordsymtable(symtable).usefieldalignment));
  4462. ppufile.putbyte(byte(trecordsymtable(symtable).recordalignmin));
  4463. ppufile.putasizeint(trecordsymtable(symtable).datasize);
  4464. ppufile.putword(trecordsymtable(symtable).paddingsize);
  4465. ppufile.putsmallset(trecordsymtable(symtable).managementoperators);
  4466. { the variantrecdesc is needed only for iso-like new statements new(prec,1,2,3 ...);
  4467. but because iso mode supports no units, there is no need to store the variantrecdesc
  4468. in the ppu
  4469. }
  4470. // writevariantrecdesc(variantrecdesc);
  4471. end;
  4472. writeentry(ppufile,ibrecorddef);
  4473. if not(df_copied_def in defoptions) then
  4474. trecordsymtable(symtable).ppuwrite(ppufile);
  4475. end;
  4476. function trecorddef.size:asizeint;
  4477. begin
  4478. result:=trecordsymtable(symtable).datasize;
  4479. end;
  4480. function trecorddef.alignment:shortint;
  4481. begin
  4482. alignment:=trecordsymtable(symtable).recordalignment;
  4483. end;
  4484. function trecorddef.padalignment:shortint;
  4485. begin
  4486. padalignment := trecordsymtable(symtable).padalignment;
  4487. end;
  4488. function trecorddef.GetTypeName : string;
  4489. begin
  4490. GetTypeName:='<record type>'
  4491. end;
  4492. {***************************************************************************
  4493. TABSTRACTPROCDEF
  4494. ***************************************************************************}
  4495. constructor tabstractprocdef.create(dt:tdeftyp;level:byte;doregister:boolean);
  4496. begin
  4497. inherited create(dt,doregister);
  4498. parast:=tparasymtable.create(self,level);
  4499. paras:=nil;
  4500. minparacount:=0;
  4501. maxparacount:=0;
  4502. proctypeoption:=potype_none;
  4503. proccalloption:=pocall_none;
  4504. procoptions:=[];
  4505. returndef:=voidtype;
  4506. returndefderef.reset;
  4507. savesize:=sizeof(pint);
  4508. callerargareasize:=0;
  4509. calleeargareasize:=0;
  4510. has_paraloc_info:=callnoside;
  4511. funcretloc[callerside].init;
  4512. funcretloc[calleeside].init;
  4513. check_mark_as_nested;
  4514. end;
  4515. destructor tabstractprocdef.destroy;
  4516. begin
  4517. if assigned(paras) then
  4518. begin
  4519. {$ifdef MEMDEBUG}
  4520. memprocpara.start;
  4521. {$endif MEMDEBUG}
  4522. paras.free;
  4523. paras:=nil;
  4524. {$ifdef MEMDEBUG}
  4525. memprocpara.stop;
  4526. {$endif MEMDEBUG}
  4527. end;
  4528. if assigned(parast) then
  4529. begin
  4530. {$ifdef MEMDEBUG}
  4531. memprocparast.start;
  4532. {$endif MEMDEBUG}
  4533. parast.free;
  4534. parast:=nil;
  4535. {$ifdef MEMDEBUG}
  4536. memprocparast.stop;
  4537. {$endif MEMDEBUG}
  4538. end;
  4539. funcretloc[callerside].done;
  4540. funcretloc[calleeside].done;
  4541. inherited destroy;
  4542. end;
  4543. procedure tabstractprocdef.count_para(p:TObject;arg:pointer);
  4544. begin
  4545. if (tsym(p).typ<>paravarsym) then
  4546. exit;
  4547. inc(plongint(arg)^);
  4548. if not(vo_is_hidden_para in tparavarsym(p).varoptions) then
  4549. begin
  4550. if not assigned(tparavarsym(p).defaultconstsym) then
  4551. inc(minparacount);
  4552. inc(maxparacount);
  4553. end;
  4554. end;
  4555. procedure tabstractprocdef.insert_para(p:TObject;arg:pointer);
  4556. begin
  4557. if (tsym(p).typ<>paravarsym) then
  4558. exit;
  4559. paras.add(p);
  4560. end;
  4561. procedure tabstractprocdef.calcparas;
  4562. var
  4563. paracount : longint;
  4564. begin
  4565. { This can already be assigned when
  4566. we need to reresolve this unit (PFV) }
  4567. if assigned(paras) then
  4568. paras.free;
  4569. paras:=tparalist.create(false);
  4570. paracount:=0;
  4571. minparacount:=0;
  4572. maxparacount:=0;
  4573. parast.SymList.ForEachCall(@count_para,@paracount);
  4574. paras.capacity:=paracount;
  4575. { Insert parameters in table }
  4576. parast.SymList.ForEachCall(@insert_para,nil);
  4577. { Order parameters }
  4578. paras.sortparas;
  4579. end;
  4580. function tabstractprocdef.mangledprocparanames(oldlen : longint) : string;
  4581. var
  4582. crc : dword;
  4583. hp : TParavarsym;
  4584. hs : TSymStr;
  4585. newlen,
  4586. i : integer;
  4587. begin
  4588. result:='';
  4589. hp:=nil;
  4590. { add parameter types }
  4591. for i:=0 to paras.count-1 do
  4592. begin
  4593. hp:=tparavarsym(paras[i]);
  4594. if not(vo_is_hidden_para in hp.varoptions) then
  4595. result:=result+'$'+hp.vardef.mangledparaname;
  4596. end;
  4597. { add resultdef, add $$ as separator to make it unique from a
  4598. parameter separator }
  4599. if not is_void(returndef) then
  4600. result:=result+'$$'+returndef.mangledparaname;
  4601. newlen:=length(result)+oldlen;
  4602. { Replace with CRC if the parameter line is very long }
  4603. if (newlen-oldlen>12) and
  4604. ((newlen>100) or (newlen-oldlen>64)) then
  4605. begin
  4606. crc:=0;
  4607. for i:=0 to paras.count-1 do
  4608. begin
  4609. hp:=tparavarsym(paras[i]);
  4610. if not(vo_is_hidden_para in hp.varoptions) then
  4611. begin
  4612. hs:=hp.vardef.mangledparaname;
  4613. crc:=UpdateCrc32(crc,hs[1],length(hs));
  4614. end;
  4615. end;
  4616. if not is_void(returndef) then
  4617. begin
  4618. { add a little prefix so that x(integer; integer) is different from x(integer):integer }
  4619. hs:='$$'+returndef.mangledparaname;
  4620. crc:=UpdateCrc32(crc,hs[1],length(hs));
  4621. end;
  4622. result:='$crc'+hexstr(crc,8);
  4623. end;
  4624. end;
  4625. procedure tabstractprocdef.buildderef;
  4626. begin
  4627. { released procdef? }
  4628. if not assigned(parast) then
  4629. exit;
  4630. inherited buildderef;
  4631. returndefderef.build(returndef);
  4632. if po_explicitparaloc in procoptions then
  4633. funcretloc[callerside].buildderef;
  4634. { parast }
  4635. tparasymtable(parast).buildderef;
  4636. end;
  4637. procedure tabstractprocdef.deref;
  4638. begin
  4639. inherited deref;
  4640. returndef:=tdef(returndefderef.resolve);
  4641. if po_explicitparaloc in procoptions then
  4642. begin
  4643. funcretloc[callerside].deref;
  4644. has_paraloc_info:=callerside;
  4645. end
  4646. else
  4647. begin
  4648. { deref is called after loading from a ppu, but also after another
  4649. unit has been reloaded/recompiled and all references must be
  4650. re-resolved. Since the funcretloc contains a reference to a tdef,
  4651. reset it so that we won't try to access the stale def }
  4652. funcretloc[callerside].init;
  4653. has_paraloc_info:=callnoside;
  4654. end;
  4655. { parast }
  4656. tparasymtable(parast).deref(false);
  4657. { recalculated parameters }
  4658. calcparas;
  4659. end;
  4660. constructor tabstractprocdef.ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
  4661. begin
  4662. inherited ppuload(dt,ppufile);
  4663. parast:=nil;
  4664. Paras:=nil;
  4665. minparacount:=0;
  4666. maxparacount:=0;
  4667. ppufile.getderef(returndefderef);
  4668. proctypeoption:=tproctypeoption(ppufile.getbyte);
  4669. proccalloption:=tproccalloption(ppufile.getbyte);
  4670. ppufile.getnormalset(procoptions);
  4671. funcretloc[callerside].init;
  4672. if po_explicitparaloc in procoptions then
  4673. funcretloc[callerside].ppuload(ppufile);
  4674. savesize:=sizeof(pint);
  4675. if (po_explicitparaloc in procoptions) then
  4676. has_paraloc_info:=callerside;
  4677. end;
  4678. procedure tabstractprocdef.ppuwrite(ppufile:tcompilerppufile);
  4679. var
  4680. oldintfcrc : boolean;
  4681. begin
  4682. { released procdef? }
  4683. if not assigned(parast) then
  4684. exit;
  4685. inherited ppuwrite(ppufile);
  4686. ppufile.putderef(returndefderef);
  4687. oldintfcrc:=ppufile.do_interface_crc;
  4688. ppufile.do_interface_crc:=false;
  4689. ppufile.putbyte(ord(proctypeoption));
  4690. ppufile.putbyte(ord(proccalloption));
  4691. ppufile.putnormalset(procoptions);
  4692. ppufile.do_interface_crc:=oldintfcrc;
  4693. if (po_explicitparaloc in procoptions) then
  4694. funcretloc[callerside].ppuwrite(ppufile);
  4695. end;
  4696. function tabstractprocdef.typename_paras(pno: tprocnameoptions) : ansistring;
  4697. var
  4698. hs,s : ansistring;
  4699. hp : TParavarsym;
  4700. hpc : tconstsym;
  4701. first : boolean;
  4702. i,j : integer;
  4703. begin
  4704. s:='';
  4705. first:=true;
  4706. for i:=0 to paras.count-1 do
  4707. begin
  4708. hp:=tparavarsym(paras[i]);
  4709. if not(vo_is_hidden_para in hp.varoptions) or
  4710. (pno_showhidden in pno) then
  4711. begin
  4712. if first then
  4713. begin
  4714. s:=s+'(';
  4715. first:=false;
  4716. end
  4717. else
  4718. s:=s+';';
  4719. if vo_is_hidden_para in hp.varoptions then
  4720. s:=s+'<';
  4721. case hp.varspez of
  4722. vs_var :
  4723. s:=s+'var ';
  4724. vs_const :
  4725. s:=s+'const ';
  4726. vs_out :
  4727. s:=s+'out ';
  4728. vs_constref :
  4729. s:=s+'constref ';
  4730. else
  4731. ;
  4732. end;
  4733. if (pno_paranames in pno) then
  4734. s:=s+hp.realname+':';
  4735. if hp.univpara then
  4736. s:=s+'univ ';
  4737. if assigned(hp.vardef.typesym) then
  4738. begin
  4739. hs:=hp.vardef.typesym.realname;
  4740. if hs[1]<>'$' then
  4741. s:=s+hp.vardef.OwnerHierarchyName+hs
  4742. else
  4743. s:=s+hp.vardef.GetTypeName;
  4744. end
  4745. else
  4746. s:=s+hp.vardef.GetTypeName;
  4747. { default value }
  4748. if assigned(hp.defaultconstsym) then
  4749. begin
  4750. hpc:=tconstsym(hp.defaultconstsym);
  4751. hs:='';
  4752. case hpc.consttyp of
  4753. constwstring:
  4754. begin
  4755. if pcompilerwidestring(hpc.value.valueptr)^.len>0 then
  4756. begin
  4757. setlength(hs,pcompilerwidestring(hpc.value.valueptr)^.len);
  4758. for j:=0 to pcompilerwidestring(hpc.value.valueptr)^.len-1 do
  4759. begin
  4760. if (ord(pcompilerwidestring(hpc.value.valueptr)^.data[j])<127) and
  4761. not(byte(pcompilerwidestring(hpc.value.valueptr)^.data[j]) in [0,10,13]) then
  4762. hs[j+1]:=char(pcompilerwidestring(hpc.value.valueptr)^.data[j])
  4763. else
  4764. hs[j+1]:='.';
  4765. end;
  4766. end;
  4767. end;
  4768. conststring,
  4769. constresourcestring :
  4770. begin
  4771. if hpc.value.len>0 then
  4772. begin
  4773. setLength(hs,hpc.value.len);
  4774. { don't write past the end of hs if the constant
  4775. is > 255 chars }
  4776. move(hpc.value.valueptr^,hs[1],length(hs));
  4777. { make sure that constant strings with newline chars
  4778. don't create a linebreak in the assembler code,
  4779. since comments are line-based. Also remove nulls
  4780. because the comments are written as a pchar. }
  4781. ReplaceCase(hs,#0,'.');
  4782. ReplaceCase(hs,#10,'.');
  4783. ReplaceCase(hs,#13,'.');
  4784. end;
  4785. end;
  4786. constreal :
  4787. str(pbestreal(hpc.value.valueptr)^,hs);
  4788. constpointer :
  4789. hs:=tostr(hpc.value.valueordptr);
  4790. constord :
  4791. begin
  4792. if is_boolean(hpc.constdef) then
  4793. begin
  4794. if hpc.value.valueord<>0 then
  4795. hs:='TRUE'
  4796. else
  4797. hs:='FALSE';
  4798. end
  4799. else
  4800. hs:=tostr(hpc.value.valueord);
  4801. end;
  4802. constnil :
  4803. hs:='nil';
  4804. constset :
  4805. hs:='<set>';
  4806. constguid:
  4807. hs:=guid2string(pguid(hpc.value.valueptr)^);
  4808. constnone:
  4809. internalerror(2019050704);
  4810. end;
  4811. if hs<>'' then
  4812. s:=s+'=`'+hs+'`';
  4813. end;
  4814. if vo_is_hidden_para in hp.varoptions then
  4815. s:=s+'>';
  4816. end;
  4817. end;
  4818. if not first then
  4819. s:=s+')';
  4820. if (po_varargs in procoptions) then
  4821. s:=s+';VarArgs';
  4822. typename_paras:=s;
  4823. end;
  4824. function tabstractprocdef.is_methodpointer:boolean;
  4825. begin
  4826. result:=false;
  4827. end;
  4828. function tabstractprocdef.is_addressonly:boolean;
  4829. begin
  4830. result:=true;
  4831. end;
  4832. function tabstractprocdef.no_self_node: boolean;
  4833. begin
  4834. Result:=([po_staticmethod,po_classmethod]<=procoptions)or
  4835. (proctypeoption in [potype_class_constructor,potype_class_destructor,potype_operator]);
  4836. end;
  4837. function tabstractprocdef.getcopyas(newtyp:tdeftyp;copytyp:tproccopytyp; const paraprefix: string): tstoreddef;
  4838. var
  4839. j, nestinglevel: longint;
  4840. pvs, npvs: tparavarsym;
  4841. begin
  4842. nestinglevel:=parast.symtablelevel;
  4843. if newtyp=procdef then
  4844. begin
  4845. if (copytyp<>pc_bareproc) then
  4846. result:=cprocdef.create(nestinglevel,true)
  4847. else
  4848. result:=cprocdef.create(normal_function_level,true);
  4849. tprocdef(result).visibility:=vis_public;
  4850. end
  4851. else
  4852. begin
  4853. result:=cprocvardef.create(nestinglevel);
  4854. end;
  4855. tabstractprocdef(result).returndef:=returndef;
  4856. tabstractprocdef(result).returndefderef:=returndefderef;
  4857. pvs:=nil;
  4858. npvs:=nil;
  4859. for j:=0 to parast.symlist.count-1 do
  4860. begin
  4861. case tsym(parast.symlist[j]).typ of
  4862. paravarsym:
  4863. begin
  4864. pvs:=tparavarsym(parast.symlist[j]);
  4865. { in case of bare proc, don't copy self, vmt or framepointer
  4866. parameters }
  4867. if (copytyp in [pc_bareproc,pc_normal_no_hidden]) and
  4868. (([vo_is_self,vo_is_vmt,vo_is_parentfp,vo_is_result,vo_is_funcret]*pvs.varoptions)<>[]) then
  4869. continue;
  4870. if paraprefix='' then
  4871. npvs:=cparavarsym.create(pvs.realname,pvs.paranr,pvs.varspez,
  4872. pvs.vardef,pvs.varoptions)
  4873. else if not(vo_is_high_para in pvs.varoptions) then
  4874. npvs:=cparavarsym.create(paraprefix+pvs.realname,pvs.paranr,pvs.varspez,
  4875. pvs.vardef,pvs.varoptions)
  4876. else
  4877. npvs:=cparavarsym.create('$high'+paraprefix+copy(pvs.name,5,length(pvs.name)),pvs.paranr,pvs.varspez,
  4878. pvs.vardef,pvs.varoptions);
  4879. npvs.defaultconstsym:=pvs.defaultconstsym;
  4880. tabstractprocdef(result).parast.insert(npvs);
  4881. end;
  4882. constsym:
  4883. begin
  4884. // ignore, reuse original constym. Should also be duplicated
  4885. // be safe though
  4886. end;
  4887. symconst.typesym:
  4888. begin
  4889. // reuse original, part of generic declaration
  4890. end
  4891. else
  4892. internalerror(201160604);
  4893. end;
  4894. end;
  4895. tabstractprocdef(result).savesize:=savesize;
  4896. if (typ<>procvardef) and
  4897. (newtyp=procvardef) then
  4898. begin
  4899. { procvars can't be (class)constructures/destructors etc }
  4900. if proctypeoption=potype_constructor then
  4901. begin
  4902. tabstractprocdef(result).returndef:=tdef(owner.defowner);
  4903. if not(is_implicit_pointer_object_type(returndef) or
  4904. (returndef.typ<>objectdef)) then
  4905. tabstractprocdef(result).returndef:=cpointerdef.getreusable(tabstractprocdef(result).returndef);
  4906. tabstractprocdef(result).proctypeoption:=potype_function;
  4907. end
  4908. else if is_void(returndef) then
  4909. tabstractprocdef(result).proctypeoption:=potype_procedure
  4910. else
  4911. tabstractprocdef(result).proctypeoption:=potype_function;
  4912. end
  4913. else
  4914. tabstractprocdef(result).proctypeoption:=proctypeoption;
  4915. tabstractprocdef(result).proccalloption:=proccalloption;
  4916. tabstractprocdef(result).procoptions:=procoptions;
  4917. if (copytyp=pc_bareproc) then
  4918. tabstractprocdef(result).procoptions:=tabstractprocdef(result).procoptions*[po_explicitparaloc,po_hascallingconvention,po_varargs,po_iocheck,po_has_importname,po_has_importdll];
  4919. if newtyp=procvardef then
  4920. tabstractprocdef(result).procoptions:=tabstractprocdef(result).procoptions-[po_has_importname,po_has_importdll];
  4921. if copytyp=pc_address_only then
  4922. include(tabstractprocdef(result).procoptions,po_addressonly);
  4923. tabstractprocdef(result).callerargareasize:=callerargareasize;
  4924. tabstractprocdef(result).calleeargareasize:=calleeargareasize;
  4925. tabstractprocdef(result).maxparacount:=maxparacount;
  4926. tabstractprocdef(result).minparacount:=minparacount;
  4927. if po_explicitparaloc in procoptions then
  4928. tabstractprocdef(result).funcretloc[callerside]:=funcretloc[callerside].getcopy;
  4929. { recalculate parameter info }
  4930. tabstractprocdef(result).has_paraloc_info:=callnoside;
  4931. {$ifdef m68k}
  4932. tabstractprocdef(result).exp_funcretloc:=exp_funcretloc;
  4933. {$endif}
  4934. if (typ=procdef) and
  4935. (newtyp=procvardef) and
  4936. (owner.symtabletype=ObjectSymtable) then
  4937. include(tprocvardef(result).procoptions,po_methodpointer);
  4938. end;
  4939. function tabstractprocdef.compatible_with_pointerdef_size(ptr: tpointerdef): boolean;
  4940. begin
  4941. result:=is_addressonly;
  4942. end;
  4943. procedure tabstractprocdef.check_mark_as_nested;
  4944. begin
  4945. { nested procvars require that nested functions use the Delphi-style
  4946. nested procedure calling convention }
  4947. if (parast.symtablelevel>normal_function_level) and
  4948. (m_nested_procvars in current_settings.modeswitches) then
  4949. include(procoptions,po_delphi_nested_cc);
  4950. end;
  4951. procedure tabstractprocdef.init_paraloc_info(side: tcallercallee);
  4952. begin
  4953. if (side in [callerside,callbothsides]) and
  4954. not(has_paraloc_info in [callerside,callbothsides]) then
  4955. begin
  4956. if not is_c_variadic(self) then
  4957. callerargareasize:=paramanager.create_paraloc_info(self,callerside)
  4958. else
  4959. callerargareasize:=paramanager.create_varargs_paraloc_info(self,callerside,nil);
  4960. if has_paraloc_info in [calleeside,callbothsides] then
  4961. has_paraloc_info:=callbothsides
  4962. else
  4963. has_paraloc_info:=callerside;
  4964. end;
  4965. if (side in [calleeside,callbothsides]) and
  4966. not(has_paraloc_info in [calleeside,callbothsides]) then
  4967. begin
  4968. if not is_c_variadic(self) then
  4969. calleeargareasize:=paramanager.create_paraloc_info(self,calleeside)
  4970. else
  4971. callerargareasize:=paramanager.create_varargs_paraloc_info(self,calleeside,nil);
  4972. if has_paraloc_info in [callerside,callbothsides] then
  4973. has_paraloc_info:=callbothsides
  4974. else
  4975. has_paraloc_info:=calleeside;
  4976. end;
  4977. end;
  4978. procedure tabstractprocdef.done_paraloc_info(side: tcallercallee);
  4979. var
  4980. i: longint;
  4981. begin
  4982. if (side in [callerside,callbothsides]) and
  4983. (has_paraloc_info in [callerside,callbothsides]) then
  4984. begin
  4985. funcretloc[callerside].done;
  4986. for i:=0 to paras.count-1 do
  4987. tparavarsym(paras[i]).paraloc[callerside].done;
  4988. if has_paraloc_info=callerside then
  4989. has_paraloc_info:=callnoside
  4990. else
  4991. has_paraloc_info:=calleeside;
  4992. end;
  4993. if (side in [calleeside,callbothsides]) and
  4994. (has_paraloc_info in [calleeside,callbothsides]) then
  4995. begin
  4996. funcretloc[calleeside].done;
  4997. for i:=0 to paras.count-1 do
  4998. tparavarsym(paras[i]).paraloc[calleeside].done;
  4999. if has_paraloc_info=calleeside then
  5000. has_paraloc_info:=callnoside
  5001. else
  5002. has_paraloc_info:=callerside;
  5003. end;
  5004. end;
  5005. function tabstractprocdef.stack_tainting_parameter(side: tcallercallee): boolean;
  5006. var
  5007. p: tparavarsym;
  5008. ploc: PCGParalocation;
  5009. i: longint;
  5010. begin
  5011. result:=false;
  5012. init_paraloc_info(side);
  5013. for i:=0 to parast.SymList.Count-1 do
  5014. if tsym(parast.SymList[i]).typ=paravarsym then
  5015. begin
  5016. p:=tparavarsym(parast.SymList[i]);
  5017. { check if no parameter is located on the stack }
  5018. if (is_open_array(p.vardef) or
  5019. is_array_of_const(p.vardef)) and (p.varspez=vs_value) then
  5020. begin
  5021. result:=true;
  5022. exit;
  5023. end;
  5024. ploc:=p.paraloc[side].location;
  5025. while assigned(ploc) do
  5026. begin
  5027. if (ploc^.loc=LOC_REFERENCE) then
  5028. begin
  5029. result:=true;
  5030. exit
  5031. end;
  5032. ploc:=ploc^.next;
  5033. end;
  5034. end;
  5035. end;
  5036. function tabstractprocdef.is_pushleftright: boolean;
  5037. begin
  5038. result:=false;
  5039. end;
  5040. function tabstractprocdef.address_type: tdef;
  5041. begin
  5042. result:=voidcodepointertype;
  5043. end;
  5044. function tabstractprocdef.ofs_address_type:tdef;
  5045. begin
  5046. result:=address_type;
  5047. end;
  5048. procedure tabstractprocdef.declared_far;
  5049. begin
  5050. Message1(parser_w_proc_directive_ignored,'FAR');
  5051. end;
  5052. procedure tabstractprocdef.declared_near;
  5053. begin
  5054. Message1(parser_w_proc_directive_ignored,'NEAR');
  5055. end;
  5056. {***************************************************************************
  5057. TPROCDEF
  5058. ***************************************************************************}
  5059. function tprocdef.GetResultName: PShortString;
  5060. begin
  5061. if not assigned(implprocdefinfo) then
  5062. internalerror(2014010301);
  5063. result:=implprocdefinfo^.resultname;
  5064. end;
  5065. procedure tprocdef.SetResultName(AValue: PShortString);
  5066. begin
  5067. if not assigned(implprocdefinfo) then
  5068. internalerror(2014010302);
  5069. implprocdefinfo^.resultname:=AValue;
  5070. end;
  5071. function tprocdef.GetParentFPInitBlock: tnode;
  5072. begin
  5073. if not assigned(implprocdefinfo) then
  5074. internalerror(2014010303);
  5075. result:=implprocdefinfo^.parentfpinitblock;
  5076. end;
  5077. function tprocdef.GetParentFPStruct: tsym;
  5078. begin
  5079. if not assigned(implprocdefinfo) then
  5080. internalerror(2014010304);
  5081. result:=implprocdefinfo^.parentfpstruct;
  5082. end;
  5083. function tprocdef.GetParentFPStructPtrType: tdef;
  5084. begin
  5085. if not assigned(implprocdefinfo) then
  5086. internalerror(2014010305);
  5087. result:=implprocdefinfo^.parentfpstructptrtype;
  5088. end;
  5089. procedure tprocdef.SetParentFPInitBlock(AValue: tnode);
  5090. begin
  5091. if not assigned(implprocdefinfo) then
  5092. internalerror(2014010306);
  5093. implprocdefinfo^.parentfpinitblock:=AValue;
  5094. end;
  5095. function tprocdef.Getprocendtai: tai;
  5096. begin
  5097. if not assigned(implprocdefinfo) then
  5098. internalerror(2014010307);
  5099. result:=implprocdefinfo^.procendtai;
  5100. end;
  5101. function tprocdef.Getprocstarttai: tai;
  5102. begin
  5103. if not assigned(implprocdefinfo) then
  5104. internalerror(2014010308);
  5105. result:=implprocdefinfo^.procstarttai;
  5106. end;
  5107. procedure tprocdef.Setprocendtai(AValue: tai);
  5108. begin
  5109. if not assigned(implprocdefinfo) then
  5110. internalerror(2014010309);
  5111. implprocdefinfo^.procendtai:=AValue;
  5112. end;
  5113. function tprocdef.Getskpara: pointer;
  5114. begin
  5115. if not assigned(implprocdefinfo) then
  5116. internalerror(2014010310);
  5117. result:=implprocdefinfo^.skpara;
  5118. end;
  5119. procedure tprocdef.Setskpara(AValue: pointer);
  5120. begin
  5121. if not assigned(implprocdefinfo) then
  5122. internalerror(2014010311);
  5123. implprocdefinfo^.skpara:=AValue;
  5124. end;
  5125. function tprocdef.Getpersonality: tprocdef;
  5126. begin
  5127. if not assigned(implprocdefinfo) then
  5128. internalerror(2016121701);
  5129. result:=implprocdefinfo^.personality;
  5130. end;
  5131. procedure tprocdef.Setpersonality(AValue: tprocdef);
  5132. begin
  5133. if not assigned(implprocdefinfo) then
  5134. internalerror(2016121702);
  5135. implprocdefinfo^.personality:=AValue;
  5136. end;
  5137. function tprocdef.Getforwarddef: boolean;
  5138. begin
  5139. if not assigned(implprocdefinfo) then
  5140. internalerror(2014010312);
  5141. result:=implprocdefinfo^.forwarddef;
  5142. end;
  5143. function tprocdef.Gethasforward: boolean;
  5144. begin
  5145. if not assigned(implprocdefinfo) then
  5146. internalerror(2014010313);
  5147. result:=implprocdefinfo^.hasforward;
  5148. end;
  5149. function tprocdef.Getinterfacedef: boolean;
  5150. begin
  5151. if not assigned(implprocdefinfo) then
  5152. internalerror(2014010314);
  5153. result:=implprocdefinfo^.interfacedef;
  5154. end;
  5155. procedure tprocdef.Setforwarddef(AValue: boolean);
  5156. begin
  5157. if not assigned(implprocdefinfo) then
  5158. internalerror(2014010315);
  5159. implprocdefinfo^.forwarddef:=AValue;
  5160. end;
  5161. procedure tprocdef.Sethasforward(AValue: boolean);
  5162. begin
  5163. if not assigned(implprocdefinfo) then
  5164. internalerror(2014010316);
  5165. implprocdefinfo^.hasforward:=AValue;
  5166. end;
  5167. function tprocdef.GetIsEmpty: boolean;
  5168. begin
  5169. result:=pio_empty in implprocoptions;
  5170. end;
  5171. procedure tprocdef.SetIsEmpty(AValue: boolean);
  5172. begin
  5173. if AValue then
  5174. include(implprocoptions,pio_empty)
  5175. else
  5176. include(implprocoptions,pio_empty);
  5177. end;
  5178. function tprocdef.GetHasInliningInfo: boolean;
  5179. begin
  5180. result:=pio_has_inlininginfo in implprocoptions;
  5181. end;
  5182. procedure tprocdef.SetHasInliningInfo(AValue: boolean);
  5183. begin
  5184. if AValue then
  5185. include(implprocoptions,pio_has_inlininginfo)
  5186. else
  5187. exclude(implprocoptions,pio_has_inlininginfo);
  5188. end;
  5189. procedure tprocdef.Setinterfacedef(AValue: boolean);
  5190. begin
  5191. if not assigned(implprocdefinfo) then
  5192. internalerror(2014010317);
  5193. implprocdefinfo^.interfacedef:=AValue;
  5194. end;
  5195. procedure tprocdef.Setprocstarttai(AValue: tai);
  5196. begin
  5197. if not assigned(implprocdefinfo) then
  5198. internalerror(2014010318);
  5199. implprocdefinfo^.procstarttai:=AValue;
  5200. end;
  5201. procedure tprocdef.SetParentFPStruct(AValue: tsym);
  5202. begin
  5203. if not assigned(implprocdefinfo) then
  5204. internalerror(2014010319);
  5205. implprocdefinfo^.parentfpstruct:=AValue;
  5206. end;
  5207. procedure tprocdef.SetParentFPStructPtrType(AValue: tdef);
  5208. begin
  5209. if not assigned(implprocdefinfo) then
  5210. internalerror(2014010320);
  5211. implprocdefinfo^.parentfpstructptrtype:=AValue;
  5212. end;
  5213. constructor tprocdef.create(level:byte;doregister:boolean);
  5214. begin
  5215. inherited create(procdef,level,doregister);
  5216. implprocdefinfo:=allocmem(sizeof(implprocdefinfo^));
  5217. localst:=tlocalsymtable.create(self,parast.symtablelevel);
  5218. {$ifdef symansistr}
  5219. _mangledname:='';
  5220. {$else symansistr}
  5221. _mangledname:=nil;
  5222. {$endif symansistr}
  5223. fileinfo:=current_filepos;
  5224. extnumber:=$ffff;
  5225. aliasnames:=TCmdStrList.create;
  5226. funcretsym:=nil;
  5227. funcretsymderef.reset;
  5228. procsymderef.reset;
  5229. forwarddef:=true;
  5230. interfacedef:=false;
  5231. hasforward:=false;
  5232. struct := nil;
  5233. structderef.reset;
  5234. import_dll:=nil;
  5235. import_name:=nil;
  5236. import_nr:=0;
  5237. inlininginfo:=nil;
  5238. deprecatedmsg:=nil;
  5239. end;
  5240. constructor tprocdef.ppuload(ppufile:tcompilerppufile);
  5241. var
  5242. i,aliasnamescount,sizeleft : longint;
  5243. level : byte;
  5244. buf : array[0..255] of byte;
  5245. begin
  5246. inherited ppuload(procdef,ppufile);
  5247. {$ifdef symansistr}
  5248. if po_has_mangledname in procoptions then
  5249. _mangledname:=ppufile.getansistring
  5250. else
  5251. _mangledname:='';
  5252. {$else symansistr}
  5253. if po_has_mangledname in procoptions then
  5254. _mangledname:=ppufile.getpshortstring
  5255. else
  5256. _mangledname:=nil;
  5257. {$endif symansistr}
  5258. extnumber:=ppufile.getword;
  5259. level:=ppufile.getbyte;
  5260. ppufile.getderef(structderef);
  5261. ppufile.getderef(procsymderef);
  5262. ppufile.getposinfo(fileinfo);
  5263. visibility:=tvisibility(ppufile.getbyte);
  5264. ppufile.getsmallset(symoptions);
  5265. if sp_has_deprecated_msg in symoptions then
  5266. deprecatedmsg:=ppufile.getpshortstring
  5267. else
  5268. deprecatedmsg:=nil;
  5269. { import stuff }
  5270. if po_has_importdll in procoptions then
  5271. import_dll:=ppufile.getpshortstring
  5272. else
  5273. import_dll:=nil;
  5274. if po_has_importname in procoptions then
  5275. import_name:=ppufile.getpshortstring
  5276. else
  5277. import_name:=nil;
  5278. import_nr:=ppufile.getword;
  5279. if (po_msgint in procoptions) then
  5280. messageinf.i:=ppufile.getlongint;
  5281. if (po_msgstr in procoptions) then
  5282. messageinf.str:=ppufile.getpshortstring;
  5283. if (po_dispid in procoptions) then
  5284. dispid:=ppufile.getlongint;
  5285. { inline stuff }
  5286. ppufile.getsmallset(implprocoptions);
  5287. if has_inlininginfo then
  5288. begin
  5289. ppufile.getderef(funcretsymderef);
  5290. new(inlininginfo);
  5291. ppufile.getsmallset(inlininginfo^.flags);
  5292. end
  5293. else
  5294. begin
  5295. inlininginfo:=nil;
  5296. funcretsym:=nil;
  5297. end;
  5298. aliasnames:=TCmdStrList.create;
  5299. { count alias names }
  5300. aliasnamescount:=ppufile.getbyte;
  5301. for i:=1 to aliasnamescount do
  5302. aliasnames.insert(ppufile.getstring);
  5303. { load the token stream containing the declaration }
  5304. sizeleft:=ppufile.getlongint;
  5305. if sizeleft>0 then
  5306. begin
  5307. init_genericdecl;
  5308. while sizeleft>0 do
  5309. begin
  5310. if sizeleft>sizeof(buf) then
  5311. i:=sizeof(buf)
  5312. else
  5313. i:=sizeleft;
  5314. ppufile.getdata(buf,i);
  5315. genericdecltokenbuf.write(buf,i);
  5316. dec(sizeleft,i);
  5317. end;
  5318. end;
  5319. ppuload_platform(ppufile);
  5320. { load para symtable }
  5321. parast:=tparasymtable.create(self,level);
  5322. tparasymtable(parast).ppuload(ppufile);
  5323. { load local symtable }
  5324. if has_inlininginfo then
  5325. begin
  5326. localst:=tlocalsymtable.create(self,level);
  5327. tlocalsymtable(localst).ppuload(ppufile);
  5328. end
  5329. else
  5330. localst:=nil;
  5331. { inline stuff }
  5332. if has_inlininginfo then
  5333. inlininginfo^.code:=ppuloadnodetree(ppufile);
  5334. { default values for no persistent data }
  5335. if (cs_link_deffile in current_settings.globalswitches) and
  5336. (tf_need_export in target_info.flags) and
  5337. (po_exports in procoptions) then
  5338. deffile.AddExport(mangledname);
  5339. { Disable po_has_inlining until the derefimpl is done }
  5340. has_inlininginfo:=false;
  5341. end;
  5342. destructor tprocdef.destroy;
  5343. begin
  5344. aliasnames.free;
  5345. aliasnames:=nil;
  5346. if assigned(localst) and
  5347. (localst.symtabletype<>staticsymtable) then
  5348. begin
  5349. {$ifdef MEMDEBUG}
  5350. memproclocalst.start;
  5351. {$endif MEMDEBUG}
  5352. localst.free;
  5353. localst:=nil;
  5354. {$ifdef MEMDEBUG}
  5355. memproclocalst.start;
  5356. {$endif MEMDEBUG}
  5357. end;
  5358. if assigned(inlininginfo) then
  5359. begin
  5360. {$ifdef MEMDEBUG}
  5361. memprocnodetree.start;
  5362. {$endif MEMDEBUG}
  5363. tnode(inlininginfo^.code).free;
  5364. {$ifdef MEMDEBUG}
  5365. memprocnodetree.start;
  5366. {$endif MEMDEBUG}
  5367. dispose(inlininginfo);
  5368. inlininginfo:=nil;
  5369. end;
  5370. freeimplprocdefinfo;
  5371. genericdecltokenbuf.free;
  5372. genericdecltokenbuf:=nil;
  5373. stringdispose(import_dll);
  5374. stringdispose(import_name);
  5375. stringdispose(deprecatedmsg);
  5376. if (po_msgstr in procoptions) then
  5377. stringdispose(messageinf.str);
  5378. {$ifndef symansistr}
  5379. if assigned(_mangledname) then
  5380. begin
  5381. {$ifdef MEMDEBUG}
  5382. memmanglednames.start;
  5383. {$endif MEMDEBUG}
  5384. stringdispose(_mangledname);
  5385. {$ifdef MEMDEBUG}
  5386. memmanglednames.stop;
  5387. {$endif MEMDEBUG}
  5388. end;
  5389. {$endif symansistr}
  5390. inherited destroy;
  5391. end;
  5392. procedure tprocdef.freeimplprocdefinfo;
  5393. begin
  5394. if assigned(implprocdefinfo) then
  5395. begin
  5396. stringdispose(implprocdefinfo^.resultname);
  5397. freemem(implprocdefinfo);
  5398. implprocdefinfo:=nil;
  5399. end;
  5400. end;
  5401. procedure tprocdef.ppuwrite(ppufile:tcompilerppufile);
  5402. var
  5403. oldintfcrc : boolean;
  5404. aliasnamescount,i,sizeleft : longint;
  5405. item : TCmdStrListItem;
  5406. buf : array[0..255] of byte;
  5407. begin
  5408. { released procdef? }
  5409. if not assigned(parast) then
  5410. exit;
  5411. inherited ppuwrite(ppufile);
  5412. {$ifdef symansistr}
  5413. if po_has_mangledname in procoptions then
  5414. ppufile.putansistring(_mangledname);
  5415. {$else symansistr}
  5416. if po_has_mangledname in procoptions then
  5417. ppufile.putstring(_mangledname^);
  5418. {$endif symansistr}
  5419. ppufile.putword(extnumber);
  5420. ppufile.putbyte(parast.symtablelevel);
  5421. ppufile.putderef(structderef);
  5422. ppufile.putderef(procsymderef);
  5423. ppufile.putposinfo(fileinfo);
  5424. ppufile.putbyte(byte(visibility));
  5425. ppufile.putsmallset(symoptions);
  5426. if sp_has_deprecated_msg in symoptions then
  5427. ppufile.putstring(deprecatedmsg^);
  5428. { import }
  5429. if po_has_importdll in procoptions then
  5430. ppufile.putstring(import_dll^);
  5431. if po_has_importname in procoptions then
  5432. ppufile.putstring(import_name^);
  5433. ppufile.putword(import_nr);
  5434. if (po_msgint in procoptions) then
  5435. ppufile.putlongint(messageinf.i);
  5436. if (po_msgstr in procoptions) then
  5437. ppufile.putstring(messageinf.str^);
  5438. if (po_dispid in procoptions) then
  5439. ppufile.putlongint(dispid);
  5440. { inline stuff }
  5441. oldintfcrc:=ppufile.do_crc;
  5442. ppufile.do_crc:=false;
  5443. ppufile.putsmallset(implprocoptions);
  5444. if has_inlininginfo then
  5445. begin
  5446. ppufile.putderef(funcretsymderef);
  5447. ppufile.putsmallset(inlininginfo^.flags);
  5448. end;
  5449. { count alias names }
  5450. aliasnamescount:=0;
  5451. item:=TCmdStrListItem(aliasnames.first);
  5452. while assigned(item) do
  5453. begin
  5454. inc(aliasnamescount);
  5455. item:=TCmdStrListItem(item.next);
  5456. end;
  5457. if aliasnamescount>255 then
  5458. internalerror(200711021);
  5459. ppufile.putbyte(aliasnamescount);
  5460. item:=TCmdStrListItem(aliasnames.first);
  5461. while assigned(item) do
  5462. begin
  5463. ppufile.putstring(item.str);
  5464. item:=TCmdStrListItem(item.next);
  5465. end;
  5466. ppufile.do_crc:=oldintfcrc;
  5467. { generic tokens for the declaration }
  5468. if assigned(genericdecltokenbuf) and (genericdecltokenbuf.size>0) then
  5469. begin
  5470. sizeleft:=genericdecltokenbuf.size;
  5471. genericdecltokenbuf.seek(0);
  5472. ppufile.putlongint(sizeleft);
  5473. while sizeleft>0 do
  5474. begin
  5475. if sizeleft>sizeof(buf) then
  5476. i:=sizeof(buf)
  5477. else
  5478. i:=sizeleft;
  5479. genericdecltokenbuf.read(buf,i);
  5480. ppufile.putdata(buf,i);
  5481. dec(sizeleft,i);
  5482. end;
  5483. end
  5484. else
  5485. ppufile.putlongint(0);
  5486. { write this entry }
  5487. writeentry(ppufile,ibprocdef);
  5488. { Save the para symtable, this is taken from the interface }
  5489. tparasymtable(parast).ppuwrite(ppufile);
  5490. { save localsymtable for inline procedures or when local
  5491. browser info is requested, this has no influence on the crc }
  5492. if has_inlininginfo then
  5493. begin
  5494. oldintfcrc:=ppufile.do_crc;
  5495. ppufile.do_crc:=false;
  5496. tlocalsymtable(localst).ppuwrite(ppufile);
  5497. ppufile.do_crc:=oldintfcrc;
  5498. end;
  5499. { node tree for inlining }
  5500. oldintfcrc:=ppufile.do_crc;
  5501. ppufile.do_crc:=false;
  5502. if has_inlininginfo then
  5503. ppuwritenodetree(ppufile,inlininginfo^.code);
  5504. ppufile.do_crc:=oldintfcrc;
  5505. end;
  5506. function tprocdef.fullprocname(showhidden:boolean):string;
  5507. var
  5508. pno: tprocnameoptions;
  5509. begin
  5510. pno:=[];
  5511. if showhidden then
  5512. include(pno,pno_showhidden);
  5513. result:=customprocname(pno);
  5514. end;
  5515. function tprocdef.customprocname(pno: tprocnameoptions):ansistring;
  5516. var
  5517. s, rn : ansistring;
  5518. t : ttoken;
  5519. syssym : tsyssym;
  5520. begin
  5521. {$ifdef EXTDEBUG}
  5522. include(pno,pno_showhidden);
  5523. {$endif EXTDEBUG}
  5524. s:='';
  5525. if proctypeoption=potype_operator then
  5526. begin
  5527. for t:=NOTOKEN to last_overloaded do
  5528. if procsym.realname='$'+overloaded_names[t] then
  5529. begin
  5530. s:='operator ';
  5531. if (pno_ownername in pno) and
  5532. assigned(struct) then
  5533. s:=s+struct.RttiName+'.';
  5534. s:=s+arraytokeninfo[t].str;
  5535. if not (pno_noparams in pno) then
  5536. s:=s+typename_paras(pno);
  5537. break;
  5538. end;
  5539. end
  5540. else
  5541. begin
  5542. if (po_classmethod in procoptions) and
  5543. not(pno_noclassmarker in pno) then
  5544. s:='class ';
  5545. case proctypeoption of
  5546. potype_constructor,
  5547. potype_class_constructor:
  5548. s:=s+'constructor ';
  5549. potype_class_destructor,
  5550. potype_destructor:
  5551. s:=s+'destructor ';
  5552. else
  5553. if (pno_proctypeoption in pno) then
  5554. begin
  5555. if assigned(returndef) and
  5556. not(is_void(returndef)) then
  5557. s:=s+'function '
  5558. else
  5559. s:=s+'procedure ';
  5560. end;
  5561. end;
  5562. if (pno_ownername in pno) and
  5563. (owner.symtabletype in [recordsymtable,objectsymtable]) then
  5564. s:=s+tabstractrecorddef(owner.defowner).RttiName+'.';
  5565. if (po_compilerproc in procoptions) and (extnumber<>$ffff) then
  5566. begin
  5567. syssym:=tsyssym.find_by_number(extnumber);
  5568. if not assigned(syssym) then
  5569. internalerror(2016060305);
  5570. rn:=syssym.realname;
  5571. end
  5572. else
  5573. rn:=procsym.realname;
  5574. if (pno_noleadingdollar in pno) and
  5575. (rn[1]='$') then
  5576. delete(rn,1,1);
  5577. s:=s+rn;
  5578. if not (pno_noparams in pno) then
  5579. s:=s+typename_paras(pno);
  5580. end;
  5581. if not(proctypeoption in [potype_constructor,potype_destructor,
  5582. potype_class_constructor,potype_class_destructor]) and
  5583. assigned(returndef) and
  5584. not(is_void(returndef)) then
  5585. s:=s+':'+returndef.GetTypeName;
  5586. if assigned(owner) and (owner.symtabletype=localsymtable) then
  5587. s:=s+' is nested'
  5588. else if po_is_block in procoptions then
  5589. s:=s+' is block';
  5590. s:=s+';';
  5591. if po_far in procoptions then
  5592. s:=s+' far;';
  5593. { forced calling convention? }
  5594. if (po_hascallingconvention in procoptions) then
  5595. s:=s+' '+ProcCallOptionStr[proccalloption]+';';
  5596. if (po_staticmethod in procoptions) and
  5597. not (proctypeoption in [potype_class_constructor,potype_class_destructor]) then
  5598. s:=s+' Static;';
  5599. if pno_mangledname in pno then
  5600. s:=s+' -- mangled name: '+mangledname;
  5601. customprocname:=s;
  5602. end;
  5603. function tprocdef.is_methodpointer:boolean;
  5604. begin
  5605. { don't check assigned(_class), that's also the case for nested
  5606. procedures inside methods }
  5607. result:=(owner.symtabletype=ObjectSymtable)and not no_self_node;
  5608. end;
  5609. function tprocdef.is_addressonly:boolean;
  5610. begin
  5611. result:=assigned(owner) and
  5612. not is_methodpointer and
  5613. (not(m_nested_procvars in current_settings.modeswitches) or
  5614. not is_nested_pd(self));
  5615. end;
  5616. procedure tprocdef.make_external;
  5617. begin
  5618. include(procoptions,po_external);
  5619. forwarddef:=false;
  5620. end;
  5621. procedure tprocdef.init_genericdecl;
  5622. begin
  5623. if assigned(genericdecltokenbuf) then
  5624. internalerror(2015061901);
  5625. genericdecltokenbuf:=tdynamicarray.create(256);
  5626. end;
  5627. function tprocdef.getfuncretsyminfo(out ressym: tsym; out resdef: tdef): boolean;
  5628. begin
  5629. result:=false;
  5630. if proctypeoption=potype_constructor then
  5631. begin
  5632. result:=true;
  5633. ressym:=tsym(parast.Find('self'));
  5634. resdef:=tabstractnormalvarsym(ressym).vardef;
  5635. { and TP-style constructors return a pointer to self }
  5636. if is_object(resdef) then
  5637. resdef:=cpointerdef.getreusable(resdef);
  5638. end
  5639. else if not is_void(returndef) then
  5640. begin
  5641. result:=true;
  5642. ressym:=funcretsym;
  5643. resdef:=tabstractnormalvarsym(ressym).vardef;
  5644. end;
  5645. end;
  5646. function tprocdef.has_alias_name(const s: TSymStr): boolean;
  5647. var
  5648. item : TCmdStrListItem;
  5649. begin
  5650. result:=true;
  5651. if mangledname=s then
  5652. exit;
  5653. item:=TCmdStrListItem(aliasnames.first);
  5654. while assigned(item) do
  5655. begin
  5656. if item.str=s then
  5657. exit;
  5658. item:=TCmdStrListItem(item.next);
  5659. end;
  5660. result:=false;
  5661. end;
  5662. function tprocdef.GetSymtable(t:tGetSymtable):TSymtable;
  5663. begin
  5664. case t of
  5665. gs_local :
  5666. GetSymtable:=localst;
  5667. gs_para :
  5668. GetSymtable:=parast;
  5669. else
  5670. GetSymtable:=nil;
  5671. end;
  5672. end;
  5673. function tprocdef.getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string): tstoreddef;
  5674. var
  5675. j : longint;
  5676. begin
  5677. result:=inherited;
  5678. if newtyp=procvardef then
  5679. begin
  5680. { create new paralist }
  5681. tprocvardef(result).calcparas;
  5682. exit;
  5683. end;
  5684. { don't copy mangled name, can be different }
  5685. tprocdef(result).messageinf:=messageinf;
  5686. tprocdef(result).dispid:=dispid;
  5687. if po_msgstr in procoptions then
  5688. tprocdef(result).messageinf.str:=stringdup(messageinf.str^);
  5689. tprocdef(result).symoptions:=symoptions;
  5690. if assigned(deprecatedmsg) then
  5691. tprocdef(result).deprecatedmsg:=stringdup(deprecatedmsg^);
  5692. { will have to be associated with appropriate procsym }
  5693. tprocdef(result).procsym:=nil;
  5694. { don't create aliases for bare copies, nor copy the funcretsym as
  5695. the function result parameter will be inserted again if necessary
  5696. (e.g. if the calling convention is changed) }
  5697. if not(copytyp in [pc_bareproc,pc_normal_no_hidden]) then
  5698. begin
  5699. tprocdef(result).aliasnames.concatListcopy(aliasnames);
  5700. if assigned(funcretsym) then
  5701. begin
  5702. if funcretsym.owner=parast then
  5703. begin
  5704. j:=parast.symlist.indexof(funcretsym);
  5705. if j<0 then
  5706. internalerror(2011040606);
  5707. tprocdef(result).funcretsym:=tsym(tprocdef(result).parast.symlist[j]);
  5708. end
  5709. else if funcretsym.owner=localst then
  5710. begin
  5711. { nothing to do, will be inserted for the new procdef while
  5712. parsing its body (by pdecsub.insert_funcret_local) }
  5713. end
  5714. else
  5715. internalerror(2011040605);
  5716. end;
  5717. end;
  5718. { will have to be associated with a new struct }
  5719. tprocdef(result).struct:=nil;
  5720. if assigned(implprocdefinfo) then
  5721. begin
  5722. if assigned(resultname) then
  5723. tprocdef(result).resultname:=stringdup(resultname^);
  5724. tprocdef(result).synthetickind:=synthetickind;
  5725. end;
  5726. if assigned(import_dll) then
  5727. tprocdef(result).import_dll:=stringdup(import_dll^);
  5728. if assigned(import_name) then
  5729. tprocdef(result).import_name:=stringdup(import_name^);
  5730. tprocdef(result).import_nr:=import_nr;
  5731. tprocdef(result).extnumber:=$ffff;
  5732. tprocdef(result).visibility:=visibility;
  5733. { we need a separate implementation for the copied def }
  5734. tprocdef(result).forwarddef:=true;
  5735. tprocdef(result).interfacedef:=true;
  5736. { create new paralist }
  5737. tprocdef(result).calcparas;
  5738. end;
  5739. function tprocdef.getcopy: tstoreddef;
  5740. begin
  5741. result:=getcopyas(procdef,pc_normal,'');
  5742. end;
  5743. procedure tprocdef.buildderef;
  5744. begin
  5745. inherited buildderef;
  5746. structderef.build(struct);
  5747. { procsym that originaly defined this definition, should be in the
  5748. same symtable }
  5749. procsymderef.build(procsym);
  5750. end;
  5751. procedure tprocdef.buildderefimpl;
  5752. begin
  5753. inherited buildderefimpl;
  5754. { inline tree }
  5755. if has_inlininginfo then
  5756. begin
  5757. { Localst is not available for main/unit init }
  5758. if assigned(localst) then
  5759. begin
  5760. tlocalsymtable(localst).buildderef;
  5761. tlocalsymtable(localst).buildderefimpl;
  5762. end;
  5763. funcretsymderef.build(funcretsym);
  5764. inlininginfo^.code.buildderefimpl;
  5765. end;
  5766. end;
  5767. procedure tprocdef.deref;
  5768. begin
  5769. inherited deref;
  5770. struct:=tabstractrecorddef(structderef.resolve);
  5771. { procsym that originaly defined this definition, should be in the
  5772. same symtable }
  5773. procsym:=tprocsym(procsymderef.resolve);
  5774. end;
  5775. procedure tprocdef.derefimpl;
  5776. begin
  5777. { Enable has_inlininginfo when the inlininginfo
  5778. structure is available. The has_inlininginfo was disabled
  5779. after the load, since the data was invalid }
  5780. if assigned(inlininginfo) then
  5781. has_inlininginfo:=true;
  5782. { Inline }
  5783. if has_inlininginfo then
  5784. begin
  5785. { Locals }
  5786. if assigned(localst) then
  5787. begin
  5788. tlocalsymtable(localst).deref(false);
  5789. tlocalsymtable(localst).derefimpl(false);
  5790. end;
  5791. inlininginfo^.code.derefimpl;
  5792. { funcretsym, this is always located in the localst }
  5793. funcretsym:=tsym(funcretsymderef.resolve);
  5794. end
  5795. else
  5796. begin
  5797. { safety }
  5798. { Not safe! A unit may be reresolved after its interface has been
  5799. parsed but before its implementation has been parsed, and in that
  5800. case the funcretsym is still required!
  5801. funcretsym:=nil; }
  5802. end;
  5803. end;
  5804. function tprocdef.GetTypeName : string;
  5805. begin
  5806. GetTypeName := FullProcName(false);
  5807. end;
  5808. function tprocdef.mangledname : TSymStr;
  5809. begin
  5810. {$ifdef symansistr}
  5811. if _mangledname='' then
  5812. begin
  5813. result:=defaultmangledname;
  5814. _mangledname:=result;
  5815. end
  5816. else
  5817. result:=_mangledname;
  5818. {$else symansistr}
  5819. if not assigned(_mangledname) then
  5820. begin
  5821. result:=defaultmangledname;
  5822. _mangledname:=stringdup(mangledname);
  5823. end
  5824. else
  5825. result:=_mangledname^;
  5826. {$endif symansistr}
  5827. end;
  5828. function tprocdef.defaultmangledname: TSymStr;
  5829. begin
  5830. { we need to use the symtable where the procsym is inserted,
  5831. because that is visible to the world }
  5832. defaultmangledname:=make_mangledname('',procsym.owner,procsym.name);
  5833. defaultmangledname:=defaultmangledname+mangledprocparanames(Length(defaultmangledname))
  5834. end;
  5835. function tprocdef.cplusplusmangledname : TSymStr;
  5836. function getcppparaname(p : tdef) : TSymStr;
  5837. const
  5838. {$ifdef NAMEMANGLING_GCC2}
  5839. ordtype2str : array[tordtype] of string[2] = (
  5840. '',
  5841. 'Uc','Us','Ui','Us','',
  5842. 'Sc','s','i','x','',
  5843. 'b','b','b','b','b','b',
  5844. 'c','w','x');
  5845. {$else NAMEMANGLING_GCC2}
  5846. ordtype2str : array[tordtype] of string[1] = (
  5847. 'v',
  5848. 'h','t','j','y','',
  5849. 'a','s','i','x','',
  5850. 'b','b','b','b','b',
  5851. 'b','b','b','b',
  5852. 'c','w','x','C');
  5853. floattype2str : array[tfloattype] of string[1] = (
  5854. 'f','d','e','e',
  5855. 'd','d','g');
  5856. {$endif NAMEMANGLING_GCC2}
  5857. var
  5858. s : TSymStr;
  5859. begin
  5860. case p.typ of
  5861. orddef:
  5862. begin
  5863. s:=ordtype2str[torddef(p).ordtype];
  5864. if s='C' then
  5865. s:=ordtype2str[range_to_basetype(torddef(p).low,torddef(p).high)];
  5866. end;
  5867. pointerdef:
  5868. s:='P'+getcppparaname(tpointerdef(p).pointeddef);
  5869. {$ifndef NAMEMANGLING_GCC2}
  5870. floatdef:
  5871. s:=floattype2str[tfloatdef(p).floattype];
  5872. {$endif NAMEMANGLING_GCC2}
  5873. else
  5874. internalerror(2103001);
  5875. end;
  5876. getcppparaname:=s;
  5877. end;
  5878. var
  5879. s,s2 : TSymStr;
  5880. hp : TParavarsym;
  5881. i : integer;
  5882. begin
  5883. {$ifdef NAMEMANGLING_GCC2}
  5884. { outdated gcc 2.x name mangling scheme }
  5885. s := procsym.realname;
  5886. if procsym.owner.symtabletype=ObjectSymtable then
  5887. begin
  5888. s2:=upper(tobjectdef(procsym.owner.defowner).objrealname^);
  5889. case proctypeoption of
  5890. potype_destructor:
  5891. s:='_$_'+tostr(length(s2))+s2;
  5892. potype_constructor:
  5893. s:='___'+tostr(length(s2))+s2;
  5894. else
  5895. s:='_'+s+'__'+tostr(length(s2))+s2;
  5896. end;
  5897. end
  5898. else s:=s+'__';
  5899. s:=s+'F';
  5900. { concat modifiers }
  5901. { !!!!! }
  5902. { now we handle the parameters }
  5903. if maxparacount>0 then
  5904. begin
  5905. for i:=0 to paras.count-1 do
  5906. begin
  5907. hp:=tparavarsym(paras[i]);
  5908. { no hidden parameters form part of a C++ mangled name:
  5909. a) self is not included
  5910. b) there are no "high" or other hidden parameters
  5911. }
  5912. if vo_is_hidden_para in hp.varoptions then
  5913. continue;
  5914. s2:=getcppparaname(hp.vardef);
  5915. if hp.varspez in [vs_var,vs_out] then
  5916. s2:='R'+s2;
  5917. s:=s+s2;
  5918. end;
  5919. end
  5920. else
  5921. s:=s+'v';
  5922. cplusplusmangledname:=s;
  5923. {$else NAMEMANGLING_GCC2}
  5924. { gcc 3.x and 4.x name mangling scheme }
  5925. { see http://www.codesourcery.com/public/cxx-abi/abi.html#mangling }
  5926. if procsym.owner.symtabletype=ObjectSymtable then
  5927. begin
  5928. s:='_ZN';
  5929. s2:=tobjectdef(procsym.owner.defowner).objextname^;
  5930. s:=s+tostr(length(s2))+s2;
  5931. case proctypeoption of
  5932. potype_constructor:
  5933. s:=s+'C1';
  5934. potype_destructor:
  5935. s:=s+'D1';
  5936. else
  5937. s:=s+tostr(length(procsym.realname))+procsym.realname;
  5938. end;
  5939. s:=s+'E';
  5940. end
  5941. else
  5942. s:=procsym.realname;
  5943. { now we handle the parameters }
  5944. if maxparacount>0 then
  5945. begin
  5946. for i:=0 to paras.count-1 do
  5947. begin
  5948. hp:=tparavarsym(paras[i]);
  5949. { no hidden parameters form part of a C++ mangled name:
  5950. a) self is not included
  5951. b) there are no "high" or other hidden parameters
  5952. }
  5953. if vo_is_hidden_para in hp.varoptions then
  5954. continue;
  5955. s2:=getcppparaname(hp.vardef);
  5956. if hp.varspez in [vs_var,vs_out] then
  5957. s2:='R'+s2;
  5958. s:=s+s2;
  5959. end;
  5960. end
  5961. else
  5962. s:=s+'v';
  5963. cplusplusmangledname:=s;
  5964. {$endif NAMEMANGLING_GCC2}
  5965. end;
  5966. function tprocdef.objcmangledname : TSymStr;
  5967. var
  5968. manglednamelen: longint;
  5969. iscatmethod : boolean;
  5970. begin
  5971. if not (po_msgstr in procoptions) then
  5972. internalerror(2009030901);
  5973. { we may very well need longer strings to handle these... }
  5974. manglednamelen:=length(tobjectdef(procsym.owner.defowner).objextname^)+
  5975. length('+"[ ]"')+length(messageinf.str^);
  5976. iscatmethod:=oo_is_classhelper in tobjectdef(procsym.owner.defowner).objectoptions;
  5977. if (iscatmethod) then
  5978. inc(manglednamelen,length(tobjectdef(procsym.owner.defowner).childof.objextname^)+length('()'));
  5979. if manglednamelen>255 then
  5980. Message1(parser_e_objc_message_name_too_long,messageinf.str^);
  5981. if not(po_classmethod in procoptions) then
  5982. result:='"-['
  5983. else
  5984. result:='"+[';
  5985. { quotes are necessary because the +/- otherwise confuse the assembler
  5986. into expecting a number
  5987. }
  5988. if iscatmethod then
  5989. result:=result+tobjectdef(procsym.owner.defowner).childof.objextname^+'(';
  5990. result:=result+tobjectdef(procsym.owner.defowner).objextname^;
  5991. if iscatmethod then
  5992. result:=result+')';
  5993. result:=result+' '+messageinf.str^+']"';
  5994. end;
  5995. procedure tprocdef.setmangledname(const s : TSymStr);
  5996. begin
  5997. { This is not allowed anymore, the forward declaration
  5998. already needs to create the correct mangledname, no changes
  5999. afterwards are allowed (PFV) }
  6000. { Exception: interface definitions in mode macpas, since in that }
  6001. { case no reference to the old name can exist yet (JM) }
  6002. {$ifdef symansistr}
  6003. if _mangledname<>'' then
  6004. if ((m_mac in current_settings.modeswitches) and
  6005. (interfacedef)) then
  6006. _mangledname:=''
  6007. else
  6008. internalerror(200411171);
  6009. {$else symansistr}
  6010. if assigned(_mangledname) then
  6011. if ((m_mac in current_settings.modeswitches) and
  6012. (interfacedef)) then
  6013. stringdispose(_mangledname)
  6014. else
  6015. internalerror(200411171);
  6016. {$endif symansistr}
  6017. {$ifdef jvm}
  6018. { this routine can be called for compilerproces. can't set mangled
  6019. name since it must be calculated, but it uses import_name when set
  6020. -> set that one }
  6021. import_name:=stringdup(s);
  6022. include(procoptions,po_has_importname);
  6023. include(procoptions,po_has_mangledname);
  6024. {$else}
  6025. {$ifdef symansistr}
  6026. _mangledname:=s;
  6027. {$else symansistr}
  6028. _mangledname:=stringdup(s);
  6029. {$endif symansistr}
  6030. {$endif jvm}
  6031. include(procoptions,po_has_mangledname);
  6032. end;
  6033. function tprocdef.needsglobalasmsym: boolean;
  6034. begin
  6035. result:=
  6036. (cs_profile in current_settings.moduleswitches) or
  6037. { smart linking using a library requires to promote
  6038. all non-nested procedures to AB_GLOBAL
  6039. otherwise you get undefined symbol error at linking
  6040. for msdos target with -CX option for instance }
  6041. (create_smartlink_library and not is_nested_pd(self)) or
  6042. (po_global in procoptions);
  6043. end;
  6044. procedure tprocdef.setcompilerprocname;
  6045. begin
  6046. procsym.realname:='$'+lower(procsym.name);
  6047. end;
  6048. {***************************************************************************
  6049. TPROCVARDEF
  6050. ***************************************************************************}
  6051. constructor tprocvardef.create(level:byte);
  6052. begin
  6053. inherited create(procvardef,level,true);
  6054. end;
  6055. class function tprocvardef.getreusableprocaddr(def: tabstractprocdef): tprocvardef;
  6056. var
  6057. res: PHashSetItem;
  6058. oldsymtablestack: tsymtablestack;
  6059. begin
  6060. if not assigned(current_module) then
  6061. internalerror(2011081301);
  6062. res:=current_module.procaddrdefs.FindOrAdd(@def,sizeof(def));
  6063. if not assigned(res^.Data) then
  6064. begin
  6065. { since these pointerdefs can be reused anywhere in the current
  6066. unit, add them to the global/staticsymtable (or local symtable
  6067. if they're a local def, because otherwise they'll be saved
  6068. to the ppu referencing a local symtable entry that doesn't
  6069. exist in the ppu) }
  6070. oldsymtablestack:=symtablestack;
  6071. { do not simply push/pop current_module.localsymtable, because
  6072. that can have side-effects (e.g., it removes helpers) }
  6073. symtablestack:=nil;
  6074. result:=tprocvardef(def.getcopyas(procvardef,pc_address_only,''));
  6075. setup_reusable_def(def,result,res,oldsymtablestack);
  6076. { res^.Data may still be nil -> don't overwrite result }
  6077. exit;
  6078. end;
  6079. result:=tprocvardef(res^.Data);
  6080. end;
  6081. class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
  6082. begin
  6083. result:=getreusableprocaddr(def);
  6084. if not result.is_registered then
  6085. include(result.defoptions,df_not_registered_no_free);
  6086. end;
  6087. constructor tprocvardef.ppuload(ppufile:tcompilerppufile);
  6088. begin
  6089. inherited ppuload(procvardef,ppufile);
  6090. { load para symtable }
  6091. parast:=tparasymtable.create(self,ppufile.getbyte);
  6092. ppuload_platform(ppufile);
  6093. tparasymtable(parast).ppuload(ppufile);
  6094. end;
  6095. function tprocvardef.getcopy : tstoreddef;
  6096. var
  6097. i : tcallercallee;
  6098. j : longint;
  6099. begin
  6100. result:=cprocvardef.create(parast.symtablelevel);
  6101. tprocvardef(result).returndef:=returndef;
  6102. tprocvardef(result).returndefderef:=returndefderef;
  6103. tprocvardef(result).parast:=parast.getcopy;
  6104. tprocvardef(result).savesize:=savesize;
  6105. { create paralist copy }
  6106. calcparas;
  6107. tprocvardef(result).paras:=tparalist.create(false);
  6108. tprocvardef(result).paras.count:=paras.count;
  6109. for j:=0 to paras.count-1 do
  6110. tprocvardef(result).paras[j]:=paras[j];
  6111. tprocvardef(result).proctypeoption:=proctypeoption;
  6112. tprocvardef(result).proccalloption:=proccalloption;
  6113. tprocvardef(result).procoptions:=procoptions;
  6114. tprocvardef(result).callerargareasize:=callerargareasize;
  6115. tprocvardef(result).calleeargareasize:=calleeargareasize;
  6116. tprocvardef(result).maxparacount:=maxparacount;
  6117. tprocvardef(result).minparacount:=minparacount;
  6118. for i:=low(funcretloc) to high(funcretloc) do
  6119. tprocvardef(result).funcretloc[i]:=funcretloc[i].getcopy;
  6120. tprocvardef(result).has_paraloc_info:=has_paraloc_info;
  6121. {$ifdef m68k}
  6122. tprocvardef(result).exp_funcretloc:=exp_funcretloc;
  6123. {$endif}
  6124. end;
  6125. procedure tprocvardef.ppuwrite(ppufile:tcompilerppufile);
  6126. begin
  6127. inherited ppuwrite(ppufile);
  6128. { Save the para symtable level (necessary to distinguish nested
  6129. procvars) }
  6130. ppufile.putbyte(parast.symtablelevel);
  6131. { Write this entry }
  6132. writeentry(ppufile,ibprocvardef);
  6133. { Save the para symtable, this is taken from the interface }
  6134. tparasymtable(parast).ppuwrite(ppufile);
  6135. end;
  6136. function tprocvardef.GetSymtable(t:tGetSymtable):TSymtable;
  6137. begin
  6138. case t of
  6139. gs_para :
  6140. GetSymtable:=parast;
  6141. else
  6142. GetSymtable:=nil;
  6143. end;
  6144. end;
  6145. function tprocvardef.size : asizeint;
  6146. begin
  6147. { we return false for is_addressonly for a block (because it's not a
  6148. simple pointer to a function), but they are handled as implicit
  6149. pointers to a datastructure that contains everything ->
  6150. voidpointertype.size instead of voidcodepointertype.size }
  6151. if po_is_block in procoptions then
  6152. size:=voidpointertype.size
  6153. else if not is_addressonly then
  6154. begin
  6155. if is_nested_pd(self) then
  6156. size:=voidcodepointertype.size+parentfpvoidpointertype.size
  6157. else
  6158. size:=voidcodepointertype.size+voidpointertype.size;
  6159. end
  6160. else
  6161. size:=voidcodepointertype.size;
  6162. end;
  6163. function tprocvardef.is_methodpointer:boolean;
  6164. begin
  6165. result:=(po_methodpointer in procoptions);
  6166. end;
  6167. function tprocvardef.is_addressonly:boolean;
  6168. begin
  6169. result:=((not(po_methodpointer in procoptions) or (po_staticmethod in procoptions)) and
  6170. not(po_is_block in procoptions) and
  6171. not is_nested_pd(self)) or
  6172. (po_addressonly in procoptions);
  6173. end;
  6174. function tprocvardef.getmangledparaname:TSymStr;
  6175. begin
  6176. if not(po_methodpointer in procoptions) then
  6177. if not is_nested_pd(self) then
  6178. result:='procvar'
  6179. else
  6180. { we need the manglednames here, because nestedprocvars can be anonymous, e.g.
  6181. having not a type name or not an unique one, see webtbs/tw27515.pp
  6182. Further, use $_ ... _$ delimiters to avoid ambiguous names, see webtbs/tw27515.pp }
  6183. result:='$_nestedprovar'+mangledprocparanames(0)+'_$'
  6184. else
  6185. result:='procvarofobj'
  6186. end;
  6187. function tprocvardef.getcopyas(newtyp: tdeftyp; copytyp: tproccopytyp; const paraprefix: string): tstoreddef;
  6188. begin
  6189. result:=inherited;
  6190. tabstractprocdef(result).calcparas;
  6191. end;
  6192. function tprocvardef.is_publishable : boolean;
  6193. begin
  6194. is_publishable:=(po_methodpointer in procoptions);
  6195. end;
  6196. function tprocvardef.GetTypeName : string;
  6197. var
  6198. s: string;
  6199. pno : tprocnameoptions;
  6200. begin
  6201. {$ifdef EXTDEBUG}
  6202. pno:=[pno_showhidden];
  6203. {$else EXTDEBUG}
  6204. pno:=[];
  6205. {$endif EXTDEBUG}
  6206. s:='<';
  6207. if po_is_block in procoptions then
  6208. s := s+'reference to'
  6209. else if po_classmethod in procoptions then
  6210. s := s+'class method type of'
  6211. else
  6212. if po_addressonly in procoptions then
  6213. s := s+'address of'
  6214. else
  6215. s := s+'procedure variable type of';
  6216. if assigned(returndef) and
  6217. (returndef<>voidtype) then
  6218. s:=s+' function'+typename_paras(pno)+':'+returndef.GetTypeName
  6219. else
  6220. s:=s+' procedure'+typename_paras(pno);
  6221. if po_methodpointer in procoptions then
  6222. s := s+' of object';
  6223. if is_nested_pd(self) then
  6224. s := s+' is nested';
  6225. if po_far in procoptions then
  6226. s := s+';far';
  6227. GetTypeName := s+';'+ProcCallOptionStr[proccalloption]+'>';
  6228. end;
  6229. {***************************************************************************
  6230. TOBJECTDEF
  6231. ***************************************************************************}
  6232. constructor tobjectdef.create(ot:tobjecttyp;const n:string;c:tobjectdef;doregister:boolean);
  6233. begin
  6234. inherited create(n,objectdef,doregister);
  6235. fcurrent_dispid:=0;
  6236. objecttype:=ot;
  6237. childof:=nil;
  6238. childofderef.reset;
  6239. vmt_fieldderef.reset;
  6240. extendeddefderef.reset;
  6241. cloneddefderef.reset;
  6242. if objecttype=odt_helper then
  6243. owner.includeoption(sto_has_helper);
  6244. symtable:=tObjectSymtable.create(self,n,current_settings.packrecords,
  6245. current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  6246. { create space for vmt !! }
  6247. vmtentries:=TFPList.Create;
  6248. set_parent(c);
  6249. if objecttype in [odt_interfacecorba,odt_interfacecom,odt_dispinterface] then
  6250. prepareguid;
  6251. { setup implemented interfaces }
  6252. if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then
  6253. ImplementedInterfaces:=TFPObjectList.Create(true)
  6254. else
  6255. ImplementedInterfaces:=nil;
  6256. writing_class_record_dbginfo:=false;
  6257. end;
  6258. constructor tobjectdef.ppuload(ppufile:tcompilerppufile);
  6259. var
  6260. i,
  6261. implintfcount : longint;
  6262. d, getterd : tderef;
  6263. ImplIntf : TImplementedInterface;
  6264. vmtentry : pvmtentry;
  6265. begin
  6266. inherited ppuload(objectdef,ppufile);
  6267. objecttype:=tobjecttyp(ppufile.getbyte);
  6268. helpertype:=thelpertype(ppufile.getbyte);
  6269. objextname:=ppufile.getpshortstring;
  6270. { only used for external Objective-C classes/protocols }
  6271. if (objextname^='') then
  6272. stringdispose(objextname);
  6273. symtable:=tObjectSymtable.create(self,objrealname^,0,0,0);
  6274. tObjectSymtable(symtable).datasize:=ppufile.getasizeint;
  6275. tObjectSymtable(symtable).paddingsize:=ppufile.getword;
  6276. tObjectSymtable(symtable).fieldalignment:=shortint(ppufile.getbyte);
  6277. tObjectSymtable(symtable).recordalignment:=shortint(ppufile.getbyte);
  6278. tObjectSymtable(symtable).recordalignmin:=shortint(ppufile.getbyte);
  6279. ppufile.getderef(vmt_fieldderef);
  6280. ppufile.getderef(childofderef);
  6281. { load guid }
  6282. iidstr:=nil;
  6283. if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
  6284. begin
  6285. new(iidguid);
  6286. ppufile.getguid(iidguid^);
  6287. iidstr:=ppufile.getpshortstring;
  6288. end;
  6289. abstractcnt:=ppufile.getlongint;
  6290. if objecttype=odt_helper then
  6291. ppufile.getderef(extendeddefderef);
  6292. vmtentries:=TFPList.Create;
  6293. vmtentries.count:=ppufile.getlongint;
  6294. for i:=0 to vmtentries.count-1 do
  6295. begin
  6296. ppufile.getderef(d);
  6297. new(vmtentry);
  6298. vmtentry^.procdef:=nil;
  6299. vmtentry^.procdefderef:=d;
  6300. vmtentry^.visibility:=tvisibility(ppufile.getbyte);
  6301. vmtentries[i]:=vmtentry;
  6302. end;
  6303. { load implemented interfaces }
  6304. if objecttype in [odt_class,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then
  6305. begin
  6306. ImplementedInterfaces:=TFPObjectList.Create(true);
  6307. implintfcount:=ppufile.getlongint;
  6308. for i:=0 to implintfcount-1 do
  6309. begin
  6310. ppufile.getderef(d);
  6311. ppufile.getderef(getterd);
  6312. ImplIntf:=TImplementedInterface.Create_deref(d,getterd);
  6313. ImplIntf.IOffset:=ppufile.getlongint;
  6314. byte(ImplIntf.IType):=ppufile.getbyte;
  6315. ImplementedInterfaces.Add(ImplIntf);
  6316. end;
  6317. end
  6318. else
  6319. ImplementedInterfaces:=nil;
  6320. if df_copied_def in defoptions then
  6321. begin
  6322. ppufile.getderef(cloneddefderef);
  6323. ppuload_platform(ppufile);
  6324. end
  6325. else
  6326. begin
  6327. ppuload_platform(ppufile);
  6328. tObjectSymtable(symtable).ppuload(ppufile);
  6329. end;
  6330. { handles the predefined class tobject }
  6331. { the last TOBJECT which is loaded gets }
  6332. { it ! }
  6333. if (childof=nil) and
  6334. (objecttype in [odt_class,odt_javaclass]) and
  6335. (objname^='TOBJECT') then
  6336. class_tobject:=self;
  6337. if (childof=nil) and
  6338. (objecttype=odt_interfacecom) then
  6339. if (objname^='IUNKNOWN') then
  6340. interface_iunknown:=self
  6341. else
  6342. if (objname^='IDISPATCH') then
  6343. interface_idispatch:=self;
  6344. if (childof=nil) and
  6345. (objecttype=odt_objcclass) and
  6346. (objname^='PROTOCOL') then
  6347. objc_protocoltype:=self;
  6348. if (objecttype=odt_javaclass) and
  6349. not(oo_is_formal in objectoptions) then
  6350. begin
  6351. if (objname^='JLOBJECT') then
  6352. java_jlobject:=self
  6353. else if (objname^='JLTHROWABLE') then
  6354. java_jlthrowable:=self
  6355. else if (objname^='FPCBASERECORDTYPE') then
  6356. java_fpcbaserecordtype:=self
  6357. else if (objname^='JLSTRING') then
  6358. java_jlstring:=self
  6359. else if (objname^='ANSISTRINGCLASS') then
  6360. java_ansistring:=self
  6361. else if (objname^='SHORTSTRINGCLASS') then
  6362. java_shortstring:=self
  6363. else if (objname^='JLENUM') then
  6364. java_jlenum:=self
  6365. else if (objname^='JUENUMSET') then
  6366. java_juenumset:=self
  6367. else if (objname^='FPCBITSET') then
  6368. java_jubitset:=self
  6369. else if (objname^='FPCBASEPROCVARTYPE') then
  6370. java_procvarbase:=self;
  6371. end;
  6372. writing_class_record_dbginfo:=false;
  6373. end;
  6374. destructor tobjectdef.destroy;
  6375. begin
  6376. if assigned(symtable) then
  6377. begin
  6378. symtable.free;
  6379. symtable:=nil;
  6380. end;
  6381. stringdispose(objextname);
  6382. stringdispose(iidstr);
  6383. if assigned(ImplementedInterfaces) then
  6384. begin
  6385. ImplementedInterfaces.free;
  6386. ImplementedInterfaces:=nil;
  6387. end;
  6388. if assigned(iidguid) then
  6389. begin
  6390. dispose(iidguid);
  6391. iidguid:=nil;
  6392. end;
  6393. if assigned(vmtentries) then
  6394. begin
  6395. resetvmtentries;
  6396. vmtentries.free;
  6397. vmtentries:=nil;
  6398. end;
  6399. if assigned(vmcallstaticinfo) then
  6400. begin
  6401. freemem(vmcallstaticinfo);
  6402. vmcallstaticinfo:=nil;
  6403. end;
  6404. inherited destroy;
  6405. end;
  6406. function tobjectdef.getcopy : tstoreddef;
  6407. var
  6408. i : longint;
  6409. begin
  6410. result:=cobjectdef.create(objecttype,objrealname^,childof,true);
  6411. { the constructor allocates a symtable which we release to avoid memory leaks }
  6412. tobjectdef(result).symtable.free;
  6413. tobjectdef(result).symtable:=symtable.getcopy;
  6414. if assigned(objextname) then
  6415. tobjectdef(result).objextname:=stringdup(objextname^);
  6416. if assigned(import_lib) then
  6417. tobjectdef(result).import_lib:=stringdup(import_lib^);
  6418. tobjectdef(result).objectoptions:=objectoptions;
  6419. include(tobjectdef(result).defoptions,df_copied_def);
  6420. tobjectdef(result).extendeddef:=extendeddef;
  6421. if assigned(tcinitcode) then
  6422. tobjectdef(result).tcinitcode:=tcinitcode.getcopy;
  6423. tobjectdef(result).vmt_field:=vmt_field;
  6424. if assigned(iidguid) then
  6425. begin
  6426. new(tobjectdef(result).iidguid);
  6427. move(iidguid^,tobjectdef(result).iidguid^,sizeof(iidguid^));
  6428. end;
  6429. if assigned(iidstr) then
  6430. tobjectdef(result).iidstr:=stringdup(iidstr^);
  6431. tobjectdef(result).abstractcnt:=abstractcnt;
  6432. if assigned(ImplementedInterfaces) then
  6433. begin
  6434. for i:=0 to ImplementedInterfaces.count-1 do
  6435. tobjectdef(result).ImplementedInterfaces.Add(TImplementedInterface(ImplementedInterfaces[i]).Getcopy);
  6436. end;
  6437. if assigned(vmtentries) then
  6438. begin
  6439. tobjectdef(result).vmtentries:=TFPList.Create;
  6440. tobjectdef(result).copyvmtentries(self);
  6441. end;
  6442. end;
  6443. procedure tobjectdef.ppuwrite(ppufile:tcompilerppufile);
  6444. var
  6445. i : longint;
  6446. vmtentry : pvmtentry;
  6447. ImplIntf : TImplementedInterface;
  6448. old_do_indirect_crc: boolean;
  6449. begin
  6450. { if class1 in unit A changes, and class2 in unit B inherits from it
  6451. (so unit B uses unit A), then unit B with class2 will be recompiled.
  6452. However, if there is also a class3 in unit C that only depends on
  6453. unit B, then unit C will not be recompiled because nothing changed
  6454. to the interface of unit B. Nevertheless, unit C can indirectly
  6455. depend on unit A via derefs, and these must be updated -> the
  6456. indirect crc keeps track of such changes. }
  6457. old_do_indirect_crc:=ppufile.do_indirect_crc;
  6458. ppufile.do_indirect_crc:=true;
  6459. inherited ppuwrite(ppufile);
  6460. ppufile.putbyte(byte(objecttype));
  6461. ppufile.putbyte(byte(helpertype));
  6462. if assigned(objextname) then
  6463. ppufile.putstring(objextname^)
  6464. else
  6465. ppufile.putstring('');
  6466. ppufile.putasizeint(tObjectSymtable(symtable).datasize);
  6467. ppufile.putword(tObjectSymtable(symtable).paddingsize);
  6468. ppufile.putbyte(byte(tObjectSymtable(symtable).fieldalignment));
  6469. ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignment));
  6470. ppufile.putbyte(byte(tObjectSymtable(symtable).recordalignmin));
  6471. ppufile.putderef(vmt_fieldderef);
  6472. ppufile.putderef(childofderef);
  6473. if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface] then
  6474. begin
  6475. ppufile.putguid(iidguid^);
  6476. ppufile.putstring(iidstr^);
  6477. end;
  6478. ppufile.putlongint(abstractcnt);
  6479. if objecttype=odt_helper then
  6480. ppufile.putderef(extendeddefderef);
  6481. ppufile.putlongint(vmtentries.count);
  6482. for i:=0 to vmtentries.count-1 do
  6483. begin
  6484. vmtentry:=pvmtentry(vmtentries[i]);
  6485. ppufile.putderef(vmtentry^.procdefderef);
  6486. ppufile.putbyte(byte(vmtentry^.visibility));
  6487. end;
  6488. if assigned(ImplementedInterfaces) then
  6489. begin
  6490. ppufile.putlongint(ImplementedInterfaces.Count);
  6491. for i:=0 to ImplementedInterfaces.Count-1 do
  6492. begin
  6493. ImplIntf:=TImplementedInterface(ImplementedInterfaces[i]);
  6494. ppufile.putderef(ImplIntf.intfdefderef);
  6495. ppufile.putderef(ImplIntf.ImplementsGetterDeref);
  6496. ppufile.putlongint(ImplIntf.Ioffset);
  6497. ppufile.putbyte(byte(ImplIntf.IType));
  6498. end;
  6499. end;
  6500. if df_copied_def in defoptions then
  6501. ppufile.putderef(cloneddefderef);
  6502. writeentry(ppufile,ibobjectdef);
  6503. if not(df_copied_def in defoptions) then
  6504. tObjectSymtable(symtable).ppuwrite(ppufile);
  6505. ppufile.do_indirect_crc:=old_do_indirect_crc;
  6506. end;
  6507. function tobjectdef.GetTypeName:string;
  6508. begin
  6509. { in this case we will go in endless recursion, because then }
  6510. { there is no tsym associated yet with the def. It can occur }
  6511. { (tests/webtbf/tw4757.pp), so for now give a generic name }
  6512. { instead of the actual type name }
  6513. if not assigned(typesym) then
  6514. result:='<Currently Parsed Class>'
  6515. else
  6516. result:=typesymbolprettyname;
  6517. end;
  6518. procedure tobjectdef.buildderef;
  6519. var
  6520. i : longint;
  6521. vmtentry : pvmtentry;
  6522. begin
  6523. inherited buildderef;
  6524. vmt_fieldderef.build(vmt_field);
  6525. childofderef.build(childof);
  6526. if df_copied_def in defoptions then
  6527. cloneddefderef.build(symtable.defowner)
  6528. else
  6529. tstoredsymtable(symtable).buildderef;
  6530. if objecttype=odt_helper then
  6531. extendeddefderef.build(extendeddef);
  6532. for i:=0 to vmtentries.count-1 do
  6533. begin
  6534. vmtentry:=pvmtentry(vmtentries[i]);
  6535. vmtentry^.procdefderef.build(vmtentry^.procdef);
  6536. end;
  6537. if assigned(ImplementedInterfaces) then
  6538. begin
  6539. for i:=0 to ImplementedInterfaces.count-1 do
  6540. TImplementedInterface(ImplementedInterfaces[i]).buildderef;
  6541. end;
  6542. end;
  6543. procedure tobjectdef.deref;
  6544. var
  6545. i : longint;
  6546. vmtentry : pvmtentry;
  6547. begin
  6548. inherited deref;
  6549. vmt_field:=tsym(vmt_fieldderef.resolve);
  6550. childof:=tobjectdef(childofderef.resolve);
  6551. if df_copied_def in defoptions then
  6552. begin
  6553. cloneddef:=tobjectdef(cloneddefderef.resolve);
  6554. symtable:=cloneddef.symtable.getcopy;
  6555. end
  6556. else
  6557. tstoredsymtable(symtable).deref(false);
  6558. if objecttype=odt_helper then
  6559. extendeddef:=tdef(extendeddefderef.resolve);
  6560. for i:=0 to vmtentries.count-1 do
  6561. begin
  6562. vmtentry:=pvmtentry(vmtentries[i]);
  6563. vmtentry^.procdef:=tprocdef(vmtentry^.procdefderef.resolve);
  6564. end;
  6565. if assigned(ImplementedInterfaces) then
  6566. begin
  6567. for i:=0 to ImplementedInterfaces.count-1 do
  6568. TImplementedInterface(ImplementedInterfaces[i]).deref;
  6569. end;
  6570. end;
  6571. procedure create_class_helper_for_procdef(def: tobject; arg: pointer);
  6572. var
  6573. pd: tprocdef absolute def;
  6574. st: tsymtable;
  6575. psym: tsym;
  6576. nname: TIDString;
  6577. begin
  6578. if (tdef(def).typ<>procdef) then
  6579. exit;
  6580. { pd.owner = objcclass symtable -> defowner = objcclassdef ->
  6581. owner = symtable in which objcclassdef is defined
  6582. }
  6583. st:=pd.owner.defowner.owner;
  6584. nname:=class_helper_prefix+tprocsym(pd.procsym).name;
  6585. { check for an existing procsym with our special name }
  6586. psym:=tsym(st.find(nname));
  6587. if not assigned(psym) then
  6588. begin
  6589. psym:=cprocsym.create(nname);
  6590. { avoid warning about this symbol being unused }
  6591. psym.IncRefCount;
  6592. { don't check for duplicates:
  6593. a) we checked above
  6594. b) in case we are in the implementation section of a unit, this
  6595. will also check for this symbol in the interface section
  6596. (since you normally cannot have symbols with the same name
  6597. both interface and implementation), and it's possible to
  6598. have class helpers for the same class in the interface and
  6599. in the implementation, and they cannot be merged since only
  6600. the once in the interface must be saved to the ppu/visible
  6601. from other units }
  6602. st.insert(psym,false);
  6603. end
  6604. else if (psym.typ<>procsym) then
  6605. internalerror(2009111501);
  6606. { add ourselves to this special procsym }
  6607. tprocsym(psym).procdeflist.add(def);
  6608. end;
  6609. procedure tobjectdef.derefimpl;
  6610. begin
  6611. inherited derefimpl;
  6612. { the procdefs are not owned by the class helper procsyms, so they
  6613. are not stored/restored either -> re-add them here }
  6614. if (objecttype in [odt_objcclass,odt_objcprotocol]) or
  6615. (oo_is_classhelper in objectoptions) then
  6616. symtable.DefList.ForEachCall(@create_class_helper_for_procdef,nil);
  6617. end;
  6618. procedure tobjectdef.resetvmtentries;
  6619. var
  6620. i : longint;
  6621. begin
  6622. for i:=0 to vmtentries.Count-1 do
  6623. Dispose(pvmtentry(vmtentries[i]));
  6624. vmtentries.clear;
  6625. end;
  6626. procedure tobjectdef.copyvmtentries(objdef:tobjectdef);
  6627. var
  6628. i : longint;
  6629. vmtentry : pvmtentry;
  6630. begin
  6631. resetvmtentries;
  6632. vmtentries.count:=objdef.vmtentries.count;
  6633. for i:=0 to objdef.vmtentries.count-1 do
  6634. begin
  6635. new(vmtentry);
  6636. vmtentry^:=pvmtentry(objdef.vmtentries[i])^;
  6637. vmtentries[i]:=vmtentry;
  6638. end;
  6639. end;
  6640. function tobjectdef.getparentdef:tdef;
  6641. begin
  6642. { TODO: Remove getparentdef hack}
  6643. { With 2 forward declared classes with the child class before the
  6644. parent class the child class is written earlier to the ppu. Leaving it
  6645. possible to have a reference to the parent class for property overriding,
  6646. but the parent class still has the childof not resolved yet (PFV) }
  6647. if childof=nil then
  6648. childof:=tobjectdef(childofderef.resolve);
  6649. result:=childof;
  6650. end;
  6651. procedure tobjectdef.prepareguid;
  6652. begin
  6653. { set up guid }
  6654. if not assigned(iidguid) then
  6655. begin
  6656. new(iidguid);
  6657. fillchar(iidguid^,sizeof(iidguid^),0); { default null guid }
  6658. end;
  6659. { setup iidstring }
  6660. if not assigned(iidstr) then
  6661. iidstr:=stringdup(''); { default is empty string }
  6662. end;
  6663. procedure tobjectdef.set_parent( c : tobjectdef);
  6664. begin
  6665. if assigned(childof) then
  6666. exit;
  6667. childof:=c;
  6668. if not assigned(c) then
  6669. exit;
  6670. { inherit options and status }
  6671. objectoptions:=objectoptions+(c.objectoptions*inherited_objectoptions);
  6672. { initially has the same number of abstract methods as the parent }
  6673. abstractcnt:=c.abstractcnt;
  6674. { add the data of the anchestor class/object }
  6675. if (objecttype in [odt_class,odt_object,odt_objcclass,odt_javaclass]) then
  6676. begin
  6677. tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize+tObjectSymtable(c.symtable).datasize;
  6678. { inherit recordalignment }
  6679. tObjectSymtable(symtable).recordalignment:=tObjectSymtable(c.symtable).recordalignment;
  6680. { if both the parent and this record use C-alignment, also inherit
  6681. the current field alignment }
  6682. if (tObjectSymtable(c.symtable).usefieldalignment=C_alignment) and
  6683. (tObjectSymtable(symtable).usefieldalignment=C_alignment) then
  6684. tObjectSymtable(symtable).fieldalignment:=tObjectSymtable(c.symtable).fieldalignment;
  6685. { the padding is not inherited for Objective-C classes (maybe not
  6686. for cppclass either?) }
  6687. if objecttype=odt_objcclass then
  6688. tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-tObjectSymtable(c.symtable).paddingsize;
  6689. if (oo_has_vmt in objectoptions) and
  6690. (oo_has_vmt in c.objectoptions) then
  6691. tObjectSymtable(symtable).datasize:=tObjectSymtable(symtable).datasize-sizeof(pint);
  6692. { if parent has a vmt field then the offset is the same for the child PM }
  6693. if (oo_has_vmt in c.objectoptions) or is_class(self) then
  6694. begin
  6695. vmt_field:=c.vmt_field;
  6696. include(objectoptions,oo_has_vmt);
  6697. end;
  6698. end;
  6699. end;
  6700. procedure tobjectdef.insertvmt;
  6701. begin
  6702. if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then
  6703. exit;
  6704. if (oo_has_vmt in objectoptions) then
  6705. internalerror(12345)
  6706. else
  6707. begin
  6708. tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,
  6709. tObjectSymtable(symtable).fieldalignment);
  6710. if (tf_requires_proper_alignment in target_info.flags) then
  6711. begin
  6712. { Align VMT pointer and whole object instance if target CPU requires alignment. }
  6713. tObjectSymtable(symtable).datasize:=align(tObjectSymtable(symtable).datasize,sizeof(pint));
  6714. tObjectSymtable(symtable).alignrecord(tObjectSymtable(symtable).datasize,sizeof(pint));
  6715. end;
  6716. vmt_field:=cfieldvarsym.create('_vptr$'+objname^,vs_value,voidpointertype,[],true);
  6717. hidesym(vmt_field);
  6718. tObjectSymtable(symtable).insert(vmt_field);
  6719. tObjectSymtable(symtable).addfield(tfieldvarsym(vmt_field),vis_hidden);
  6720. include(objectoptions,oo_has_vmt);
  6721. end;
  6722. end;
  6723. function tobjectdef.vmt_offset: asizeint;
  6724. begin
  6725. if objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava] then
  6726. result:=0
  6727. else if (tObjectSymtable(symtable).usefieldalignment<>bit_alignment) then
  6728. result:=tfieldvarsym(vmt_field).fieldoffset
  6729. else
  6730. result:=tfieldvarsym(vmt_field).fieldoffset div 8;
  6731. end;
  6732. procedure tobjectdef.check_forwards;
  6733. begin
  6734. if not(objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcprotocol,odt_interfacejava]) then
  6735. inherited;
  6736. if (oo_is_forward in objectoptions) then
  6737. begin
  6738. { ok, in future, the forward can be resolved }
  6739. Message1(sym_e_class_forward_not_resolved,objrealname^);
  6740. exclude(objectoptions,oo_is_forward);
  6741. end;
  6742. end;
  6743. function tobjectdef.find_destructor: tprocdef;
  6744. var
  6745. objdef: tobjectdef;
  6746. begin
  6747. objdef:=self;
  6748. while assigned(objdef) do
  6749. begin
  6750. result:=objdef.find_procdef_bytype(potype_destructor);
  6751. if assigned(result) then
  6752. exit;
  6753. objdef:=objdef.childof;
  6754. end;
  6755. result:=nil;
  6756. end;
  6757. function tobjectdef.implements_any_interfaces: boolean;
  6758. begin
  6759. result := (ImplementedInterfaces.Count > 0) or
  6760. (assigned(childof) and childof.implements_any_interfaces);
  6761. end;
  6762. function tobjectdef.size : asizeint;
  6763. begin
  6764. if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava] then
  6765. result:=voidpointertype.size
  6766. else
  6767. result:=tObjectSymtable(symtable).datasize;
  6768. end;
  6769. function tobjectdef.alignment:shortint;
  6770. begin
  6771. if objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava] then
  6772. alignment:=voidpointertype.alignment
  6773. else
  6774. alignment:=tObjectSymtable(symtable).recordalignment;
  6775. end;
  6776. function tobjectdef.vmtmethodoffset(index:longint):longint;
  6777. begin
  6778. { for offset of methods for classes, see rtl/inc/objpash.inc }
  6779. case objecttype of
  6780. odt_class:
  6781. { the +2*sizeof(pint) is size and -size }
  6782. vmtmethodoffset:=index*voidcodepointertype.size+10*voidpointertype.size+2*sizeof(pint);
  6783. odt_helper,
  6784. odt_objcclass,
  6785. odt_objcprotocol:
  6786. vmtmethodoffset:=0;
  6787. odt_interfacecom,odt_interfacecorba,odt_dispinterface:
  6788. vmtmethodoffset:=index*voidcodepointertype.size;
  6789. odt_javaclass,
  6790. odt_interfacejava:
  6791. { invalid }
  6792. vmtmethodoffset:=-1;
  6793. else
  6794. { the +2*sizeof(pint) is size and -size }
  6795. {$ifdef WITHDMT}
  6796. vmtmethodoffset:=index*voidcodepointertype.size+2*voidpointertype.size+2*sizeof(pint);
  6797. {$else WITHDMT}
  6798. vmtmethodoffset:=index*voidcodepointertype.size+1*voidpointertype.size+2*sizeof(pint);
  6799. {$endif WITHDMT}
  6800. end;
  6801. end;
  6802. function tobjectdef.vmt_mangledname : TSymStr;
  6803. begin
  6804. if not(oo_has_vmt in objectoptions) then
  6805. Message1(parser_n_object_has_no_vmt,objrealname^);
  6806. vmt_mangledname:=make_mangledname('VMT',owner,objname^);
  6807. end;
  6808. function tobjectdef.vmt_def: trecorddef;
  6809. var
  6810. vmttypesym: tsym;
  6811. begin
  6812. if not(typesym.owner.symtabletype in [ObjectSymtable,recordsymtable]) then
  6813. vmttypesym:=tsym(typesym.owner.Find('vmtdef$'+mangledparaname))
  6814. else
  6815. vmttypesym:=tsym(tobjectsymtable(typesym.owner).get_unit_symtable.Find('vmtdef$'+mangledparaname));
  6816. if not assigned(vmttypesym) or
  6817. (vmttypesym.typ<>symconst.typesym) or
  6818. (ttypesym(vmttypesym).typedef.typ<>recorddef) then
  6819. internalerror(2015052501);
  6820. result:=trecorddef(ttypesym(vmttypesym).typedef);
  6821. end;
  6822. function tobjectdef.needs_inittable : boolean;
  6823. var
  6824. hp : tobjectdef;
  6825. begin
  6826. case objecttype of
  6827. odt_helper,
  6828. odt_class :
  6829. needs_inittable:=false;
  6830. odt_dispinterface,
  6831. odt_interfacecom:
  6832. needs_inittable:=true;
  6833. odt_interfacecorba:
  6834. begin
  6835. hp:=childof;
  6836. while assigned(hp) do
  6837. begin
  6838. if hp=interface_iunknown then
  6839. begin
  6840. needs_inittable:=true;
  6841. exit;
  6842. end;
  6843. hp:=hp.childof;
  6844. end;
  6845. needs_inittable:=false;
  6846. end;
  6847. odt_object:
  6848. needs_inittable:=
  6849. tObjectSymtable(symtable).needs_init_final or
  6850. (assigned(childof) and
  6851. childof.needs_inittable);
  6852. odt_cppclass,
  6853. odt_objcclass,
  6854. odt_objcprotocol,
  6855. odt_javaclass,
  6856. odt_interfacejava:
  6857. needs_inittable:=false;
  6858. else
  6859. internalerror(200108267);
  6860. end;
  6861. end;
  6862. function tobjectdef.needs_separate_initrtti : boolean;
  6863. begin
  6864. result:=not (objecttype in [odt_interfacecom,odt_interfacecorba,odt_dispinterface]);
  6865. end;
  6866. function tobjectdef.has_non_trivial_init_child(check_parent:boolean):boolean;
  6867. begin
  6868. if objecttype in [odt_class,odt_object] then
  6869. begin
  6870. result:=tobjectsymtable(symtable).has_non_trivial_init or
  6871. (check_parent and assigned(childof) and childof.has_non_trivial_init_child(true));
  6872. end
  6873. else
  6874. result:=false;
  6875. end;
  6876. function tobjectdef.rtti_mangledname(rt: trttitype): TSymStr;
  6877. begin
  6878. if not(objecttype in [odt_objcclass,odt_objcprotocol]) then
  6879. result:=inherited rtti_mangledname(rt)
  6880. else
  6881. begin
  6882. { necessary in case of a dynamic array of nsobject, or
  6883. if an nsobject field appears in a record that needs
  6884. init/finalisation }
  6885. if rt=initrtti then
  6886. begin
  6887. result:=voidpointertype.rtti_mangledname(rt);
  6888. exit;
  6889. end;
  6890. if not(target_info.system in systems_objc_nfabi) then
  6891. begin
  6892. result:=target_asm.labelprefix;
  6893. case objecttype of
  6894. odt_objcclass:
  6895. begin
  6896. case rt of
  6897. objcclassrtti:
  6898. if not(oo_is_classhelper in objectoptions) then
  6899. result:=result+'_OBJC_CLASS_'
  6900. else
  6901. result:=result+'_OBJC_CATEGORY_';
  6902. objcmetartti:
  6903. if not(oo_is_classhelper in objectoptions) then
  6904. result:=result+'_OBJC_METACLASS_'
  6905. else
  6906. internalerror(2009111511);
  6907. else
  6908. internalerror(2009092302);
  6909. end;
  6910. end;
  6911. odt_objcprotocol:
  6912. result:=result+'_OBJC_PROTOCOL_';
  6913. else
  6914. ;
  6915. end;
  6916. end
  6917. else
  6918. begin
  6919. case objecttype of
  6920. odt_objcclass:
  6921. begin
  6922. if (oo_is_classhelper in objectoptions) and
  6923. (rt<>objcclassrtti) then
  6924. internalerror(2009111512);
  6925. case rt of
  6926. objcclassrtti:
  6927. if not(oo_is_classhelper in objectoptions) then
  6928. result:='_OBJC_CLASS_$_'
  6929. else
  6930. result:='_OBJC_$_CATEGORY_';
  6931. objcmetartti:
  6932. result:='_OBJC_METACLASS_$_';
  6933. objcclassrortti:
  6934. result:=lower(target_asm.labelprefix)+'_OBJC_CLASS_RO_$_';
  6935. objcmetarortti:
  6936. result:=lower(target_asm.labelprefix)+'_OBJC_METACLASS_RO_$_';
  6937. else
  6938. internalerror(2009092303);
  6939. end;
  6940. end;
  6941. odt_objcprotocol:
  6942. begin
  6943. result:=lower(target_asm.labelprefix);
  6944. case rt of
  6945. objcclassrtti:
  6946. result:=result+'_OBJC_PROTOCOL_$_';
  6947. objcmetartti:
  6948. result:=result+'_OBJC_LABEL_PROTOCOL_$_';
  6949. else
  6950. internalerror(2009092501);
  6951. end;
  6952. end;
  6953. else
  6954. internalerror(2013113005);
  6955. end;
  6956. end;
  6957. result:=result+objextname^;
  6958. end;
  6959. end;
  6960. function tobjectdef.members_need_inittable : boolean;
  6961. begin
  6962. members_need_inittable:=tObjectSymtable(symtable).needs_init_final;
  6963. end;
  6964. function tobjectdef.is_publishable : boolean;
  6965. begin
  6966. is_publishable:=objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface];
  6967. end;
  6968. function tobjectdef.get_next_dispid: longint;
  6969. begin
  6970. inc(fcurrent_dispid);
  6971. result:=fcurrent_dispid;
  6972. end;
  6973. function tobjectdef.search_enumerator_get: tprocdef;
  6974. begin
  6975. result:=inherited;
  6976. if not assigned(result) and assigned(childof) then
  6977. result:=childof.search_enumerator_get;
  6978. end;
  6979. function tobjectdef.search_enumerator_move: tprocdef;
  6980. begin
  6981. result:=inherited;
  6982. if not assigned(result) and assigned(childof) then
  6983. result:=childof.search_enumerator_move;
  6984. end;
  6985. function tobjectdef.search_enumerator_current: tsym;
  6986. begin
  6987. result:=inherited;
  6988. if not assigned(result) and assigned(childof) then
  6989. result:=childof.search_enumerator_current;
  6990. end;
  6991. procedure tobjectdef.register_created_classref_type;
  6992. begin
  6993. if not classref_created_in_current_module then
  6994. begin
  6995. classref_created_in_current_module:=true;
  6996. current_module.wpoinfo.addcreatedobjtypeforclassref(self);
  6997. end;
  6998. end;
  6999. procedure tobjectdef.register_created_object_type;
  7000. begin
  7001. if not created_in_current_module then
  7002. begin
  7003. created_in_current_module:=true;
  7004. current_module.wpoinfo.addcreatedobjtype(self);
  7005. end;
  7006. end;
  7007. procedure tobjectdef.register_maybe_created_object_type;
  7008. begin
  7009. { if we know it has been created for sure, no need
  7010. to also record that it maybe can be created in
  7011. this module
  7012. }
  7013. if not (created_in_current_module) and
  7014. not (maybe_created_in_current_module) then
  7015. begin
  7016. maybe_created_in_current_module:=true;
  7017. current_module.wpoinfo.addmaybecreatedbyclassref(self);
  7018. end;
  7019. end;
  7020. procedure tobjectdef.register_vmt_call(index: longint);
  7021. begin
  7022. if (is_object(self) or is_class(self)) then
  7023. current_module.wpoinfo.addcalledvmtentry(self,index);
  7024. end;
  7025. procedure check_and_finish_msg(data: tobject; arg: pointer);
  7026. var
  7027. def: tdef absolute data;
  7028. pd: tprocdef absolute data;
  7029. i,
  7030. paracount: longint;
  7031. begin
  7032. if (def.typ=procdef) then
  7033. begin
  7034. { add all messages also under a dummy name to the symtable in
  7035. which the objcclass/protocol/category is declared, so they can
  7036. be called via id.<name>
  7037. }
  7038. create_class_helper_for_procdef(pd,nil);
  7039. { we have to wait until now to set the mangled name because it
  7040. depends on the (possibly external) class name, which is defined
  7041. at the very end. }
  7042. if not(po_msgstr in pd.procoptions) then
  7043. begin
  7044. CGMessagePos(pd.fileinfo,parser_e_objc_requires_msgstr);
  7045. { recover to avoid internalerror later on }
  7046. include(pd.procoptions,po_msgstr);
  7047. pd.messageinf.str:=stringdup('MissingDeclaration');
  7048. end;
  7049. { Mangled name is already set in case this is a copy of
  7050. another type. }
  7051. if not(po_has_mangledname in pd.procoptions) then
  7052. begin
  7053. { check whether the number of formal parameters is correct,
  7054. and whether they have valid Objective-C types }
  7055. paracount:=0;
  7056. for i:=1 to length(pd.messageinf.str^) do
  7057. if pd.messageinf.str^[i]=':' then
  7058. inc(paracount);
  7059. for i:=0 to pd.paras.count-1 do
  7060. if not(vo_is_hidden_para in tparavarsym(pd.paras[i]).varoptions) and
  7061. not is_array_of_const(tparavarsym(pd.paras[i]).vardef) then
  7062. dec(paracount);
  7063. if (paracount<>0) then
  7064. MessagePos(pd.fileinfo,sym_e_objc_para_mismatch);
  7065. pd.setmangledname(pd.objcmangledname);
  7066. end
  7067. else
  7068. { all checks already done }
  7069. exit;
  7070. if not(oo_is_external in pd.struct.objectoptions) then
  7071. begin
  7072. if (po_varargs in pd.procoptions) then
  7073. MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external)
  7074. else
  7075. begin
  7076. { check for "array of const" parameters }
  7077. for i:=0 to pd.parast.symlist.count-1 do
  7078. begin
  7079. if (tsym(pd.parast.symlist[i]).typ=paravarsym) and
  7080. is_array_of_const(tparavarsym(pd.parast.symlist[i]).vardef) then
  7081. MessagePos(pd.fileinfo,parser_e_varargs_need_cdecl_and_external);
  7082. end;
  7083. end;
  7084. end;
  7085. end;
  7086. end;
  7087. procedure mark_private_fields_used(data: tobject; arg: pointer);
  7088. var
  7089. sym: tsym absolute data;
  7090. begin
  7091. if (sym.typ=fieldvarsym) and
  7092. (tfieldvarsym(sym).visibility in [vis_private,vis_strictprivate]) then
  7093. sym.IncRefCount;
  7094. end;
  7095. procedure tobjectdef.finish_objc_data;
  7096. begin
  7097. self.symtable.DefList.foreachcall(@check_and_finish_msg,nil);
  7098. if (oo_is_external in objectoptions) then
  7099. self.symtable.SymList.ForEachCall(@mark_private_fields_used,nil);
  7100. end;
  7101. procedure verify_objc_vardef(data: tobject; arg: pointer);
  7102. var
  7103. sym: tabstractvarsym absolute data;
  7104. res: pboolean absolute arg;
  7105. founderrordef: tdef;
  7106. begin
  7107. if not(tsym(data).typ in [paravarsym,fieldvarsym]) then
  7108. exit;
  7109. if (sym.typ=paravarsym) and
  7110. ((vo_is_hidden_para in tparavarsym(sym).varoptions) or
  7111. is_array_of_const(tparavarsym(sym).vardef)) then
  7112. exit;
  7113. if not objcchecktype(sym.vardef,founderrordef) then
  7114. begin
  7115. MessagePos1(sym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);
  7116. res^:=false;
  7117. end;
  7118. end;
  7119. procedure verify_objc_procdef_paras(data: tobject; arg: pointer);
  7120. var
  7121. def: tdef absolute data;
  7122. res: pboolean absolute arg;
  7123. founderrordef: tdef;
  7124. begin
  7125. if (def.typ<>procdef) then
  7126. exit;
  7127. { check parameter types for validity }
  7128. tprocdef(def).paras.foreachcall(@verify_objc_vardef,arg);
  7129. { check the result type for validity }
  7130. if not objcchecktype(tprocdef(def).returndef,founderrordef) then
  7131. begin
  7132. MessagePos1(tprocdef(def).funcretsym.fileinfo,type_e_objc_type_unsupported,founderrordef.typename);
  7133. res^:=false;
  7134. end;
  7135. end;
  7136. function tobjectdef.check_objc_types: boolean;
  7137. begin
  7138. { done in separate step from finish_objc_data, because when
  7139. finish_objc_data is called, not all forwarddefs have been resolved
  7140. yet and we need to know all types here }
  7141. result:=true;
  7142. self.symtable.symlist.foreachcall(@verify_objc_vardef,@result);
  7143. self.symtable.deflist.foreachcall(@verify_objc_procdef_paras,@result);
  7144. end;
  7145. procedure do_cpp_import_info(data: tobject; arg: pointer);
  7146. var
  7147. def: tdef absolute data;
  7148. pd: tprocdef absolute data;
  7149. begin
  7150. if (def.typ=procdef) then
  7151. begin
  7152. pd.setmangledname(target_info.Cprefix+pd.cplusplusmangledname);
  7153. if (oo_is_external in pd.struct.objectoptions) then
  7154. begin
  7155. { copied from psub.read_proc }
  7156. if assigned(tobjectdef(pd.struct).import_lib) then
  7157. current_module.AddExternalImport(tobjectdef(pd.struct).import_lib^,pd.mangledname,pd.mangledname,0,false,false)
  7158. else
  7159. begin
  7160. { add import name to external list for DLL scanning }
  7161. if tf_has_dllscanner in target_info.flags then
  7162. current_module.dllscannerinputlist.Add(pd.mangledname,pd);
  7163. end;
  7164. end;
  7165. end;
  7166. end;
  7167. procedure tobjectdef.finish_cpp_data;
  7168. begin
  7169. self.symtable.DefList.ForEachCall(@do_cpp_import_info,nil);
  7170. end;
  7171. {****************************************************************************
  7172. TImplementedInterface
  7173. ****************************************************************************}
  7174. function TImplementedInterface.GetIOffset: longint;
  7175. begin
  7176. if (fIOffset=-1) and
  7177. (IType in [etFieldValue,etFieldValueClass]) then
  7178. result:=tfieldvarsym(ImplementsField).fieldoffset
  7179. else
  7180. result:=fIOffset;
  7181. end;
  7182. constructor TImplementedInterface.create(aintf: tobjectdef);
  7183. begin
  7184. inherited create;
  7185. intfdef:=aintf;
  7186. intfdefderef.reset;
  7187. IOffset:=-1;
  7188. IType:=etStandard;
  7189. NameMappings:=nil;
  7190. procdefs:=nil;
  7191. end;
  7192. constructor TImplementedInterface.create_deref(intfd,getterd:tderef);
  7193. begin
  7194. inherited create;
  7195. intfdef:=nil;
  7196. intfdefderef:=intfd;
  7197. ImplementsGetterDeref:=getterd;
  7198. IOffset:=-1;
  7199. IType:=etStandard;
  7200. NameMappings:=nil;
  7201. procdefs:=nil;
  7202. end;
  7203. destructor TImplementedInterface.destroy;
  7204. var
  7205. i : longint;
  7206. mappedname : pshortstring;
  7207. begin
  7208. if assigned(NameMappings) then
  7209. begin
  7210. for i:=0 to NameMappings.Count-1 do
  7211. begin
  7212. mappedname:=pshortstring(NameMappings[i]);
  7213. stringdispose(mappedname);
  7214. end;
  7215. NameMappings.free;
  7216. NameMappings:=nil;
  7217. end;
  7218. if assigned(procdefs) then
  7219. begin
  7220. procdefs.free;
  7221. procdefs:=nil;
  7222. end;
  7223. inherited destroy;
  7224. end;
  7225. procedure TImplementedInterface.buildderef;
  7226. begin
  7227. intfdefderef.build(intfdef);
  7228. ImplementsGetterDeref.build(ImplementsGetter);
  7229. end;
  7230. procedure TImplementedInterface.deref;
  7231. begin
  7232. intfdef:=tobjectdef(intfdefderef.resolve);
  7233. ImplementsGetter:=tsym(ImplementsGetterDeref.resolve);
  7234. end;
  7235. procedure TImplementedInterface.AddMapping(const origname,newname: string);
  7236. begin
  7237. if not assigned(NameMappings) then
  7238. NameMappings:=TFPHashList.Create;
  7239. NameMappings.Add(origname,stringdup(newname));
  7240. end;
  7241. function TImplementedInterface.GetMapping(const origname: string):string;
  7242. var
  7243. mappedname : pshortstring;
  7244. begin
  7245. result:='';
  7246. if not assigned(NameMappings) then
  7247. exit;
  7248. mappedname:=PShortstring(NameMappings.Find(origname));
  7249. if assigned(mappedname) then
  7250. result:=mappedname^;
  7251. end;
  7252. procedure TImplementedInterface.AddImplProc(pd:tprocdef);
  7253. begin
  7254. if not assigned(procdefs) then
  7255. procdefs:=TFPObjectList.Create(false);
  7256. { duplicate entries must be stored, because multiple }
  7257. { interfaces can declare methods with the same name }
  7258. { and all of these get their own VMT entry }
  7259. procdefs.Add(pd);
  7260. end;
  7261. function TImplementedInterface.IsImplMergePossible(MergingIntf:TImplementedInterface;out weight: longint): boolean;
  7262. var
  7263. i : longint;
  7264. begin
  7265. result:=false;
  7266. { interfaces being implemented through delegation are not mergable (FK) }
  7267. if (IType<>etStandard) or (MergingIntf.IType<>etStandard) or not(assigned(ProcDefs)) or not(assigned(MergingIntf.ProcDefs)) then
  7268. exit;
  7269. weight:=0;
  7270. { empty interface is mergeable }
  7271. if ProcDefs.Count=0 then
  7272. begin
  7273. result:=true;
  7274. exit;
  7275. end;
  7276. { The interface to merge must at least the number of
  7277. procedures of this interface }
  7278. if MergingIntf.ProcDefs.Count<ProcDefs.Count then
  7279. exit;
  7280. for i:=0 to ProcDefs.Count-1 do
  7281. begin
  7282. if MergingIntf.ProcDefs[i]<>ProcDefs[i] then
  7283. exit;
  7284. end;
  7285. weight:=ProcDefs.Count;
  7286. result:=true;
  7287. end;
  7288. function TImplementedInterface.getcopy:TImplementedInterface;
  7289. begin
  7290. Result:=TImplementedInterface.Create(nil);
  7291. { 1) the procdefs list will be freed once for each copy
  7292. 2) since the procdefs list owns its elements, those will also be freed for each copy
  7293. 3) idem for the name mappings
  7294. }
  7295. { warning: this is completely wrong on so many levels...
  7296. Move(pointer(self)^,pointer(result)^,InstanceSize);
  7297. We need to make clean copies of the different fields
  7298. this is not implemented yet, and thus we generate an internal
  7299. error instead PM 2011-06-14 }
  7300. internalerror(2011061401);
  7301. end;
  7302. {****************************************************************************
  7303. TFORWARDDEF
  7304. ****************************************************************************}
  7305. constructor tforwarddef.create(const s:string;const pos:tfileposinfo);
  7306. begin
  7307. inherited create(forwarddef,true);
  7308. tosymname:=stringdup(s);
  7309. forwardpos:=pos;
  7310. end;
  7311. function tforwarddef.GetTypeName:string;
  7312. begin
  7313. GetTypeName:='unresolved forward to '+tosymname^;
  7314. end;
  7315. destructor tforwarddef.destroy;
  7316. begin
  7317. stringdispose(tosymname);
  7318. inherited destroy;
  7319. end;
  7320. function tforwarddef.getcopy:tstoreddef;
  7321. begin
  7322. result:=cforwarddef.create(tosymname^, forwardpos);
  7323. end;
  7324. {****************************************************************************
  7325. TUNDEFINEDDEF
  7326. ****************************************************************************}
  7327. constructor tundefineddef.create(doregister:boolean);
  7328. begin
  7329. inherited create(undefineddef,doregister);
  7330. end;
  7331. constructor tundefineddef.ppuload(ppufile:tcompilerppufile);
  7332. begin
  7333. inherited ppuload(undefineddef,ppufile);
  7334. ppuload_platform(ppufile);
  7335. end;
  7336. function tundefineddef.GetTypeName:string;
  7337. begin
  7338. GetTypeName:='<undefined type>';
  7339. end;
  7340. procedure tundefineddef.ppuwrite(ppufile:tcompilerppufile);
  7341. begin
  7342. inherited ppuwrite(ppufile);
  7343. writeentry(ppufile,ibundefineddef);
  7344. end;
  7345. {****************************************************************************
  7346. TERRORDEF
  7347. ****************************************************************************}
  7348. constructor terrordef.create;
  7349. begin
  7350. inherited create(errordef,true);
  7351. { prevent consecutive faults }
  7352. savesize:=1;
  7353. end;
  7354. procedure terrordef.ppuwrite(ppufile:tcompilerppufile);
  7355. begin
  7356. { Can't write errordefs to ppu }
  7357. internalerror(200411063);
  7358. end;
  7359. function terrordef.GetTypeName:string;
  7360. begin
  7361. GetTypeName:='<erroneous type>';
  7362. end;
  7363. function terrordef.getmangledparaname:TSymStr;
  7364. begin
  7365. getmangledparaname:='error';
  7366. end;
  7367. {****************************************************************************
  7368. Definition Helpers
  7369. ****************************************************************************}
  7370. function is_interfacecom(def: tdef): boolean;
  7371. begin
  7372. is_interfacecom:=
  7373. assigned(def) and
  7374. (def.typ=objectdef) and
  7375. (tobjectdef(def).objecttype=odt_interfacecom);
  7376. end;
  7377. function is_interfacecom_or_dispinterface(def: tdef): boolean;
  7378. begin
  7379. is_interfacecom_or_dispinterface:=
  7380. assigned(def) and
  7381. (def.typ=objectdef) and
  7382. (tobjectdef(def).objecttype in [odt_interfacecom,odt_dispinterface]);
  7383. end;
  7384. function is_any_interface_kind(def: tdef): boolean;
  7385. begin
  7386. result:=
  7387. assigned(def) and
  7388. (def.typ=objectdef) and
  7389. ((tobjectdef(def).objecttype in [odt_interfacecom,odt_dispinterface,odt_interfacecorba,odt_interfacejava,odt_objcprotocol]) or
  7390. is_objccategory(def));
  7391. end;
  7392. function is_interfacecorba(def: tdef): boolean;
  7393. begin
  7394. is_interfacecorba:=
  7395. assigned(def) and
  7396. (def.typ=objectdef) and
  7397. (tobjectdef(def).objecttype=odt_interfacecorba);
  7398. end;
  7399. function is_interface(def: tdef): boolean;
  7400. begin
  7401. is_interface:=
  7402. assigned(def) and
  7403. (def.typ=objectdef) and
  7404. (tobjectdef(def).objecttype in [odt_interfacecom,odt_interfacecorba]);
  7405. end;
  7406. function is_dispinterface(def: tdef): boolean;
  7407. begin
  7408. result:=
  7409. assigned(def) and
  7410. (def.typ=objectdef) and
  7411. (tobjectdef(def).objecttype=odt_dispinterface);
  7412. end;
  7413. function is_class(def: tdef): boolean;
  7414. begin
  7415. is_class:=
  7416. assigned(def) and
  7417. (def.typ=objectdef) and
  7418. (tobjectdef(def).objecttype=odt_class);
  7419. end;
  7420. function is_object(def: tdef): boolean;
  7421. begin
  7422. is_object:=
  7423. assigned(def) and
  7424. (def.typ=objectdef) and
  7425. (tobjectdef(def).objecttype=odt_object);
  7426. end;
  7427. function is_cppclass(def: tdef): boolean;
  7428. begin
  7429. is_cppclass:=
  7430. assigned(def) and
  7431. (def.typ=objectdef) and
  7432. (tobjectdef(def).objecttype=odt_cppclass);
  7433. end;
  7434. function is_objcclass(def: tdef): boolean;
  7435. begin
  7436. is_objcclass:=
  7437. assigned(def) and
  7438. (def.typ=objectdef) and
  7439. (tobjectdef(def).objecttype=odt_objcclass);
  7440. end;
  7441. function is_objectpascal_helper(def: tdef): boolean;
  7442. begin
  7443. result:=
  7444. assigned(def) and
  7445. (def.typ=objectdef) and
  7446. (tobjectdef(def).objecttype=odt_helper);
  7447. end;
  7448. function is_objcclassref(def: tdef): boolean;
  7449. begin
  7450. is_objcclassref:=
  7451. assigned(def) and
  7452. (def.typ=classrefdef) and
  7453. is_objcclass(tclassrefdef(def).pointeddef);
  7454. end;
  7455. function is_objcprotocol(def: tdef): boolean;
  7456. begin
  7457. result:=
  7458. assigned(def) and
  7459. (def.typ=objectdef) and
  7460. (tobjectdef(def).objecttype=odt_objcprotocol);
  7461. end;
  7462. function is_objccategory(def: tdef): boolean;
  7463. begin
  7464. result:=
  7465. assigned(def) and
  7466. (def.typ=objectdef) and
  7467. { if used as a forward type }
  7468. ((tobjectdef(def).objecttype=odt_objccategory) or
  7469. { if used as after it has been resolved }
  7470. ((tobjectdef(def).objecttype=odt_objcclass) and
  7471. (oo_is_classhelper in tobjectdef(def).objectoptions)));
  7472. end;
  7473. function is_objc_class_or_protocol(def: tdef): boolean;
  7474. begin
  7475. result:=
  7476. assigned(def) and
  7477. (def.typ=objectdef) and
  7478. (tobjectdef(def).objecttype in [odt_objcclass,odt_objcprotocol]);
  7479. end;
  7480. function is_objc_protocol_or_category(def: tdef): boolean;
  7481. begin
  7482. result:=
  7483. assigned(def) and
  7484. (def.typ=objectdef) and
  7485. ((tobjectdef(def).objecttype = odt_objcprotocol) or
  7486. ((tobjectdef(def).objecttype = odt_objcclass) and
  7487. (oo_is_classhelper in tobjectdef(def).objectoptions)));
  7488. end;
  7489. function is_classhelper(def: tdef): boolean;
  7490. begin
  7491. result:=
  7492. is_objectpascal_helper(def) or
  7493. is_objccategory(def);
  7494. end;
  7495. function is_class_or_interface(def: tdef): boolean;
  7496. begin
  7497. result:=
  7498. assigned(def) and
  7499. (def.typ=objectdef) and
  7500. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba]);
  7501. end;
  7502. function is_class_or_interface_or_objc(def: tdef): boolean;
  7503. begin
  7504. result:=
  7505. assigned(def) and
  7506. (def.typ=objectdef) and
  7507. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_objcclass,odt_objcprotocol]);
  7508. end;
  7509. function is_class_or_interface_or_objc_or_java(def: tdef): boolean;
  7510. begin
  7511. result:=
  7512. assigned(def) and
  7513. (def.typ=objectdef) and
  7514. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava]);
  7515. end;
  7516. function is_class_or_interface_or_dispinterface_or_objc_or_java(def: tdef): boolean;
  7517. begin
  7518. result:=
  7519. assigned(def) and
  7520. (def.typ=objectdef) and
  7521. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_javaclass,odt_interfacejava]);
  7522. end;
  7523. function is_class_or_interface_or_object(def: tdef): boolean;
  7524. begin
  7525. result:=
  7526. assigned(def) and
  7527. (def.typ=objectdef) and
  7528. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_object]);
  7529. end;
  7530. function is_class_or_interface_or_dispinterface(def: tdef): boolean;
  7531. begin
  7532. result:=
  7533. assigned(def) and
  7534. (def.typ=objectdef) and
  7535. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface]);
  7536. end;
  7537. function is_implicit_pointer_object_type(def: tdef): boolean;
  7538. begin
  7539. result:=
  7540. assigned(def) and
  7541. (((def.typ=objectdef) and
  7542. (tobjectdef(def).objecttype in [odt_class,odt_interfacecom,odt_interfacecorba,odt_dispinterface,odt_objcclass,odt_objcprotocol,odt_helper,odt_javaclass,odt_interfacejava])) or
  7543. ((target_info.system in systems_jvm) and
  7544. (def.typ=recorddef)));
  7545. end;
  7546. function is_implicit_array_pointer(def: tdef): boolean;
  7547. begin
  7548. result:=is_dynamic_array(def) or is_dynamicstring(def);
  7549. end;
  7550. function is_class_or_object(def: tdef): boolean;
  7551. begin
  7552. result:=
  7553. assigned(def) and
  7554. (def.typ=objectdef) and
  7555. (tobjectdef(def).objecttype in [odt_class,odt_object]);
  7556. end;
  7557. function is_record(def: tdef): boolean;
  7558. begin
  7559. result:=
  7560. assigned(def) and
  7561. (def.typ=recorddef);
  7562. end;
  7563. function is_javaclass(def: tdef): boolean;
  7564. begin
  7565. result:=
  7566. assigned(def) and
  7567. (def.typ=objectdef) and
  7568. (tobjectdef(def).objecttype=odt_javaclass);
  7569. end;
  7570. function is_javaclassref(def: tdef): boolean;
  7571. begin
  7572. is_javaclassref:=
  7573. assigned(def) and
  7574. (def.typ=classrefdef) and
  7575. is_javaclass(tclassrefdef(def).pointeddef);
  7576. end;
  7577. function is_javainterface(def: tdef): boolean;
  7578. begin
  7579. result:=
  7580. assigned(def) and
  7581. (def.typ=objectdef) and
  7582. (tobjectdef(def).objecttype=odt_interfacejava);
  7583. end;
  7584. function is_java_class_or_interface(def: tdef): boolean;
  7585. begin
  7586. result:=
  7587. assigned(def) and
  7588. (def.typ=objectdef) and
  7589. (tobjectdef(def).objecttype in [odt_javaclass,odt_interfacejava]);
  7590. end;
  7591. procedure loadobjctypes;
  7592. begin
  7593. objc_metaclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_CLASS',true).typedef);
  7594. objc_superclasstype:=tpointerdef(search_named_unit_globaltype('OBJC','POBJC_SUPER',true).typedef);
  7595. objc_idtype:=tpointerdef(search_named_unit_globaltype('OBJC','ID',true).typedef);
  7596. objc_seltype:=tpointerdef(search_named_unit_globaltype('OBJC','SEL',true).typedef);
  7597. objc_objecttype:=trecorddef(search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef);
  7598. end;
  7599. procedure maybeloadcocoatypes;
  7600. var
  7601. tsym: ttypesym;
  7602. cocoaunit: string[15];
  7603. begin
  7604. if assigned(objc_fastenumeration) then
  7605. exit;
  7606. if not(target_info.system in [system_arm_darwin,system_i386_iphonesim,system_aarch64_darwin,system_x86_64_iphonesim]) then
  7607. cocoaunit:='COCOAALL'
  7608. else
  7609. cocoaunit:='IPHONEALL';
  7610. tsym:=search_named_unit_globaltype(cocoaunit,'NSFASTENUMERATIONPROTOCOL',false);
  7611. if assigned(tsym) then
  7612. objc_fastenumeration:=tobjectdef(tsym.typedef)
  7613. else
  7614. objc_fastenumeration:=nil;
  7615. tsym:=search_named_unit_globaltype(cocoaunit,'NSFASTENUMERATIONSTATE',false);
  7616. if assigned(tsym) then
  7617. objc_fastenumerationstate:=trecorddef(tsym.typedef)
  7618. else
  7619. objc_fastenumerationstate:=nil;
  7620. end;
  7621. function use_vectorfpu(def : tdef) : boolean;
  7622. begin
  7623. {$ifdef x86}
  7624. {$define use_vectorfpuimplemented}
  7625. use_vectorfpu:=(is_single(def) and (current_settings.fputype in sse_singlescalar)) or
  7626. (is_double(def) and (current_settings.fputype in sse_doublescalar));
  7627. {$endif x86}
  7628. {$ifdef arm}
  7629. {$define use_vectorfpuimplemented}
  7630. use_vectorfpu:=(current_settings.fputype in vfp_scalar);
  7631. {$endif arm}
  7632. {$ifdef aarch64}
  7633. {$define use_vectorfpuimplemented}
  7634. use_vectorfpu:=true;
  7635. {$endif aarch64}
  7636. {$ifndef use_vectorfpuimplemented}
  7637. use_vectorfpu:=false;
  7638. {$endif}
  7639. end;
  7640. end.