symdef.pas 284 KB

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