1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122 |
- {
- $Id$
- Copyright (c) 1996-98 by Florian Klaempfl
- This unit implements the first pass of the code generator
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- {$ifdef tp}
- {$F+}
- {$endif tp}
- unit pass_1;
- interface
- uses tree;
- function do_firstpass(var p : ptree) : boolean;
- implementation
- uses
- cobjects,verbose,systems,globals,aasm,symtable,
- types,strings,hcodegen,files
- {$ifdef i386}
- ,i386
- ,tgeni386
- {$endif}
- {$ifdef m68k}
- ,m68k
- ,tgen68k
- {$endif}
- {$ifdef UseBrowser}
- ,browser
- {$endif UseBrowser}
- ;
- { firstcallparan without varspez
- we don't count the ref }
- const
- count_ref : boolean = true;
- procedure message(const t : tmsgconst);
- var
- olderrorcount : longint;
- begin
- if not(codegenerror) then
- begin
- olderrorcount:=errorcount;
- verbose.Message(t);
- codegenerror:=olderrorcount<>errorcount;
- end;
- end;
- procedure message1(const t : tmsgconst;const s : string);
- var
- olderrorcount : longint;
- begin
- if not(codegenerror) then
- begin
- olderrorcount:=errorcount;
- verbose.Message1(t,s);
- codegenerror:=olderrorcount<>errorcount;
- end;
- end;
- procedure message2(const t : tmsgconst;const s1,s2 : string);
- var
- olderrorcount : longint;
- begin
- if not(codegenerror) then
- begin
- olderrorcount:=errorcount;
- verbose.Message2(t,s1,s2);
- codegenerror:=olderrorcount<>errorcount;
- end;
- end;
- procedure message3(const t : tmsgconst;const s1,s2,s3 : string);
- var
- olderrorcount : longint;
- begin
- if not(codegenerror) then
- begin
- olderrorcount:=errorcount;
- verbose.Message3(t,s1,s2,s3);
- codegenerror:=olderrorcount<>errorcount;
- end;
- end;
- procedure firstpass(var p : ptree);forward;
- { marks an lvalue as "unregable" }
- procedure make_not_regable(p : ptree);
- begin
- case p^.treetype of
- typeconvn : make_not_regable(p^.left);
- loadn : if p^.symtableentry^.typ=varsym then
- pvarsym(p^.symtableentry)^.regable:=false;
- end;
- end;
- { calculates the needed registers for a binary operator }
- procedure calcregisters(p : ptree;r32,fpu,mmx : word);
- begin
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- { Nur wenn links und rechts ein Unterschied < ben”tige Anzahl ist, }
- { wird ein zus„tzliches Register ben”tigt, da es dann keinen }
- { schwierigeren Ast gibt, welcher erst ausgewertet werden kann }
- if (abs(p^.left^.registers32-p^.right^.registers32)<r32) then
- inc(p^.registers32,r32);
- if (abs(p^.left^.registersfpu-p^.right^.registersfpu)<fpu) then
- inc(p^.registersfpu,fpu);
- {$ifdef SUPPORT_MMX}
- if (abs(p^.left^.registersmmx-p^.right^.registersmmx)<mmx) then
- inc(p^.registersmmx,mmx);
- {$endif SUPPORT_MMX}
- { error message, if more than 8 floating point }
- { registers are needed }
- if p^.registersfpu>8 then
- Message(cg_e_too_complex_expr);
- end;
- function both_rm(p : ptree) : boolean;
- begin
- both_rm:=(p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
- (p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE]);
- end;
- function isconvertable(def_from,def_to : pdef;
- var doconv : tconverttype;fromtreetype : ttreetyp) : boolean;
- { from_is_cstring muá true sein, wenn def_from die Definition einer }
- { Stringkonstanten ist, n”tig wegen der Konvertierung von String- }
- { konstante zu nullterminiertem String }
- { Hilfsliste: u8bit,s32bit,uvoid,
- bool8bit,uchar,s8bit,s16bit,u16bit,u32bit }
- const
- basedefconverts : array[u8bit..u32bit,u8bit..u32bit] of tconverttype =
- {u8bit}
- ((tc_only_rangechecks32bit,tc_u8bit_2_s32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_only_rangechecks32bit,tc_u8bit_2_s16bit,
- tc_u8bit_2_u16bit,{tc_not_possible}tc_u8bit_2_u32bit),
- {s32bit}
- (tc_s32bit_2_u8bit,tc_only_rangechecks32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_s32bit_2_s8bit,
- tc_s32bit_2_s16bit,tc_s32bit_2_u16bit,{tc_not_possible}tc_s32bit_2_u32bit),
- {uvoid}
- (tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_not_possible,tc_not_possible,
- tc_not_possible),
- {bool8bit}
- (tc_not_possible,tc_not_possible,tc_not_possible,
- tc_only_rangechecks32bit,tc_not_possible,tc_not_possible,tc_not_possible,
- tc_not_possible,tc_not_possible),
- {uchar}
- (tc_not_possible,tc_not_possible,tc_not_possible,
- tc_not_possible,tc_only_rangechecks32bit,tc_not_possible,tc_not_possible,
- tc_not_possible,tc_not_possible),
- {s8bit}
- (tc_only_rangechecks32bit,tc_s8bit_2_s32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_only_rangechecks32bit,tc_s8bit_2_s16bit,
- tc_s8bit_2_u16bit,{tc_not_possible}tc_s8bit_2_u32bit),
- {s16bit}
- (tc_s16bit_2_u8bit,tc_s16bit_2_s32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_s16bit_2_s8bit,tc_only_rangechecks32bit,
- tc_only_rangechecks32bit,{tc_not_possible}tc_s8bit_2_u32bit),
- {u16bit}
- (tc_u16bit_2_u8bit,tc_u16bit_2_s32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_u16bit_2_s8bit,tc_only_rangechecks32bit,
- tc_only_rangechecks32bit,{tc_not_possible}tc_u16bit_2_u32bit),
- {u32bit}
- (tc_u32bit_2_u8bit,{tc_not_possible}tc_u32bit_2_s32bit,tc_not_possible,
- tc_not_possible,tc_not_possible,tc_u32bit_2_s8bit,tc_u32bit_2_s16bit,
- tc_u32bit_2_u16bit,tc_only_rangechecks32bit)
- );
- var
- b : boolean;
- begin
- b:=false;
- if (not assigned(def_from)) or (not assigned(def_to)) then
- begin
- isconvertable:=false;
- exit;
- end;
- if (def_from^.deftype=orddef) and (def_to^.deftype=orddef) then
- begin
- doconv:=basedefconverts[porddef(def_from)^.typ,porddef(def_to)^.typ];
- if doconv<>tc_not_possible then
- b:=true;
- end
- else if (def_from^.deftype=orddef) and (def_to^.deftype=floatdef) then
- begin
- if pfloatdef(def_to)^.typ=f32bit then
- doconv:=tc_int_2_fix
- else
- doconv:=tc_int_2_real;
- b:=true;
- end
- else if (def_from^.deftype=floatdef) and (def_to^.deftype=floatdef) then
- begin
- if pfloatdef(def_from)^.typ=pfloatdef(def_to)^.typ then
- doconv:=tc_equal
- else
- begin
- if pfloatdef(def_from)^.typ=f32bit then
- doconv:=tc_fix_2_real
- else if pfloatdef(def_to)^.typ=f32bit then
- doconv:=tc_real_2_fix
- else
- doconv:=tc_real_2_real;
- { comp isn't a floating type }
- {$ifdef i386}
- if (pfloatdef(def_to)^.typ=s64bit) then
- Message(parser_w_convert_real_2_comp);
- {$endif}
- end;
- b:=true;
- end
- else if (def_from^.deftype=pointerdef) and (def_to^.deftype=arraydef) and
- (parraydef(def_to)^.lowrange=0) and
- is_equal(ppointerdef(def_from)^.definition,
- parraydef(def_to)^.definition) then
- begin
- doconv:=tc_pointer_to_array;
- b:=true;
- end
- else if (def_from^.deftype=arraydef) and (def_to^.deftype=pointerdef) and
- (parraydef(def_from)^.lowrange=0) and
- is_equal(parraydef(def_from)^.definition,
- ppointerdef(def_to)^.definition) then
- begin
- doconv:=tc_array_to_pointer;
- b:=true;
- end
- { typed files are all equal to the abstract file type
- name TYPEDFILE in system.pp in is_equal in types.pas
- the problem is that it sholud be also compatible to FILE
- but this would leed to a problem for ASSIGN RESET and REWRITE
- when trying to find the good overloaded function !!
- so all file function are doubled in system.pp
- this is not very beautiful !!}
- else if (def_from^.deftype=filedef) and (def_to^.deftype=filedef) and
- (
- (
- (pfiledef(def_from)^.filetype = ft_typed) and
- (pfiledef(def_to)^.filetype = ft_typed) and
- (
- (pfiledef(def_from)^.typed_as = pdef(voiddef)) or
- (pfiledef(def_to)^.typed_as = pdef(voiddef))
- )
- ) or
- (
- (
- (pfiledef(def_from)^.filetype = ft_untyped) and
- (pfiledef(def_to)^.filetype = ft_typed)
- ) or
- (
- (pfiledef(def_from)^.filetype = ft_typed) and
- (pfiledef(def_to)^.filetype = ft_untyped)
- )
- )
- ) then
- begin
- doconv:=tc_equal;
- b:=true;
- end
- { object pascal objects }
- else if (def_from^.deftype=objectdef) and (def_to^.deftype=objectdef) and
- pobjectdef(def_from)^.isclass and pobjectdef(def_to)^.isclass then
- begin
- doconv:=tc_equal;
- b:=pobjectdef(def_from)^.isrelated(
- pobjectdef(def_to));
- end
- { class reference types }
- else if (def_from^.deftype=classrefdef) and (def_from^.deftype=classrefdef) then
- begin
- doconv:=tc_equal;
- b:=pobjectdef(pclassrefdef(def_from)^.definition)^.isrelated(
- pobjectdef(pclassrefdef(def_to)^.definition));
- end
- else if (def_from^.deftype=pointerdef) and (def_to^.deftype=pointerdef) then
- begin
- { child class pointer can be assigned to anchestor pointers }
- if (
- (ppointerdef(def_from)^.definition^.deftype=objectdef) and
- (ppointerdef(def_to)^.definition^.deftype=objectdef) and
- pobjectdef(ppointerdef(def_from)^.definition)^.isrelated(
- pobjectdef(ppointerdef(def_to)^.definition))
- ) or
- { all pointers can be assigned to void-pointer }
- is_equal(ppointerdef(def_to)^.definition,voiddef) or
- { in my opnion, is this not clean pascal }
- { well, but it's handy to use, it isn't ? (FK) }
- is_equal(ppointerdef(def_from)^.definition,voiddef) then
- begin
- doconv:=tc_equal;
- b:=true;
- end
- end
- else
- if (def_from^.deftype=stringdef) and (def_to^.deftype=stringdef) then
- begin
- doconv:=tc_string_to_string;
- b:=true;
- end
- else
- { char to string}
- if is_equal(def_from,cchardef) and
- (def_to^.deftype=stringdef) then
- begin
- doconv:=tc_char_to_string;
- b:=true;
- end
- else
- { string constant to zero terminated string constant }
- if (fromtreetype=stringconstn) and
- (
- (def_to^.deftype=pointerdef) and
- is_equal(Ppointerdef(def_to)^.definition,cchardef)
- ) then
- begin
- doconv:=tc_cstring_charpointer;
- b:=true;
- end
- else
- { array of char to string }
- { the length check is done by the firstpass of this node }
- if (def_from^.deftype=stringdef) and
- (
- (def_to^.deftype=arraydef) and
- is_equal(parraydef(def_to)^.definition,cchardef)
- ) then
- begin
- doconv:=tc_string_chararray;
- b:=true;
- end
- else
- { string to array of char }
- { the length check is done by the firstpass of this node }
- if (
- (def_from^.deftype=arraydef) and
- is_equal(parraydef(def_from)^.definition,cchardef)
- ) and
- (def_to^.deftype=stringdef) then
- begin
- doconv:=tc_chararray_2_string;
- b:=true;
- end
- else
- if (fromtreetype=ordconstn) and is_equal(def_from,cchardef) then
- begin
- if (def_to^.deftype=pointerdef) and
- is_equal(ppointerdef(def_to)^.definition,cchardef) then
- begin
- doconv:=tc_cchar_charpointer;
- b:=true;
- end;
- end
- else
- if (def_to^.deftype=procvardef) and (def_from^.deftype=procdef) then
- begin
- def_from^.deftype:=procvardef;
- doconv:=tc_proc2procvar;
- b:=is_equal(def_from,def_to);
- def_from^.deftype:=procdef;
- end
- else
- { nil is compatible with class instances }
- if (fromtreetype=niln) and (def_to^.deftype=objectdef)
- and (pobjectdef(def_to)^.isclass) then
- begin
- doconv:=tc_equal;
- b:=true;
- end
- else
- { nil is compatible with class references }
- if (fromtreetype=niln) and (def_to^.deftype=classrefdef) then
- begin
- doconv:=tc_equal;
- b:=true;
- end
- else
- { nil is compatible with procvars }
- if (fromtreetype=niln) and (def_to^.deftype=procvardef) then
- begin
- doconv:=tc_equal;
- b:=true;
- end
- { procedure variable can be assigned to an void pointer }
- { Not anymore. Use the @ operator now.}
- else
- if not (cs_tp_compatible in aktswitches) then
- begin
- if (def_from^.deftype=procvardef) and
- (def_to^.deftype=pointerdef) and
- (ppointerdef(def_to)^.definition^.deftype=orddef) and
- (porddef(ppointerdef(def_to)^.definition)^.typ=uvoid) then
- begin
- doconv:=tc_equal;
- b:=true;
- end;
- end;
- isconvertable:=b;
- end;
- procedure firsterror(var p : ptree);
- begin
- p^.error:=true;
- codegenerror:=true;
- p^.resulttype:=generrordef;
- end;
- procedure firstload(var p : ptree);
- begin
- p^.location.loc:=LOC_REFERENCE;
- p^.registers32:=0;
- p^.registersfpu:=0;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=0;
- {$endif SUPPORT_MMX}
- clear_reference(p^.location.reference);
- {$ifdef TEST_FUNCRET}
- if p^.symtableentry^.typ=funcretsym then
- begin
- putnode(p);
- p:=genzeronode(funcretn);
- p^.funcretprocinfo:=pprocinfo(pfuncretsym(p^.symtableentry)^.funcretprocinfo);
- p^.retdef:=pfuncretsym(p^.symtableentry)^.retdef;
- firstpass(p);
- exit;
- end;
- {$endif TEST_FUNCRET}
- if p^.symtableentry^.typ=absolutesym then
- begin
- p^.resulttype:=pabsolutesym(p^.symtableentry)^.definition;
- if pabsolutesym(p^.symtableentry)^.abstyp=tovar then
- p^.symtableentry:=pabsolutesym(p^.symtableentry)^.ref;
- p^.symtable:=p^.symtableentry^.owner;
- p^.is_absolute:=true;
- end;
- case p^.symtableentry^.typ of
- absolutesym :;
- varsym :
- begin
- if not(p^.is_absolute) and (p^.resulttype=nil) then
- p^.resulttype:=pvarsym(p^.symtableentry)^.definition;
- if ((p^.symtable^.symtabletype=parasymtable) or
- (p^.symtable^.symtabletype=localsymtable)) and
- (lexlevel>p^.symtable^.symtablelevel) then
- begin
- { sollte sich die Variable in einem anderen Stackframe }
- { befinden, so brauchen wir ein Register zum Dereferenceieren }
- if (p^.symtable^.symtablelevel)>0 then
- begin
- p^.registers32:=1;
- { auáerdem kann sie nicht mehr in ein Register
- geladen werden }
- pvarsym(p^.symtableentry)^.regable:=false;
- end;
- end;
- if (pvarsym(p^.symtableentry)^.varspez=vs_const) then
- p^.location.loc:=LOC_MEM;
- { we need a register for call by reference parameters }
- if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
- ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
- dont_copy_const_param(pvarsym(p^.symtableentry)^.definition)
- ) or
- { call by value open arrays are also indirect addressed }
- is_open_array(pvarsym(p^.symtableentry)^.definition) then
- p^.registers32:=1;
- if p^.symtable^.symtabletype=withsymtable then
- p^.registers32:=1;
- { a class variable is a pointer !!!
- yes, but we have to resolve the reference in an
- appropriate tree node (FK)
- if (pvarsym(p^.symtableentry)^.definition^.deftype=objectdef) and
- ((pobjectdef(pvarsym(p^.symtableentry)^.definition)^.options and oois_class)<>0) then
- p^.registers32:=1;
- }
- { count variable references }
- if must_be_valid and p^.is_first then
- begin
- if pvarsym(p^.symtableentry)^.is_valid=2 then
- if (assigned(pvarsym(p^.symtableentry)^.owner) and assigned(aktprocsym)
- and (pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst)) then
- Message1(sym_n_uninitialized_local_variable,pvarsym(p^.symtableentry)^.name);
- end;
- if count_ref then
- begin
- if (p^.is_first) then
- begin
- if (pvarsym(p^.symtableentry)^.is_valid=2) then
- pvarsym(p^.symtableentry)^.is_valid:=1;
- p^.is_first:=false;
- end;
- end;
- { this will create problem with local var set by
- under_procedures
- if (assigned(pvarsym(p^.symtableentry)^.owner) and assigned(aktprocsym)
- and ((pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst)
- or (pvarsym(p^.symtableentry)^.owner = aktprocsym^.definition^.localst))) then }
- if t_times<1 then
- inc(pvarsym(p^.symtableentry)^.refs)
- else
- inc(pvarsym(p^.symtableentry)^.refs,t_times);
- end;
- typedconstsym :
- if not p^.is_absolute then
- p^.resulttype:=ptypedconstsym(p^.symtableentry)^.definition;
- procsym :
- begin
- if assigned(pprocsym(p^.symtableentry)^.definition^.nextoverloaded) then
- Message(parser_e_no_overloaded_procvars);
- p^.resulttype:=pprocsym(p^.symtableentry)^.definition;
- end;
- else internalerror(3);
- end;
- end;
- procedure firstadd(var p : ptree);
- var
- lt,rt : ttreetyp;
- t : ptree;
- rv,lv : longint;
- rvd,lvd : {double}bestreal;
- rd,ld : pdef;
- concatstrings : boolean;
- { to evalute const sets }
- resultset : pconstset;
- i : longint;
- b : boolean;
- {$ifndef UseAnsiString}
- s1,s2:^string;
- {$else UseAnsiString}
- s1,s2 : pchar;
- l1,l2 : longint;
- {$endif UseAnsiString}
- { this totally forgets to set the pi_do_call flag !! }
- label
- no_overload;
- begin
- { first do the two subtrees }
- firstpass(p^.left);
- firstpass(p^.right);
- lt:=p^.left^.treetype;
- rt:=p^.right^.treetype;
- rd:=p^.right^.resulttype;
- ld:=p^.left^.resulttype;
- if codegenerror then
- exit;
- { overloaded operator ? }
- if (p^.treetype=caretn) or
- (ld^.deftype=recorddef) or
- { <> and = are defined for classes }
- ((ld^.deftype=objectdef) and
- (not(pobjectdef(ld)^.isclass) or
- not(p^.treetype in [equaln,unequaln])
- )
- ) or
- (rd^.deftype=recorddef) or
- { <> and = are defined for classes }
- ((rd^.deftype=objectdef) and
- (not(pobjectdef(rd)^.isclass) or
- not(p^.treetype in [equaln,unequaln])
- )
- ) then
- begin
- {!!!!!!!!! handle paras }
- case p^.treetype of
- { the nil as symtable signs firstcalln that this is
- an overloaded operator }
- addn:
- t:=gencallnode(overloaded_operators[plus],nil);
- subn:
- t:=gencallnode(overloaded_operators[minus],nil);
- muln:
- t:=gencallnode(overloaded_operators[star],nil);
- starstarn:
- t:=gencallnode(overloaded_operators[starstar],nil);
- slashn:
- t:=gencallnode(overloaded_operators[slash],nil);
- ltn:
- t:=gencallnode(overloaded_operators[globals.lt],nil);
- gtn:
- t:=gencallnode(overloaded_operators[gt],nil);
- lten:
- t:=gencallnode(overloaded_operators[lte],nil);
- gten:
- t:=gencallnode(overloaded_operators[gte],nil);
- equaln,unequaln :
- t:=gencallnode(overloaded_operators[equal],nil);
- else goto no_overload;
- end;
- { we have to convert p^.left and p^.right into
- callparanodes }
- t^.left:=gencallparanode(p^.left,nil);
- t^.left:=gencallparanode(p^.right,t^.left);
- if t^.symtableprocentry=nil then
- Message(parser_e_operator_not_overloaded);
- if p^.treetype=unequaln then
- t:=gensinglenode(notn,t);
- firstpass(t);
- putnode(p);
- p:=t;
- exit;
- end;
- no_overload:
- { compact consts }
- { convert int consts to real consts, if the }
- { other operand is a real const }
- if is_constintnode(p^.left) and
- (rt=realconstn) then
- begin
- t:=genrealconstnode(p^.left^.value);
- disposetree(p^.left);
- p^.left:=t;
- lt:=realconstn;
- end;
- if is_constintnode(p^.right) and
- (lt=realconstn) then
- begin
- t:=genrealconstnode(p^.right^.value);
- disposetree(p^.right);
- p^.right:=t;
- rt:=realconstn;
- end;
- if is_constintnode(p^.left) and
- is_constintnode(p^.right) then
- begin
- lv:=p^.left^.value;
- rv:=p^.right^.value;
- case p^.treetype of
- addn:
- t:=genordinalconstnode(lv+rv,s32bitdef);
- subn:
- t:=genordinalconstnode(lv-rv,s32bitdef);
- muln:
- t:=genordinalconstnode(lv*rv,s32bitdef);
- xorn:
- t:=genordinalconstnode(lv xor rv,s32bitdef);
- orn:
- t:=genordinalconstnode(lv or rv,s32bitdef);
- andn:
- t:=genordinalconstnode(lv and rv,s32bitdef);
- ltn:
- t:=genordinalconstnode(ord(lv<rv),booldef);
- lten:
- t:=genordinalconstnode(ord(lv<=rv),booldef);
- gtn:
- t:=genordinalconstnode(ord(lv>rv),booldef);
- gten:
- t:=genordinalconstnode(ord(lv>=rv),booldef);
- equaln:
- t:=genordinalconstnode(ord(lv=rv),booldef);
- unequaln:
- t:=genordinalconstnode(ord(lv<>rv),booldef);
- slashn :
- begin
- { int/int becomes a real }
- t:=genrealconstnode(int(lv)/int(rv));
- firstpass(t);
- end;
- else
- Message(sym_e_type_mismatch);
- end;
- disposetree(p);
- p:=t;
- exit;
- end
- else
- { real constants }
- if (lt=realconstn) and (rt=realconstn) then
- begin
- lvd:=p^.left^.valued;
- rvd:=p^.right^.valued;
- case p^.treetype of
- addn:
- t:=genrealconstnode(lvd+rvd);
- subn:
- t:=genrealconstnode(lvd-rvd);
- muln:
- t:=genrealconstnode(lvd*rvd);
- caretn:
- t:=genrealconstnode(exp(ln(lvd)*rvd));
- slashn:
- t:=genrealconstnode(lvd/rvd);
- ltn:
- t:=genordinalconstnode(ord(lvd<rvd),booldef);
- lten:
- t:=genordinalconstnode(ord(lvd<=rvd),booldef);
- gtn:
- t:=genordinalconstnode(ord(lvd>rvd),booldef);
- gten:
- t:=genordinalconstnode(ord(lvd>=rvd),booldef);
- equaln:
- t:=genordinalconstnode(ord(lvd=rvd),booldef);
- unequaln:
- t:=genordinalconstnode(ord(lvd<>rvd),booldef);
- else
- Message(sym_e_type_mismatch);
- end;
- disposetree(p);
- p:=t;
- firstpass(p);
- exit;
- end;
- concatstrings:=false;
- {$ifdef UseAnsiString}
- s1:=nil;
- s2:=nil;
- {$else UseAnsiString}
- new(s1);
- new(s2);
- {$endif UseAnsiString}
- if (lt=ordconstn) and (rt=ordconstn) and
- (ld^.deftype=orddef) and
- (porddef(ld)^.typ=uchar) and
- (rd^.deftype=orddef) and
- (porddef(rd)^.typ=uchar) then
- begin
- {$ifdef UseAnsiString}
- s1:=strpnew(char(byte(p^.left^.value)));
- s2:=strpnew(char(byte(p^.right^.value)));
- l1:=1;l2:=1;
- {$else UseAnsiString}
- s1^:=char(byte(p^.left^.value));
- s2^:=char(byte(p^.right^.value));
- concatstrings:=true;
- {$endif UseAnsiString}
- end
- else if (lt=stringconstn) and (rt=ordconstn) and
- (rd^.deftype=orddef) and
- (porddef(rd)^.typ=uchar) then
- begin
- {$ifdef UseAnsiString}
- { here there is allways the damn #0 problem !! }
- s1:=getpcharcopy(p^.left);
- l1:=p^.left^.length;
- s2:=strpnew(char(byte(p^.right^.value)));
- l2:=1;
- {$else UseAnsiString}
- s1^:=p^.left^.values^;
- s2^:=char(byte(p^.right^.value));
- concatstrings:=true;
- {$endif UseAnsiString}
- end
- else if (lt=ordconstn) and (rt=stringconstn) and
- (ld^.deftype=orddef) and
- (porddef(ld)^.typ=uchar) then
- begin
- {$ifdef UseAnsiString}
- { here there is allways the damn #0 problem !! }
- s1:=strpnew(char(byte(p^.left^.value)));
- l1:=1;
- s2:=getpcharcopy(p^.right);
- l2:=p^.right^.length;
- {$else UseAnsiString}
- s1^:=char(byte(p^.left^.value));
- s2^:=p^.right^.values^;
- concatstrings:=true;
- {$endif UseAnsiString}
- end
- else if (lt=stringconstn) and (rt=stringconstn) then
- begin
- {$ifdef UseAnsiString}
- s1:=getpcharcopy(p^.left);
- l1:=p^.left^.length;
- s2:=getpcharcopy(p^.right);
- l2:=p^.right^.length;
- concatstrings:=true;
- {$else UseAnsiString}
- s1^:=p^.left^.values^;
- s2^:=p^.right^.values^;
- concatstrings:=true;
- {$endif UseAnsiString}
- end;
- { I will need to translate all this to ansistrings !!! }
- if concatstrings then
- begin
- case p^.treetype of
- {$ifndef UseAnsiString}
- addn : t:=genstringconstnode(s1^+s2^);
- ltn : t:=genordinalconstnode(byte(s1^<s2^),booldef);
- lten : t:=genordinalconstnode(byte(s1^<=s2^),booldef);
- gtn : t:=genordinalconstnode(byte(s1^>s2^),booldef);
- gten : t:=genordinalconstnode(byte(s1^>=s2^),booldef);
- equaln : t:=genordinalconstnode(byte(s1^=s2^),booldef);
- unequaln : t:=genordinalconstnode(byte(s1^<>s2^),booldef);
- {$else UseAnsiString}
- addn : t:=genpcharconstnode(
- concatansistrings(s1,s2,l1,l2),l1+l2);
- ltn : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)<0),booldef);
- lten : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)<=0),booldef);
- gtn : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)>0),booldef);
- gten : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)>=0),booldef);
- equaln : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)=0),booldef);
- unequaln : t:=genordinalconstnode(
- byte(compareansistrings(s1,s2,l1,l2)<>0),booldef);
- {$endif UseAnsiString}
- end;
- {$ifdef UseAnsiString}
- ansistringdispose(s1,l1);
- ansistringdispose(s2,l2);
- {$else UseAnsiString}
- dispose(s1);
- dispose(s2);
- {$endif UseAnsiString}
- disposetree(p);
- p:=t;
- exit;
- end;
- {$ifdef UseAnsiString}
- ansistringdispose(s1,l1);
- ansistringdispose(s2,l2);
- {$else UseAnsiString}
- dispose(s1);
- dispose(s2);
- {$endif UseAnsiString}
- { we can set this globally but it not allways true }
- { procinfo.flags:=procinfo.flags or pi_do_call; }
- { if both are boolean: }
- if ((ld^.deftype=orddef) and
- (porddef(ld)^.typ=bool8bit)) and
- ((rd^.deftype=orddef) and
- (porddef(rd)^.typ=bool8bit)) then
- begin
- if (p^.treetype=andn) or (p^.treetype=orn) then
- begin
- calcregisters(p,0,0,0);
- p^.location.loc:=LOC_JUMP;
- end
- else if p^.treetype in [unequaln,equaln,xorn] then
- begin
- { I'am not very content with this solution, but it's
- a working hack (FK) }
- p^.left:=gentypeconvnode(p^.left,u8bitdef);
- p^.right:=gentypeconvnode(p^.right,u8bitdef);
- p^.left^.convtyp:=tc_bool_2_u8bit;
- p^.left^.explizit:=true;
- firstpass(p^.left);
- p^.left^.resulttype:=booldef;
- p^.right^.convtyp:=tc_bool_2_u8bit;
- p^.right^.explizit:=true;
- firstpass(p^.right);
- p^.right^.resulttype:=booldef;
- calcregisters(p,1,0,0);
- { is done commonly for all data types
- p^.location.loc:=LOC_FLAGS;
- p^.resulttype:=booldef;
- }
- end
- else Message(sym_e_type_mismatch);
- end
- { wenn beides vom Char dann keine Konvertiereung einf�gen }
- { h”chstens es handelt sich um einen +-Operator }
- else if ((rd^.deftype=orddef) and (porddef(rd)^.typ=uchar)) and
- ((ld^.deftype=orddef) and (porddef(ld)^.typ=uchar)) then
- begin
- if p^.treetype=addn then
- begin
- p^.left:=gentypeconvnode(p^.left,cstringdef);
- firstpass(p^.left);
- p^.right:=gentypeconvnode(p^.right,cstringdef);
- firstpass(p^.right);
- { here we call STRCOPY }
- procinfo.flags:=procinfo.flags or pi_do_call;
- calcregisters(p,0,0,0);
- p^.location.loc:=LOC_MEM;
- end
- else
- calcregisters(p,1,0,0);
- end
- { if string and character, then conver the character to a string }
- else if ((rd^.deftype=stringdef) and
- ((ld^.deftype=orddef) and (porddef(ld)^.typ=uchar))) or
- ((ld^.deftype=stringdef) and
- ((rd^.deftype=orddef) and (porddef(rd)^.typ=uchar))) then
- begin
- if ((ld^.deftype=orddef) and (porddef(ld)^.typ=uchar)) then
- p^.left:=gentypeconvnode(p^.left,cstringdef)
- else
- p^.right:=gentypeconvnode(p^.right,cstringdef);
- firstpass(p^.left);
- firstpass(p^.right);
- { here we call STRCONCAT or STRCMP }
- procinfo.flags:=procinfo.flags or pi_do_call;
- calcregisters(p,0,0,0);
- p^.location.loc:=LOC_MEM;
- end
- else
- if ((rd^.deftype=setdef) and (ld^.deftype=setdef)) then
- begin
- case p^.treetype of
- subn,symdifn,addn,muln,equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- if not(is_equal(rd,ld)) then
- Message(sym_e_set_element_are_not_comp);
- { why here its is alredy in entry of firstadd
- firstpass(p^.left);
- firstpass(p^.right); }
- { do constant evalution }
- { set constructor ? }
- if (p^.right^.treetype=setconstrn) and
- (p^.left^.treetype=setconstrn) and
- { and no variables ? }
- (p^.right^.left=nil) and
- (p^.left^.left=nil) then
- begin
- new(resultset);
- case p^.treetype of
- addn : begin
- for i:=0 to 31 do
- resultset^[i]:=
- p^.right^.constset^[i] or p^.left^.constset^[i];
- t:=gensetconstruktnode(resultset,psetdef(ld));
- end;
- muln : begin
- for i:=0 to 31 do
- resultset^[i]:=
- p^.right^.constset^[i] and p^.left^.constset^[i];
- t:=gensetconstruktnode(resultset,psetdef(ld));
- end;
- subn : begin
- for i:=0 to 31 do
- resultset^[i]:=
- p^.left^.constset^[i] and not(p^.right^.constset^[i]);
- t:=gensetconstruktnode(resultset,psetdef(ld));
- end;
- symdifn : begin
- for i:=0 to 31 do
- resultset^[i]:=
- p^.left^.constset^[i] xor p^.right^.constset^[i];
- t:=gensetconstruktnode(resultset,psetdef(ld));
- end;
- unequaln : begin
- b:=true;
- for i:=0 to 31 do
- if p^.right^.constset^[i]=p^.left^.constset^[i] then
- begin
- b:=false;
- break;
- end;
- t:=genordinalconstnode(ord(b),booldef);
- end;
- equaln : begin
- b:=true;
- for i:=0 to 31 do
- if p^.right^.constset^[i]<>p^.left^.constset^[i] then
- begin
- b:=false;
- break;
- end;
- t:=genordinalconstnode(ord(b),booldef);
- end;
- end;
- dispose(resultset);
- disposetree(p);
- p:=t;
- firstpass(p);
- exit;
- end
- else if psetdef(rd)^.settype=smallset then
- begin
- calcregisters(p,1,0,0);
- p^.location.loc:=LOC_REGISTER;
- end
- else
- begin
- calcregisters(p,0,0,0);
- { here we call SET... }
- procinfo.flags:=procinfo.flags or pi_do_call;
- p^.location.loc:=LOC_MEM;
- end;
- end
- else
- if ((rd^.deftype=stringdef) and (ld^.deftype=stringdef)) then
- { here we call STR... }
- procinfo.flags:=procinfo.flags or pi_do_call
- { if there is a real float, convert both to float 80 bit }
- else
- if ((rd^.deftype=floatdef) and (pfloatdef(rd)^.typ<>f32bit)) or
- ((ld^.deftype=floatdef) and (pfloatdef(ld)^.typ<>f32bit)) then
- begin
- p^.right:=gentypeconvnode(p^.right,c64floatdef);
- p^.left:=gentypeconvnode(p^.left,c64floatdef);
- firstpass(p^.left);
- firstpass(p^.right);
- calcregisters(p,1,1,0);
- p^.location.loc:=LOC_FPU;
- end
- else
- { if there is one fix comma number, convert both to 32 bit fixcomma }
- if ((rd^.deftype=floatdef) and (pfloatdef(rd)^.typ=f32bit)) or
- ((ld^.deftype=floatdef) and (pfloatdef(ld)^.typ=f32bit)) then
- begin
- if not(porddef(rd)^.typ in [u8bit,s8bit,u16bit,
- s16bit,s32bit]) or (p^.treetype<>muln) then
- p^.right:=gentypeconvnode(p^.right,s32fixeddef);
- if not(porddef(rd)^.typ in [u8bit,s8bit,u16bit,
- s16bit,s32bit]) or (p^.treetype<>muln) then
- p^.left:=gentypeconvnode(p^.left,s32fixeddef);
- firstpass(p^.left);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- p^.location.loc:=LOC_REGISTER;
- end
- { pointer comperation and subtraction }
- else if (rd^.deftype=pointerdef) and (ld^.deftype=pointerdef) then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.right:=gentypeconvnode(p^.right,ld);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- ltn,lten,gtn,gten:
- begin
- if not(cs_extsyntax in aktswitches) then
- Message(sym_e_type_mismatch);
- end;
- subn:
- begin
- if not(cs_extsyntax in aktswitches) then
- Message(sym_e_type_mismatch);
- p^.resulttype:=s32bitdef;
- exit;
- end;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (rd^.deftype=objectdef) and (ld^.deftype=objectdef) and
- pobjectdef(rd)^.isclass and pobjectdef(ld)^.isclass then
- begin
- p^.location.loc:=LOC_REGISTER;
- if pobjectdef(rd)^.isrelated(pobjectdef(ld)) then
- p^.right:=gentypeconvnode(p^.right,ld)
- else
- p^.left:=gentypeconvnode(p^.left,rd);
- firstpass(p^.right);
- firstpass(p^.left);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (rd^.deftype=classrefdef) and (ld^.deftype=classrefdef) then
- begin
- p^.location.loc:=LOC_REGISTER;
- if pobjectdef(pclassrefdef(rd)^.definition)^.isrelated(pobjectdef(
- pclassrefdef(ld)^.definition)) then
- p^.right:=gentypeconvnode(p^.right,ld)
- else
- p^.left:=gentypeconvnode(p^.left,rd);
- firstpass(p^.right);
- firstpass(p^.left);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- { allows comperasion with nil pointer }
- else if (rd^.deftype=objectdef) and
- pobjectdef(rd)^.isclass then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.left:=gentypeconvnode(p^.left,rd);
- firstpass(p^.left);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (ld^.deftype=objectdef) and
- pobjectdef(ld)^.isclass then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.right:=gentypeconvnode(p^.right,ld);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (rd^.deftype=classrefdef) then
- begin
- p^.left:=gentypeconvnode(p^.left,rd);
- firstpass(p^.left);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (ld^.deftype=classrefdef) then
- begin
- p^.right:=gentypeconvnode(p^.right,ld);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (rd^.deftype=pointerdef) then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- calcregisters(p,1,0,0);
- if p^.treetype=addn then
- begin
- if not(cs_extsyntax in aktswitches) then
- Message(sym_e_type_mismatch);
- end
- else Message(sym_e_type_mismatch);
- end
- else if (ld^.deftype=pointerdef) then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- case p^.treetype of
- addn,subn : if not(cs_extsyntax in aktswitches) then
- Message(sym_e_type_mismatch);
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (rd^.deftype=procvardef) and (ld^.deftype=procvardef) and
- is_equal(rd,ld) then
- begin
- calcregisters(p,1,0,0);
- p^.location.loc:=LOC_REGISTER;
- case p^.treetype of
- equaln,unequaln : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- else if (ld^.deftype=enumdef) and (rd^.deftype=enumdef)
- and (is_equal(ld,rd)) then
- begin
- calcregisters(p,1,0,0);
- case p^.treetype of
- equaln,unequaln,
- ltn,lten,gtn,gten : ;
- else Message(sym_e_type_mismatch);
- end;
- end
- {$ifdef SUPPORT_MMX}
- else if (cs_mmx in aktswitches) and is_mmx_able_array(ld)
- and is_mmx_able_array(rd) and is_equal(ld,rd) then
- begin
- firstpass(p^.right);
- firstpass(p^.left);
- case p^.treetype of
- addn,subn,xorn,orn,andn:
- ;
- { mul is a little bit restricted }
- muln:
- if not(mmx_type(p^.left^.resulttype) in
- [mmxu16bit,mmxs16bit,mmxfixed16]) then
- Message(sym_e_type_mismatch);
- else
- Message(sym_e_type_mismatch);
- end;
- p^.location.loc:=LOC_MMXREGISTER;
- calcregisters(p,0,0,1);
- end
- {$endif SUPPORT_MMX}
- { the general solution is to convert to 32 bit int }
- else
- begin
- { but an int/int gives real/real! }
- if p^.treetype=slashn then
- begin
- Message(parser_w_use_int_div_int_op);
- p^.right:=gentypeconvnode(p^.right,c64floatdef);
- p^.left:=gentypeconvnode(p^.left,c64floatdef);
- firstpass(p^.left);
- firstpass(p^.right);
- { maybe we need an integer register to save }
- { a reference }
- if ((p^.left^.location.loc<>LOC_FPU) or
- (p^.right^.location.loc<>LOC_FPU)) and
- (p^.left^.registers32=p^.right^.registers32) then
- calcregisters(p,1,1,0)
- else
- calcregisters(p,0,1,0);
- p^.location.loc:=LOC_FPU;
- end
- else
- begin
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- firstpass(p^.right);
- calcregisters(p,1,0,0);
- p^.location.loc:=LOC_REGISTER;
- end;
- end;
- if codegenerror then
- exit;
- { determines result type for comparions }
- case p^.treetype of
- ltn,lten,gtn,gten,equaln,unequaln:
- begin
- p^.resulttype:=booldef;
- p^.location.loc:=LOC_FLAGS;
- end;
- addn:
- begin
- { the result of a string addition is a string of length 255 }
- if (p^.left^.resulttype^.deftype=stringdef) or
- (p^.right^.resulttype^.deftype=stringdef) then
- begin
- {$ifndef UseAnsiString}
- p^.resulttype:=cstringdef
- {$else UseAnsiString}
- if is_ansistring(p^.left^.resulttype) or
- is_ansistring(p^.right^.resulttype) then
- p^.resulttype:=cansistringdef
- else
- p^.resulttype:=cstringdef;
- {$endif UseAnsiString}
- end
- else
- p^.resulttype:=p^.left^.resulttype;
- end;
- else p^.resulttype:=p^.left^.resulttype;
- end;
- end;
- procedure firstmoddiv(var p : ptree);
- var
- t : ptree;
- {power : longint; }
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- if is_constintnode(p^.left) and is_constintnode(p^.right) then
- begin
- case p^.treetype of
- modn : t:=genordinalconstnode(p^.left^.value mod p^.right^.value,s32bitdef);
- divn : t:=genordinalconstnode(p^.left^.value div p^.right^.value,s32bitdef);
- end;
- disposetree(p);
- p:=t;
- exit;
- end;
- { !!!!!! u32bit }
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- if p^.registers32<2 then p^.registers32:=2;
- p^.resulttype:=s32bitdef;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstshlshr(var p : ptree);
- var
- t : ptree;
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- if is_constintnode(p^.left) and is_constintnode(p^.right) then
- begin
- case p^.treetype of
- shrn : t:=genordinalconstnode(p^.left^.value shr p^.right^.value,s32bitdef);
- shln : t:=genordinalconstnode(p^.left^.value shl p^.right^.value,s32bitdef);
- end;
- disposetree(p);
- p:=t;
- exit;
- end;
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- calcregisters(p,2,0,0);
- {
- p^.registers32:=p^.left^.registers32;
- if p^.registers32<p^.right^.registers32 then
- p^.registers32:=p^.right^.registers32;
- if p^.registers32<1 then p^.registers32:=1;
- }
- p^.resulttype:=s32bitdef;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstrealconst(var p : ptree);
- begin
- p^.location.loc:=LOC_MEM;
- end;
- procedure firstfixconst(var p : ptree);
- begin
- p^.location.loc:=LOC_MEM;
- end;
- procedure firstordconst(var p : ptree);
- begin
- p^.location.loc:=LOC_MEM;
- end;
- procedure firstniln(var p : ptree);
- begin
- p^.resulttype:=voidpointerdef;
- p^.location.loc:=LOC_MEM;
- end;
- procedure firststringconst(var p : ptree);
- begin
- {$ifdef GDB}
- {why this !!! lost of dummy type definitions
- one per const string !!!
- p^.resulttype:=new(pstringdef,init(length(p^.values^)));}
- p^.resulttype:=cstringdef;
- {$Else GDB}
- p^.resulttype:=new(pstringdef,init(length(p^.values^)));
- {$endif * GDB *}
- p^.location.loc:=LOC_MEM;
- end;
- procedure firstumminus(var p : ptree);
- var
- t : ptree;
- minusdef : pprocdef;
- begin
- firstpass(p^.left);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- p^.resulttype:=p^.left^.resulttype;
- if codegenerror then
- exit;
- if is_constintnode(p^.left) then
- begin
- t:=genordinalconstnode(-p^.left^.value,s32bitdef);
- disposetree(p);
- firstpass(t);
- p:=t;
- exit;
- end;
- { nasm can not cope with negativ reals !! }
- if is_constrealnode(p^.left)
- {$ifdef i386}
- and not(current_module^.output_format in [of_nasm,of_obj])
- {$endif}
- then
- begin
- t:=genrealconstnode(-p^.left^.valued);
- disposetree(p);
- firstpass(t);
- p:=t;
- exit;
- end;
- if (p^.left^.resulttype^.deftype=floatdef) then
- begin
- if pfloatdef(p^.left^.resulttype)^.typ=f32bit then
- begin
- if (p^.left^.location.loc<>LOC_REGISTER) and
- (p^.registers32<1) then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end
- else
- p^.location.loc:=LOC_FPU;
- end
- {$ifdef SUPPORT_MMX}
- else if (cs_mmx in aktswitches) and
- is_mmx_able_array(p^.left^.resulttype) then
- begin
- if (p^.left^.location.loc<>LOC_MMXREGISTER) and
- (p^.registersmmx<1) then
- p^.registersmmx:=1;
- { if saturation is on, p^.left^.resulttype isn't
- "mmx able" (FK)
- if (cs_mmx_saturation in aktswitches^) and
- (porddef(parraydef(p^.resulttype)^.definition)^.typ in
- [s32bit,u32bit]) then
- Message(sym_e_type_mismatch);
- }
- end
- {$endif SUPPORT_MMX}
- else if (p^.left^.resulttype^.deftype=orddef) then
- begin
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- p^.registers32:=p^.left^.registers32;
- if codegenerror then
- exit;
- if (p^.left^.location.loc<>LOC_REGISTER) and
- (p^.registers32<1) then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- p^.resulttype:=p^.left^.resulttype;
- end
- else
- begin
- if assigned(overloaded_operators[minus]) then
- minusdef:=overloaded_operators[minus]^.definition
- else
- minusdef:=nil;
- while assigned(minusdef) do
- begin
- if (minusdef^.para1^.data=p^.left^.resulttype) and
- (minusdef^.para1^.next=nil) then
- begin
- t:=gencallnode(overloaded_operators[minus],nil);
- t^.left:=gencallparanode(p^.left,nil);
- putnode(p);
- p:=t;
- firstpass(p);
- exit;
- end;
- minusdef:=minusdef^.nextoverloaded;
- end;
- Message(sym_e_type_mismatch);
- end;
- end;
- procedure firstaddr(var p : ptree);
- var
- hp : ptree;
- hp2 : pdefcoll;
- store_valid : boolean;
- begin
- make_not_regable(p^.left);
- if not(assigned(p^.resulttype)) then
- begin
- if p^.left^.treetype=calln then
- begin
- hp:=genloadnode(pvarsym(p^.left^.symtableprocentry),p^.left^.symtableproc);
- { result is a procedure variable }
- { No, to be TP compatible, you must return a pointer to
- the procedure that is stored in the procvar.}
- if not(cs_tp_compatible in aktswitches) then
- begin
- p^.resulttype:=new(pprocvardef,init);
- pprocvardef(p^.resulttype)^.options:=
- p^.left^.symtableprocentry^.definition^.options;
- pprocvardef(p^.resulttype)^.retdef:=
- p^.left^.symtableprocentry^.definition^.retdef;
- hp2:=p^.left^.symtableprocentry^.definition^.para1;
- while assigned(hp2) do
- begin
- pprocvardef(p^.resulttype)^.concatdef(hp2^.data,hp2^.paratyp);
- hp2:=hp2^.next;
- end;
- end
- else
- p^.resulttype:=voidpointerdef;
- disposetree(p^.left);
- p^.left:=hp;
- end
- else
- begin
- if not(cs_typed_addresses in aktswitches) then
- p^.resulttype:=voidpointerdef
- else p^.resulttype:=new(ppointerdef,init(p^.left^.resulttype));
- end;
- end;
- store_valid:=must_be_valid;
- must_be_valid:=false;
- firstpass(p^.left);
- must_be_valid:=store_valid;
- if codegenerror then
- exit;
- { we should allow loc_mem for @string }
- if (p^.left^.location.loc<>LOC_REFERENCE) and
- (p^.left^.location.loc<>LOC_MEM) then
- Message(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstdoubleaddr(var p : ptree);
- var
- hp : ptree;
- hp2 : pdefcoll;
- begin
- make_not_regable(p^.left);
- firstpass(p^.left);
- if p^.resulttype=nil then
- p^.resulttype:=voidpointerdef;
- if (p^.left^.resulttype^.deftype)<>procvardef then
- Message(cg_e_illegal_expression);
- if codegenerror then
- exit;
- if (p^.left^.location.loc<>LOC_REFERENCE) then
- Message(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstnot(var p : ptree);
- var
- t : ptree;
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- if (p^.left^.treetype=ordconstn) then
- begin
- t:=genordinalconstnode(not(p^.left^.value),p^.left^.resulttype);
- disposetree(p);
- p:=t;
- exit;
- end;
- p^.resulttype:=p^.left^.resulttype;
- p^.location.loc:=p^.left^.location.loc;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if is_equal(p^.resulttype,booldef) then
- begin
- p^.registers32:=p^.left^.registers32;
- if ((p^.location.loc=LOC_REFERENCE) or
- (p^.location.loc=LOC_CREGISTER)) and
- (p^.registers32<1) then
- p^.registers32:=1;
- end
- else
- {$ifdef SUPPORT_MMX}
- if (cs_mmx in aktswitches) and
- is_mmx_able_array(p^.left^.resulttype) then
- begin
- if (p^.left^.location.loc<>LOC_MMXREGISTER) and
- (p^.registersmmx<1) then
- p^.registersmmx:=1;
- end
- else
- {$endif SUPPORT_MMX}
- begin
- p^.left:=gentypeconvnode(p^.left,s32bitdef);
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.resulttype:=p^.left^.resulttype;
- p^.registers32:=p^.left^.registers32;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if (p^.left^.location.loc<>LOC_REGISTER) and
- (p^.registers32<1) then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- p^.registersfpu:=p^.left^.registersfpu;
- end;
- procedure firstnothing(var p : ptree);
- begin
- p^.resulttype:=voiddef;
- end;
- procedure firstassignment(var p : ptree);
- var
- store_valid : boolean;
- hp : ptree;
- begin
- store_valid:=must_be_valid;
- must_be_valid:=false;
- firstpass(p^.left);
- { assignements to open arrays aren't allowed }
- if is_open_array(p^.left^.resulttype) then
- Message(sym_e_type_mismatch);
- { test if we can avoid copying string to temp
- as in s:=s+...; (PM) }
- {$ifdef dummyi386}
- if ((p^.right^.treetype=addn) or (p^.right^.treetype=subn)) and
- equal_trees(p^.left,p^.right^.left) and
- (ret_in_acc(p^.left^.resulttype)) and
- (not cs_rangechecking in aktswitches^) then
- begin
- disposetree(p^.right^.left);
- hp:=p^.right;
- p^.right:=p^.right^.right;
- if hp^.treetype=addn then
- p^.assigntyp:=at_plus
- else
- p^.assigntyp:=at_minus;
- putnode(hp);
- end;
- if p^.assigntyp<>at_normal then
- begin
- { for fpu type there is no faster way }
- if is_fpu(p^.left^.resulttype) then
- case p^.assigntyp of
- at_plus : p^.right:=gennode(addn,getcopy(p^.left),p^.right);
- at_minus : p^.right:=gennode(subn,getcopy(p^.left),p^.right);
- at_star : p^.right:=gennode(muln,getcopy(p^.left),p^.right);
- at_slash : p^.right:=gennode(slashn,getcopy(p^.left),p^.right);
- end;
- end;
- {$endif i386}
- must_be_valid:=true;
- firstpass(p^.right);
- must_be_valid:=store_valid;
- if codegenerror then
- exit;
- { some string functions don't need conversion, so treat them separatly }
- if (p^.left^.resulttype^.deftype=stringdef) and (assigned(p^.right^.resulttype)) then
- begin
- if not (p^.right^.resulttype^.deftype in [stringdef,orddef]) then
- begin
- p^.right:=gentypeconvnode(p^.right,p^.left^.resulttype);
- firstpass(p^.right);
- if codegenerror then
- exit;
- end;
- { we call STRCOPY }
- procinfo.flags:=procinfo.flags or pi_do_call;
- hp:=p^.right;
- { test for s:=s+anything ... }
- { the problem is for
- s:=s+s+s;
- this is broken here !! }
- { while hp^.treetype=addn do hp:=hp^.left;
- if equal_trees(p^.left,hp) then
- begin
- p^.concat_string:=true;
- hp:=p^.right;
- while hp^.treetype=addn do
- begin
- hp^.use_strconcat:=true;
- hp:=hp^.left;
- end;
- end; }
- end
- else
- begin
- if (p^.right^.treetype=realconstn) then
- begin
- if p^.left^.resulttype^.deftype=floatdef then
- begin
- case pfloatdef(p^.left^.resulttype)^.typ of
- s32real : p^.right^.realtyp:=ait_real_32bit;
- s64real : p^.right^.realtyp:=ait_real_64bit;
- s80real : p^.right^.realtyp:=ait_real_extended;
- { what about f32bit and s64bit }
- else
- begin
- p^.right:=gentypeconvnode(p^.right,p^.left^.resulttype);
- { nochmal firstpass wegen der Typkonvertierung aufrufen }
- firstpass(p^.right);
- if codegenerror then
- exit;
- end;
- end;
- end;
- end
- else
- begin
- p^.right:=gentypeconvnode(p^.right,p^.left^.resulttype);
- firstpass(p^.right);
- if codegenerror then
- exit;
- end;
- end;
- p^.resulttype:=voiddef;
- {
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- }
- p^.registers32:=p^.left^.registers32+p^.right^.registers32;
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- end;
- procedure firstlr(var p : ptree);
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- end;
- procedure firstderef(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=max(p^.left^.registers32,1);
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.left^.resulttype^.deftype<>pointerdef then
- Message(cg_e_invalid_qualifier);
- p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
- p^.location.loc:=LOC_REFERENCE;
- end;
- procedure firstrange(var p : ptree);
- var
- ct : tconverttype;
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- { allow only ordinal constants }
- if not((p^.left^.treetype=ordconstn) and
- (p^.right^.treetype=ordconstn)) then
- Message(cg_e_illegal_expression);
- { upper limit must be greater or equalt than lower limit }
- { not if u32bit }
- if (p^.left^.value>p^.right^.value) and
- (( p^.left^.value<0) or (p^.right^.value>=0)) then
- Message(cg_e_upper_lower_than_lower);
- { both types must be compatible }
- if not(isconvertable(p^.left^.resulttype,p^.right^.resulttype,
- ct,ordconstn)) and
- not(is_equal(p^.left^.resulttype,p^.right^.resulttype)) then
- Message(sym_e_type_mismatch);
- end;
- procedure firstvecn(var p : ptree);
- var
- harr : pdef;
- ct : tconverttype;
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if codegenerror then
- exit;
- { range check only for arrays }
- if (p^.left^.resulttype^.deftype=arraydef) then
- begin
- if not(isconvertable(p^.right^.resulttype,
- parraydef(p^.left^.resulttype)^.rangedef,
- ct,ordconstn)) and
- not(is_equal(p^.right^.resulttype,
- parraydef(p^.left^.resulttype)^.rangedef)) then
- Message(sym_e_type_mismatch);
- end;
- { Never convert a boolean or a char !}
- { maybe type conversion }
- if (p^.right^.resulttype^.deftype<>enumdef) and
- not ((p^.right^.resulttype^.deftype=orddef) and
- (Porddef(p^.right^.resulttype)^.typ in [bool8bit,uchar])) then
- begin
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- { once more firstpass }
- {?? It's better to only firstpass when the tree has
- changed, isn't it ?}
- firstpass(p^.right);
- end;
- if codegenerror then
- exit;
- { determine return type }
- if p^.left^.resulttype^.deftype=arraydef then
- p^.resulttype:=parraydef(p^.left^.resulttype)^.definition
- else if (p^.left^.resulttype^.deftype=pointerdef) then
- begin
- { convert pointer to array }
- harr:=new(parraydef,init(0,$7fffffff,s32bitdef));
- parraydef(harr)^.definition:=ppointerdef(p^.left^.resulttype)^.definition;
- p^.left:=gentypeconvnode(p^.left,harr);
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.resulttype:=parraydef(harr)^.definition
- end
- else
- { indexed access to arrays }
- p^.resulttype:=cchardef;
- { the register calculation is easy if a const index is used }
- if p^.right^.treetype=ordconstn then
- p^.registers32:=p^.left^.registers32
- else
- begin
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- { not correct, but what works better ? }
- if p^.left^.registers32>0 then
- p^.registers32:=max(p^.registers32,2)
- else
- { min. one register }
- p^.registers32:=max(p^.registers32,1);
- end;
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- p^.location.loc:=p^.left^.location.loc;
- end;
- type
- tfirstconvproc = procedure(var p : ptree);
- procedure first_bigger_smaller(var p : ptree);
- begin
- if (p^.left^.location.loc<>LOC_REGISTER) and (p^.registers32=0) then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure first_cstring_charpointer(var p : ptree);
- begin
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure first_string_chararray(var p : ptree);
- begin
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure first_string_string(var p : ptree);
- begin
- if pstringdef(p^.resulttype)^.string_typ<>
- pstringdef(p^.left^.resulttype)^.string_typ then
- begin
- { call shortstring_to_ansistring or ansistring_to_shortstring }
- procinfo.flags:=procinfo.flags or pi_do_call;
- end;
- { for simplicity lets first keep all ansistrings
- as LOC_MEM, could also become LOC_REGISTER }
- p^.location.loc:=LOC_MEM;
- end;
- procedure first_char_to_string(var p : ptree);
- var
- hp : ptree;
- begin
- if p^.left^.treetype=ordconstn then
- begin
- hp:=genstringconstnode(chr(p^.left^.value));
- firstpass(hp);
- disposetree(p);
- p:=hp;
- end
- else
- p^.location.loc:=LOC_MEM;
- end;
- procedure first_nothing(var p : ptree);
- begin
- p^.location.loc:=LOC_MEM;
- end;
- procedure first_array_to_pointer(var p : ptree);
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure first_int_real(var p : ptree);
- var t : ptree;
- begin
- if p^.left^.treetype=ordconstn then
- begin
- { convert constants direct }
- { not because of type conversion }
- t:=genrealconstnode(p^.left^.value);
- firstpass(t);
- { the type can be something else than s64real !!}
- t:=gentypeconvnode(t,p^.resulttype);
- firstpass(t);
- disposetree(p);
- p:=t;
- exit;
- end
- else
- begin
- if p^.registersfpu<1 then
- p^.registersfpu:=1;
- p^.location.loc:=LOC_FPU;
- end;
- end;
- procedure first_int_fix(var p : ptree);
- begin
- if p^.left^.treetype=ordconstn then
- begin
- { convert constants direct }
- p^.treetype:=fixconstn;
- p^.valuef:=p^.left^.value shl 16;
- p^.disposetyp:=dt_nothing;
- disposetree(p^.left);
- p^.location.loc:=LOC_MEM;
- end
- else
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- end;
- procedure first_real_fix(var p : ptree);
- begin
- if p^.left^.treetype=realconstn then
- begin
- { convert constants direct }
- p^.treetype:=fixconstn;
- p^.valuef:=round(p^.left^.valued*65536);
- p^.disposetyp:=dt_nothing;
- disposetree(p^.left);
- p^.location.loc:=LOC_MEM;
- end
- else
- begin
- { at least one fpu and int register needed }
- if p^.registers32<1 then
- p^.registers32:=1;
- if p^.registersfpu<1 then
- p^.registersfpu:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- end;
- procedure first_fix_real(var p : ptree);
- begin
- if p^.left^.treetype=fixconstn then
- begin
- { convert constants direct }
- p^.treetype:=realconstn;
- p^.valued:=round(p^.left^.valuef/65536.0);
- p^.disposetyp:=dt_nothing;
- disposetree(p^.left);
- p^.location.loc:=LOC_MEM;
- end
- else
- begin
- if p^.registersfpu<1 then
- p^.registersfpu:=1;
- p^.location.loc:=LOC_FPU;
- end;
- end;
- procedure first_real_real(var p : ptree);
- begin
- if p^.registersfpu<1 then
- p^.registersfpu:=1;
- p^.location.loc:=LOC_FPU;
- end;
- procedure first_pointer_to_array(var p : ptree);
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REFERENCE;
- end;
- procedure first_chararray_string(var p : ptree);
- begin
- { the only important information is the location of the }
- { result }
- { other stuff is done by firsttypeconv }
- p^.location.loc:=LOC_MEM;
- end;
- procedure first_cchar_charpointer(var p : ptree);
- begin
- p^.left:=gentypeconvnode(p^.left,cstringdef);
- { convert constant char to constant string }
- firstpass(p^.left);
- { evalute tree }
- firstpass(p);
- end;
- procedure first_locmem(var p : ptree);
- begin
- p^.location.loc:=LOC_MEM;
- end;
- procedure first_bool_byte(var p : ptree);
- begin
- p^.location.loc:=LOC_REGISTER;
- { Florian I think this is overestimated
- but I still do not really understand how to get this right (PM) }
- { Hmmm, I think we need only one reg to return the result of }
- { this node => so
- if p^.registers32<1 then
- p^.registers32:=1;
- should work (FK)
- }
- p^.registers32:=p^.left^.registers32+1;
- end;
- procedure first_proc_to_procvar(var p : ptree);
- var
- hp : ptree;
- hp2 : pdefcoll;
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- if (p^.left^.location.loc<>LOC_REFERENCE) then
- Message(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- function is_procsym_load(p:Ptree):boolean;
- begin
- is_procsym_load:=((p^.treetype=loadn) and (p^.symtableentry^.typ=procsym)) or
- ((p^.treetype=addrn) and (p^.left^.treetype=loadn)
- and (p^.left^.symtableentry^.typ=procsym)) ;
- end;
- { change a proc call to a procload for assignment to a procvar }
- { this can only happen for proc/function without arguments }
- function is_procsym_call(p:Ptree):boolean;
- begin
- is_procsym_call:=(p^.treetype=calln) and (p^.left=nil) and
- (((p^.symtableprocentry^.typ=procsym) and (p^.right=nil)) or
- ((p^.right<>nil) and (p^.right^.symtableprocentry^.typ=varsym)));
- end;
- {***}
- function is_assignment_overloaded(from_def,to_def : pdef) : boolean;
- var
- passproc : pprocdef;
- begin
- is_assignment_overloaded:=false;
- if assigned(overloaded_operators[assignment]) then
- passproc:=overloaded_operators[assignment]^.definition
- else
- passproc:=nil;
- while passproc<>nil do
- begin
- if (passproc^.retdef=to_def) and (passproc^.para1^.data=from_def) then
- begin
- is_assignment_overloaded:=true;
- break;
- end;
- passproc:=passproc^.nextoverloaded;
- end;
- end;
- { Attention: do *** no *** recursive call of firstpass }
- { because the child tree is always passed }
- procedure firsttypeconv(var p : ptree);
- var
- hp : ptree;
- hp2,hp3:Pdefcoll;
- aprocdef : pprocdef;
- proctype : tdeftype;
- const
- firstconvert : array[tc_u8bit_2_s32bit..tc_cchar_charpointer] of
- tfirstconvproc = (first_bigger_smaller,first_nothing,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_string_string,
- first_cstring_charpointer,first_string_chararray,
- first_array_to_pointer,first_pointer_to_array,
- first_char_to_string,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_bigger_smaller,first_bigger_smaller,
- first_int_real,first_real_fix,
- first_fix_real,first_int_fix,first_real_real,
- first_locmem,first_bool_byte,first_proc_to_procvar,
- first_cchar_charpointer);
- begin
- aprocdef:=nil;
- { if explicite type conversation, then run firstpass }
- if p^.explizit then
- firstpass(p^.left);
- if codegenerror then
- exit;
- if not assigned(p^.left^.resulttype) then
- begin
- codegenerror:=true;
- internalerror(52349);
- exit;
- end;
- { remove obsolete type conversions }
- if is_equal(p^.left^.resulttype,p^.resulttype) then
- begin
- hp:=p;
- p:=p^.left;
- p^.resulttype:=hp^.resulttype;
- putnode(hp);
- exit;
- end;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif}
- set_location(p^.location,p^.left^.location);
- if (not(isconvertable(p^.left^.resulttype,p^.resulttype,p^.convtyp,p^.left^.treetype))) then
- begin
- if is_assignment_overloaded(p^.left^.resulttype,p^.resulttype) then
- begin
- procinfo.flags:=procinfo.flags or pi_do_call;
- hp:=gencallnode(overloaded_operators[assignment],nil);
- hp^.left:=gencallparanode(p^.left,nil);
- putnode(p);
- p:=hp;
- firstpass(p);
- exit;
- end;
- {Procedures have a resulttype of voiddef and functions of their
- own resulttype. They will therefore always be incompatible with
- a procvar. Because isconvertable cannot check for procedures we
- use an extra check for them.}
- if (cs_tp_compatible in aktswitches) and
- ((is_procsym_load(p^.left) or is_procsym_call(p^.left)) and
- (p^.resulttype^.deftype=procvardef)) then
- begin
- { just a test: p^.explizit:=false; }
- if is_procsym_call(p^.left) then
- begin
- if p^.left^.right=nil then
- begin
- p^.left^.treetype:=loadn;
- { are at same offset so this could be spared, but
- it more secure to do it anyway }
- p^.left^.symtableentry:=p^.left^.symtableprocentry;
- p^.left^.resulttype:=pprocsym(p^.left^.symtableentry)^.definition;
- aprocdef:=pprocdef(p^.left^.resulttype);
- end
- else
- begin
- p^.left^.right^.treetype:=loadn;
- p^.left^.right^.symtableentry:=p^.left^.right^.symtableentry;
- P^.left^.right^.resulttype:=pvarsym(p^.left^.symtableentry)^.definition;
- hp:=p^.left^.right;
- putnode(p^.left);
- p^.left:=hp;
- { should we do that ? }
- firstpass(p^.left);
- if not is_equal(p^.left^.resulttype,p^.resulttype) then
- begin
- Message(sym_e_type_mismatch);
- exit;
- end
- else
- begin
- hp:=p;
- p:=p^.left;
- p^.resulttype:=hp^.resulttype;
- putnode(hp);
- exit;
- end;
- end;
- end
- else
- begin
- if p^.left^.treetype=addrn then
- begin
- hp:=p^.left;
- p^.left:=p^.left^.left;
- putnode(p^.left);
- end
- else
- aprocdef:=pprocsym(p^.left^.symtableentry)^.definition;
- end;
- p^.convtyp:=tc_proc2procvar;
- { Now check if the procedure we are going to assign to
- the procvar, is compatible with the procvar's type.
- Did the original procvar support do such a check?
- I can't find any.}
- { answer : is_equal works for procvardefs !! }
- { but both must be procvardefs, so we cheet little }
- if assigned(aprocdef) then
- begin
- proctype:=aprocdef^.deftype;
- aprocdef^.deftype:=procvardef;
- if not is_equal(aprocdef,p^.resulttype) then
- begin
- aprocdef^.deftype:=proctype;
- Message(sym_e_type_mismatch);
- end;
- aprocdef^.deftype:=proctype;
- firstconvert[p^.convtyp](p);
- end
- else
- Message(sym_e_type_mismatch);
- exit;
- end
- else
- begin
- if p^.explizit then
- begin
- { boolean to byte are special because the
- location can be different }
- if (p^.resulttype^.deftype=orddef) and
- (porddef(p^.resulttype)^.typ=u8bit) and
- (p^.left^.resulttype^.deftype=orddef) and
- (porddef(p^.left^.resulttype)^.typ=bool8bit) then
- begin
- p^.convtyp:=tc_bool_2_u8bit;
- firstconvert[p^.convtyp](p);
- exit;
- end;
- { normal tc_equal-Konvertierung durchf�hren }
- p^.convtyp:=tc_equal;
- { wenn Aufz„hltyp nach Ordinal konvertiert werden soll }
- { dann Aufz„hltyp=s32bit }
- if (p^.left^.resulttype^.deftype=enumdef) and
- is_ordinal(p^.resulttype) then
- begin
- if p^.left^.treetype=ordconstn then
- begin
- hp:=genordinalconstnode(p^.left^.value,p^.resulttype);
- disposetree(p);
- p:=hp;
- exit;
- end
- else
- begin
- if not isconvertable(s32bitdef,p^.resulttype,p^.convtyp,ordconstn { nur Dummy} ) then
- Message(cg_e_illegal_type_conversion);
- end;
- end
- { ordinal to enumeration }
- else
- if (p^.resulttype^.deftype=enumdef) and
- is_ordinal(p^.left^.resulttype) then
- begin
- if p^.left^.treetype=ordconstn then
- begin
- hp:=genordinalconstnode(p^.left^.value,p^.resulttype);
- disposetree(p);
- p:=hp;
- exit;
- end
- else
- begin
- if not isconvertable(p^.left^.resulttype,s32bitdef,p^.convtyp,ordconstn { nur Dummy} ) then
- Message(cg_e_illegal_type_conversion);
- end;
- end
- {Are we typecasting an ordconst to a char?}
- else
- if is_equal(p^.resulttype,cchardef) and
- is_ordinal(p^.left^.resulttype) then
- begin
- if p^.left^.treetype=ordconstn then
- begin
- hp:=genordinalconstnode(p^.left^.value,p^.resulttype);
- disposetree(p);
- p:=hp;
- exit;
- end
- else
- begin
- { this is wrong because it converts to a 4 byte long var !!
- if not isconvertable(p^.left^.resulttype,s32bitdef,p^.convtyp,ordconstn nur Dummy ) then }
- if not isconvertable(p^.left^.resulttype,u8bitdef,p^.convtyp,ordconstn { nur Dummy} ) then
- Message(cg_e_illegal_type_conversion);
- end;
- end
- { only if the same size or formal def }
- { why do we allow typecasting of voiddef ?? (PM) }
- else
- if not(
- (p^.left^.resulttype^.deftype=formaldef) or
- (p^.left^.resulttype^.size=p^.resulttype^.size) or
- (is_equal(p^.left^.resulttype,voiddef) and
- (p^.left^.treetype=derefn))
- ) then
- Message(cg_e_illegal_type_conversion);
- { the conversion into a strutured type is only }
- { possible, if the source is no register }
- if (p^.resulttype^.deftype in [recorddef,stringdef,arraydef,objectdef]) and
- (p^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
- Message(cg_e_illegal_type_conversion);
- end
- else
- Message(sym_e_type_mismatch);
- end
- end
- else
- begin
- { just a test: p^.explizit:=false; }
- { ordinale contants are direct converted }
- if (p^.left^.treetype=ordconstn) and is_ordinal(p^.resulttype) then
- begin
- { perform range checking }
- if not(p^.explizit and (cs_tp_compatible in aktswitches)) then
- testrange(p^.resulttype,p^.left^.value);
- hp:=genordinalconstnode(p^.left^.value,p^.resulttype);
- disposetree(p);
- p:=hp;
- exit;
- end;
- if p^.convtyp<>tc_equal then
- firstconvert[p^.convtyp](p);
- end;
- end;
- { *************** subroutine handling **************** }
- procedure firstcallparan(var p : ptree;defcoll : pdefcoll);
- var store_valid : boolean;
- convtyp : tconverttype;
- begin
- inc(parsing_para_level);
- if assigned(p^.right) then
- begin
- if defcoll=nil then
- firstcallparan(p^.right,nil)
- else
- firstcallparan(p^.right,defcoll^.next);
- p^.registers32:=p^.right^.registers32;
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif}
- end;
- if defcoll=nil then
- begin
- if not(assigned(p^.resulttype)) then
- firstpass(p^.left)
- else
- exit;
- if codegenerror then
- begin
- dec(parsing_para_level);
- exit;
- end;
- p^.resulttype:=p^.left^.resulttype;
- end
- { if we know the routine which is called, then the type }
- { conversions are inserted }
- else
- begin
- if count_ref then
- begin
- store_valid:=must_be_valid;
- if (defcoll^.paratyp<>vs_var) then
- must_be_valid:=true
- else
- must_be_valid:=false;
- { here we must add something for the implicit type }
- { conversion from array of char to pchar }
- if isconvertable(p^.left^.resulttype,defcoll^.data,convtyp,p^.left^.treetype) then
- if convtyp=tc_array_to_pointer then
- must_be_valid:=false;
- firstpass(p^.left);
- must_be_valid:=store_valid;
- end;
- if not((p^.left^.resulttype^.deftype=stringdef) and
- (defcoll^.data^.deftype=stringdef)) and
- (defcoll^.data^.deftype<>formaldef) then
- begin
- if (defcoll^.paratyp=vs_var) and
- { allows conversion from word to integer and
- byte to shortint }
- (not(
- (p^.left^.resulttype^.deftype=orddef) and
- (defcoll^.data^.deftype=orddef) and
- (p^.left^.resulttype^.size=defcoll^.data^.size)
- ) and
- { an implicit pointer conversion is allowed }
- not(
- (p^.left^.resulttype^.deftype=pointerdef) and
- (defcoll^.data^.deftype=pointerdef)
- ) and
- { an implicit file conversion is also allowed }
- { from a typed file to an untyped one }
- not(
- (p^.left^.resulttype^.deftype=filedef) and
- (defcoll^.data^.deftype=filedef) and
- (pfiledef(defcoll^.data)^.filetype = ft_untyped) and
- (pfiledef(p^.left^.resulttype)^.filetype = ft_typed)
- ) and
- not(is_equal(p^.left^.resulttype,defcoll^.data))) then
- Message(parser_e_call_by_ref_without_typeconv);
- { don't generate an type conversion for open arrays }
- { else we loss the ranges }
- if not(is_open_array(defcoll^.data)) then
- begin
- p^.left:=gentypeconvnode(p^.left,defcoll^.data);
- firstpass(p^.left);
- end;
- if codegenerror then
- begin
- dec(parsing_para_level);
- exit;
- end;
- end;
- { check var strings }
- if (cs_strict_var_strings in aktswitches) and
- (p^.left^.resulttype^.deftype=stringdef) and
- (defcoll^.data^.deftype=stringdef) and
- (defcoll^.paratyp=vs_var) and
- not(is_equal(p^.left^.resulttype,defcoll^.data)) then
- Message(parser_e_strict_var_string_violation);
- { Variablen, die call by reference �bergeben werden, }
- { k”nnen nicht in ein Register kopiert werden }
- { is this usefull here ? }
- { this was missing in formal parameter list }
- if defcoll^.paratyp=vs_var then
- make_not_regable(p^.left);
- p^.resulttype:=defcoll^.data;
- end;
- if p^.left^.registers32>p^.registers32 then
- p^.registers32:=p^.left^.registers32;
- if p^.left^.registersfpu>p^.registersfpu then
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.left^.registersmmx>p^.registersmmx then
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- dec(parsing_para_level);
- end;
- procedure firstcalln(var p : ptree);
- type
- pprocdefcoll = ^tprocdefcoll;
- tprocdefcoll = record
- data : pprocdef;
- nextpara : pdefcoll;
- firstpara : pdefcoll;
- next : pprocdefcoll;
- end;
- var
- hp,procs,hp2 : pprocdefcoll;
- pd : pprocdef;
- st : psymtable;
- actprocsym : pprocsym;
- def_from,def_to,conv_to : pdef;
- pt : ptree;
- exactmatch : boolean;
- paralength,l : longint;
- pdc : pdefcoll;
- { only Dummy }
- hcvt : tconverttype;
- regi : tregister;
- store_valid, old_count_ref : boolean;
- { types.is_equal can't handle a formaldef ! }
- function is_equal(def1,def2 : pdef) : boolean;
- begin
- { all types can be passed to a formaldef }
- is_equal:=(def1^.deftype=formaldef) or
- (assigned(def2) and types.is_equal(def1,def2));
- end;
- function is_in_limit(def_from,def_to : pdef) : boolean;
- begin
- is_in_limit:=(def_from^.deftype = orddef) and
- (def_to^.deftype = orddef) and
- (porddef(def_from)^.von>porddef(def_to)^.von) and
- (porddef(def_from)^.bis<porddef(def_to)^.bis);
- end;
- begin
- { release registers! }
- { if procdefinition<>nil then we called firstpass already }
- { it seems to be bad because of the registers }
- { at least we can avoid the overloaded search !! }
- procs:=nil;
- { made this global for disposing !! }
- store_valid:=must_be_valid;
- must_be_valid:=false;
- { procedure variable ? }
- if assigned(p^.right) then
- begin
- { procedure does a call }
- procinfo.flags:=procinfo.flags or pi_do_call;
- { calc the correture value for the register }
- {$ifdef i386}
- for regi:=R_EAX to R_EDI do
- inc(reg_pushes[regi],t_times*2);
- {$endif}
- {$ifdef m68k}
- for regi:=R_D0 to R_A6 do
- inc(reg_pushes[regi],t_times*2);
- {$endif}
- { calculate the type of the parameters }
- if assigned(p^.left) then
- begin
- old_count_ref:=count_ref;
- count_ref:=false;
- firstcallparan(p^.left,nil);
- count_ref:=old_count_ref;
- if codegenerror then
- exit;
- end;
- firstpass(p^.right);
- { check the parameters }
- pdc:=pprocvardef(p^.right^.resulttype)^.para1;
- pt:=p^.left;
- while assigned(pdc) and assigned(pt) do
- begin
- pt:=pt^.right;
- pdc:=pdc^.next;
- end;
- if assigned(pt) or assigned(pdc) then
- Message(parser_e_illegal_parameter_list);
- { insert type conversions }
- if assigned(p^.left) then
- begin
- old_count_ref:=count_ref;
- count_ref:=true;
- firstcallparan(p^.left,pprocvardef(p^.right^.resulttype)^.para1);
- count_ref:=old_count_ref;
- if codegenerror then
- exit;
- end;
- p^.resulttype:=pprocvardef(p^.right^.resulttype)^.retdef;
- { this was missing, leads to a bug below if
- the procvar is a function }
- p^.procdefinition:=pprocdef(p^.right^.resulttype);
- end
- else
- { not a procedure variable }
- begin
- { determine the type of the parameters }
- if assigned(p^.left) then
- begin
- old_count_ref:=count_ref;
- count_ref:=false;
- store_valid:=must_be_valid;
- must_be_valid:=false;
- firstcallparan(p^.left,nil);
- count_ref:=old_count_ref;
- must_be_valid:=store_valid;
- if codegenerror then
- exit;
- end;
- { do we know the procedure to call ? }
- if not(assigned(p^.procdefinition)) then
- begin
- actprocsym:=p^.symtableprocentry;
- { determine length of parameter list }
- pt:=p^.left;
- paralength:=0;
- while assigned(pt) do
- begin
- inc(paralength);
- pt:=pt^.right;
- end;
- { alle in Frage kommenden Prozeduren in eine }
- { verkettete Liste einf�gen }
- pd:=actprocsym^.definition;
- while assigned(pd) do
- begin
- { we should also check that the overloaded function
- has been declared in a unit that is in the uses !! }
- { pd^.owner should be in the symtablestack !! }
- { Laenge der deklarierten Parameterliste feststellen: }
- { not necessary why nextprocsym field }
- {st:=symtablestack;
- if (pd^.owner^.symtabletype<>objectsymtable) then
- while assigned(st) do
- begin
- if (st=pd^.owner) then break;
- st:=st^.next;
- end;
- if assigned(st) then }
- begin
- pdc:=pd^.para1;
- l:=0;
- while assigned(pdc) do
- begin
- inc(l);
- pdc:=pdc^.next;
- end;
- { nur wenn die Parameterl„nge paát, dann Einf�gen }
- if l=paralength then
- begin
- new(hp);
- hp^.data:=pd;
- hp^.next:=procs;
- hp^.nextpara:=pd^.para1;
- hp^.firstpara:=pd^.para1;
- procs:=hp;
- end;
- end;
- pd:=pd^.nextoverloaded;
- {$ifdef CHAINPROCSYMS}
- if (pd=nil) and not (p^.unit_specific) then
- begin
- actprocsym:=actprocsym^.nextprocsym;
- if assigned(actprocsym) then
- pd:=actprocsym^.definition;
- end;
- {$endif CHAINPROCSYMS}
- end;
- { nun alle Parameter nacheinander vergleichen }
- pt:=p^.left;
- while assigned(pt) do
- begin
- { matches a parameter of one procedure exact ? }
- exactmatch:=false;
- hp:=procs;
- while assigned(hp) do
- begin
- if is_equal(hp^.nextpara^.data,pt^.resulttype) then
- begin
- if hp^.nextpara^.data=pt^.resulttype then
- begin
- pt^.exact_match_found:=true;
- hp^.nextpara^.argconvtyp:=act_exact;
- end
- else
- hp^.nextpara^.argconvtyp:=act_equal;
- exactmatch:=true;
- end
- else
- hp^.nextpara^.argconvtyp:=act_convertable;
- hp:=hp^.next;
- end;
- { .... if yes, del all the other procedures }
- if exactmatch then
- begin
- { the first .... }
- while (assigned(procs)) and not(is_equal(procs^.nextpara^.data,pt^.resulttype)) do
- begin
- hp:=procs^.next;
- dispose(procs);
- procs:=hp;
- end;
- { and the others }
- hp:=procs;
- while (assigned(hp)) and assigned(hp^.next) do
- begin
- if not(is_equal(hp^.next^.nextpara^.data,pt^.resulttype)) then
- begin
- hp2:=hp^.next^.next;
- dispose(hp^.next);
- hp^.next:=hp2;
- end
- else
- hp:=hp^.next;
- end;
- end
- { sollte nirgendwo ein Parameter exakt passen, }
- { so alle Prozeduren entfernen, bei denen }
- { der Parameter auch nach einer impliziten }
- { Typkonvertierung nicht passt }
- else
- begin
- { erst am Anfang }
- while (assigned(procs)) and
- not(isconvertable(pt^.resulttype,procs^.nextpara^.data,hcvt,pt^.left^.treetype)) do
- begin
- hp:=procs^.next;
- dispose(procs);
- procs:=hp;
- end;
- { und jetzt aus der Mitte }
- hp:=procs;
- while (assigned(hp)) and assigned(hp^.next) do
- begin
- if not(isconvertable(pt^.resulttype,hp^.next^.nextpara^.data,
- hcvt,pt^.left^.treetype)) then
- begin
- hp2:=hp^.next^.next;
- dispose(hp^.next);
- hp^.next:=hp2;
- end
- else
- hp:=hp^.next;
- end;
- end;
- { nun bei denn Prozeduren den nextpara-Zeiger auf den }
- { naechsten Parameter setzen }
- hp:=procs;
- while assigned(hp) do
- begin
- hp^.nextpara:=hp^.nextpara^.next;
- hp:=hp^.next;
- end;
- pt:=pt^.right;
- end;
- if procs=nil then
- if (parsing_para_level=0) or (p^.left<>nil) then
- begin
- Message(parser_e_illegal_parameter_list);
- exit;
- end
- else
- begin
- { try to convert to procvar }
- p^.treetype:=loadn;
- p^.resulttype:=pprocsym(p^.symtableprocentry)^.definition;
- p^.symtableentry:=p^.symtableprocentry;
- p^.is_first:=false;
- p^.disposetyp:=dt_nothing;
- firstpass(p);
- exit;
- end;
- { if there are several choices left then for orddef }
- { if a type is totally included in the other }
- { we don't fear an overflow , }
- { so we can do as if it is an exact match }
- { this will convert integer to longint }
- { rather than to words }
- { conversion of byte to integer or longint }
- {would still not be solved }
- if assigned(procs^.next) then
- begin
- hp:=procs;
- while assigned(hp) do
- begin
- hp^.nextpara:=hp^.firstpara;
- hp:=hp^.next;
- end;
- pt:=p^.left;
- while assigned(pt) do
- begin
- { matches a parameter of one procedure exact ? }
- exactmatch:=false;
- def_from:=pt^.resulttype;
- hp:=procs;
- while assigned(hp) do
- begin
- if not is_equal(hp^.nextpara^.data,pt^.resulttype) then
- begin
- def_to:=hp^.nextpara^.data;
- if (def_from^.deftype=orddef) and (def_to^.deftype=orddef) then
- if is_in_limit(def_from,def_to) or
- ((hp^.nextpara^.paratyp=vs_var) and
- (def_from^.size=def_to^.size)) then
- begin
- exactmatch:=true;
- conv_to:=def_to;
- end;
- end;
- hp:=hp^.next;
- end;
- { .... if yes, del all the other procedures }
- if exactmatch then
- begin
- { the first .... }
- while (assigned(procs)) and not(is_in_limit(def_from,procs^.nextpara^.data)) do
- begin
- hp:=procs^.next;
- dispose(procs);
- procs:=hp;
- end;
- { and the others }
- hp:=procs;
- while (assigned(hp)) and assigned(hp^.next) do
- begin
- if not(is_in_limit(def_from,hp^.next^.nextpara^.data)) then
- begin
- hp2:=hp^.next^.next;
- dispose(hp^.next);
- hp^.next:=hp2;
- end
- else
- begin
- def_to:=hp^.next^.nextpara^.data;
- if (conv_to^.size>def_to^.size) or
- ((porddef(conv_to)^.von<porddef(def_to)^.von) and
- (porddef(conv_to)^.bis>porddef(def_to)^.bis)) then
- begin
- hp2:=procs;
- procs:=hp;
- conv_to:=def_to;
- dispose(hp2);
- end
- else
- hp:=hp^.next;
- end;
- end;
- end;
- { nun bei denn Prozeduren den nextpara-Zeiger auf den }
- { naechsten Parameter setzen }
- hp:=procs;
- while assigned(hp) do
- begin
- hp^.nextpara:=hp^.nextpara^.next;
- hp:=hp^.next;
- end;
- pt:=pt^.right;
- end;
- end;
- { let's try to eliminate equal is exact is there }
- {if assigned(procs^.next) then
- begin
- pt:=p^.left;
- while assigned(pt) do
- begin
- if pt^.exact_match_found then
- begin
- hp:=procs;
- while (assigned(procs)) and (procs^.nextpara^.data<>pt^.resulttype) do
- begin
- hp:=procs^.next;
- dispose(procs);
- procs:=hp;
- end;
- end;
- pt:=pt^.right;
- end;
- end; }
- {$ifndef CHAINPROCSYMS}
- if assigned(procs^.next) then
- Message(cg_e_cant_choose_overload_function);
- {$else CHAINPROCSYMS}
- if assigned(procs^.next) then
- { if the last retained is the only one }
- { from a unit it is OK PM }
- { the last is the one coming from the first symtable }
- { as the diff defcoll are inserted in front }
- begin
- hp2:=procs;
- while assigned(hp2^.next) and assigned(hp2^.next^.next) do
- hp2:=hp2^.next;
- if (hp2^.data^.owner<>hp2^.next^.data^.owner) then
- begin
- hp:=procs^.next;
- {hp2 is the correct one }
- hp2:=hp2^.next;
- while hp<>hp2 do
- begin
- dispose(procs);
- procs:=hp;
- hp:=procs^.next;
- end;
- procs:=hp2;
- end
- else
- Message(cg_e_cant_choose_overload_function);
- error(too_much_matches);
- end;
- {$endif CHAINPROCSYMS}
- {$ifdef UseBrowser}
- add_new_ref(procs^.data^.lastref);
- {$endif UseBrowser}
- p^.procdefinition:=procs^.data;
- p^.resulttype:=procs^.data^.retdef;
- p^.symtableproc:=p^.procdefinition^.owner;
- p^.location.loc:=LOC_MEM;
- {$ifdef CHAINPROCSYMS}
- { object with method read;
- call to read(x) will be a usual procedure call }
- if assigned(p^.methodpointer) and
- (p^.procdefinition^._class=nil) then
- begin
- { not ok for extended }
- case p^.methodpointer^.treetype of
- typen,hnewn : fatalerror(no_para_match);
- end;
- disposetree(p^.methodpointer);
- p^.methodpointer:=nil;
- end;
- {$endif CHAINPROCSYMS}
- end;{ end of procedure to call determination }
- { work trough all parameters to insert the type conversions }
- if assigned(p^.left) then
- begin
- old_count_ref:=count_ref;
- count_ref:=true;
- firstcallparan(p^.left,p^.procdefinition^.para1);
- count_ref:=old_count_ref;
- end;
- { handle predefined procedures }
- if (p^.procdefinition^.options and pointernproc)<>0 then
- begin
- { settextbuf needs two args }
- if assigned(p^.left^.right) then
- pt:=geninlinenode(pprocdef(p^.procdefinition)^.extnumber,p^.left)
- else
- begin
- pt:=geninlinenode(pprocdef(p^.procdefinition)^.extnumber,p^.left^.left);
- putnode(p^.left);
- end;
- putnode(p);
- firstpass(pt);
- { was placed after the exit }
- { caused GPF }
- { error caused and corrected by (PM) }
- p:=pt;
- must_be_valid:=store_valid;
- if codegenerror then
- exit;
- dispose(procs);
- exit;
- end
- else
- { no intern procedure => we do a call }
- { handle predefined procedures }
- if (p^.procdefinition^.options and poinline)<>0 then
- begin
- if assigned(p^.methodpointer) then
- comment(v_fatal,'Unable to inline object methods');
- if assigned(p^.right) then
- comment(v_fatal,'Unable to inline procvar calls');
- { p^.treetype:=procinlinen; }
- if assigned(p^.procdefinition^.code) then
- p^.right:=genprocinlinenode(p,ptree(p^.procdefinition^.code))
- else
- comment(v_fatal,'no code for inline procedure stored');
- firstpass(p^.right);
- end
- else
- procinfo.flags:=procinfo.flags or pi_do_call;
- { calc the correture value for the register }
- {$ifdef i386}
- for regi:=R_EAX to R_EDI do
- begin
- if (p^.procdefinition^.usedregisters and ($80 shr word(regi)))<>0 then
- inc(reg_pushes[regi],t_times*2);
- end;
- {$endif}
- {$ifdef m68k}
- for regi:=R_D0 to R_A6 do
- begin
- if (p^.procdefinition^.usedregisters and ($800 shr word(regi)))<>0 then
- inc(reg_pushes[regi],t_times*2);
- end;
- {$endif}
- end;
- { ensure that the result type is set }
- p^.resulttype:=p^.procdefinition^.retdef;
- { get a register for the return value }
- if (p^.resulttype<>pdef(voiddef)) then
- begin
- if (p^.procdefinition^.options and poconstructor)<>0 then
- begin
- { extra handling of classes }
- { p^.methodpointer should be assigned! }
- if assigned(p^.methodpointer) and assigned(p^.methodpointer^.resulttype) and
- (p^.methodpointer^.resulttype^.deftype=classrefdef) then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.registers32:=1;
- { the result type depends on the classref }
- p^.resulttype:=pclassrefdef(p^.methodpointer^.resulttype)^.definition;
- end
- { a object constructor returns the result with the flags }
- else
- p^.location.loc:=LOC_FLAGS;
- end
- else
- begin
- {$ifdef SUPPORT_MMX}
- if (cs_mmx in aktswitches) and
- is_mmx_able_array(p^.resulttype) then
- begin
- p^.location.loc:=LOC_MMXREGISTER;
- p^.registersmmx:=1;
- end
- else
- {$endif SUPPORT_MMX}
- if ret_in_acc(p^.resulttype) then
- begin
- p^.location.loc:=LOC_REGISTER;
- p^.registers32:=1;
- end
- else if (p^.resulttype^.deftype=floatdef) then
- begin
- p^.location.loc:=LOC_FPU;
- p^.registersfpu:=1;
- end
- end;
- end;
- { if this is a call to a method calc the registers }
- if (p^.methodpointer<>nil) then
- begin
- case p^.methodpointer^.treetype of
- { but only, if this is not a supporting node }
- typen,hnewn : ;
- else
- begin
- { R.Assign is not a constructor !!! }
- { but for R^.Assign, R must be valid !! }
- if ((p^.procdefinition^.options and poconstructor) <> 0) or
- ((p^.methodpointer^.treetype=loadn) and
- ((pobjectdef(p^.methodpointer^.resulttype)^.options and oo_hasvirtual) = 0)) then
- must_be_valid:=false
- else
- must_be_valid:=true;
- firstpass(p^.methodpointer);
- p^.registersfpu:=max(p^.methodpointer^.registersfpu,p^.registersfpu);
- p^.registers32:=max(p^.methodpointer^.registers32,p^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.methodpointer^.registersmmx,p^.registersmmx);
- {$endif SUPPORT_MMX}
- end;
- end;
- end;
- { determine the registers of the procedure variable }
- { is this OK for inlined procs also ?? (PM) }
- if assigned(p^.right) then
- begin
- p^.registersfpu:=max(p^.right^.registersfpu,p^.registersfpu);
- p^.registers32:=max(p^.right^.registers32,p^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.right^.registersmmx,p^.registersmmx);
- {$endif SUPPORT_MMX}
- end;
- { determine the registers of the procedure }
- if assigned(p^.left) then
- begin
- p^.registersfpu:=max(p^.left^.registersfpu,p^.registersfpu);
- p^.registers32:=max(p^.left^.registers32,p^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.registersmmx);
- {$endif SUPPORT_MMX}
- end;
- if assigned(procs) then
- dispose(procs);
- must_be_valid:=store_valid;
- end;
- procedure firstfuncret(var p : ptree);
- begin
- {$ifdef TEST_FUNCRET}
- p^.resulttype:=p^.retdef;
- p^.location.loc:=LOC_REFERENCE;
- if ret_in_param(p^.retdef) or
- (@procinfo<>pprocinfo(p^.funcretprocinfo)) then
- p^.registers32:=1;
- {$ifdef GDB}
- if must_be_valid and not pprocinfo(p^.funcretprocinfo)^.funcret_is_valid then
- note(uninitialized_function_return);
- if count_ref then pprocinfo(p^.funcretprocinfo)^.funcret_is_valid:=true;
- {$endif * GDB *}
- {$else TEST_FUNCRET}
- p^.resulttype:=procinfo.retdef;
- p^.location.loc:=LOC_REFERENCE;
- if ret_in_param(procinfo.retdef) then
- p^.registers32:=1;
- {$ifdef GDB}
- if must_be_valid and
- not(procinfo.funcret_is_valid) {and
- ((procinfo.flags and pi_uses_asm)=0)} then
- Message(sym_w_function_result_not_set);
- if count_ref then procinfo.funcret_is_valid:=true;
- {$endif * GDB *}
- {$endif TEST_FUNCRET}
- end;
- { intern inline suborutines }
- procedure firstinline(var p : ptree);
- var
- hp,hpp : ptree;
- isreal,store_valid,file_is_typed : boolean;
- convtyp : tconverttype;
- procedure do_lowhigh(adef : pdef);
- var
- v : longint;
- enum : penumsym;
- begin
- case Adef^.deftype of
- orddef:
- begin
- if p^.inlinenumber=in_low_x then
- v:=porddef(Adef)^.von
- else
- v:=porddef(Adef)^.bis;
- hp:=genordinalconstnode(v,adef);
- disposetree(p);
- p:=hp;
- end;
- enumdef:
- begin
- enum:=Penumdef(Adef)^.first;
- if p^.inlinenumber=in_high_x then
- while enum^.next<>nil do
- enum:=enum^.next;
- hp:=genenumnode(enum);
- disposetree(p);
- p:=hp;
- end
- end;
- end;
- begin
- { if we handle writeln; p^.left contains no valid address }
- if assigned(p^.left) then
- begin
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- set_location(p^.location,p^.left^.location);
- end;
- store_valid:=must_be_valid;
- if not (p^.inlinenumber in [in_read_x,in_readln_x,in_sizeof_x,
- in_typeof_x,in_ord_x,
- in_reset_typedfile,in_rewrite_typedfile]) then
- must_be_valid:=true
- else must_be_valid:=false;
- case p^.inlinenumber of
- in_lo_word,in_hi_word:
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.resulttype:=u8bitdef;
- p^.location.loc:=LOC_REGISTER;
- end;
- in_lo_long,in_hi_long:
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.resulttype:=u16bitdef;
- p^.location.loc:=LOC_REGISTER;
- end;
- in_sizeof_x:
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.resulttype:=s32bitdef;
- p^.location.loc:=LOC_REGISTER;
- end;
- in_typeof_x:
- begin
- if p^.registers32<1 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- p^.resulttype:=voidpointerdef;
- end;
- in_ord_x:
- begin
- if (p^.left^.treetype=ordconstn) then
- begin
- hp:=genordinalconstnode(p^.left^.value,s32bitdef);
- disposetree(p);
- p:=hp;
- firstpass(p);
- end
- else
- begin
- if (p^.left^.resulttype^.deftype=orddef) then
- if (porddef(p^.left^.resulttype)^.typ=uchar) or
- (porddef(p^.left^.resulttype)^.typ=bool8bit) then
- begin
- if porddef(p^.left^.resulttype)^.typ=bool8bit then
- begin
- hp:=gentypeconvnode(p^.left,u8bitdef);
- putnode(p);
- p:=hp;
- p^.convtyp:=tc_bool_2_u8bit;
- p^.explizit:=true;
- firstpass(p);
- end
- else
- begin
- hp:=gentypeconvnode(p^.left,u8bitdef);
- putnode(p);
- p:=hp;
- p^.explizit:=true;
- firstpass(p);
- end;
- end
- { can this happen ? }
- else if (porddef(p^.left^.resulttype)^.typ=uvoid) then
- Message(sym_e_type_mismatch)
- else
- { all other orddef need no transformation }
- begin
- hp:=p^.left;
- putnode(p);
- p:=hp;
- end
- else if (p^.left^.resulttype^.deftype=enumdef) then
- begin
- hp:=gentypeconvnode(p^.left,s32bitdef);
- putnode(p);
- p:=hp;
- p^.explizit:=true;
- firstpass(p);
- end
- else
- begin
- { can anything else be ord() ?}
- Message(sym_e_type_mismatch);
- end;
- end;
- end;
- in_chr_byte:
- begin
- hp:=gentypeconvnode(p^.left,cchardef);
- putnode(p);
- p:=hp;
- p^.explizit:=true;
- firstpass(p);
- end;
- in_length_string:
- begin
- {$ifdef UseAnsiString}
- if is_ansistring(p^.left^.resulttype) then
- p^.resulttype:=s32bitdef
- else
- {$endif UseAnsiString}
- p^.resulttype:=u8bitdef;
- { wer don't need string conversations here }
- if (p^.left^.treetype=typeconvn) and
- (p^.left^.left^.resulttype^.deftype=stringdef) then
- begin
- hp:=p^.left^.left;
- putnode(p^.left);
- p^.left:=hp;
- end;
- { evalutes length of constant strings direct }
- if (p^.left^.treetype=stringconstn) then
- begin
- hp:=genordinalconstnode(length(p^.left^.values^),s32bitdef);
- disposetree(p);
- firstpass(hp);
- p:=hp;
- end;
- end;
- in_assigned_x:
- begin
- p^.resulttype:=booldef;
- p^.location.loc:=LOC_FLAGS;
- end;
- in_pred_x,
- in_succ_x:
- begin
- p^.resulttype:=p^.left^.resulttype;
- p^.location.loc:=LOC_REGISTER;
- if not is_ordinal(p^.resulttype) then
- Message(sym_e_type_mismatch)
- else
- begin
- if (p^.resulttype^.deftype=enumdef) and
- (penumdef(p^.resulttype)^.has_jumps) then
- begin
- Message(parser_e_succ_and_pred_enums_with_assign_not_possible);
- exit;
- end;
- if p^.left^.treetype=ordconstn then
- begin
- if p^.inlinenumber=in_pred_x then
- hp:=genordinalconstnode(p^.left^.value+1,
- p^.left^.resulttype)
- else
- hp:=genordinalconstnode(p^.left^.value-1,
- p^.left^.resulttype);
- disposetree(p);
- firstpass(hp);
- p:=hp;
- end;
- end;
- end;
- in_dec_dword,
- in_dec_word,
- in_dec_byte,
- in_inc_dword,
- in_inc_word,
- in_inc_byte :
- begin
- p^.resulttype:=voiddef;
- if p^.left^.location.loc<>LOC_REFERENCE then
- Message(cg_e_illegal_expression);
- end;
- in_inc_x,
- in_dec_x:
- begin
- p^.resulttype:=voiddef;
- if assigned(p^.left) then
- begin
- firstcallparan(p^.left,nil);
- { first param must be var }
- if p^.left^.left^.location.loc<>LOC_REFERENCE then
- Message(cg_e_illegal_expression);
- { check type }
- if (p^.left^.resulttype^.deftype=pointerdef) or
- (p^.left^.resulttype^.deftype=enumdef) or
- ( (p^.left^.resulttype^.deftype=orddef) and
- (porddef(p^.left^.resulttype)^.typ in [u8bit,s8bit,u16bit,s16bit,u32bit,s32bit])
- ) then
- begin
- { two paras ? }
- if assigned(p^.left^.right) then
- begin
- { insert a type conversion }
- { the second param is always longint }
- p^.left^.right^.left:=gentypeconvnode(
- p^.left^.right^.left,
- s32bitdef);
- { check the type conversion }
- firstpass(p^.left^.right^.left);
- if assigned(p^.left^.right^.right) then
- Message(cg_e_illegal_expression);
- end;
- end
- else
- Message(sym_e_type_mismatch);
- end
- else
- Message(sym_e_type_mismatch);
- end;
- in_read_x,
- in_readln_x,
- in_write_x,
- in_writeln_x :
- begin
- { needs a call }
- procinfo.flags:=procinfo.flags or pi_do_call;
- p^.resulttype:=voiddef;
- { we must know if it is a typed file or not }
- { but we must first do the firstpass for it }
- file_is_typed:=false;
- if assigned(p^.left) then
- begin
- firstcallparan(p^.left,nil);
- { now we can check }
- hp:=p^.left;
- while assigned(hp^.right) do
- hp:=hp^.right;
- { if resulttype is not assigned, then automatically }
- { file is not typed. }
- if assigned(hp) and assigned(hp^.resulttype) then
- Begin
- if (hp^.resulttype^.deftype=filedef) and
- (pfiledef(hp^.resulttype)^.filetype=ft_typed) then
- begin
- file_is_typed:=true;
- { test the type here
- so we can use a trick in cgi386 (PM) }
- hpp:=p^.left;
- while (hpp<>hp) do
- begin
- { should we allow type conversion ? (PM)
- if not isconvertable(hpp^.resulttype,
- pfiledef(hp^.resulttype)^.typed_as,convtyp,hpp^.treetype) then
- Message(sym_e_type_mismatch);
- if not(is_equal(hpp^.resulttype,pfiledef(hp^.resulttype)^.typed_as)) then
- begin
- hpp^.left:=gentypeconvnode(hpp^.left,pfiledef(hp^.resulttype)^.typed_as);
- end; }
- if not is_equal(hpp^.resulttype,pfiledef(hp^.resulttype)^.typed_as) then
- Message(sym_e_type_mismatch);
- hpp:=hpp^.right;
- end;
- { once again for typeconversions }
- firstcallparan(p^.left,nil);
- end;
- end; { endif assigned(hp) }
- { insert type conversions for write(ln) }
- if (not file_is_typed) and
- ((p^.inlinenumber=in_write_x) or (p^.inlinenumber=in_writeln_x)) then
- begin
- hp:=p^.left;
- while assigned(hp) do
- begin
- if assigned(hp^.left^.resulttype) then
- begin
- if hp^.left^.resulttype^.deftype=floatdef then
- begin
- isreal:=true;
- end
- else if hp^.left^.resulttype^.deftype=orddef then
- case porddef(hp^.left^.resulttype)^.typ of
- u8bit,s8bit,
- u16bit,s16bit :
- hp^.left:=gentypeconvnode(hp^.left,s32bitdef);
- end
- { but we convert only if the first index<>0, because in this case }
- { we have a ASCIIZ string }
- else if (hp^.left^.resulttype^.deftype=arraydef) and
- (parraydef(hp^.left^.resulttype)^.lowrange<>0) and
- (parraydef(hp^.left^.resulttype)^.definition^.deftype=orddef) and
- (porddef(parraydef(hp^.left^.resulttype)^.definition)^.typ=uchar) then
- hp^.left:=gentypeconvnode(hp^.left,cstringdef);
- end;
- hp:=hp^.right;
- end;
- end;
- { pass all parameters again }
- firstcallparan(p^.left,nil);
- end;
- end;
- in_settextbuf_file_x :
- begin
- { warning here p^.left is the callparannode
- not the argument directly }
- { p^.left^.left is text var }
- { p^.left^.right^.left is the buffer var }
- { firstcallparan(p^.left,nil);
- already done in firstcalln }
- { now we know the type of buffer }
- getsymonlyin(systemunit,'SETTEXTBUF');
- hp:=gencallnode(pprocsym(srsym),systemunit);
- hp^.left:=gencallparanode(
- genordinalconstnode(p^.left^.left^.resulttype^.size,s32bitdef),p^.left);
- putnode(p);
- p:=hp;
- firstpass(p);
- end;
- { the firstpass of the arg has been done in firstcalln ? }
- in_reset_typedfile,in_rewrite_typedfile :
- begin
- procinfo.flags:=procinfo.flags or pi_do_call;
- { to be sure the right definition is loaded }
- p^.left^.resulttype:=nil;
- firstload(p^.left);
- p^.resulttype:=voiddef;
- end;
- in_str_x_string :
- begin
- procinfo.flags:=procinfo.flags or pi_do_call;
- p^.resulttype:=voiddef;
- if assigned(p^.left) then
- begin
- hp:=p^.left^.right;
- { first pass just the string for first local use }
- must_be_valid:=false;
- count_ref:=true;
- p^.left^.right:=nil;
- firstcallparan(p^.left,nil);
- p^.left^.right:=hp;
- must_be_valid:=true;
- firstcallparan(p^.left,nil);
- hp:=p^.left;
- isreal:=false;
- { valid string ? }
- if not assigned(hp) or
- (hp^.left^.resulttype^.deftype<>stringdef) or
- (hp^.right=nil) or
- (hp^.left^.location.loc<>LOC_REFERENCE) then
- Message(cg_e_illegal_expression);
- { !!!! check length of string }
- while assigned(hp^.right) do hp:=hp^.right;
- { check and convert the first param }
- if hp^.is_colon_para then
- Message(cg_e_illegal_expression)
- else if hp^.resulttype^.deftype=orddef then
- case porddef(hp^.left^.resulttype)^.typ of
- u8bit,s8bit,
- u16bit,s16bit :
- hp^.left:=gentypeconvnode(hp^.left,s32bitdef);
- end
- else if hp^.resulttype^.deftype=floatdef then
- begin
- isreal:=true;
- end
- else Message(cg_e_illegal_expression);
- { some format options ? }
- hp:=p^.left^.right;
- if assigned(hp) and hp^.is_colon_para then
- begin
- hp^.left:=gentypeconvnode(hp^.left,s32bitdef);
- hp:=hp^.right;
- end;
- if assigned(hp) and hp^.is_colon_para then
- begin
- if isreal then
- hp^.left:=gentypeconvnode(hp^.left,s32bitdef)
- else
- Message(parser_e_illegal_colon_qualifier);
- hp:=hp^.right;
- end;
- { for first local use }
- must_be_valid:=false;
- count_ref:=true;
- if assigned(hp) then
- firstcallparan(hp,nil);
- end
- else
- Message(parser_e_illegal_parameter_list);
- { check params once more }
- if codegenerror then
- exit;
- must_be_valid:=true;
- firstcallparan(p^.left,nil);
- end;
- in_include_x_y,
- in_exclude_x_y:
- begin
- p^.resulttype:=voiddef;
- if assigned(p^.left) then
- begin
- firstcallparan(p^.left,nil);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { first param must be var }
- if (p^.left^.left^.location.loc<>LOC_REFERENCE) and
- (p^.left^.left^.location.loc<>LOC_CREGISTER) then
- Message(cg_e_illegal_expression);
- { check type }
- if (p^.left^.resulttype^.deftype=setdef) then
- begin
- { two paras ? }
- if assigned(p^.left^.right) then
- begin
- { insert a type conversion }
- { to the type of the set elements }
- p^.left^.right^.left:=gentypeconvnode(
- p^.left^.right^.left,
- psetdef(p^.left^.resulttype)^.setof);
- { check the type conversion }
- firstpass(p^.left^.right^.left);
- { only three parameters are allowed }
- if assigned(p^.left^.right^.right) then
- Message(cg_e_illegal_expression);
- end;
- end
- else
- Message(sym_e_type_mismatch);
- end
- else
- Message(sym_e_type_mismatch);
- end;
- in_low_x,in_high_x:
- begin
- if p^.left^.treetype in [typen,loadn] then
- begin
- case p^.left^.resulttype^.deftype of
- orddef,enumdef:
- begin
- do_lowhigh(p^.left^.resulttype);
- firstpass(p);
- end;
- setdef:
- begin
- do_lowhigh(Psetdef(p^.left^.resulttype)^.setof);
- firstpass(p);
- end;
- arraydef:
- begin
- if is_open_array(p^.left^.resulttype) then
- begin
- if p^.inlinenumber=in_low_x then
- begin
- hp:=genordinalconstnode(Parraydef(p^.left^.resulttype)^.lowrange,s32bitdef);
- disposetree(p);
- p:=hp;
- firstpass(p);
- end
- else
- begin
- p^.resulttype:=s32bitdef;
- p^.registers32:=max(1,
- p^.registers32);
- p^.location.loc:=LOC_REGISTER;
- end;
- end
- else
- begin
- if p^.inlinenumber=in_low_x then
- hp:=genordinalconstnode(Parraydef(p^.left^.resulttype)^.lowrange,s32bitdef)
- else
- hp:=genordinalconstnode(Parraydef(p^.left^.resulttype)^.highrange,s32bitdef);
- disposetree(p);
- p:=hp;
- firstpass(p);
- end;
- end;
- stringdef:
- begin
- if p^.inlinenumber=in_low_x then
- hp:=genordinalconstnode(0,u8bitdef)
- else
- hp:=genordinalconstnode(Pstringdef(p^.left^.resulttype)^.len,u8bitdef);
- disposetree(p);
- p:=hp;
- firstpass(p);
- end;
- else
- Message(sym_e_type_mismatch);
- end;
- end
- else
- Message(parser_e_varid_or_typeid_expected);
- end
- else internalerror(8);
- end;
- must_be_valid:=store_valid;
- end;
- procedure firstsubscriptn(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.resulttype:=p^.vs^.definition;
- if count_ref and not must_be_valid then
- if (p^.vs^.properties and sp_protected)<>0 then
- Message(parser_e_cant_write_protected_member);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { classes must be dereferenced implicit }
- if (p^.left^.resulttype^.deftype=objectdef) and
- pobjectdef(p^.left^.resulttype)^.isclass then
- begin
- if p^.registers32=0 then
- p^.registers32:=1;
- p^.location.loc:=LOC_REFERENCE;
- end
- else
- begin
- if (p^.left^.location.loc<>LOC_MEM) and
- (p^.left^.location.loc<>LOC_REFERENCE) then
- Message(cg_e_illegal_expression);
- set_location(p^.location,p^.left^.location);
- end;
- end;
- procedure firstselfn(var p : ptree);
- begin
- if (p^.resulttype^.deftype=classrefdef) or
- ((p^.resulttype^.deftype=objectdef)
- and pobjectdef(p^.resulttype)^.isclass
- ) then
- p^.location.loc:=LOC_REGISTER
- else
- p^.location.loc:=LOC_REFERENCE;
- end;
- procedure firsttypen(var p : ptree);
- begin
- { DM: Why not allowed? For example: low(word) results in a type
- id of word.
- error(typeid_here_not_allowed);}
- end;
- procedure firsthnewn(var p : ptree);
- begin
- end;
- procedure firsthdisposen(var p : ptree);
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.registers32<1 then
- p^.registers32:=1;
- {
- if p^.left^.location.loc<>LOC_REFERENCE then
- Message(cg_e_illegal_expression);
- }
- p^.location.loc:=LOC_REFERENCE;
- p^.resulttype:=ppointerdef(p^.left^.resulttype)^.definition;
- end;
- procedure firstnewn(var p : ptree);
- begin
- { Standardeinleitung }
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { result type is already set }
- procinfo.flags:=procinfo.flags or pi_do_call;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstsimplenewdispose(var p : ptree);
- begin
- { this cannot be in a register !! }
- make_not_regable(p^.left);
- firstpass(p^.left);
- { check the type }
- if (p^.left^.resulttype=nil) or (p^.left^.resulttype^.deftype<>pointerdef) then
- Message(parser_e_pointer_type_expected);
- if (p^.left^.location.loc<>LOC_REFERENCE) {and
- (p^.left^.location.loc<>LOC_CREGISTER)} then
- Message(cg_e_illegal_expression);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- p^.resulttype:=voiddef;
- procinfo.flags:=procinfo.flags or pi_do_call;
- end;
- procedure firstsetcons(var p : ptree);
- var
- hp : ptree;
- begin
- p^.location.loc:=LOC_MEM;
- hp:=p^.left;
- { is done by getnode*
- p^.registers32:=0;
- p^.registersfpu:=0;
- }
- while assigned(hp) do
- begin
- firstpass(hp^.left);
- if codegenerror then
- exit;
- p^.registers32:=max(p^.registers32,hp^.left^.registers32);
- p^.registersfpu:=max(p^.registersfpu,hp^.left^.registersfpu);;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.registersmmx,hp^.left^.registersmmx);
- {$endif SUPPORT_MMX}
- hp:=hp^.right;
- end;
- { result type is already set }
- end;
- procedure firstin(var p : ptree);
- begin
- p^.location.loc:=LOC_FLAGS;
- p^.resulttype:=booldef;
- firstpass(p^.right);
- if codegenerror then
- exit;
- if p^.right^.resulttype^.deftype<>setdef then
- Message(sym_e_set_expected);
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.left:=gentypeconvnode(p^.left,psetdef(p^.right^.resulttype)^.setof);
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- { this is not allways true due to optimization }
- { but if we don't set this we get problems with optimizing self code }
- if psetdef(p^.right^.resulttype)^.settype<>smallset then
- procinfo.flags:=procinfo.flags or pi_do_call;
- end;
- procedure firststatement(var p : ptree);
- begin
- { left is the next statement in the list }
- p^.resulttype:=voiddef;
- { no temps over several statements }
- cleartempgen;
- { right is the statement itself calln assignn or a complex one }
- firstpass(p^.right);
- if (not (cs_extsyntax in aktswitches)) and
- assigned(p^.right^.resulttype) and
- (p^.right^.resulttype<>pdef(voiddef)) then
- Message(cg_e_illegal_expression);
- if codegenerror then
- exit;
- p^.registers32:=p^.right^.registers32;
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- firstpass(p^.left);
- if codegenerror then
- exit;
- if p^.right^.registers32>p^.registers32 then
- p^.registers32:=p^.right^.registers32;
- if p^.right^.registersfpu>p^.registersfpu then
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.right^.registersmmx>p^.registersmmx then
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif}
- end;
- procedure firstblock(var p : ptree);
- var
- hp : ptree;
- count : longint;
- begin
- count:=0;
- hp:=p^.left;
- while assigned(hp) do
- begin
- if cs_maxoptimieren in aktswitches then
- begin
- { Codeumstellungen }
- { Funktionsresultate an exit anh„ngen }
- { this is wrong for string or other complex
- result types !!! }
- if ret_in_acc(procinfo.retdef) and
- assigned(hp^.left) and
- (hp^.left^.right^.treetype=exitn) and
- (hp^.right^.treetype=assignn) and
- (hp^.right^.left^.treetype=funcretn) then
- begin
- if assigned(hp^.left^.right^.left) then
- Message(cg_n_inefficient_code)
- else
- begin
- hp^.left^.right^.left:=getcopy(hp^.right^.right);
- disposetree(hp^.right);
- hp^.right:=nil;
- end;
- end
- { warning if unreachable code occurs and elimate this }
- else if (hp^.right^.treetype in
- [exitn,breakn,continuen,goton]) and
- assigned(hp^.left) and
- (hp^.left^.treetype<>labeln) then
- begin
- { use correct line number }
- set_current_file_line(hp^.left);
- disposetree(hp^.left);
- hp^.left:=nil;
- Message(cg_w_unreachable_code);
- { old lines }
- set_current_file_line(hp^.right);
- end;
- end;
- if assigned(hp^.right) then
- begin
- cleartempgen;
- firstpass(hp^.right);
- if (not (cs_extsyntax in aktswitches)) and
- assigned(hp^.right^.resulttype) and
- (hp^.right^.resulttype<>pdef(voiddef)) then
- Message(cg_e_illegal_expression);
- if codegenerror then
- exit;
- hp^.registers32:=hp^.right^.registers32;
- hp^.registersfpu:=hp^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- hp^.registersmmx:=hp^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- end
- else
- hp^.registers32:=0;
- if hp^.registers32>p^.registers32 then
- p^.registers32:=hp^.registers32;
- if hp^.registersfpu>p^.registersfpu then
- p^.registersfpu:=hp^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if hp^.registersmmx>p^.registersmmx then
- p^.registersmmx:=hp^.registersmmx;
- {$endif}
- inc(count);
- hp:=hp^.left;
- end;
- { p^.registers32:=round(p^.registers32/count); }
- end;
- procedure first_while_repeat(var p : ptree);
- var
- old_t_times : longint;
- begin
- old_t_times:=t_times;
- { Registergewichtung bestimmen }
- if not(cs_littlesize in aktswitches ) then
- t_times:=t_times*8;
- cleartempgen;
- must_be_valid:=true;
- firstpass(p^.left);
- if codegenerror then
- exit;
- if not((p^.left^.resulttype^.deftype=orddef) and
- (porddef(p^.left^.resulttype)^.typ=bool8bit)) then
- begin
- Message(sym_e_type_mismatch);
- exit;
- end;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { loop instruction }
- if assigned(p^.right) then
- begin
- cleartempgen;
- firstpass(p^.right);
- if codegenerror then
- exit;
- if p^.registers32<p^.right^.registers32 then
- p^.registers32:=p^.right^.registers32;
- if p^.registersfpu<p^.right^.registersfpu then
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.registersmmx<p^.right^.registersmmx then
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- t_times:=old_t_times;
- end;
- procedure firstif(var p : ptree);
- var
- old_t_times : longint;
- hp : ptree;
- begin
- old_t_times:=t_times;
- cleartempgen;
- must_be_valid:=true;
- firstpass(p^.left);
- if codegenerror then
- exit;
- if not((p^.left^.resulttype^.deftype=orddef) and
- (porddef(p^.left^.resulttype)^.typ=bool8bit)) then
- begin
- Message(sym_e_type_mismatch);
- exit;
- end;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { determines registers weigths }
- if not(cs_littlesize in aktswitches ) then
- t_times:=t_times div 2;
- if t_times=0 then
- t_times:=1;
- { if path }
- if assigned(p^.right) then
- begin
- cleartempgen;
- firstpass(p^.right);
- if codegenerror then
- exit;
- if p^.registers32<p^.right^.registers32 then
- p^.registers32:=p^.right^.registers32;
- if p^.registersfpu<p^.right^.registersfpu then
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.registersmmx<p^.right^.registersmmx then
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- { else path }
- if assigned(p^.t1) then
- begin
- cleartempgen;
- firstpass(p^.t1);
- if codegenerror then
- exit;
- if p^.registers32<p^.t1^.registers32 then
- p^.registers32:=p^.t1^.registers32;
- if p^.registersfpu<p^.t1^.registersfpu then
- p^.registersfpu:=p^.t1^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.registersmmx<p^.t1^.registersmmx then
- p^.registersmmx:=p^.t1^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- if p^.left^.treetype=ordconstn then
- begin
- { optimize }
- if p^.left^.value=1 then
- begin
- disposetree(p^.left);
- hp:=p^.right;
- disposetree(p^.t1);
- { we cannot set p to nil !!! }
- if assigned(hp) then
- begin
- putnode(p);
- p:=hp;
- end
- else
- begin
- p^.left:=nil;
- p^.t1:=nil;
- p^.treetype:=nothingn;
- end;
- end
- else
- begin
- disposetree(p^.left);
- hp:=p^.t1;
- disposetree(p^.right);
- { we cannot set p to nil !!! }
- if assigned(hp) then
- begin
- putnode(p);
- p:=hp;
- end
- else
- begin
- p^.left:=nil;
- p^.right:=nil;
- p^.treetype:=nothingn;
- end;
- end;
- end;
- t_times:=old_t_times;
- end;
- procedure firstexitn(var p : ptree);
- begin
- if assigned(p^.left) then
- begin
- firstpass(p^.left);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- end;
- procedure firstfor(var p : ptree);
- var
- old_t_times : longint;
- begin
- { Registergewichtung bestimmen
- (nicht genau), }
- old_t_times:=t_times;
- if not(cs_littlesize in aktswitches ) then
- t_times:=t_times*8;
- cleartempgen;
- if p^.t1<>nil then
- firstpass(p^.t1);
- p^.registers32:=p^.t1^.registers32;
- p^.registersfpu:=p^.t1^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if p^.left^.treetype<>assignn then
- Message(cg_e_illegal_expression);
- { Laufvariable retten }
- p^.t2:=getcopy(p^.left^.left);
- { Check count var }
- if (p^.t2^.treetype<>loadn) then
- Message(cg_e_illegal_count_var);
- if (not(is_ordinal(p^.t2^.resulttype))) then
- Message(parser_e_ordinal_expected);
- cleartempgen;
- must_be_valid:=false;
- firstpass(p^.left);
- must_be_valid:=true;
- if p^.left^.registers32>p^.registers32 then
- p^.registers32:=p^.left^.registers32;
- if p^.left^.registersfpu>p^.registersfpu then
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.left^.registersmmx>p^.registersmmx then
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- cleartempgen;
- firstpass(p^.t2);
- if p^.t2^.registers32>p^.registers32 then
- p^.registers32:=p^.t2^.registers32;
- if p^.t2^.registersfpu>p^.registersfpu then
- p^.registersfpu:=p^.t2^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.t2^.registersmmx>p^.registersmmx then
- p^.registersmmx:=p^.t2^.registersmmx;
- {$endif SUPPORT_MMX}
- cleartempgen;
- firstpass(p^.right);
- if p^.right^.treetype<>ordconstn then
- begin
- p^.right:=gentypeconvnode(p^.right,p^.t2^.resulttype);
- cleartempgen;
- firstpass(p^.right);
- end;
- if p^.right^.registers32>p^.registers32 then
- p^.registers32:=p^.right^.registers32;
- if p^.right^.registersfpu>p^.registersfpu then
- p^.registersfpu:=p^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.right^.registersmmx>p^.registersmmx then
- p^.registersmmx:=p^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- t_times:=old_t_times;
- end;
- procedure firstasm(var p : ptree);
- begin
- { it's a f... to determine the used registers }
- { should be done by getnode
- I think also, that all values should be set to their maximum (FK)
- p^.registers32:=0;
- p^.registersfpu:=0;
- p^.registersmmx:=0;
- }
- procinfo.flags:=procinfo.flags or pi_uses_asm;
- end;
- procedure firstgoto(var p : ptree);
- begin
- {
- p^.registers32:=0;
- p^.registersfpu:=0;
- }
- p^.resulttype:=voiddef;
- end;
- procedure firstlabel(var p : ptree);
- begin
- cleartempgen;
- firstpass(p^.left);
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- p^.resulttype:=voiddef;
- end;
- procedure firstcase(var p : ptree);
- var
- old_t_times : longint;
- hp : ptree;
- begin
- { evalutes the case expression }
- cleartempgen;
- must_be_valid:=true;
- firstpass(p^.left);
- if codegenerror then
- exit;
- p^.registers32:=p^.left^.registers32;
- p^.registersfpu:=p^.left^.registersfpu;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- { walk through all instructions }
- { estimates the repeat of each instruction }
- old_t_times:=t_times;
- if not(cs_littlesize in aktswitches ) then
- begin
- t_times:=t_times div case_count_labels(p^.nodes);
- if t_times<1 then
- t_times:=1;
- end;
- { first case }
- hp:=p^.right;
- while assigned(hp) do
- begin
- cleartempgen;
- firstpass(hp^.right);
- { searchs max registers }
- if hp^.right^.registers32>p^.registers32 then
- p^.registers32:=hp^.right^.registers32;
- if hp^.right^.registersfpu>p^.registersfpu then
- p^.registersfpu:=hp^.right^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if hp^.right^.registersmmx>p^.registersmmx then
- p^.registersmmx:=hp^.right^.registersmmx;
- {$endif SUPPORT_MMX}
- hp:=hp^.left;
- end;
- { may be handle else tree }
- if assigned(p^.elseblock) then
- begin
- cleartempgen;
- firstpass(p^.elseblock);
- if codegenerror then
- exit;
- if p^.registers32<p^.elseblock^.registers32 then
- p^.registers32:=p^.elseblock^.registers32;
- if p^.registersfpu<p^.elseblock^.registersfpu then
- p^.registersfpu:=p^.elseblock^.registersfpu;
- {$ifdef SUPPORT_MMX}
- if p^.registersmmx<p^.elseblock^.registersmmx then
- p^.registersmmx:=p^.elseblock^.registersmmx;
- {$endif SUPPORT_MMX}
- end;
- t_times:=old_t_times;
- { there is one register required for the case expression }
- if p^.registers32<1 then p^.registers32:=1;
- end;
- procedure firsttryexcept(var p : ptree);
- begin
- end;
- procedure firsttryfinally(var p : ptree);
- begin
- end;
- procedure firstis(var p : ptree);
- begin
- firstpass(p^.left);
- firstpass(p^.right);
- if (p^.right^.resulttype^.deftype<>classrefdef) then
- Message(sym_e_type_mismatch);
- if codegenerror then
- exit;
- p^.registersfpu:=max(p^.left^.registersfpu,p^.right^.registersfpu);
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- { left must be a class }
- if (p^.left^.resulttype^.deftype<>objectdef) or
- not(pobjectdef(p^.left^.resulttype)^.isclass) then
- Message(sym_e_type_mismatch);
- { the operands must be related }
- if (not(pobjectdef(p^.left^.resulttype)^.isrelated(
- pobjectdef(pclassrefdef(p^.right^.resulttype)^.definition)))) and
- (not(pobjectdef(pclassrefdef(p^.right^.resulttype)^.definition)^.isrelated(
- pobjectdef(p^.left^.resulttype)))) then
- Message(sym_e_type_mismatch);
- p^.location.loc:=LOC_FLAGS;
- p^.resulttype:=booldef;
- end;
- procedure firstas(var p : ptree);
- begin
- firstpass(p^.right);
- firstpass(p^.left);
- if (p^.right^.resulttype^.deftype<>classrefdef) then
- Message(sym_e_type_mismatch);
- if codegenerror then
- exit;
- p^.registersfpu:=max(p^.left^.registersfpu,p^.left^.registersfpu);
- p^.registers32:=max(p^.left^.registers32,p^.right^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- { left must be a class }
- if (p^.left^.resulttype^.deftype<>objectdef) or
- not(pobjectdef(p^.left^.resulttype)^.isclass) then
- Message(sym_e_type_mismatch);
- { the operands must be related }
- if (not(pobjectdef(p^.left^.resulttype)^.isrelated(
- pobjectdef(pclassrefdef(p^.right^.resulttype)^.definition)))) and
- (not(pobjectdef(pclassrefdef(p^.right^.resulttype)^.definition)^.isrelated(
- pobjectdef(p^.left^.resulttype)))) then
- Message(sym_e_type_mismatch);
- p^.location:=p^.left^.location;
- p^.resulttype:=pclassrefdef(p^.right^.resulttype)^.definition;
- end;
- procedure firstloadvmt(var p : ptree);
- begin
- { resulttype must be set !
- p^.registersfpu:=0;
- }
- p^.registers32:=1;
- p^.location.loc:=LOC_REGISTER;
- end;
- procedure firstraise(var p : ptree);
- begin
- p^.resulttype:=voiddef;
- {
- p^.registersfpu:=0;
- p^.registers32:=0;
- }
- if assigned(p^.left) then
- begin
- firstpass(p^.left);
- { this must be a _class_ }
- if (p^.left^.resulttype^.deftype<>objectdef) or
- ((pobjectdef(p^.left^.resulttype)^.options and oois_class)=0) then
- Message(sym_e_type_mismatch);
- p^.registersfpu:=p^.left^.registersfpu;
- p^.registers32:=p^.left^.registers32;
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=p^.left^.registersmmx;
- {$endif SUPPORT_MMX}
- if assigned(p^.right) then
- begin
- firstpass(p^.right);
- p^.right:=gentypeconvnode(p^.right,s32bitdef);
- firstpass(p^.right);
- p^.registersfpu:=max(p^.left^.registersfpu,
- p^.right^.registersfpu);
- p^.registers32:=max(p^.left^.registers32,
- p^.right^.registers32);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,
- p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- end;
- end;
- end;
- procedure firstwith(var p : ptree);
- begin
- if assigned(p^.left) and assigned(p^.right) then
- begin
- firstpass(p^.left);
- if codegenerror then
- exit;
- firstpass(p^.right);
- if codegenerror then
- exit;
- p^.registers32:=max(p^.left^.registers32,
- p^.right^.registers32);
- p^.registersfpu:=max(p^.left^.registersfpu,
- p^.right^.registersfpu);
- {$ifdef SUPPORT_MMX}
- p^.registersmmx:=max(p^.left^.registersmmx,
- p^.right^.registersmmx);
- {$endif SUPPORT_MMX}
- p^.resulttype:=voiddef;
- end
- else
- begin
- { optimization }
- disposetree(p);
- p:=nil;
- end;
- end;
- procedure firstprocinline(var p : ptree);
- begin
- {left contains the code in tree form }
- { but it has already been firstpassed }
- { so firstpass(p^.left); does not seem required }
- { might be required later if we change the arg handling !! }
- end;
- type
- firstpassproc = procedure(var p : ptree);
- procedure firstpass(var p : ptree);
- (* ttreetyp = (addn, {Represents the + operator.}
- muln, {Represents the * operator.}
- subn, {Represents the - operator.}
- divn, {Represents the div operator.}
- symdifn, {Represents the >< operator.}
- modn, {Represents the mod operator.}
- assignn, {Represents an assignment.}
- loadn, {Represents the use of a variabele.}
- rangen, {Represents a range (i.e. 0..9).}
- ltn, {Represents the < operator.}
- lten, {Represents the <= operator.}
- gtn, {Represents the > operator.}
- gten, {Represents the >= operator.}
- equaln, {Represents the = operator.}
- unequaln, {Represents the <> operator.}
- inn, {Represents the in operator.}
- orn, {Represents the or operator.}
- xorn, {Represents the xor operator.}
- shrn, {Represents the shr operator.}
- shln, {Represents the shl operator.}
- slashn, {Represents the / operator.}
- andn, {Represents the and operator.}
- subscriptn, {??? Field in a record/object?}
- derefn, {Dereferences a pointer.}
- addrn, {Represents the @ operator.}
- doubleaddrn, {Represents the @@ operator.}
- ordconstn, {Represents an ordinal value.}
- typeconvn, {Represents type-conversion/typecast.}
- calln, {Represents a call node.}
- callparan, {Represents a parameter.}
- realconstn, {Represents a real value.}
- fixconstn, {Represents a fixed value.}
- umminusn, {Represents a sign change (i.e. -2).}
- asmn, {Represents an assembler node }
- vecn, {Represents array indexing.}
- stringconstn, {Represents a string constant.}
- funcretn, {Represents the function result var.}
- selfn, {Represents the self parameter.}
- notn, {Represents the not operator.}
- inlinen, {Internal procedures (i.e. writeln).}
- niln, {Represents the nil pointer.}
- errorn, {This part of the tree could not be
- parsed because of a compiler error.}
- typen, {A type name. Used for i.e. typeof(obj).}
- hnewn, {The new operation, constructor call.}
- hdisposen, {The dispose operation with destructor call.}
- newn, {The new operation, constructor call.}
- simpledisposen, {The dispose operation.}
- setelen, {A set element (i.e. [a,b]).}
- setconstrn, {A set constant (i.e. [1,2]).}
- blockn, {A block of statements.}
- statementn, {One statement in list of nodes.}
- loopn, { used in genloopnode, must be converted }
- ifn, {An if statement.}
- breakn, {A break statement.}
- continuen, {A continue statement.}
- repeatn, {A repeat until block.}
- whilen, {A while do statement.}
- forn, {A for loop.}
- exitn, {An exit statement.}
- withn, {A with statement.}
- casen, {A case statement.}
- labeln, {A label.}
- goton, {A goto statement.}
- simplenewn, {The new operation.}
- tryexceptn, {A try except block.}
- raisen, {A raise statement.}
- switchesn, {??? Currently unused...}
- tryfinallyn, {A try finally statement.}
- isn, {Represents the is operator.}
- asn, {Represents the as typecast.}
- caretn, {Represents the ^ operator.}
- failn, {Represents the fail statement.}
- starstarn, {Represents the ** operator exponentiation }
- procinlinen, {Procedures that can be inlined }
- { added for optimizations where we cannot suppress }
- nothingn,
- loadvmtn); {???.} *)
- const
- procedures : array[ttreetyp] of firstpassproc =
- (firstadd,firstadd,firstadd,firstmoddiv,firstadd,
- firstmoddiv,firstassignment,firstload,firstrange,
- firstadd,firstadd,firstadd,firstadd,
- firstadd,firstadd,firstin,firstadd,
- firstadd,firstshlshr,firstshlshr,firstadd,
- firstadd,firstsubscriptn,firstderef,firstaddr,firstdoubleaddr,
- firstordconst,firsttypeconv,firstcalln,firstnothing,
- firstrealconst,firstfixconst,firstumminus,firstasm,firstvecn,
- firststringconst,firstfuncret,firstselfn,
- firstnot,firstinline,firstniln,firsterror,
- firsttypen,firsthnewn,firsthdisposen,firstnewn,
- firstsimplenewdispose,firstnothing,firstsetcons,firstblock,
- firststatement,firstnothing,firstif,firstnothing,
- firstnothing,first_while_repeat,first_while_repeat,firstfor,
- firstexitn,firstwith,firstcase,firstlabel,
- firstgoto,firstsimplenewdispose,firsttryexcept,firstraise,
- firstnothing,firsttryfinally,firstis,firstas,firstadd,
- firstnothing,firstadd,firstprocinline,firstnothing,firstloadvmt);
- var
- oldcodegenerror : boolean;
- oldswitches : Tcswitches;
- { there some calls of do_firstpass in the parser }
- oldis : pinputfile;
- oldnr : longint;
- begin
- { if we save there the whole stuff, }
- { line numbers become more correct }
- oldis:=current_module^.current_inputfile;
- oldnr:=current_module^.current_inputfile^.line_no;
- oldcodegenerror:=codegenerror;
- oldswitches:=aktswitches;
- {$ifdef extdebug}
- inc(p^.firstpasscount);
- {$endif extdebug}
- codegenerror:=false;
- current_module^.current_inputfile:=
- pinputfile(current_module^.sourcefiles.get_file(p^.fileinfo.fileindex));
- current_module^.current_inputfile^.line_no:=p^.fileinfo.line;
- aktswitches:=p^.pragmas;
- if not(p^.error) then
- begin
- procedures[p^.treetype](p);
- p^.error:=codegenerror;
- codegenerror:=codegenerror or oldcodegenerror;
- end
- else codegenerror:=true;
- aktswitches:=oldswitches;
- current_module^.current_inputfile:=oldis;
- current_module^.current_inputfile^.line_no:=oldnr;
- end;
- function do_firstpass(var p : ptree) : boolean;
- begin
- codegenerror:=false;
- firstpass(p);
- do_firstpass:=codegenerror;
- end;
- { to be called only for a whole function }
- { to insert code at entry and exit }
- function function_firstpass(var p : ptree) : boolean;
- begin
- codegenerror:=false;
- firstpass(p);
- function_firstpass:=codegenerror;
- end;
- end.
- {
- $Log$
- Revision 1.14 1998-04-30 15:59:41 pierre
- * GDB works again better :
- correct type info in one pass
- + UseTokenInfo for better source position
- * fixed one remaining bug in scanner for line counts
- * several little fixes
- Revision 1.13 1998/04/29 10:33:56 pierre
- + added some code for ansistring (not complete nor working yet)
- * corrected operator overloading
- * corrected nasm output
- + started inline procedures
- + added starstarn : use ** for exponentiation (^ gave problems)
- + started UseTokenInfo cond to get accurate positions
- Revision 1.12 1998/04/22 21:06:50 florian
- * last fixes before the release:
- - veryyyy slow firstcall fixed
- Revision 1.11 1998/04/21 10:16:48 peter
- * patches from strasbourg
- * objects is not used anymore in the fpc compiled version
- Revision 1.10 1998/04/14 23:27:03 florian
- + exclude/include with constant second parameter added
- Revision 1.9 1998/04/13 21:15:42 florian
- * error handling of pass_1 and cgi386 fixed
- * the following bugs fixed: 0117, 0118, 0119 and 0129, 0122 was already
- fixed, verified
- Revision 1.8 1998/04/13 08:42:52 florian
- * call by reference and call by value open arrays fixed
- Revision 1.7 1998/04/12 22:39:44 florian
- * problem with read access to properties solved
- * correct handling of hidding methods via virtual (COM)
- * correct result type of constructor calls (COM), the resulttype
- depends now on the type of the class reference
- Revision 1.6 1998/04/09 22:16:34 florian
- * problem with previous REGALLOC solved
- * improved property support
- Revision 1.5 1998/04/08 16:58:04 pierre
- * several bugfixes
- ADD ADC and AND are also sign extended
- nasm output OK (program still crashes at end
- and creates wrong assembler files !!)
- procsym types sym in tdef removed !!
- Revision 1.4 1998/04/07 22:45:04 florian
- * bug0092, bug0115 and bug0121 fixed
- + packed object/class/array
- Revision 1.3 1998/03/28 23:09:56 florian
- * secondin bugfix (m68k and i386)
- * overflow checking bugfix (m68k and i386) -- pretty useless in
- secondadd, since everything is done using 32-bit
- * loading pointer to routines hopefully fixed (m68k)
- * flags problem with calls to RTL internal routines fixed (still strcmp
- to fix) (m68k)
- * #ELSE was still incorrect (didn't take care of the previous level)
- * problem with filenames in the command line solved
- * problem with mangledname solved
- * linking name problem solved (was case insensitive)
- * double id problem and potential crash solved
- * stop after first error
- * and=>test problem removed
- * correct read for all float types
- * 2 sigsegv fixes and a cosmetic fix for Internal Error
- * push/pop is now correct optimized (=> mov (%esp),reg)
- Revision 1.2 1998/03/26 11:18:31 florian
- - switch -Sa removed
- - support of a:=b:=0 removed
- Revision 1.1.1.1 1998/03/25 11:18:14 root
- * Restored version
- Revision 1.41 1998/03/13 22:45:59 florian
- * small bug fixes applied
- Revision 1.40 1998/03/10 23:48:36 florian
- * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
- enough, it doesn't run
- Revision 1.39 1998/03/10 16:27:41 pierre
- * better line info in stabs debug
- * symtabletype and lexlevel separated into two fields of tsymtable
- + ifdef MAKELIB for direct library output, not complete
- + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
- working
- + ifdef TESTFUNCRET for setting func result in underfunction, not
- working
- Revision 1.38 1998/03/10 01:11:11 peter
- * removed one of my previous optimizations with string+char, which
- generated wrong code
- Revision 1.37 1998/03/09 10:44:38 peter
- + string='', string<>'', string:='', string:=char optimizes (the first 2
- were already in cg68k2)
- Revision 1.36 1998/03/06 00:52:38 peter
- * replaced all old messages from errore.msg, only ExtDebug and some
- Comment() calls are left
- * fixed options.pas
- Revision 1.35 1998/03/04 08:38:19 florian
- * problem with unary minus fixed
- Revision 1.34 1998/03/03 01:08:31 florian
- * bug0105 and bug0106 problem solved
- Revision 1.33 1998/03/02 01:48:56 peter
- * renamed target_DOS to target_GO32V1
- + new verbose system, merged old errors and verbose units into one new
- verbose.pas, so errors.pas is obsolete
- Revision 1.32 1998/03/01 22:46:14 florian
- + some win95 linking stuff
- * a couple of bugs fixed:
- bug0055,bug0058,bug0059,bug0064,bug0072,bug0093,bug0095,bug0098
- Revision 1.31 1998/02/28 17:26:46 carl
- * bugfix #47 and more checking for aprocdef
- Revision 1.30 1998/02/13 10:35:20 daniel
- * Made Motorola version compilable.
- * Fixed optimizer
- Revision 1.29 1998/02/12 17:19:16 florian
- * fixed to get remake3 work, but needs additional fixes (output, I don't like
- also that aktswitches isn't a pointer)
- Revision 1.28 1998/02/12 11:50:23 daniel
- Yes! Finally! After three retries, my patch!
- Changes:
- Complete rewrite of psub.pas.
- Added support for DLL's.
- Compiler requires less memory.
- Platform units for each platform.
- Revision 1.27 1998/02/11 21:56:34 florian
- * bugfixes: bug0093, bug0053, bug0088, bug0087, bug0089
- Revision 1.26 1998/02/07 23:05:03 florian
- * once more MMX
- Revision 1.25 1998/02/07 09:39:24 florian
- * correct handling of in_main
- + $D,$T,$X,$V like tp
- Revision 1.24 1998/02/06 10:34:21 florian
- * bug0082 and bug0084 fixed
- Revision 1.23 1998/02/05 21:54:34 florian
- + more MMX
- Revision 1.22 1998/02/05 20:54:30 peter
- * fixed a Sigsegv
- Revision 1.21 1998/02/04 23:04:21 florian
- + unary minus for mmx data types added
- Revision 1.20 1998/02/04 22:00:56 florian
- + NOT operator for mmx arrays
- Revision 1.19 1998/02/04 14:38:49 florian
- * clean up
- * a lot of potential bugs removed adding some neccessary register allocations
- (FPU!)
- + allocation of MMX registers
- Revision 1.18 1998/02/03 23:07:34 florian
- * AS and IS do now a correct type checking
- + is_convertable handles now also instances of classes
- Revision 1.17 1998/02/01 19:40:51 florian
- * clean up
- * bug0029 fixed
- Revision 1.16 1998/02/01 17:14:04 florian
- + comparsion of class references
- Revision 1.15 1998/01/30 21:23:59 carl
- * bugfix of compiler crash with new/dispose (fourth crash of new bug)
- * bugfix of write/read compiler crash
- Revision 1.14 1998/01/25 22:29:00 florian
- * a lot bug fixes on the DOM
- Revision 1.13 1998/01/21 22:34:25 florian
- + comparsion of Delphi classes
- Revision 1.12 1998/01/21 21:29:55 florian
- * some fixes for Delphi classes
- Revision 1.11 1998/01/16 23:34:13 florian
- + nil is compatible with class variable (tobject(x):=nil)
- Revision 1.10 1998/01/16 22:34:40 michael
- * Changed 'conversation' to 'conversion'. Waayyy too much chatting going on
- in this compiler :)
- Revision 1.9 1998/01/13 23:11:10 florian
- + class methods
- Revision 1.8 1998/01/07 00:17:01 michael
- Restored released version (plus fixes) as current
- Revision 1.7 1997/12/10 23:07:26 florian
- * bugs fixed: 12,38 (also m68k),39,40,41
- + warning if a system unit is without -Us compiled
- + warning if a method is virtual and private (was an error)
- * some indentions changed
- + factor does a better error recovering (omit some crashes)
- + problem with @type(x) removed (crashed the compiler)
- Revision 1.6 1997/12/09 13:54:26 carl
- + renamed some stuff (real types mostly)
- Revision 1.5 1997/12/04 12:02:19 pierre
- + added a counter of max firstpass's for a ptree
- for debugging only in ifdef extdebug
- Revision 1.4 1997/12/03 13:53:01 carl
- + ifdef i386.
- Revision 1.3 1997/11/29 15:38:43 florian
- * bug0033 fixed
- * duplicate strings are now really once generated (there was a bug)
- Revision 1.2 1997/11/28 11:11:43 pierre
- negativ real constants are not supported by nasm assembler
- Revision 1.1.1.1 1997/11/27 08:32:59 michael
- FPC Compiler CVS start
- Pre-CVS log:
- CEC Carl-Eric Codere
- FK Florian Klaempfl
- PM Pierre Muller
- + feature added
- - removed
- * bug fixed or changed
- History:
- 6th september 1997:
- + added basic support for MC68000 (CEC)
- (lines: 189,1860,1884 + ifdef m68k)
- 19th september 1997:
- + added evalution of constant sets (FK)
- + empty and constant sets are now compatible with all other
- set types (FK)
- 20th september 1997:
- * p^.register32 bug in firstcalln (max with register32 of p^.left i.e. args) (PM)
- 24th september 1997:
- * line_no and inputfile are now in firstpass saved (FK)
- 25th september 1997:
- + support of high for open arrays (FK)
- + the high parameter is now pushed for open arrays (FK)
- 1th october 1997:
- + added support for unary minus operator and for:=overloading (PM)
- 2nd october 1997:
- + added handling of in_ord_x (PM)
- boolean to byte with ord is special because the location may be different
- 3rd october 1997:
- + renamed ret_in_eax to ret_in_acc (CEC)
- + find ifdef m68k to find other changes (CEC)
- * bugfix or calc correct val for regs. for m68k in firstcalln (CEC)
- 4th october 1997:
- + added code for in_pred_x in_succ_x
- fails for enums with jumps (PM)
- 25th october 1997:
- + direct evalution of pred and succ with const parameter (FK)
- 6th november 1997:
- * added typeconversion for floatdef in write(ln) for text to s64real (PM)
- + code for str with length arg rewritten (PM)
- 13th november 1997:
- * floatdef in write(ln) for text for different types in RTL (PM)
- * bug causing convertability from floatdef to orddef removed (PM)
- * typecasting from voiddef to any type not allowed anymore (PM)
- + handling of different real const to diff realtype (PM)
- 18th november 1997:
- * changed first_type_conv function arg as var p : ptree
- to be able to change the tree (PM)
- }
|