twobit-input-long.sch 850 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795217962179721798217992180021801218022180321804218052180621807218082180921810218112181221813218142181521816218172181821819218202182121822218232182421825218262182721828218292183021831218322183321834218352183621837218382183921840218412184221843218442184521846218472184821849218502185121852218532185421855218562185721858218592186021861218622186321864218652186621867218682186921870218712187221873218742187521876218772187821879218802188121882218832188421885218862188721888218892189021891218922189321894218952189621897218982189921900219012190221903219042190521906219072190821909219102191121912219132191421915219162191721918219192192021921219222192321924219252192621927219282192921930219312193221933219342193521936219372193821939219402194121942219432194421945219462194721948219492195021951219522195321954219552195621957219582195921960219612196221963219642196521966219672196821969219702197121972219732197421975219762197721978219792198021981219822198321984219852198621987219882198921990219912199221993219942199521996219972199821999220002200122002220032200422005220062200722008220092201022011220122201322014220152201622017220182201922020220212202222023220242202522026220272202822029220302203122032220332203422035220362203722038220392204022041220422204322044220452204622047220482204922050220512205222053220542205522056220572205822059220602206122062220632206422065220662206722068220692207022071220722207322074220752207622077220782207922080220812208222083220842208522086220872208822089220902209122092220932209422095220962209722098220992210022101221022210322104221052210622107221082210922110221112211222113221142211522116221172211822119221202212122122221232212422125221262212722128221292213022131221322213322134221352213622137221382213922140221412214222143221442214522146221472214822149221502215122152221532215422155221562215722158221592216022161221622216322164221652216622167221682216922170221712217222173221742217522176221772217822179221802218122182221832218422185221862218722188221892219022191221922219322194221952219622197221982219922200222012220222203222042220522206222072220822209222102221122212222132221422215222162221722218222192222022221222222222322224222252222622227222282222922230222312223222233222342223522236222372223822239222402224122242222432224422245222462224722248222492225022251222522225322254222552225622257222582225922260222612226222263222642226522266222672226822269222702227122272222732227422275222762227722278222792228022281222822228322284222852228622287222882228922290222912229222293222942229522296222972229822299223002230122302223032230422305223062230722308223092231022311223122231322314223152231622317223182231922320223212232222323223242232522326223272232822329223302233122332223332233422335223362233722338223392234022341223422234322344223452234622347223482234922350223512235222353223542235522356223572235822359223602236122362223632236422365223662236722368223692237022371223722237322374223752237622377223782237922380223812238222383223842238522386223872238822389223902239122392223932239422395223962239722398223992240022401224022240322404224052240622407224082240922410224112241222413224142241522416224172241822419224202242122422224232242422425224262242722428224292243022431224322243322434224352243622437224382243922440224412244222443224442244522446224472244822449224502245122452224532245422455224562245722458224592246022461224622246322464224652246622467224682246922470224712247222473224742247522476224772247822479224802248122482224832248422485224862248722488224892249022491224922249322494224952249622497224982249922500225012250222503225042250522506225072250822509225102251122512225132251422515225162251722518225192252022521225222252322524225252252622527225282252922530225312253222533225342253522536225372253822539225402254122542225432254422545225462254722548225492255022551225522255322554225552255622557225582255922560225612256222563225642256522566225672256822569225702257122572225732257422575225762257722578225792258022581225822258322584225852258622587225882258922590225912259222593225942259522596225972259822599226002260122602226032260422605226062260722608226092261022611226122261322614226152261622617226182261922620226212262222623226242262522626226272262822629226302263122632226332263422635226362263722638226392264022641226422264322644226452264622647226482264922650226512265222653226542265522656226572265822659226602266122662226632266422665226662266722668226692267022671226722267322674226752267622677226782267922680226812268222683226842268522686226872268822689226902269122692226932269422695226962269722698226992270022701227022270322704227052270622707227082270922710227112271222713227142271522716227172271822719227202272122722227232272422725227262272722728227292273022731227322273322734227352273622737227382273922740227412274222743227442274522746227472274822749227502275122752227532275422755227562275722758227592276022761227622276322764227652276622767227682276922770227712277222773227742277522776227772277822779227802278122782227832278422785227862278722788227892279022791227922279322794227952279622797227982279922800228012280222803228042280522806228072280822809228102281122812228132281422815228162281722818228192282022821228222282322824228252282622827228282282922830228312283222833228342283522836228372283822839228402284122842228432284422845228462284722848228492285022851228522285322854228552285622857228582285922860228612286222863228642286522866228672286822869228702287122872228732287422875228762287722878228792288022881228822288322884228852288622887228882288922890228912289222893228942289522896228972289822899229002290122902229032290422905229062290722908229092291022911229122291322914229152291622917229182291922920229212292222923229242292522926229272292822929229302293122932229332293422935229362293722938229392294022941229422294322944229452294622947229482294922950229512295222953229542295522956229572295822959229602296122962229632296422965229662296722968229692297022971229722297322974229752297622977229782297922980229812298222983229842298522986229872298822989229902299122992229932299422995229962299722998229992300023001230022300323004230052300623007230082300923010230112301223013230142301523016230172301823019230202302123022230232302423025230262302723028230292303023031230322303323034230352303623037230382303923040230412304223043230442304523046230472304823049230502305123052230532305423055230562305723058230592306023061230622306323064230652306623067230682306923070230712307223073230742307523076230772307823079230802308123082230832308423085230862308723088230892309023091230922309323094230952309623097230982309923100231012310223103231042310523106231072310823109231102311123112231132311423115231162311723118231192312023121231222312323124231252312623127231282312923130231312313223133231342313523136231372313823139231402314123142231432314423145231462314723148231492315023151231522315323154231552315623157231582315923160231612316223163231642316523166231672316823169231702317123172231732317423175231762317723178231792318023181231822318323184231852318623187231882318923190231912319223193231942319523196231972319823199232002320123202232032320423205232062320723208232092321023211232122321323214232152321623217232182321923220232212322223223232242322523226232272322823229232302323123232232332323423235232362323723238232392324023241232422324323244232452324623247232482324923250232512325223253232542325523256232572325823259232602326123262232632326423265232662326723268232692327023271232722327323274232752327623277232782327923280232812328223283232842328523286232872328823289232902329123292232932329423295232962329723298232992330023301233022330323304233052330623307233082330923310233112331223313233142331523316233172331823319233202332123322233232332423325233262332723328233292333023331233322333323334233352333623337233382333923340233412334223343233442334523346233472334823349233502335123352233532335423355233562335723358233592336023361233622336323364233652336623367233682336923370233712337223373233742337523376233772337823379233802338123382233832338423385233862338723388233892339023391233922339323394233952339623397233982339923400234012340223403234042340523406234072340823409234102341123412234132341423415234162341723418234192342023421234222342323424234252342623427234282342923430234312343223433234342343523436234372343823439234402344123442234432344423445234462344723448234492345023451234522345323454234552345623457234582345923460234612346223463234642346523466234672346823469234702347123472234732347423475234762347723478234792348023481234822348323484234852348623487234882348923490234912349223493234942349523496234972349823499235002350123502235032350423505235062350723508235092351023511235122351323514235152351623517235182351923520235212352223523235242352523526235272352823529235302353123532235332353423535235362353723538235392354023541235422354323544235452354623547235482354923550235512355223553235542355523556235572355823559235602356123562235632356423565235662356723568235692357023571235722357323574235752357623577235782357923580235812358223583235842358523586235872358823589235902359123592235932359423595235962359723598235992360023601236022360323604236052360623607236082360923610236112361223613236142361523616236172361823619236202362123622236232362423625236262362723628236292363023631236322363323634236352363623637236382363923640236412364223643236442364523646236472364823649236502365123652236532365423655236562365723658236592366023661236622366323664236652366623667236682366923670236712367223673236742367523676236772367823679236802368123682236832368423685236862368723688236892369023691236922369323694236952369623697236982369923700237012370223703237042370523706237072370823709237102371123712237132371423715237162371723718237192372023721237222372323724237252372623727237282372923730237312373223733237342373523736237372373823739237402374123742237432374423745237462374723748237492375023751237522375323754237552375623757237582375923760237612376223763237642376523766237672376823769237702377123772237732377423775237762377723778237792378023781237822378323784237852378623787237882378923790237912379223793237942379523796237972379823799
  1. ; Complete source for Twobit and Sparc assembler in one file.
  2. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  3. ;
  4. ; See 'twobit-benchmark', at end.
  5. ; Copyright 1998 Lars T Hansen.
  6. ;
  7. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  8. ;
  9. ; Completely fundamental pathname manipulation.
  10. ; This takes zero or more directory components and a file name and
  11. ; constructs a filename relative to the current directory.
  12. (define (make-relative-filename . components)
  13. (define (construct l)
  14. (if (null? (cdr l))
  15. l
  16. (cons (car l)
  17. (cons "/" (construct (cdr l))))))
  18. (if (null? (cdr components))
  19. (car components)
  20. (apply string-append (construct components))))
  21. ; This takes one or more directory components and constructs a
  22. ; directory name with proper termination (a crock -- we can finess
  23. ; this later).
  24. (define (pathname-append . components)
  25. (define (construct l)
  26. (cond ((null? (cdr l))
  27. l)
  28. ((string=? (car l) "")
  29. (construct (cdr l)))
  30. ((char=? #\/ (string-ref (car l) (- (string-length (car l)) 1)))
  31. (cons (car l) (construct (cdr l))))
  32. (else
  33. (cons (car l)
  34. (cons "/" (construct (cdr l)))))))
  35. (let ((n (if (null? (cdr components))
  36. (car components)
  37. (apply string-append (construct components)))))
  38. (if (not (char=? #\/ (string-ref n (- (string-length n) 1))))
  39. (string-append n "/")
  40. n)))
  41. ; eof
  42. ; Copyright 1998 Lars T Hansen.
  43. ;
  44. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  45. ;
  46. ; Nbuild parameters for SPARC Larceny.
  47. (define (make-nbuild-parameter dir source? verbose? hostdir hostname)
  48. (let ((parameters
  49. `((compiler . ,(pathname-append dir "Compiler"))
  50. (util . ,(pathname-append dir "Util"))
  51. (build . ,(pathname-append dir "Rts" "Build"))
  52. (source . ,(pathname-append dir "Lib"))
  53. (common-source . ,(pathname-append dir "Lib" "Common"))
  54. (repl-source . ,(pathname-append dir "Repl"))
  55. (interp-source . ,(pathname-append dir "Eval"))
  56. (machine-source . ,(pathname-append dir "Lib" "Sparc"))
  57. (common-asm . ,(pathname-append dir "Asm" "Common"))
  58. (sparc-asm . ,(pathname-append dir "Asm" "Sparc"))
  59. (target-machine . SPARC)
  60. (endianness . big)
  61. (word-size . 32)
  62. (always-source? . ,source?)
  63. (verbose-load? . ,verbose?)
  64. (compatibility . ,(pathname-append dir "Compat" hostdir))
  65. (host-system . ,hostname)
  66. )))
  67. (lambda (key)
  68. (let ((probe (assq key parameters)))
  69. (if probe
  70. (cdr probe)
  71. #f)))))
  72. (define nbuild-parameter
  73. (make-nbuild-parameter "" #f #f "Larceny" "Larceny"))
  74. ; eof
  75. ; Copyright 1998 Lars T Hansen.
  76. ;
  77. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  78. ;
  79. ; Useful list functions.
  80. ;
  81. ; Notes:
  82. ; * Reduce, reduce-right, fold-right, fold-left are compatible with MIT Scheme.
  83. ; * Make-list is compatible with MIT Scheme and Chez Scheme.
  84. ; * These are not (yet) compatible with Shivers's proposed list functions.
  85. ; * remq, remv, remove, remq!, remv!, remov!, every?, and some? are in the
  86. ; basic library.
  87. ; Destructively remove all associations whose key matches `key' from `alist'.
  88. (define (aremq! key alist)
  89. (cond ((null? alist) alist)
  90. ((eq? key (caar alist))
  91. (aremq! key (cdr alist)))
  92. (else
  93. (set-cdr! alist (aremq! key (cdr alist)))
  94. alist)))
  95. (define (aremv! key alist)
  96. (cond ((null? alist) alist)
  97. ((eqv? key (caar alist))
  98. (aremv! key (cdr alist)))
  99. (else
  100. (set-cdr! alist (aremv! key (cdr alist)))
  101. alist)))
  102. (define (aremove! key alist)
  103. (cond ((null? alist) alist)
  104. ((equal? key (caar alist))
  105. (aremove! key (cdr alist)))
  106. (else
  107. (set-cdr! alist (aremove! key (cdr alist)))
  108. alist)))
  109. ; Return a list of elements of `list' selected by the predicate.
  110. (define (filter select? list)
  111. (cond ((null? list) list)
  112. ((select? (car list))
  113. (cons (car list) (filter select? (cdr list))))
  114. (else
  115. (filter select? (cdr list)))))
  116. ; Return the first element of `list' selected by the predicate.
  117. (define (find selected? list)
  118. (cond ((null? list) #f)
  119. ((selected? (car list)) (car list))
  120. (else (find selected? (cdr list)))))
  121. ; Return a list with all duplicates (according to predicate) removed.
  122. (define (remove-duplicates list same?)
  123. (define (member? x list)
  124. (cond ((null? list) #f)
  125. ((same? x (car list)) #t)
  126. (else (member? x (cdr list)))))
  127. (cond ((null? list) list)
  128. ((member? (car list) (cdr list))
  129. (remove-duplicates (cdr list) same?))
  130. (else
  131. (cons (car list) (remove-duplicates (cdr list) same?)))))
  132. ; Return the least element of `list' according to some total order.
  133. (define (least less? list)
  134. (reduce (lambda (a b) (if (less? a b) a b)) #f list))
  135. ; Return the greatest element of `list' according to some total order.
  136. (define (greatest greater? list)
  137. (reduce (lambda (a b) (if (greater? a b) a b)) #f list))
  138. ; (mappend p l) = (apply append (map p l))
  139. (define (mappend proc l)
  140. (apply append (map proc l)))
  141. ; (make-list n) => (a1 ... an) for some ai
  142. ; (make-list n x) => (a1 ... an) where ai = x
  143. (define (make-list nelem . rest)
  144. (let ((val (if (null? rest) #f (car rest))))
  145. (define (loop n l)
  146. (if (zero? n)
  147. l
  148. (loop (- n 1) (cons val l))))
  149. (loop nelem '())))
  150. ; (reduce p x ()) => x
  151. ; (reduce p x (a)) => a
  152. ; (reduce p x (a b ...)) => (p (p a b) ...))
  153. (define (reduce proc initial l)
  154. (define (loop val l)
  155. (if (null? l)
  156. val
  157. (loop (proc val (car l)) (cdr l))))
  158. (cond ((null? l) initial)
  159. ((null? (cdr l)) (car l))
  160. (else (loop (car l) (cdr l)))))
  161. ; (reduce-right p x ()) => x
  162. ; (reduce-right p x (a)) => a
  163. ; (reduce-right p x (a b ...)) => (p a (p b ...))
  164. (define (reduce-right proc initial l)
  165. (define (loop l)
  166. (if (null? (cdr l))
  167. (car l)
  168. (proc (car l) (loop (cdr l)))))
  169. (cond ((null? l) initial)
  170. ((null? (cdr l)) (car l))
  171. (else (loop l))))
  172. ; (fold-left p x (a b ...)) => (p (p (p x a) b) ...)
  173. (define (fold-left proc initial l)
  174. (if (null? l)
  175. initial
  176. (fold-left proc (proc initial (car l)) (cdr l))))
  177. ; (fold-right p x (a b ...)) => (p a (p b (p ... x)))
  178. (define (fold-right proc initial l)
  179. (if (null? l)
  180. initial
  181. (proc (car l) (fold-right proc initial (cdr l)))))
  182. ; (iota n) => (0 1 2 ... n-1)
  183. (define (iota n)
  184. (let loop ((n (- n 1)) (r '()))
  185. (let ((r (cons n r)))
  186. (if (= n 0)
  187. r
  188. (loop (- n 1) r)))))
  189. ; (list-head (a1 ... an) m) => (a1 ... am) for m <= n
  190. (define (list-head l n)
  191. (if (zero? n)
  192. '()
  193. (cons (car l) (list-head (cdr l) (- n 1)))))
  194. ; eof
  195. ; Copyright 1998 Lars T Hansen.
  196. ;
  197. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  198. ;
  199. ; Larceny -- compatibility library for Twobit running under Larceny.
  200. (define ($$trace x) #t)
  201. (define host-system 'larceny)
  202. ; Temporary?
  203. (define (.check! flag exn . args)
  204. (if (not flag)
  205. (apply error "Runtime check exception: " exn args)))
  206. ; The compatibility library loads Auxlib if compat:initialize is called
  207. ; without arguments. Compat:load will load fasl files when appropriate.
  208. (define (compat:initialize . rest)
  209. (if (null? rest)
  210. (let ((dir (nbuild-parameter 'compatibility)))
  211. (compat:load (string-append dir "compat2.sch"))
  212. (compat:load (string-append dir "../../Auxlib/list.sch"))
  213. (compat:load (string-append dir "../../Auxlib/pp.sch")))))
  214. (define (with-optimization level thunk)
  215. (thunk))
  216. ; Calls thunk1, and if thunk1 causes an error to be signaled, calls thunk2.
  217. (define (call-with-error-control thunk1 thunk2)
  218. (let ((eh (error-handler)))
  219. (error-handler (lambda args
  220. (error-handler eh)
  221. (thunk2)
  222. (apply eh args)))
  223. (thunk1)
  224. (error-handler eh)))
  225. (define (larc-new-extension fn ext)
  226. (let* ((l (string-length fn))
  227. (x (let loop ((i (- l 1)))
  228. (cond ((< i 0) #f)
  229. ((char=? (string-ref fn i) #\.) (+ i 1))
  230. (else (loop (- i 1)))))))
  231. (if (not x)
  232. (string-append fn "." ext)
  233. (string-append (substring fn 0 x) ext))))
  234. (define (compat:load filename)
  235. (define (loadit fn)
  236. (if (nbuild-parameter 'verbose-load?)
  237. (format #t "~a~%" fn))
  238. (load fn))
  239. (if (nbuild-parameter 'always-source?)
  240. (loadit filename)
  241. (let ((fn (larc-new-extension filename "fasl")))
  242. (if (and (file-exists? fn)
  243. (compat:file-newer? fn filename))
  244. (loadit fn)
  245. (loadit filename)))))
  246. (define (compat:file-newer? a b)
  247. (let* ((ta (file-modification-time a))
  248. (tb (file-modification-time b))
  249. (limit (vector-length ta)))
  250. (let loop ((i 0))
  251. (cond ((= i limit)
  252. #f)
  253. ((= (vector-ref ta i) (vector-ref tb i))
  254. (loop (+ i 1)))
  255. (else
  256. (> (vector-ref ta i) (vector-ref tb i)))))))
  257. ; eof
  258. ; Copyright 1998 Lars T Hansen.
  259. ;
  260. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  261. ;
  262. ; Larceny -- second part of compatibility code
  263. ; This file ought to be compiled, but doesn't have to be.
  264. ;
  265. ; 12 April 1999
  266. (define host-system 'larceny) ; Don't remove this!
  267. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  268. ;
  269. ; A well-defined sorting procedure.
  270. (define compat:sort (lambda (list less?) (sort list less?)))
  271. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  272. ;
  273. ; Well-defined character codes.
  274. ; Returns the UCS-2 code for a character.
  275. (define compat:char->integer char->integer)
  276. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  277. ;
  278. ; Input and output
  279. (define (write-lop item port)
  280. (lowlevel-write item port)
  281. (newline port)
  282. (newline port))
  283. (define write-fasl-datum lowlevel-write)
  284. ; The power of self-hosting ;-)
  285. (define (misc->bytevector x)
  286. (let ((bv (bytevector-like-copy x)))
  287. (typetag-set! bv $tag.bytevector-typetag)
  288. bv))
  289. (define string->bytevector misc->bytevector)
  290. (define bignum->bytevector misc->bytevector)
  291. (define (flonum->bytevector x)
  292. (clear-first-word (misc->bytevector x)))
  293. (define (compnum->bytevector x)
  294. (clear-first-word (misc->bytevector x)))
  295. ; Clears garbage word of compnum/flonum; makes regression testing much
  296. ; easier.
  297. (define (clear-first-word bv)
  298. (bytevector-like-set! bv 0 0)
  299. (bytevector-like-set! bv 1 0)
  300. (bytevector-like-set! bv 2 0)
  301. (bytevector-like-set! bv 3 0)
  302. bv)
  303. (define (list->bytevector l)
  304. (let ((b (make-bytevector (length l))))
  305. (do ((i 0 (+ i 1))
  306. (l l (cdr l)))
  307. ((null? l) b)
  308. (bytevector-set! b i (car l)))))
  309. (define bytevector-word-ref
  310. (let ((two^8 (expt 2 8))
  311. (two^16 (expt 2 16))
  312. (two^24 (expt 2 24)))
  313. (lambda (bv i)
  314. (+ (* (bytevector-ref bv i) two^24)
  315. (* (bytevector-ref bv (+ i 1)) two^16)
  316. (* (bytevector-ref bv (+ i 2)) two^8)
  317. (bytevector-ref bv (+ i 3))))))
  318. (define (twobit-format fmt . rest)
  319. (let ((out (open-output-string)))
  320. (apply format out fmt rest)
  321. (get-output-string out)))
  322. ; This needs to be a random number in both a weaker and stronger sense
  323. ; than `random': it doesn't need to be a truly random number, so a sequence
  324. ; of calls can return a non-random sequence, but if two processes generate
  325. ; two sequences, then those sequences should not be the same.
  326. ;
  327. ; Gross, huh?
  328. (define (an-arbitrary-number)
  329. (system "echo \\\"`date`\\\" > a-random-number")
  330. (let ((x (string-hash (call-with-input-file "a-random-number" read))))
  331. (delete-file "a-random-number")
  332. x))
  333. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  334. ;
  335. ; Miscellaneous
  336. (define cerror error)
  337. ; eof
  338. ; Copyright 1991 Wiliam Clinger.
  339. ;
  340. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  341. ;
  342. ; Sets represented as lists.
  343. ;
  344. ; 5 April 1999.
  345. (define (empty-set) '())
  346. (define (empty-set? x) (null? x))
  347. (define (make-set x)
  348. (define (loop x y)
  349. (cond ((null? x) y)
  350. ((member (car x) y) (loop (cdr x) y))
  351. (else (loop (cdr x) (cons (car x) y)))))
  352. (loop x '()))
  353. (define (set-equal? x y)
  354. (and (subset? x y) (subset? y x)))
  355. (define (subset? x y)
  356. (every? (lambda (x) (member x y))
  357. x))
  358. ; To get around MacScheme's limit on the number of arguments.
  359. (define apply-union)
  360. (define union
  361. (letrec ((union2
  362. (lambda (x y)
  363. (cond ((null? x) y)
  364. ((member (car x) y)
  365. (union2 (cdr x) y))
  366. (else (union2 (cdr x) (cons (car x) y)))))))
  367. (set! apply-union
  368. (lambda (sets)
  369. (do ((sets sets (cdr sets))
  370. (result '() (union2 (car sets) result)))
  371. ((null? sets)
  372. result))))
  373. (lambda args
  374. (cond ((null? args) '())
  375. ((null? (cdr args)) (car args))
  376. ((null? (cddr args)) (union2 (car args) (cadr args)))
  377. (else (union2 (union2 (car args)
  378. (cadr args))
  379. (apply union (cddr args))))))))
  380. (define intersection
  381. (letrec ((intersection2
  382. (lambda (x y)
  383. (cond ((null? x) '())
  384. ((member (car x) y)
  385. (cons (car x) (intersection2 (cdr x) y)))
  386. (else (intersection2 (cdr x) y))))))
  387. (lambda args
  388. (cond ((null? args) '())
  389. ((null? (cdr args)) (car args))
  390. ((null? (cddr args)) (intersection2 (car args) (cadr args)))
  391. (else (intersection2 (intersection2 (car args)
  392. (cadr args))
  393. (apply intersection (cddr args))))))))
  394. (define (difference x y)
  395. (cond ((null? x) '())
  396. ((member (car x) y)
  397. (difference (cdr x) y))
  398. (else (cons (car x) (difference (cdr x) y)))))
  399. ; Reasonably portable hashing on EQ?, EQV?, EQUAL?.
  400. ; Requires bignums, SYMBOL-HASH.
  401. ;
  402. ; Given any Scheme object, returns a non-negative exact integer
  403. ; less than 2^24.
  404. (define object-hash (lambda (x) 0)) ; hash on EQ?, EQV?
  405. (define equal-hash (lambda (x) 0)) ; hash on EQUAL?
  406. (let ((n 16777216)
  407. (n-1 16777215)
  408. (adj:fixnum 9000000)
  409. (adj:negative 8000000)
  410. (adj:large 7900000)
  411. (adj:ratnum 7800000)
  412. (adj:complex 7700000)
  413. (adj:flonum 7000000)
  414. (adj:compnum 6900000)
  415. (adj:char 6111000)
  416. (adj:string 5022200)
  417. (adj:vector 4003330)
  418. (adj:misc 3000444)
  419. (adj:pair 2555000)
  420. (adj:proc 2321001)
  421. (adj:iport 2321002)
  422. (adj:oport 2321003)
  423. (adj:weird 2321004)
  424. (budget0 32))
  425. (define (combine hash adjustment)
  426. (modulo (+ hash hash hash adjustment) 16777216))
  427. (define (hash-on-equal x budget)
  428. (if (> budget 0)
  429. (cond ((string? x)
  430. (string-hash x))
  431. ((pair? x)
  432. (let ((budget (quotient budget 2)))
  433. (combine (hash-on-equal (car x) budget)
  434. (hash-on-equal (cdr x) budget))))
  435. ((vector? x)
  436. (let ((n (vector-length x))
  437. (budget (quotient budget 4)))
  438. (if (> n 0)
  439. (combine
  440. (combine (hash-on-equal (vector-ref x 0) budget)
  441. (hash-on-equal (vector-ref x (- n 1)) budget))
  442. (hash-on-equal (vector-ref x (quotient n 2))
  443. (+ budget budget)))
  444. adj:vector)))
  445. (else
  446. (object-hash x)))
  447. adj:weird))
  448. (set! object-hash
  449. (lambda (x)
  450. (cond ((symbol? x)
  451. (symbol-hash x))
  452. ((number? x)
  453. (if (exact? x)
  454. (cond ((integer? x)
  455. (cond ((negative? x)
  456. (combine (object-hash (- x)) adj:negative))
  457. ((< x n)
  458. (combine x adj:fixnum))
  459. (else
  460. (combine (modulo x n) adj:large))))
  461. ((rational? x)
  462. (combine (combine (object-hash (numerator x))
  463. adj:ratnum)
  464. (object-hash (denominator x))))
  465. ((real? x)
  466. adj:weird)
  467. ((complex? x)
  468. (combine (combine (object-hash (real-part x))
  469. adj:complex)
  470. (object-hash (imag-part x))))
  471. (else
  472. adj:weird))
  473. (cond (#t
  474. ; We can't really do anything with inexact numbers
  475. ; unless infinities and NaNs behave reasonably.
  476. adj:flonum)
  477. ((rational? x)
  478. (combine
  479. (combine (object-hash
  480. (inexact->exact (numerator x)))
  481. adj:flonum)
  482. (object-hash (inexact->exact (denominator x)))))
  483. ((real? x)
  484. adj:weird)
  485. ((complex? x)
  486. (combine (combine (object-hash (real-part x))
  487. adj:compnum)
  488. (object-hash (imag-part x))))
  489. (else adj:weird))))
  490. ((char? x)
  491. (combine (char->integer x) adj:char))
  492. ((string? x)
  493. (combine (string-length x) adj:string))
  494. ((vector? x)
  495. (combine (vector-length x) adj:vector))
  496. ((eq? x #t)
  497. (combine 1 adj:misc))
  498. ((eq? x #f)
  499. (combine 2 adj:misc))
  500. ((null? x)
  501. (combine 3 adj:misc))
  502. ((pair? x)
  503. adj:pair)
  504. ((procedure? x)
  505. adj:proc)
  506. ((input-port? x)
  507. adj:iport)
  508. ((output-port? x)
  509. adj:oport)
  510. (else
  511. adj:weird))))
  512. (set! equal-hash
  513. (lambda (x)
  514. (hash-on-equal x budget0)))); Hash tables.
  515. ; Requires CALL-WITHOUT-INTERRUPTS.
  516. ; This code should be thread-safe provided VECTOR-REF is atomic.
  517. ;
  518. ; (make-hashtable <hash-function> <bucket-searcher> <size>)
  519. ;
  520. ; Returns a newly allocated mutable hash table
  521. ; using <hash-function> as the hash function
  522. ; and <bucket-searcher>, e.g. ASSQ, ASSV, ASSOC, to search a bucket
  523. ; with <size> buckets at first, expanding the number of buckets as needed.
  524. ; The <hash-function> must accept a key and return a non-negative exact
  525. ; integer.
  526. ;
  527. ; (make-hashtable <hash-function> <bucket-searcher>)
  528. ;
  529. ; Equivalent to (make-hashtable <hash-function> <bucket-searcher> n)
  530. ; for some value of n chosen by the implementation.
  531. ;
  532. ; (make-hashtable <hash-function>)
  533. ;
  534. ; Equivalent to (make-hashtable <hash-function> assv).
  535. ;
  536. ; (make-hashtable)
  537. ;
  538. ; Equivalent to (make-hashtable object-hash assv).
  539. ;
  540. ; (hashtable-contains? <hashtable> <key>)
  541. ;
  542. ; Returns true iff the <hashtable> contains an entry for <key>.
  543. ;
  544. ; (hashtable-fetch <hashtable> <key> <flag>)
  545. ;
  546. ; Returns the value associated with <key> in the <hashtable> if the
  547. ; <hashtable> contains <key>; otherwise returns <flag>.
  548. ;
  549. ; (hashtable-get <hashtable> <key>)
  550. ;
  551. ; Equivalent to (hashtable-fetch <hashtable> <key> #f)
  552. ;
  553. ; (hashtable-put! <hashtable> <key> <value>)
  554. ;
  555. ; Changes the <hashtable> to associate <key> with <value>, replacing
  556. ; any existing association for <key>.
  557. ;
  558. ; (hashtable-remove! <hashtable> <key>)
  559. ;
  560. ; Removes any association for <key> within the <hashtable>.
  561. ;
  562. ; (hashtable-clear! <hashtable>)
  563. ;
  564. ; Removes all associations from the <hashtable>.
  565. ;
  566. ; (hashtable-size <hashtable>)
  567. ;
  568. ; Returns the number of keys contained within the <hashtable>.
  569. ;
  570. ; (hashtable-for-each <procedure> <hashtable>)
  571. ;
  572. ; The <procedure> must accept two arguments, a key and the value
  573. ; associated with that key. Calls the <procedure> once for each
  574. ; key-value association. The order of these calls is indeterminate.
  575. ;
  576. ; (hashtable-map <procedure> <hashtable>)
  577. ;
  578. ; The <procedure> must accept two arguments, a key and the value
  579. ; associated with that key. Calls the <procedure> once for each
  580. ; key-value association, and returns a list of the results. The
  581. ; order of the calls is indeterminate.
  582. ;
  583. ; (hashtable-copy <hashtable>)
  584. ;
  585. ; Returns a copy of the <hashtable>.
  586. ; These global variables are assigned new values later.
  587. (define make-hashtable (lambda args '*))
  588. (define hashtable-contains? (lambda (ht key) #f))
  589. (define hashtable-fetch (lambda (ht key flag) flag))
  590. (define hashtable-get (lambda (ht key) (hashtable-fetch ht key #f)))
  591. (define hashtable-put! (lambda (ht key val) '*))
  592. (define hashtable-remove! (lambda (ht key) '*))
  593. (define hashtable-clear! (lambda (ht) '*))
  594. (define hashtable-size (lambda (ht) 0))
  595. (define hashtable-for-each (lambda (ht proc) '*))
  596. (define hashtable-map (lambda (ht proc) '()))
  597. (define hashtable-copy (lambda (ht) ht))
  598. ; Implementation.
  599. ; A hashtable is represented as a vector of the form
  600. ;
  601. ; #(("HASHTABLE") <count> <hasher> <searcher> <buckets>)
  602. ;
  603. ; where <count> is the number of associations within the hashtable,
  604. ; <hasher> is the hash function, <searcher> is the bucket searcher,
  605. ; and <buckets> is a vector of buckets.
  606. ;
  607. ; The <hasher> and <searcher> fields are constant, but
  608. ; the <count> and <buckets> fields are mutable.
  609. ;
  610. ; For thread-safe operation, the mutators must modify both
  611. ; as an atomic operation. Other operations do not require
  612. ; critical sections provided VECTOR-REF is an atomic operation
  613. ; and the operation does not modify the hashtable, does not
  614. ; reference the <count> field, and fetches the <buckets>
  615. ; field exactly once.
  616. (let ((doc (list "HASHTABLE"))
  617. (count (lambda (ht) (vector-ref ht 1)))
  618. (count! (lambda (ht n) (vector-set! ht 1 n)))
  619. (hasher (lambda (ht) (vector-ref ht 2)))
  620. (searcher (lambda (ht) (vector-ref ht 3)))
  621. (buckets (lambda (ht) (vector-ref ht 4)))
  622. (buckets! (lambda (ht v) (vector-set! ht 4 v)))
  623. (defaultn 10))
  624. (let ((hashtable? (lambda (ht)
  625. (and (vector? ht)
  626. (= 5 (vector-length ht))
  627. (eq? doc (vector-ref ht 0)))))
  628. (hashtable-error (lambda (x)
  629. (display "ERROR: Bad hash table: ")
  630. (newline)
  631. (write x)
  632. (newline))))
  633. ; Internal operations.
  634. (define (make-ht hashfun searcher size)
  635. (vector doc 0 hashfun searcher (make-vector size '())))
  636. ; Substitute x for the first occurrence of y within the list z.
  637. ; y is known to occur within z.
  638. (define (substitute1 x y z)
  639. (cond ((eq? y (car z))
  640. (cons x (cdr z)))
  641. (else
  642. (cons (car z)
  643. (substitute1 x y (cdr z))))))
  644. ; Remove the first occurrence of x from y.
  645. ; x is known to occur within y.
  646. (define (remq1 x y)
  647. (cond ((eq? x (car y))
  648. (cdr y))
  649. (else
  650. (cons (car y)
  651. (remq1 x (cdr y))))))
  652. (define (resize ht0)
  653. (call-without-interrupts
  654. (lambda ()
  655. (let ((ht (make-ht (hasher ht0)
  656. (searcher ht0)
  657. (+ 1 (* 2 (count ht0))))))
  658. (ht-for-each (lambda (key val)
  659. (put! ht key val))
  660. ht0)
  661. (buckets! ht0 (buckets ht))))))
  662. ; Returns the contents of the hashtable as a vector of pairs.
  663. (define (contents ht)
  664. (let* ((v (buckets ht))
  665. (n (vector-length v))
  666. (z (make-vector (count ht) '())))
  667. (define (loop i bucket j)
  668. (if (null? bucket)
  669. (if (= i n)
  670. (if (= j (vector-length z))
  671. z
  672. (begin (display "BUG in hashtable")
  673. (newline)
  674. '#()))
  675. (loop (+ i 1)
  676. (vector-ref v i)
  677. j))
  678. (let ((entry (car bucket)))
  679. (vector-set! z j (cons (car entry) (cdr entry)))
  680. (loop i
  681. (cdr bucket)
  682. (+ j 1)))))
  683. (loop 0 '() 0)))
  684. (define (contains? ht key)
  685. (if (hashtable? ht)
  686. (let* ((v (buckets ht))
  687. (n (vector-length v))
  688. (h (modulo ((hasher ht) key) n))
  689. (b (vector-ref v h)))
  690. (if ((searcher ht) key b)
  691. #t
  692. #f))
  693. (hashtable-error ht)))
  694. (define (fetch ht key flag)
  695. (if (hashtable? ht)
  696. (let* ((v (buckets ht))
  697. (n (vector-length v))
  698. (h (modulo ((hasher ht) key) n))
  699. (b (vector-ref v h))
  700. (probe ((searcher ht) key b)))
  701. (if probe
  702. (cdr probe)
  703. flag))
  704. (hashtable-error ht)))
  705. (define (put! ht key val)
  706. (if (hashtable? ht)
  707. (call-without-interrupts
  708. (lambda ()
  709. (let* ((v (buckets ht))
  710. (n (vector-length v))
  711. (h (modulo ((hasher ht) key) n))
  712. (b (vector-ref v h))
  713. (probe ((searcher ht) key b)))
  714. (if probe
  715. ; Using SET-CDR! on the probe would make it necessary
  716. ; to synchronize the CONTENTS routine.
  717. (vector-set! v h (substitute1 (cons key val) probe b))
  718. (begin (count! ht (+ (count ht) 1))
  719. (vector-set! v h (cons (cons key val) b))
  720. (if (> (count ht) n)
  721. (resize ht)))))
  722. #f))
  723. (hashtable-error ht)))
  724. (define (remove! ht key)
  725. (if (hashtable? ht)
  726. (call-without-interrupts
  727. (lambda ()
  728. (let* ((v (buckets ht))
  729. (n (vector-length v))
  730. (h (modulo ((hasher ht) key) n))
  731. (b (vector-ref v h))
  732. (probe ((searcher ht) key b)))
  733. (if probe
  734. (begin (count! ht (- (count ht) 1))
  735. (vector-set! v h (remq1 probe b))
  736. (if (< (* 2 (+ defaultn (count ht))) n)
  737. (resize ht))))
  738. #f)))
  739. (hashtable-error ht)))
  740. (define (clear! ht)
  741. (if (hashtable? ht)
  742. (call-without-interrupts
  743. (lambda ()
  744. (begin (count! ht 0)
  745. (buckets! ht (make-vector defaultn '()))
  746. #f)))
  747. (hashtable-error ht)))
  748. (define (size ht)
  749. (if (hashtable? ht)
  750. (count ht)
  751. (hashtable-error ht)))
  752. ; This code must be written so that the procedure can modify the
  753. ; hashtable without breaking any invariants.
  754. (define (ht-for-each f ht)
  755. (if (hashtable? ht)
  756. (let* ((v (contents ht))
  757. (n (vector-length v)))
  758. (do ((j 0 (+ j 1)))
  759. ((= j n))
  760. (let ((x (vector-ref v j)))
  761. (f (car x) (cdr x)))))
  762. (hashtable-error ht)))
  763. (define (ht-map f ht)
  764. (if (hashtable? ht)
  765. (let* ((v (contents ht))
  766. (n (vector-length v)))
  767. (do ((j 0 (+ j 1))
  768. (results '() (let ((x (vector-ref v j)))
  769. (cons (f (car x) (cdr x))
  770. results))))
  771. ((= j n)
  772. (reverse results))))
  773. (hashtable-error ht)))
  774. (define (ht-copy ht)
  775. (if (hashtable? ht)
  776. (let* ((newtable (make-hashtable (hasher ht) (searcher ht) 0))
  777. (v (buckets ht))
  778. (n (vector-length v))
  779. (newvector (make-vector n '())))
  780. (count! newtable (count ht))
  781. (buckets! newtable newvector)
  782. (do ((i 0 (+ i 1)))
  783. ((= i n))
  784. (vector-set! newvector i (append (vector-ref v i) '())))
  785. newtable)
  786. (hashtable-error ht)))
  787. ; External entry points.
  788. (set! make-hashtable
  789. (lambda args
  790. (let* ((hashfun (if (null? args) object-hash (car args)))
  791. (searcher (if (or (null? args) (null? (cdr args)))
  792. assv
  793. (cadr args)))
  794. (size (if (or (null? args) (null? (cdr args)) (null? (cddr args)))
  795. defaultn
  796. (caddr args))))
  797. (make-ht hashfun searcher size))))
  798. (set! hashtable-contains? (lambda (ht key) (contains? ht key)))
  799. (set! hashtable-fetch (lambda (ht key flag) (fetch ht key flag)))
  800. (set! hashtable-get (lambda (ht key) (fetch ht key #f)))
  801. (set! hashtable-put! (lambda (ht key val) (put! ht key val)))
  802. (set! hashtable-remove! (lambda (ht key) (remove! ht key)))
  803. (set! hashtable-clear! (lambda (ht) (clear! ht)))
  804. (set! hashtable-size (lambda (ht) (size ht)))
  805. (set! hashtable-for-each (lambda (ht proc) (ht-for-each ht proc)))
  806. (set! hashtable-map (lambda (ht proc) (ht-map ht proc)))
  807. (set! hashtable-copy (lambda (ht) (ht-copy ht)))
  808. #f))
  809. ; Hash trees: a functional data structure analogous to hash tables.
  810. ;
  811. ; (make-hashtree <hash-function> <bucket-searcher>)
  812. ;
  813. ; Returns a newly allocated mutable hash table
  814. ; using <hash-function> as the hash function
  815. ; and <bucket-searcher>, e.g. ASSQ, ASSV, ASSOC, to search a bucket.
  816. ; The <hash-function> must accept a key and return a non-negative exact
  817. ; integer.
  818. ;
  819. ; (make-hashtree <hash-function>)
  820. ;
  821. ; Equivalent to (make-hashtree <hash-function> assv).
  822. ;
  823. ; (make-hashtree)
  824. ;
  825. ; Equivalent to (make-hashtree object-hash assv).
  826. ;
  827. ; (hashtree-contains? <hashtree> <key>)
  828. ;
  829. ; Returns true iff the <hashtree> contains an entry for <key>.
  830. ;
  831. ; (hashtree-fetch <hashtree> <key> <flag>)
  832. ;
  833. ; Returns the value associated with <key> in the <hashtree> if the
  834. ; <hashtree> contains <key>; otherwise returns <flag>.
  835. ;
  836. ; (hashtree-get <hashtree> <key>)
  837. ;
  838. ; Equivalent to (hashtree-fetch <hashtree> <key> #f)
  839. ;
  840. ; (hashtree-put <hashtree> <key> <value>)
  841. ;
  842. ; Returns a new hashtree that is like <hashtree> except that
  843. ; <key> is associated with <value>.
  844. ;
  845. ; (hashtree-remove <hashtree> <key>)
  846. ;
  847. ; Returns a new hashtree that is like <hashtree> except that
  848. ; <key> is not associated with any value.
  849. ;
  850. ; (hashtree-size <hashtree>)
  851. ;
  852. ; Returns the number of keys contained within the <hashtree>.
  853. ;
  854. ; (hashtree-for-each <procedure> <hashtree>)
  855. ;
  856. ; The <procedure> must accept two arguments, a key and the value
  857. ; associated with that key. Calls the <procedure> once for each
  858. ; key-value association. The order of these calls is indeterminate.
  859. ;
  860. ; (hashtree-map <procedure> <hashtree>)
  861. ;
  862. ; The <procedure> must accept two arguments, a key and the value
  863. ; associated with that key. Calls the <procedure> once for each
  864. ; key-value association, and returns a list of the results. The
  865. ; order of the calls is indeterminate.
  866. ; These global variables are assigned new values later.
  867. (define make-hashtree (lambda args '*))
  868. (define hashtree-contains? (lambda (ht key) #f))
  869. (define hashtree-fetch (lambda (ht key flag) flag))
  870. (define hashtree-get (lambda (ht key) (hashtree-fetch ht key #f)))
  871. (define hashtree-put (lambda (ht key val) '*))
  872. (define hashtree-remove (lambda (ht key) '*))
  873. (define hashtree-size (lambda (ht) 0))
  874. (define hashtree-for-each (lambda (ht proc) '*))
  875. (define hashtree-map (lambda (ht proc) '()))
  876. ; Implementation.
  877. ; A hashtree is represented as a vector of the form
  878. ;
  879. ; #(("hashtree") <count> <hasher> <searcher> <buckets>)
  880. ;
  881. ; where <count> is the number of associations within the hashtree,
  882. ; <hasher> is the hash function, <searcher> is the bucket searcher,
  883. ; and <buckets> is generated by the following grammar:
  884. ;
  885. ; <buckets> ::= ()
  886. ; | (<fixnum> <associations> <buckets> <buckets>)
  887. ; <alist> ::= (<associations>)
  888. ; <associations> ::=
  889. ; | <association> <associations>
  890. ; <association> ::= (<key> . <value>)
  891. ;
  892. ; If <buckets> is of the form (n alist buckets1 buckets2),
  893. ; then n is the hash code of all keys in alist, all keys in buckets1
  894. ; have a hash code less than n, and all keys in buckets2 have a hash
  895. ; code greater than n.
  896. (let ((doc (list "hashtree"))
  897. (count (lambda (ht) (vector-ref ht 1)))
  898. (hasher (lambda (ht) (vector-ref ht 2)))
  899. (searcher (lambda (ht) (vector-ref ht 3)))
  900. (buckets (lambda (ht) (vector-ref ht 4)))
  901. (make-empty-buckets (lambda () '()))
  902. (make-buckets
  903. (lambda (h alist buckets1 buckets2)
  904. (list h alist buckets1 buckets2)))
  905. (buckets-empty? (lambda (buckets) (null? buckets)))
  906. (buckets-n (lambda (buckets) (car buckets)))
  907. (buckets-alist (lambda (buckets) (cadr buckets)))
  908. (buckets-left (lambda (buckets) (caddr buckets)))
  909. (buckets-right (lambda (buckets) (cadddr buckets))))
  910. (let ((hashtree? (lambda (ht)
  911. (and (vector? ht)
  912. (= 5 (vector-length ht))
  913. (eq? doc (vector-ref ht 0)))))
  914. (hashtree-error (lambda (x)
  915. (display "ERROR: Bad hash tree: ")
  916. (newline)
  917. (write x)
  918. (newline))))
  919. ; Internal operations.
  920. (define (make-ht count hashfun searcher buckets)
  921. (vector doc count hashfun searcher buckets))
  922. ; Substitute x for the first occurrence of y within the list z.
  923. ; y is known to occur within z.
  924. (define (substitute1 x y z)
  925. (cond ((eq? y (car z))
  926. (cons x (cdr z)))
  927. (else
  928. (cons (car z)
  929. (substitute1 x y (cdr z))))))
  930. ; Remove the first occurrence of x from y.
  931. ; x is known to occur within y.
  932. (define (remq1 x y)
  933. (cond ((eq? x (car y))
  934. (cdr y))
  935. (else
  936. (cons (car y)
  937. (remq1 x (cdr y))))))
  938. ; Returns the contents of the hashtree as a list of pairs.
  939. (define (contents ht)
  940. (let* ((t (buckets ht)))
  941. (define (contents t alist)
  942. (if (buckets-empty? t)
  943. alist
  944. (contents (buckets-left t)
  945. (contents (buckets-right t)
  946. (append-reverse (buckets-alist t)
  947. alist)))))
  948. (define (append-reverse x y)
  949. (if (null? x)
  950. y
  951. (append-reverse (cdr x)
  952. (cons (car x) y))))
  953. ; Creating a new hashtree from a list that is almost sorted
  954. ; in hash code order would create an extremely unbalanced
  955. ; hashtree, so this routine randomizes the order a bit.
  956. (define (randomize1 alist alist1 alist2 alist3)
  957. (if (null? alist)
  958. (randomize-combine alist1 alist2 alist3)
  959. (randomize2 (cdr alist)
  960. (cons (car alist) alist1)
  961. alist2
  962. alist3)))
  963. (define (randomize2 alist alist1 alist2 alist3)
  964. (if (null? alist)
  965. (randomize-combine alist1 alist2 alist3)
  966. (randomize3 (cdr alist)
  967. alist1
  968. (cons (car alist) alist2)
  969. alist3)))
  970. (define (randomize3 alist alist1 alist2 alist3)
  971. (if (null? alist)
  972. (randomize-combine alist1 alist2 alist3)
  973. (randomize1 (cdr alist)
  974. alist1
  975. alist2
  976. (cons (car alist) alist3))))
  977. (define (randomize-combine alist1 alist2 alist3)
  978. (cond ((null? alist2)
  979. alist1)
  980. ((null? alist3)
  981. (append-reverse alist2 alist1))
  982. (else
  983. (append-reverse
  984. (randomize1 alist3 '() '() '())
  985. (append-reverse
  986. (randomize1 alist1 '() '() '())
  987. (randomize1 alist2 '() '() '()))))))
  988. (randomize1 (contents t '()) '() '() '())))
  989. (define (contains? ht key)
  990. (if (hashtree? ht)
  991. (let* ((t (buckets ht))
  992. (h ((hasher ht) key)))
  993. (if ((searcher ht) key (find-bucket t h))
  994. #t
  995. #f))
  996. (hashtree-error ht)))
  997. (define (fetch ht key flag)
  998. (if (hashtree? ht)
  999. (let* ((t (buckets ht))
  1000. (h ((hasher ht) key))
  1001. (probe ((searcher ht) key (find-bucket t h))))
  1002. (if probe
  1003. (cdr probe)
  1004. flag))
  1005. (hashtree-error ht)))
  1006. ; Given a <buckets> t and a hash code h, returns the alist for h.
  1007. (define (find-bucket t h)
  1008. (if (buckets-empty? t)
  1009. '()
  1010. (let ((n (buckets-n t)))
  1011. (cond ((< h n)
  1012. (find-bucket (buckets-left t) h))
  1013. ((< n h)
  1014. (find-bucket (buckets-right t) h))
  1015. (else
  1016. (buckets-alist t))))))
  1017. (define (put ht key val)
  1018. (if (hashtree? ht)
  1019. (let ((t (buckets ht))
  1020. (h ((hasher ht) key))
  1021. (association (cons key val))
  1022. (c (count ht)))
  1023. (define (put t h)
  1024. (if (buckets-empty? t)
  1025. (begin (set! c (+ c 1))
  1026. (make-buckets h (list association) t t))
  1027. (let ((n (buckets-n t))
  1028. (alist (buckets-alist t))
  1029. (left (buckets-left t))
  1030. (right (buckets-right t)))
  1031. (cond ((< h n)
  1032. (make-buckets n
  1033. alist
  1034. (put (buckets-left t) h)
  1035. right))
  1036. ((< n h)
  1037. (make-buckets n
  1038. alist
  1039. left
  1040. (put (buckets-right t) h)))
  1041. (else
  1042. (let ((probe ((searcher ht) key alist)))
  1043. (if probe
  1044. (make-buckets n
  1045. (substitute1 association
  1046. probe
  1047. alist)
  1048. left
  1049. right)
  1050. (begin
  1051. (set! c (+ c 1))
  1052. (make-buckets n
  1053. (cons association alist)
  1054. left
  1055. right)))))))))
  1056. (let ((buckets (put t h)))
  1057. (make-ht c (hasher ht) (searcher ht) buckets)))
  1058. (hashtree-error ht)))
  1059. (define (remove ht key)
  1060. (if (hashtree? ht)
  1061. (let ((t (buckets ht))
  1062. (h ((hasher ht) key))
  1063. (c (count ht)))
  1064. (define (remove t h)
  1065. (if (buckets-empty? t)
  1066. t
  1067. (let ((n (buckets-n t))
  1068. (alist (buckets-alist t))
  1069. (left (buckets-left t))
  1070. (right (buckets-right t)))
  1071. (cond ((< h n)
  1072. (make-buckets n
  1073. alist
  1074. (remove left h)
  1075. right))
  1076. ((< n h)
  1077. (make-buckets n
  1078. alist
  1079. left
  1080. (remove right h)))
  1081. (else
  1082. (let ((probe ((searcher ht) key alist)))
  1083. (if probe
  1084. (begin (set! c (- c 1))
  1085. (make-buckets n
  1086. (remq1 probe alist)
  1087. left
  1088. right))
  1089. t)))))))
  1090. (let ((buckets (remove t h)))
  1091. (make-ht c (hasher ht) (searcher ht) buckets)))
  1092. (hashtree-error ht)))
  1093. (define (size ht)
  1094. (if (hashtree? ht)
  1095. (count ht)
  1096. (hashtree-error ht)))
  1097. (define (ht-for-each f ht)
  1098. (if (hashtree? ht)
  1099. (for-each (lambda (association)
  1100. (f (car association)
  1101. (cdr association)))
  1102. (contents ht))
  1103. (hashtree-error ht)))
  1104. (define (ht-map f ht)
  1105. (if (hashtree? ht)
  1106. (map (lambda (association)
  1107. (f (car association)
  1108. (cdr association)))
  1109. (contents ht))
  1110. (hashtree-error ht)))
  1111. ; External entry points.
  1112. (set! make-hashtree
  1113. (lambda args
  1114. (let* ((hashfun (if (null? args) object-hash (car args)))
  1115. (searcher (if (or (null? args) (null? (cdr args)))
  1116. assv
  1117. (cadr args))))
  1118. (make-ht 0 hashfun searcher (make-empty-buckets)))))
  1119. (set! hashtree-contains? (lambda (ht key) (contains? ht key)))
  1120. (set! hashtree-fetch (lambda (ht key flag) (fetch ht key flag)))
  1121. (set! hashtree-get (lambda (ht key) (fetch ht key #f)))
  1122. (set! hashtree-put (lambda (ht key val) (put ht key val)))
  1123. (set! hashtree-remove (lambda (ht key) (remove ht key)))
  1124. (set! hashtree-size (lambda (ht) (size ht)))
  1125. (set! hashtree-for-each (lambda (ht proc) (ht-for-each ht proc)))
  1126. (set! hashtree-map (lambda (ht proc) (ht-map ht proc)))
  1127. #f))
  1128. ; Copyright 1994 William Clinger
  1129. ;
  1130. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  1131. ;
  1132. ; 24 April 1999
  1133. ;
  1134. ; Compiler switches needed by Twobit.
  1135. (define make-twobit-flag)
  1136. (define display-twobit-flag)
  1137. (define make-twobit-flag
  1138. (lambda (name)
  1139. (define (twobit-warning)
  1140. (display "Error: incorrect arguments to ")
  1141. (write name)
  1142. (newline)
  1143. (reset))
  1144. (define (display-flag state)
  1145. (display (if state " + " " - "))
  1146. (display name)
  1147. (display " is ")
  1148. (display (if state "on" "off"))
  1149. (newline))
  1150. (let ((state #t))
  1151. (lambda args
  1152. (cond ((null? args) state)
  1153. ((and (null? (cdr args))
  1154. (boolean? (car args)))
  1155. (set! state (car args))
  1156. state)
  1157. ((and (null? (cdr args))
  1158. (eq? (car args) 'display))
  1159. (display-flag state))
  1160. (else (twobit-warning)))))))
  1161. (define (display-twobit-flag flag)
  1162. (flag 'display))
  1163. ; Debugging and convenience.
  1164. (define issue-warnings
  1165. (make-twobit-flag 'issue-warnings))
  1166. (define include-source-code
  1167. (make-twobit-flag 'include-source-code))
  1168. (define include-variable-names
  1169. (make-twobit-flag 'include-variable-names))
  1170. (define include-procedure-names
  1171. (make-twobit-flag 'include-procedure-names))
  1172. ; Space efficiency.
  1173. ; This switch isn't fully implemented yet. If it is true, then
  1174. ; Twobit will generate flat closures and will go to some trouble
  1175. ; to zero stale registers and stack slots.
  1176. ; Don't turn this switch off unless space is more important than speed.
  1177. (define avoid-space-leaks
  1178. (make-twobit-flag 'avoid-space-leaks))
  1179. ; Major optimizations.
  1180. (define integrate-usual-procedures
  1181. (make-twobit-flag 'integrate-usual-procedures))
  1182. (define control-optimization
  1183. (make-twobit-flag 'control-optimization))
  1184. (define parallel-assignment-optimization
  1185. (make-twobit-flag 'parallel-assignment-optimization))
  1186. (define lambda-optimization
  1187. (make-twobit-flag 'lambda-optimization))
  1188. (define benchmark-mode
  1189. (make-twobit-flag 'benchmark-mode))
  1190. (define benchmark-block-mode
  1191. (make-twobit-flag 'benchmark-block-mode))
  1192. (define global-optimization
  1193. (make-twobit-flag 'global-optimization))
  1194. (define interprocedural-inlining
  1195. (make-twobit-flag 'interprocedural-inlining))
  1196. (define interprocedural-constant-propagation
  1197. (make-twobit-flag 'interprocedural-constant-propagation))
  1198. (define common-subexpression-elimination
  1199. (make-twobit-flag 'common-subexpression-elimination))
  1200. (define representation-inference
  1201. (make-twobit-flag 'representation-inference))
  1202. (define local-optimization
  1203. (make-twobit-flag 'local-optimization))
  1204. ; For backwards compatibility, until I can change the code.
  1205. (define (ignore-space-leaks . args)
  1206. (if (null? args)
  1207. (not (avoid-space-leaks))
  1208. (avoid-space-leaks (not (car args)))))
  1209. (define lambda-optimizations lambda-optimization)
  1210. (define local-optimizations local-optimization)
  1211. (define (set-compiler-flags! how)
  1212. (case how
  1213. ((no-optimization)
  1214. (set-compiler-flags! 'standard)
  1215. (avoid-space-leaks #t)
  1216. (integrate-usual-procedures #f)
  1217. (control-optimization #f)
  1218. (parallel-assignment-optimization #f)
  1219. (lambda-optimization #f)
  1220. (benchmark-mode #f)
  1221. (benchmark-block-mode #f)
  1222. (global-optimization #f)
  1223. (interprocedural-inlining #f)
  1224. (interprocedural-constant-propagation #f)
  1225. (common-subexpression-elimination #f)
  1226. (representation-inference #f)
  1227. (local-optimization #f))
  1228. ((standard)
  1229. (issue-warnings #t)
  1230. (include-source-code #f)
  1231. (include-procedure-names #t)
  1232. (include-variable-names #t)
  1233. (avoid-space-leaks #f)
  1234. (runtime-safety-checking #t)
  1235. (integrate-usual-procedures #f)
  1236. (control-optimization #t)
  1237. (parallel-assignment-optimization #t)
  1238. (lambda-optimization #t)
  1239. (benchmark-mode #f)
  1240. (benchmark-block-mode #f)
  1241. (global-optimization #t)
  1242. (interprocedural-inlining #t)
  1243. (interprocedural-constant-propagation #t)
  1244. (common-subexpression-elimination #t)
  1245. (representation-inference #t)
  1246. (local-optimization #t))
  1247. ((fast-safe)
  1248. (let ((bbmode (benchmark-block-mode)))
  1249. (set-compiler-flags! 'standard)
  1250. (integrate-usual-procedures #t)
  1251. (benchmark-mode #t)
  1252. (benchmark-block-mode bbmode)))
  1253. ((fast-unsafe)
  1254. (set-compiler-flags! 'fast-safe)
  1255. (runtime-safety-checking #f))
  1256. (else
  1257. (error "set-compiler-flags!: unknown mode " how))))
  1258. (define (display-twobit-flags which)
  1259. (case which
  1260. ((debugging)
  1261. (display-twobit-flag issue-warnings)
  1262. (display-twobit-flag include-procedure-names)
  1263. (display-twobit-flag include-variable-names)
  1264. (display-twobit-flag include-source-code))
  1265. ((safety)
  1266. (display-twobit-flag avoid-space-leaks))
  1267. ((optimization)
  1268. (display-twobit-flag integrate-usual-procedures)
  1269. (display-twobit-flag control-optimization)
  1270. (display-twobit-flag parallel-assignment-optimization)
  1271. (display-twobit-flag lambda-optimization)
  1272. (display-twobit-flag benchmark-mode)
  1273. (display-twobit-flag benchmark-block-mode)
  1274. (display-twobit-flag global-optimization)
  1275. (if (global-optimization)
  1276. (begin (display " ")
  1277. (display-twobit-flag interprocedural-inlining)
  1278. (display " ")
  1279. (display-twobit-flag interprocedural-constant-propagation)
  1280. (display " ")
  1281. (display-twobit-flag common-subexpression-elimination)
  1282. (display " ")
  1283. (display-twobit-flag representation-inference)))
  1284. (display-twobit-flag local-optimization))
  1285. (else
  1286. ; The switch might mean something to the assembler, but not to Twobit
  1287. #t)))
  1288. ; eof
  1289. ; Copyright 1991 William Clinger
  1290. ;
  1291. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  1292. ;
  1293. ; 14 April 1999 / wdc
  1294. ($$trace "pass1.aux")
  1295. ;***************************************************************
  1296. ;
  1297. ; Each definition in this section should be overridden by an assignment
  1298. ; in a target-specific file.
  1299. ;
  1300. ; If a lambda expression has more than @maxargs-with-rest-arg@ required
  1301. ; arguments followed by a rest argument, then the macro expander will
  1302. ; rewrite the lambda expression as a lambda expression with only one
  1303. ; argument (a rest argument) whose body is a LET that binds the arguments
  1304. ; of the original lambda expression.
  1305. (define @maxargs-with-rest-arg@
  1306. 1000000) ; infinity
  1307. (define (prim-entry name) #f) ; no integrable procedures
  1308. (define (prim-arity name) 0) ; all of which take 0 arguments
  1309. (define (prim-opcodename name) name) ; and go by their source names
  1310. ; End of definitions to be overridden by target-specific assignments.
  1311. ;
  1312. ;***************************************************************
  1313. ; Miscellaneous routines.
  1314. (define (m-warn msg . more)
  1315. (if (issue-warnings)
  1316. (begin
  1317. (display "WARNING from macro expander:")
  1318. (newline)
  1319. (display msg)
  1320. (newline)
  1321. (for-each (lambda (x) (write x) (newline))
  1322. more))))
  1323. (define (m-error msg . more)
  1324. (display "ERROR detected during macro expansion:")
  1325. (newline)
  1326. (display msg)
  1327. (newline)
  1328. (for-each (lambda (x) (write x) (newline))
  1329. more)
  1330. (m-quit (make-constant #f)))
  1331. (define (m-bug msg . more)
  1332. (display "BUG in macro expander: ")
  1333. (newline)
  1334. (display msg)
  1335. (newline)
  1336. (for-each (lambda (x) (write x) (newline))
  1337. more)
  1338. (m-quit (make-constant #f)))
  1339. ; Given a <formals>, returns a list of bound variables.
  1340. '
  1341. (define (make-null-terminated x)
  1342. (cond ((null? x) '())
  1343. ((pair? x)
  1344. (cons (car x) (make-null-terminated (cdr x))))
  1345. (else (list x))))
  1346. ; Returns the length of the given list, or -1 if the argument
  1347. ; is not a list. Does not check for circular lists.
  1348. (define (safe-length x)
  1349. (define (loop x n)
  1350. (cond ((null? x) n)
  1351. ((pair? x) (loop (cdr x) (+ n 1)))
  1352. (else -1)))
  1353. (loop x 0))
  1354. ; Given a unary predicate and a list, returns a list of those
  1355. ; elements for which the predicate is true.
  1356. (define (filter1 p x)
  1357. (cond ((null? x) '())
  1358. ((p (car x)) (cons (car x) (filter1 p (cdr x))))
  1359. (else (filter1 p (cdr x)))))
  1360. ; Given a unary predicate and a list, returns #t if the
  1361. ; predicate is true of every element of the list.
  1362. (define (every1? p x)
  1363. (cond ((null? x) #t)
  1364. ((p (car x)) (every1? p (cdr x)))
  1365. (else #f)))
  1366. ; Binary union of two sets represented as lists, using equal?.
  1367. (define (union2 x y)
  1368. (cond ((null? x) y)
  1369. ((member (car x) y)
  1370. (union2 (cdr x) y))
  1371. (else (union2 (cdr x) (cons (car x) y)))))
  1372. ; Given an association list, copies the association pairs.
  1373. (define (copy-alist alist)
  1374. (map (lambda (x) (cons (car x) (cdr x)))
  1375. alist))
  1376. ; Removes a value from a list. May destroy the list.
  1377. '
  1378. (define remq!
  1379. (letrec ((loop (lambda (x y prev)
  1380. (cond ((null? y) #t)
  1381. ((eq? x (car y))
  1382. (set-cdr! prev (cdr y))
  1383. (loop x (cdr prev) prev))
  1384. (else
  1385. (loop x (cdr y) y))))))
  1386. (lambda (x y)
  1387. (cond ((null? y) '())
  1388. ((eq? x (car y))
  1389. (remq! x (cdr y)))
  1390. (else
  1391. (loop x (cdr y) y)
  1392. y)))))
  1393. ; Procedure-specific source code transformations.
  1394. ; The transformer is passed a source code expression and a predicate
  1395. ; and returns one of:
  1396. ;
  1397. ; the original source code expression
  1398. ; a new source code expression to use in place of the original
  1399. ; #f to indicate that the procedure is being called
  1400. ; with an incorrect number of arguments or
  1401. ; with an incorrect operand
  1402. ;
  1403. ; The original source code expression is guaranteed to be a list whose
  1404. ; car is the name associated with the transformer.
  1405. ; The predicate takes an identifier (a symbol) and returns true iff
  1406. ; that identifier is bound to something other than its global binding.
  1407. ;
  1408. ; Since the procedures and their transformations are target-specific,
  1409. ; they are defined in another file, in the Target subdirectory.
  1410. ; FIXME:
  1411. ; I think this is now used in only one place, in simplify-if.
  1412. (define (integrable? name)
  1413. (and (integrate-usual-procedures)
  1414. (prim-entry name)))
  1415. ; MAKE-READABLE strips the referencing information
  1416. ; and replaces (begin I) by I.
  1417. ; If the optional argument is true, then it also reconstructs LET.
  1418. (define (make-readable exp . rest)
  1419. (let ((fancy? (and (not (null? rest))
  1420. (car rest))))
  1421. (define (make-readable exp)
  1422. (case (car exp)
  1423. ((quote) (make-readable-quote exp))
  1424. ((lambda) `(lambda ,(lambda.args exp)
  1425. ,@(map (lambda (def)
  1426. `(define ,(def.lhs def)
  1427. ,(make-readable (def.rhs def))))
  1428. (lambda.defs exp))
  1429. ,(make-readable (lambda.body exp))))
  1430. ((set!) `(set! ,(assignment.lhs exp)
  1431. ,(make-readable (assignment.rhs exp))))
  1432. ((if) `(if ,(make-readable (if.test exp))
  1433. ,(make-readable (if.then exp))
  1434. ,(make-readable (if.else exp))))
  1435. ((begin) (if (variable? exp)
  1436. (variable.name exp)
  1437. `(begin ,@(map make-readable (begin.exprs exp)))))
  1438. (else (make-readable-call exp))))
  1439. (define (make-readable-quote exp)
  1440. (let ((x (constant.value exp)))
  1441. (if (and fancy?
  1442. (or (boolean? x)
  1443. (number? x)
  1444. (char? x)
  1445. (string? x)))
  1446. x
  1447. exp)))
  1448. (define (make-readable-call exp)
  1449. (let ((proc (call.proc exp)))
  1450. (if (and fancy?
  1451. (lambda? proc)
  1452. (list? (lambda.args proc)))
  1453. ;(make-readable-let* exp '() '() '())
  1454. (make-readable-let exp)
  1455. `(,(make-readable (call.proc exp))
  1456. ,@(map make-readable (call.args exp))))))
  1457. (define (make-readable-let exp)
  1458. (let* ((L (call.proc exp))
  1459. (formals (lambda.args L))
  1460. (args (map make-readable (call.args exp)))
  1461. (body (make-readable (lambda.body L))))
  1462. (if (and (null? (lambda.defs L))
  1463. (= (length args) 1)
  1464. (pair? body)
  1465. (or (and (eq? (car body) 'let)
  1466. (= (length (cadr body)) 1))
  1467. (eq? (car body) 'let*)))
  1468. `(let* ((,(car formals) ,(car args))
  1469. ,@(cadr body))
  1470. ,@(cddr body))
  1471. `(let ,(map list
  1472. (lambda.args L)
  1473. args)
  1474. ,@(map (lambda (def)
  1475. `(define ,(def.lhs def)
  1476. ,(make-readable (def.rhs def))))
  1477. (lambda.defs L))
  1478. ,body))))
  1479. (define (make-readable-let* exp vars inits defs)
  1480. (if (and (null? defs)
  1481. (call? exp)
  1482. (lambda? (call.proc exp))
  1483. (= 1 (length (lambda.args (call.proc exp)))))
  1484. (let ((proc (call.proc exp))
  1485. (arg (car (call.args exp))))
  1486. (if (and (call? arg)
  1487. (lambda? (call.proc arg))
  1488. (= 1 (length (lambda.args (call.proc arg))))
  1489. (null? (lambda.defs (call.proc arg))))
  1490. (make-readable-let*
  1491. (make-call proc (list (lambda.body (call.proc arg))))
  1492. (cons (car (lambda.args (call.proc arg))) vars)
  1493. (cons (make-readable (car (call.args arg))) inits)
  1494. '())
  1495. (make-readable-let* (lambda.body proc)
  1496. (cons (car (lambda.args proc)) vars)
  1497. (cons (make-readable (car (call.args exp)))
  1498. inits)
  1499. (map (lambda (def)
  1500. `(define ,(def.lhs def)
  1501. ,(make-readable (def.rhs def))))
  1502. (reverse (lambda.defs proc))))))
  1503. (cond ((or (not (null? vars))
  1504. (not (null? defs)))
  1505. `(let* ,(map list
  1506. (reverse vars)
  1507. (reverse inits))
  1508. ,@defs
  1509. ,(make-readable exp)))
  1510. ((and (call? exp)
  1511. (lambda? (call.proc exp)))
  1512. (let ((proc (call.proc exp)))
  1513. `(let ,(map list
  1514. (lambda.args proc)
  1515. (map make-readable (call.args exp)))
  1516. ,@(map (lambda (def)
  1517. `(define ,(def.lhs def)
  1518. ,(make-readable (def.rhs def))))
  1519. (lambda.defs proc))
  1520. ,(make-readable (lambda.body proc)))))
  1521. (else
  1522. (make-readable exp)))))
  1523. (make-readable exp)))
  1524. ; For testing.
  1525. ; MAKE-UNREADABLE does the reverse.
  1526. ; It assumes there are no internal definitions.
  1527. (define (make-unreadable exp)
  1528. (cond ((symbol? exp) (list 'begin exp))
  1529. ((pair? exp)
  1530. (case (car exp)
  1531. ((quote) exp)
  1532. ((lambda) (list 'lambda
  1533. (cadr exp)
  1534. '(begin)
  1535. (list '() '() '() '())
  1536. (make-unreadable (cons 'begin (cddr exp)))))
  1537. ((set!) (list 'set! (cadr exp) (make-unreadable (caddr exp))))
  1538. ((if) (list 'if
  1539. (make-unreadable (cadr exp))
  1540. (make-unreadable (caddr exp))
  1541. (if (= (length exp) 3)
  1542. '(unspecified)
  1543. (make-unreadable (cadddr exp)))))
  1544. ((begin) (if (= (length exp) 2)
  1545. (make-unreadable (cadr exp))
  1546. (cons 'begin (map make-unreadable (cdr exp)))))
  1547. (else (map make-unreadable exp))))
  1548. (else (list 'quote exp))))
  1549. ; Copyright 1991 William D Clinger.
  1550. ;
  1551. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  1552. ;
  1553. ; 12 April 1999.
  1554. ;
  1555. ; Procedures for fetching and clobbering parts of expressions.
  1556. ($$trace "pass2.aux")
  1557. (define (constant? exp) (eq? (car exp) 'quote))
  1558. (define (variable? exp)
  1559. (and (eq? (car exp) 'begin)
  1560. (null? (cddr exp))))
  1561. (define (lambda? exp) (eq? (car exp) 'lambda))
  1562. (define (call? exp) (pair? (car exp)))
  1563. (define (assignment? exp) (eq? (car exp) 'set!))
  1564. (define (conditional? exp) (eq? (car exp) 'if))
  1565. (define (begin? exp)
  1566. (and (eq? (car exp) 'begin)
  1567. (not (null? (cddr exp)))))
  1568. (define (make-constant value) (list 'quote value))
  1569. (define (make-variable name) (list 'begin name))
  1570. (define (make-lambda formals defs R F G decls doc body)
  1571. (list 'lambda
  1572. formals
  1573. (cons 'begin defs)
  1574. (list 'quote (list R F G decls doc))
  1575. body))
  1576. (define (make-call proc args) (cons proc (append args '())))
  1577. (define (make-assignment lhs rhs) (list 'set! lhs rhs))
  1578. (define (make-conditional e0 e1 e2) (list 'if e0 e1 e2))
  1579. (define (make-begin exprs)
  1580. (if (null? (cdr exprs))
  1581. (car exprs)
  1582. (cons 'begin (append exprs '()))))
  1583. (define (make-definition lhs rhs) (list 'define lhs rhs))
  1584. (define (constant.value exp) (cadr exp))
  1585. (define (variable.name exp) (cadr exp))
  1586. (define (lambda.args exp) (cadr exp))
  1587. (define (lambda.defs exp) (cdr (caddr exp)))
  1588. (define (lambda.R exp) (car (cadr (cadddr exp))))
  1589. (define (lambda.F exp) (cadr (cadr (cadddr exp))))
  1590. (define (lambda.G exp) (caddr (cadr (cadddr exp))))
  1591. (define (lambda.decls exp) (cadddr (cadr (cadddr exp))))
  1592. (define (lambda.doc exp) (car (cddddr (cadr (cadddr exp)))))
  1593. (define (lambda.body exp) (car (cddddr exp)))
  1594. (define (call.proc exp) (car exp))
  1595. (define (call.args exp) (cdr exp))
  1596. (define (assignment.lhs exp) (cadr exp))
  1597. (define (assignment.rhs exp) (caddr exp))
  1598. (define (if.test exp) (cadr exp))
  1599. (define (if.then exp) (caddr exp))
  1600. (define (if.else exp) (cadddr exp))
  1601. (define (begin.exprs exp) (cdr exp))
  1602. (define (def.lhs exp) (cadr exp))
  1603. (define (def.rhs exp) (caddr exp))
  1604. (define (variable-set! exp newexp)
  1605. (set-car! exp (car newexp))
  1606. (set-cdr! exp (append (cdr newexp) '())))
  1607. (define (lambda.args-set! exp args) (set-car! (cdr exp) args))
  1608. (define (lambda.defs-set! exp defs) (set-cdr! (caddr exp) defs))
  1609. (define (lambda.R-set! exp R) (set-car! (cadr (cadddr exp)) R))
  1610. (define (lambda.F-set! exp F) (set-car! (cdr (cadr (cadddr exp))) F))
  1611. (define (lambda.G-set! exp G) (set-car! (cddr (cadr (cadddr exp))) G))
  1612. (define (lambda.decls-set! exp decls) (set-car! (cdddr (cadr (cadddr exp))) decls))
  1613. (define (lambda.doc-set! exp doc) (set-car! (cddddr (cadr (cadddr exp))) doc))
  1614. (define (lambda.body-set! exp exp0) (set-car! (cddddr exp) exp0))
  1615. (define (call.proc-set! exp exp0) (set-car! exp exp0))
  1616. (define (call.args-set! exp exprs) (set-cdr! exp exprs))
  1617. (define (assignment.rhs-set! exp exp0) (set-car! (cddr exp) exp0))
  1618. (define (if.test-set! exp exp0) (set-car! (cdr exp) exp0))
  1619. (define (if.then-set! exp exp0) (set-car! (cddr exp) exp0))
  1620. (define (if.else-set! exp exp0) (set-car! (cdddr exp) exp0))
  1621. (define (begin.exprs-set! exp exprs) (set-cdr! exp exprs))
  1622. (define expression-set! variable-set!) ; used only by pass 3
  1623. ; FIXME: This duplicates information in Lib/procinfo.sch.
  1624. (define (make-doc name arity formals source-code filename filepos)
  1625. (vector name source-code arity filename filepos formals))
  1626. (define (doc.name d) (vector-ref d 0))
  1627. (define (doc.code d) (vector-ref d 1))
  1628. (define (doc.arity d) (vector-ref d 2))
  1629. (define (doc.file d) (vector-ref d 3))
  1630. (define (doc.filepos d) (vector-ref d 4))
  1631. (define (doc.formals d) (vector-ref d 5))
  1632. (define (doc.name-set! d x) (if d (vector-set! d 0 x)))
  1633. (define (doc.code-set! d x) (if d (vector-set! d 1 x)))
  1634. (define (doc.arity-set! d x) (if d (vector-set! d 2 x)))
  1635. (define (doc.file-set! d x) (if d (vector-set! d 3 x)))
  1636. (define (doc.filepos-set! d x) (if d (vector-set! d 4 x)))
  1637. (define (doc.formals-set! d x) (if d (vector-set! d 5 x)))
  1638. (define (doc-copy d) (list->vector (vector->list d)))
  1639. (define (ignored? name) (eq? name name:IGNORED))
  1640. ; Fairly harmless bug: rest arguments aren't getting flagged.
  1641. (define (flag-as-ignored name L)
  1642. (define (loop name formals)
  1643. (cond ((null? formals)
  1644. ;(pass2-error p2error:violation-of-invariant name formals)
  1645. #t)
  1646. ((symbol? formals) #t)
  1647. ((eq? name (car formals))
  1648. (set-car! formals name:IGNORED)
  1649. (if (not (local? (lambda.R L) name:IGNORED))
  1650. (lambda.R-set! L
  1651. (cons (make-R-entry name:IGNORED '() '() '())
  1652. (lambda.R L)))))
  1653. (else (loop name (cdr formals)))))
  1654. (loop name (lambda.args L)))
  1655. (define (make-null-terminated formals)
  1656. (cond ((null? formals) '())
  1657. ((symbol? formals) (list formals))
  1658. (else (cons (car formals)
  1659. (make-null-terminated (cdr formals))))))
  1660. (define (list-head x n)
  1661. (cond ((zero? n) '())
  1662. (else (cons (car x) (list-head (cdr x) (- n 1))))))
  1663. (define (remq x y)
  1664. (cond ((null? y) '())
  1665. ((eq? x (car y)) (remq x (cdr y)))
  1666. (else (cons (car y) (remq x (cdr y))))))
  1667. (define (make-call-to-LIST args)
  1668. (cond ((null? args) (make-constant '()))
  1669. ((null? (cdr args))
  1670. (make-call (make-variable name:CONS)
  1671. (list (car args) (make-constant '()))))
  1672. (else (make-call (make-variable name:LIST) args))))
  1673. (define (pass2-error i . etc)
  1674. (apply cerror (cons (vector-ref pass2-error-messages i) etc)))
  1675. (define pass2-error-messages
  1676. '#("System error: violation of an invariant in pass 2"
  1677. "Wrong number of arguments to known procedure"))
  1678. (define p2error:violation-of-invariant 0)
  1679. (define p2error:wna 1)
  1680. ; Procedures for fetching referencing information from R-tables.
  1681. (define (make-R-entry name refs assigns calls)
  1682. (list name refs assigns calls))
  1683. (define (R-entry.name x) (car x))
  1684. (define (R-entry.references x) (cadr x))
  1685. (define (R-entry.assignments x) (caddr x))
  1686. (define (R-entry.calls x) (cadddr x))
  1687. (define (R-entry.references-set! x refs) (set-car! (cdr x) refs))
  1688. (define (R-entry.assignments-set! x assignments) (set-car! (cddr x) assignments))
  1689. (define (R-entry.calls-set! x calls) (set-car! (cdddr x) calls))
  1690. (define (local? R I)
  1691. (assq I R))
  1692. (define (R-entry R I)
  1693. (assq I R))
  1694. (define (R-lookup R I)
  1695. (or (assq I R)
  1696. (pass2-error p2error:violation-of-invariant R I)))
  1697. (define (references R I)
  1698. (cadr (R-lookup R I)))
  1699. (define (assignments R I)
  1700. (caddr (R-lookup R I)))
  1701. (define (calls R I)
  1702. (cadddr (R-lookup R I)))
  1703. (define (references-set! R I X)
  1704. (set-car! (cdr (R-lookup R I)) X))
  1705. (define (assignments-set! R I X)
  1706. (set-car! (cddr (R-lookup R I)) X))
  1707. (define (calls-set! R I X)
  1708. (set-car! (cdddr (R-lookup R I)) X))
  1709. ; A notepad is a vector of the form #(L0 (L1 ...) (L2 ...) (I ...)),
  1710. ; where the components are:
  1711. ; element 0: a parent lambda expression (or #f if there is no enclosing
  1712. ; parent, or we want to pretend that there isn't).
  1713. ; element 1: a list of lambda expressions that the parent lambda
  1714. ; expression encloses immediately.
  1715. ; element 2: a subset of that list that does not escape.
  1716. ; element 3: a list of free variables.
  1717. (define (make-notepad L)
  1718. (vector L '() '() '()))
  1719. (define (notepad.parent np) (vector-ref np 0))
  1720. (define (notepad.lambdas np) (vector-ref np 1))
  1721. (define (notepad.nonescaping np) (vector-ref np 2))
  1722. (define (notepad.vars np) (vector-ref np 3))
  1723. (define (notepad.lambdas-set! np x) (vector-set! np 1 x))
  1724. (define (notepad.nonescaping-set! np x) (vector-set! np 2 x))
  1725. (define (notepad.vars-set! np x) (vector-set! np 3 x))
  1726. (define (notepad-lambda-add! np L)
  1727. (notepad.lambdas-set! np (cons L (notepad.lambdas np))))
  1728. (define (notepad-nonescaping-add! np L)
  1729. (notepad.nonescaping-set! np (cons L (notepad.nonescaping np))))
  1730. (define (notepad-var-add! np I)
  1731. (let ((vars (notepad.vars np)))
  1732. (if (not (memq I vars))
  1733. (notepad.vars-set! np (cons I vars)))))
  1734. ; Given a notepad, returns the list of variables that are closed
  1735. ; over by some nested lambda expression that escapes.
  1736. (define (notepad-captured-variables np)
  1737. (let ((nonescaping (notepad.nonescaping np)))
  1738. (apply-union
  1739. (map (lambda (L)
  1740. (if (memq L nonescaping)
  1741. (lambda.G L)
  1742. (lambda.F L)))
  1743. (notepad.lambdas np)))))
  1744. ; Given a notepad, returns a list of free variables computed
  1745. ; as the union of the immediate free variables with the free
  1746. ; variables of nested lambda expressions.
  1747. (define (notepad-free-variables np)
  1748. (do ((lambdas (notepad.lambdas np) (cdr lambdas))
  1749. (fv (notepad.vars np)
  1750. (let ((L (car lambdas)))
  1751. (union (difference (lambda.F L)
  1752. (make-null-terminated (lambda.args L)))
  1753. fv))))
  1754. ((null? lambdas) fv)))
  1755. ; Copyright 1992 William Clinger
  1756. ;
  1757. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  1758. ;
  1759. ; 13 December 1998
  1760. ; Implementation-dependent parameters and preferences that determine
  1761. ; how identifiers are represented in the output of the macro expander.
  1762. ;
  1763. ; The basic problem is that there are no reserved words, so the
  1764. ; syntactic keywords of core Scheme that are used to express the
  1765. ; output need to be represented by data that cannot appear in the
  1766. ; input. This file defines those data.
  1767. ($$trace "prefs")
  1768. ; FIXME: The following definitions are currently ignored.
  1769. ; The following definitions assume that identifiers of mixed case
  1770. ; cannot appear in the input.
  1771. (define begin1 (string->symbol "Begin"))
  1772. (define define1 (string->symbol "Define"))
  1773. (define quote1 (string->symbol "Quote"))
  1774. (define lambda1 (string->symbol "Lambda"))
  1775. (define if1 (string->symbol "If"))
  1776. (define set!1 (string->symbol "Set!"))
  1777. ; The following defines an implementation-dependent expression
  1778. ; that evaluates to an undefined (not unspecified!) value, for
  1779. ; use in expanding the (define x) syntax.
  1780. (define undefined1 (list (string->symbol "Undefined")))
  1781. ; End of FIXME.
  1782. ; A variable is renamed by suffixing a vertical bar followed by a unique
  1783. ; integer. In IEEE and R4RS Scheme, a vertical bar cannot appear as part
  1784. ; of an identifier, but presumably this is enforced by the reader and not
  1785. ; by the compiler. Any other character that cannot appear as part of an
  1786. ; identifier may be used instead of the vertical bar.
  1787. (define renaming-prefix-character #\.)
  1788. (define renaming-suffix-character #\|)
  1789. (define renaming-prefix (string renaming-prefix-character))
  1790. (define renaming-suffix (string renaming-suffix-character))
  1791. ; Patches for Twobit. Here temporarily.
  1792. (define (make-toplevel-definition id exp)
  1793. (if (lambda? exp)
  1794. (doc.name-set! (lambda.doc exp) id))
  1795. (make-begin
  1796. (list (make-assignment id exp)
  1797. (make-constant id))))
  1798. (define (make-undefined)
  1799. (make-call (make-variable 'undefined) '()))
  1800. (define (make-unspecified)
  1801. (make-call (make-variable 'unspecified) '()))
  1802. ; Copyright 1992 William Clinger
  1803. ;
  1804. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  1805. ;
  1806. ; 9 December 1998
  1807. ; Syntactic environments.
  1808. ;
  1809. ; A syntactic environment maps identifiers to denotations,
  1810. ; where a denotation is one of
  1811. ;
  1812. ; (special <special>)
  1813. ; (macro <rules> <env>)
  1814. ; (inline <rules> <env>)
  1815. ; (identifier <id> <references> <assignments> <calls>)
  1816. ;
  1817. ; and where <special> is one of
  1818. ;
  1819. ; quote
  1820. ; lambda
  1821. ; if
  1822. ; set!
  1823. ; begin
  1824. ; define
  1825. ; define-syntax
  1826. ; let-syntax
  1827. ; letrec-syntax
  1828. ; syntax-rules
  1829. ;
  1830. ; and where <rules> is a compiled <transformer spec> (see R4RS),
  1831. ; <env> is a syntactic environment, and <id> is an identifier.
  1832. ;
  1833. ; An inline denotation is like a macro denotation, except that it
  1834. ; is not an error when none of the rules match the use. Inline
  1835. ; denotations are created by DEFINE-INLINE.
  1836. ; The standard syntactic environment should not include any
  1837. ; identifier denotations; space leaks will result if it does.
  1838. ($$trace "syntaxenv")
  1839. (define standard-syntactic-environment
  1840. `((quote . (special quote))
  1841. (lambda . (special lambda))
  1842. (if . (special if))
  1843. (set! . (special set!))
  1844. (begin . (special begin))
  1845. (define . (special define))
  1846. (define-inline . (special define-inline))
  1847. (define-syntax . (special define-syntax))
  1848. (let-syntax . (special let-syntax))
  1849. (letrec-syntax . (special letrec-syntax))
  1850. (syntax-rules . (special syntax-rules))
  1851. ))
  1852. ; Unforgeable synonyms for lambda and set!, used to expand definitions.
  1853. (define lambda0 (string->symbol " lambda "))
  1854. (define set!0 (string->symbol " set! "))
  1855. (define (syntactic-copy env)
  1856. (copy-alist env))
  1857. (define (make-basic-syntactic-environment)
  1858. (cons (cons lambda0
  1859. (cdr (assq 'lambda standard-syntactic-environment)))
  1860. (cons (cons set!0
  1861. (cdr (assq 'set! standard-syntactic-environment)))
  1862. (syntactic-copy standard-syntactic-environment))))
  1863. ; The global-syntactic-environment will always be a nonempty
  1864. ; association list since there is no way to remove the entry
  1865. ; for lambda0. That entry is used as a header by destructive
  1866. ; operations.
  1867. (define global-syntactic-environment
  1868. (make-basic-syntactic-environment))
  1869. (define (global-syntactic-environment-set! env)
  1870. (set-cdr! global-syntactic-environment env)
  1871. #t)
  1872. (define (syntactic-bind-globally! id denotation)
  1873. (if (and (identifier-denotation? denotation)
  1874. (eq? id (identifier-name denotation)))
  1875. (letrec ((remove-bindings-for-id
  1876. (lambda (bindings)
  1877. (cond ((null? bindings) '())
  1878. ((eq? (caar bindings) id)
  1879. (remove-bindings-for-id (cdr bindings)))
  1880. (else (cons (car bindings)
  1881. (remove-bindings-for-id (cdr bindings))))))))
  1882. (global-syntactic-environment-set!
  1883. (remove-bindings-for-id (cdr global-syntactic-environment))))
  1884. (let ((x (assq id global-syntactic-environment)))
  1885. (if x
  1886. (begin (set-cdr! x denotation) #t)
  1887. (global-syntactic-environment-set!
  1888. (cons (cons id denotation)
  1889. (cdr global-syntactic-environment)))))))
  1890. (define (syntactic-divert env1 env2)
  1891. (append env2 env1))
  1892. (define (syntactic-extend env ids denotations)
  1893. (syntactic-divert env (map cons ids denotations)))
  1894. (define (syntactic-lookup env id)
  1895. (let ((entry (assq id env)))
  1896. (if entry
  1897. (cdr entry)
  1898. (make-identifier-denotation id))))
  1899. (define (syntactic-assign! env id denotation)
  1900. (let ((entry (assq id env)))
  1901. (if entry
  1902. (set-cdr! entry denotation)
  1903. (m-bug "Bug detected in syntactic-assign!" env id denotation))))
  1904. ; Denotations.
  1905. (define denotation-class car)
  1906. (define (special-denotation? denotation)
  1907. (eq? (denotation-class denotation) 'special))
  1908. (define (macro-denotation? denotation)
  1909. (eq? (denotation-class denotation) 'macro))
  1910. (define (inline-denotation? denotation)
  1911. (eq? (denotation-class denotation) 'inline))
  1912. (define (identifier-denotation? denotation)
  1913. (eq? (denotation-class denotation) 'identifier))
  1914. (define (make-macro-denotation rules env)
  1915. (list 'macro rules env))
  1916. (define (make-inline-denotation id rules env)
  1917. (list 'inline rules env id))
  1918. (define (make-identifier-denotation id)
  1919. (list 'identifier id '() '() '()))
  1920. (define macro-rules cadr)
  1921. (define macro-env caddr)
  1922. (define inline-rules macro-rules)
  1923. (define inline-env macro-env)
  1924. (define inline-name cadddr)
  1925. (define identifier-name cadr)
  1926. (define identifier-R-entry cdr)
  1927. (define (same-denotation? d1 d2)
  1928. (or (eq? d1 d2)
  1929. (and (identifier-denotation? d1)
  1930. (identifier-denotation? d2)
  1931. (eq? (identifier-name d1)
  1932. (identifier-name d2)))))
  1933. (define denotation-of-quote
  1934. (syntactic-lookup standard-syntactic-environment 'quote))
  1935. (define denotation-of-lambda
  1936. (syntactic-lookup standard-syntactic-environment 'lambda))
  1937. (define denotation-of-if
  1938. (syntactic-lookup standard-syntactic-environment 'if))
  1939. (define denotation-of-set!
  1940. (syntactic-lookup standard-syntactic-environment 'set!))
  1941. (define denotation-of-begin
  1942. (syntactic-lookup standard-syntactic-environment 'begin))
  1943. (define denotation-of-define
  1944. (syntactic-lookup standard-syntactic-environment 'define))
  1945. (define denotation-of-define-inline
  1946. (syntactic-lookup standard-syntactic-environment 'define-inline))
  1947. (define denotation-of-define-syntax
  1948. (syntactic-lookup standard-syntactic-environment 'define-syntax))
  1949. (define denotation-of-let-syntax
  1950. (syntactic-lookup standard-syntactic-environment 'let-syntax))
  1951. (define denotation-of-letrec-syntax
  1952. (syntactic-lookup standard-syntactic-environment 'letrec-syntax))
  1953. (define denotation-of-syntax-rules
  1954. (syntactic-lookup standard-syntactic-environment 'syntax-rules))
  1955. (define denotation-of-...
  1956. (syntactic-lookup standard-syntactic-environment '...))
  1957. (define denotation-of-transformer
  1958. (syntactic-lookup standard-syntactic-environment 'transformer))
  1959. ; Given a syntactic environment env to be extended, an alist returned
  1960. ; by rename-vars, and a syntactic environment env2, extends env by
  1961. ; binding the fresh identifiers to the denotations of the original
  1962. ; identifiers in env2.
  1963. (define (syntactic-alias env alist env2)
  1964. (syntactic-divert
  1965. env
  1966. (map (lambda (name-pair)
  1967. (let ((old-name (car name-pair))
  1968. (new-name (cdr name-pair)))
  1969. (cons new-name
  1970. (syntactic-lookup env2 old-name))))
  1971. alist)))
  1972. ; Given a syntactic environment and an alist returned by rename-vars,
  1973. ; extends the environment by binding the old identifiers to the fresh
  1974. ; identifiers.
  1975. ; For Twobit, it also binds the fresh identifiers to their denotations.
  1976. ; This is ok so long as the fresh identifiers are not legal Scheme
  1977. ; identifiers.
  1978. (define (syntactic-rename env alist)
  1979. (if (null? alist)
  1980. env
  1981. (let* ((old (caar alist))
  1982. (new (cdar alist))
  1983. (denotation (make-identifier-denotation new)))
  1984. (syntactic-rename
  1985. (cons (cons old denotation)
  1986. (cons (cons new denotation)
  1987. env))
  1988. (cdr alist)))))
  1989. ; Renaming of variables.
  1990. (define renaming-counter 0)
  1991. (define (make-rename-procedure)
  1992. (set! renaming-counter (+ renaming-counter 1))
  1993. (let ((suffix (string-append renaming-suffix (number->string renaming-counter))))
  1994. (lambda (sym)
  1995. (if (symbol? sym)
  1996. (let ((s (symbol->string sym)))
  1997. (if (and (positive? (string-length s))
  1998. (char=? (string-ref s 0) renaming-prefix-character))
  1999. (string->symbol (string-append s suffix))
  2000. (string->symbol (string-append renaming-prefix s suffix))))
  2001. (m-warn "Illegal use of rename procedure" 'ok:FIXME sym)))))
  2002. ; Given a datum, strips the suffixes from any symbols that appear within
  2003. ; the datum, trying not to copy any more of the datum than necessary.
  2004. (define (m-strip x)
  2005. (define (original-symbol x)
  2006. (define (loop sym s i n)
  2007. (cond ((= i n) sym)
  2008. ((char=? (string-ref s i)
  2009. renaming-suffix-character)
  2010. (string->symbol (substring s 1 i)))
  2011. (else
  2012. (loop sym s (+ i 1) n))))
  2013. (let ((s (symbol->string x)))
  2014. (if (and (positive? (string-length s))
  2015. (char=? (string-ref s 0) renaming-prefix-character))
  2016. (loop x s 0 (string-length s))
  2017. x)))
  2018. (cond ((symbol? x)
  2019. (original-symbol x))
  2020. ((pair? x)
  2021. (let ((a (m-strip (car x)))
  2022. (b (m-strip (cdr x))))
  2023. (if (and (eq? a (car x))
  2024. (eq? b (cdr x)))
  2025. x
  2026. (cons a b))))
  2027. ((vector? x)
  2028. (let* ((v (vector->list x))
  2029. (v2 (map m-strip v)))
  2030. (if (equal? v v2)
  2031. x
  2032. (list->vector v2))))
  2033. (else x)))
  2034. ; Given a list of identifiers, or a formal parameter "list",
  2035. ; returns an alist that associates each identifier with a fresh identifier.
  2036. (define (rename-vars original-vars)
  2037. (let ((rename (make-rename-procedure)))
  2038. (define (loop vars newvars)
  2039. (cond ((null? vars) (reverse newvars))
  2040. ((pair? vars)
  2041. (let ((var (car vars)))
  2042. (if (symbol? var)
  2043. (loop (cdr vars)
  2044. (cons (cons var (rename var))
  2045. newvars))
  2046. (m-error "Illegal variable" var))))
  2047. ((symbol? vars)
  2048. (loop (list vars) newvars))
  2049. (else (m-error "Malformed parameter list" original-vars))))
  2050. (loop original-vars '())))
  2051. ; Given a <formals> and an alist returned by rename-vars that contains
  2052. ; a new name for each formal identifier in <formals>, renames the
  2053. ; formal identifiers.
  2054. (define (rename-formals formals alist)
  2055. (cond ((null? formals) '())
  2056. ((pair? formals)
  2057. (cons (cdr (assq (car formals) alist))
  2058. (rename-formals (cdr formals) alist)))
  2059. (else (cdr (assq formals alist)))))
  2060. ; Copyright 1992 William Clinger
  2061. ;
  2062. ; Permission to copy this software, in whole or in part, to use this
  2063. ; software for any lawful purpose, and to redistribute this software
  2064. ; is granted subject to the restriction that all copies made of this
  2065. ; software must include this copyright notice in full.
  2066. ;
  2067. ; I also request that you send me a copy of any improvements that you
  2068. ; make to this software so that they may be incorporated within it to
  2069. ; the benefit of the Scheme community.
  2070. ;
  2071. ; 23 November 1998
  2072. ; Compiler for a <transformer spec>.
  2073. ;
  2074. ; References:
  2075. ;
  2076. ; The Revised^4 Report on the Algorithmic Language Scheme.
  2077. ; Clinger and Rees [editors]. To appear in Lisp Pointers.
  2078. ; Also available as a technical report from U of Oregon,
  2079. ; MIT AI Lab, and Cornell.
  2080. ;
  2081. ; Macros That Work. Clinger and Rees. POPL '91.
  2082. ;
  2083. ; The input is a <transformer spec> and a syntactic environment.
  2084. ; Syntactic environments are described in another file.
  2085. ;
  2086. ; The supported syntax differs from the R4RS in that vectors are
  2087. ; allowed as patterns and as templates and are not allowed as
  2088. ; pattern or template data.
  2089. ;
  2090. ; <transformer spec> --> (syntax-rules <literals> <rules>)
  2091. ; <rules> --> () | (<rule> . <rules>)
  2092. ; <rule> --> (<pattern> <template>)
  2093. ; <pattern> --> <pattern_var> ; a <symbol> not in <literals>
  2094. ; | <symbol> ; a <symbol> in <literals>
  2095. ; | ()
  2096. ; | (<pattern> . <pattern>)
  2097. ; | (<ellipsis_pattern>)
  2098. ; | #(<pattern>*) ; extends R4RS
  2099. ; | #(<pattern>* <ellipsis_pattern>) ; extends R4RS
  2100. ; | <pattern_datum>
  2101. ; <template> --> <pattern_var>
  2102. ; | <symbol>
  2103. ; | ()
  2104. ; | (<template2> . <template2>)
  2105. ; | #(<template>*) ; extends R4RS
  2106. ; | <pattern_datum>
  2107. ; <template2> --> <template> | <ellipsis_template>
  2108. ; <pattern_datum> --> <string> ; no <vector>
  2109. ; | <character>
  2110. ; | <boolean>
  2111. ; | <number>
  2112. ; <ellipsis_pattern> --> <pattern> ...
  2113. ; <ellipsis_template> --> <template> ...
  2114. ; <pattern_var> --> <symbol> ; not in <literals>
  2115. ; <literals> --> () | (<symbol> . <literals>)
  2116. ;
  2117. ; Definitions.
  2118. ;
  2119. ; scope of an ellipsis
  2120. ;
  2121. ; Within a pattern or template, the scope of an ellipsis
  2122. ; (...) is the pattern or template that appears to its left.
  2123. ;
  2124. ; rank of a pattern variable
  2125. ;
  2126. ; The rank of a pattern variable is the number of ellipses
  2127. ; within whose scope it appears in the pattern.
  2128. ;
  2129. ; rank of a subtemplate
  2130. ;
  2131. ; The rank of a subtemplate is the number of ellipses within
  2132. ; whose scope it appears in the template.
  2133. ;
  2134. ; template rank of an occurrence of a pattern variable
  2135. ;
  2136. ; The template rank of an occurrence of a pattern variable
  2137. ; within a template is the rank of that occurrence, viewed
  2138. ; as a subtemplate.
  2139. ;
  2140. ; variables bound by a pattern
  2141. ;
  2142. ; The variables bound by a pattern are the pattern variables
  2143. ; that appear within it.
  2144. ;
  2145. ; referenced variables of a subtemplate
  2146. ;
  2147. ; The referenced variables of a subtemplate are the pattern
  2148. ; variables that appear within it.
  2149. ;
  2150. ; variables opened by an ellipsis template
  2151. ;
  2152. ; The variables opened by an ellipsis template are the
  2153. ; referenced pattern variables whose rank is greater than
  2154. ; the rank of the ellipsis template.
  2155. ;
  2156. ;
  2157. ; Restrictions.
  2158. ;
  2159. ; No pattern variable appears more than once within a pattern.
  2160. ;
  2161. ; For every occurrence of a pattern variable within a template,
  2162. ; the template rank of the occurrence must be greater than or
  2163. ; equal to the pattern variable's rank.
  2164. ;
  2165. ; Every ellipsis template must open at least one variable.
  2166. ;
  2167. ; For every ellipsis template, the variables opened by an
  2168. ; ellipsis template must all be bound to sequences of the
  2169. ; same length.
  2170. ;
  2171. ;
  2172. ; The compiled form of a <rule> is
  2173. ;
  2174. ; <rule> --> (<pattern> <template> <inserted>)
  2175. ; <pattern> --> <pattern_var>
  2176. ; | <symbol>
  2177. ; | ()
  2178. ; | (<pattern> . <pattern>)
  2179. ; | <ellipsis_pattern>
  2180. ; | #(<pattern>)
  2181. ; | <pattern_datum>
  2182. ; <template> --> <pattern_var>
  2183. ; | <symbol>
  2184. ; | ()
  2185. ; | (<template2> . <template2>)
  2186. ; | #(<pattern>)
  2187. ; | <pattern_datum>
  2188. ; <template2> --> <template> | <ellipsis_template>
  2189. ; <pattern_datum> --> <string>
  2190. ; | <character>
  2191. ; | <boolean>
  2192. ; | <number>
  2193. ; <pattern_var> --> #(<V> <symbol> <rank>)
  2194. ; <ellipsis_pattern> --> #(<E> <pattern> <pattern_vars>)
  2195. ; <ellipsis_template> --> #(<E> <template> <pattern_vars>)
  2196. ; <inserted> --> () | (<symbol> . <inserted>)
  2197. ; <pattern_vars> --> () | (<pattern_var> . <pattern_vars>)
  2198. ; <rank> --> <exact non-negative integer>
  2199. ;
  2200. ; where <V> and <E> are unforgeable values.
  2201. ; The pattern variables associated with an ellipsis pattern
  2202. ; are the variables bound by the pattern, and the pattern
  2203. ; variables associated with an ellipsis template are the
  2204. ; variables opened by the ellipsis template.
  2205. ;
  2206. ;
  2207. ; What's wrong with the above?
  2208. ; If the template contains a big chunk that contains no pattern variables
  2209. ; or inserted identifiers, then the big chunk will be copied unnecessarily.
  2210. ; That shouldn't matter very often.
  2211. ($$trace "syntaxrules")
  2212. (define pattern-variable-flag (list 'v))
  2213. (define ellipsis-pattern-flag (list 'e))
  2214. (define ellipsis-template-flag ellipsis-pattern-flag)
  2215. (define (make-patternvar v rank)
  2216. (vector pattern-variable-flag v rank))
  2217. (define (make-ellipsis-pattern P vars)
  2218. (vector ellipsis-pattern-flag P vars))
  2219. (define (make-ellipsis-template T vars)
  2220. (vector ellipsis-template-flag T vars))
  2221. (define (patternvar? x)
  2222. (and (vector? x)
  2223. (= (vector-length x) 3)
  2224. (eq? (vector-ref x 0) pattern-variable-flag)))
  2225. (define (ellipsis-pattern? x)
  2226. (and (vector? x)
  2227. (= (vector-length x) 3)
  2228. (eq? (vector-ref x 0) ellipsis-pattern-flag)))
  2229. (define (ellipsis-template? x)
  2230. (and (vector? x)
  2231. (= (vector-length x) 3)
  2232. (eq? (vector-ref x 0) ellipsis-template-flag)))
  2233. (define (patternvar-name V) (vector-ref V 1))
  2234. (define (patternvar-rank V) (vector-ref V 2))
  2235. (define (ellipsis-pattern P) (vector-ref P 1))
  2236. (define (ellipsis-pattern-vars P) (vector-ref P 2))
  2237. (define (ellipsis-template T) (vector-ref T 1))
  2238. (define (ellipsis-template-vars T) (vector-ref T 2))
  2239. (define (pattern-variable v vars)
  2240. (cond ((null? vars) #f)
  2241. ((eq? v (patternvar-name (car vars)))
  2242. (car vars))
  2243. (else (pattern-variable v (cdr vars)))))
  2244. ; Given a <transformer spec> and a syntactic environment,
  2245. ; returns a macro denotation.
  2246. ;
  2247. ; A macro denotation is of the form
  2248. ;
  2249. ; (macro (<rule> ...) env)
  2250. ;
  2251. ; where each <rule> has been compiled as described above.
  2252. (define (m-compile-transformer-spec spec env)
  2253. (if (and (> (safe-length spec) 1)
  2254. (eq? (syntactic-lookup env (car spec))
  2255. denotation-of-syntax-rules))
  2256. (let ((literals (cadr spec))
  2257. (rules (cddr spec)))
  2258. (if (or (not (list? literals))
  2259. (not (every1? (lambda (rule)
  2260. (and (= (safe-length rule) 2)
  2261. (pair? (car rule))))
  2262. rules)))
  2263. (m-error "Malformed syntax-rules" spec))
  2264. (list 'macro
  2265. (map (lambda (rule)
  2266. (m-compile-rule rule literals env))
  2267. rules)
  2268. env))
  2269. (m-error "Malformed syntax-rules" spec)))
  2270. (define (m-compile-rule rule literals env)
  2271. (m-compile-pattern (cdr (car rule))
  2272. literals
  2273. env
  2274. (lambda (compiled-rule patternvars)
  2275. ; FIXME
  2276. ; should check uniqueness of pattern variables here
  2277. (cons compiled-rule
  2278. (m-compile-template
  2279. (cadr rule)
  2280. patternvars
  2281. env)))))
  2282. (define (m-compile-pattern P literals env k)
  2283. (define (loop P vars rank k)
  2284. (cond ((symbol? P)
  2285. (if (memq P literals)
  2286. (k P vars)
  2287. (let ((var (make-patternvar P rank)))
  2288. (k var (cons var vars)))))
  2289. ((null? P) (k '() vars))
  2290. ((pair? P)
  2291. (if (and (pair? (cdr P))
  2292. (symbol? (cadr P))
  2293. (same-denotation? (syntactic-lookup env (cadr P))
  2294. denotation-of-...))
  2295. (if (null? (cddr P))
  2296. (loop (car P)
  2297. '()
  2298. (+ rank 1)
  2299. (lambda (P vars1)
  2300. (k (make-ellipsis-pattern P vars1)
  2301. (union2 vars1 vars))))
  2302. (m-error "Malformed pattern" P))
  2303. (loop (car P)
  2304. vars
  2305. rank
  2306. (lambda (P1 vars)
  2307. (loop (cdr P)
  2308. vars
  2309. rank
  2310. (lambda (P2 vars)
  2311. (k (cons P1 P2) vars)))))))
  2312. ((vector? P)
  2313. (loop (vector->list P)
  2314. vars
  2315. rank
  2316. (lambda (P vars)
  2317. (k (vector P) vars))))
  2318. (else (k P vars))))
  2319. (loop P '() 0 k))
  2320. (define (m-compile-template T vars env)
  2321. (define (loop T inserted referenced rank escaped? k)
  2322. (cond ((symbol? T)
  2323. (let ((x (pattern-variable T vars)))
  2324. (if x
  2325. (if (>= rank (patternvar-rank x))
  2326. (k x inserted (cons x referenced))
  2327. (m-error
  2328. "Too few ellipses follow pattern variable in template"
  2329. (patternvar-name x)))
  2330. (k T (cons T inserted) referenced))))
  2331. ((null? T) (k '() inserted referenced))
  2332. ((pair? T)
  2333. (cond ((and (not escaped?)
  2334. (symbol? (car T))
  2335. (same-denotation? (syntactic-lookup env (car T))
  2336. denotation-of-...)
  2337. (pair? (cdr T))
  2338. (null? (cddr T)))
  2339. (loop (cadr T) inserted referenced rank #t k))
  2340. ((and (not escaped?)
  2341. (pair? (cdr T))
  2342. (symbol? (cadr T))
  2343. (same-denotation? (syntactic-lookup env (cadr T))
  2344. denotation-of-...))
  2345. (loop1 T inserted referenced rank escaped? k))
  2346. (else
  2347. (loop (car T)
  2348. inserted
  2349. referenced
  2350. rank
  2351. escaped?
  2352. (lambda (T1 inserted referenced)
  2353. (loop (cdr T)
  2354. inserted
  2355. referenced
  2356. rank
  2357. escaped?
  2358. (lambda (T2 inserted referenced)
  2359. (k (cons T1 T2) inserted referenced))))))))
  2360. ((vector? T)
  2361. (loop (vector->list T)
  2362. inserted
  2363. referenced
  2364. rank
  2365. escaped?
  2366. (lambda (T inserted referenced)
  2367. (k (vector T) inserted referenced))))
  2368. (else (k T inserted referenced))))
  2369. (define (loop1 T inserted referenced rank escaped? k)
  2370. (loop (car T)
  2371. inserted
  2372. '()
  2373. (+ rank 1)
  2374. escaped?
  2375. (lambda (T1 inserted referenced1)
  2376. (loop (cddr T)
  2377. inserted
  2378. (append referenced1 referenced)
  2379. rank
  2380. escaped?
  2381. (lambda (T2 inserted referenced)
  2382. (k (cons (make-ellipsis-template
  2383. T1
  2384. (filter1 (lambda (var)
  2385. (> (patternvar-rank var)
  2386. rank))
  2387. referenced1))
  2388. T2)
  2389. inserted
  2390. referenced))))))
  2391. (loop T
  2392. '()
  2393. '()
  2394. 0
  2395. #f
  2396. (lambda (T inserted referenced)
  2397. (list T inserted))))
  2398. ; The pattern matcher.
  2399. ;
  2400. ; Given an input, a pattern, and two syntactic environments,
  2401. ; returns a pattern variable environment (represented as an alist)
  2402. ; if the input matches the pattern, otherwise returns #f.
  2403. (define empty-pattern-variable-environment
  2404. (list (make-patternvar (string->symbol "") 0)))
  2405. (define (m-match F P env-def env-use)
  2406. (define (match F P answer rank)
  2407. (cond ((null? P)
  2408. (and (null? F) answer))
  2409. ((pair? P)
  2410. (and (pair? F)
  2411. (let ((answer (match (car F) (car P) answer rank)))
  2412. (and answer (match (cdr F) (cdr P) answer rank)))))
  2413. ((symbol? P)
  2414. (and (symbol? F)
  2415. (same-denotation? (syntactic-lookup env-def P)
  2416. (syntactic-lookup env-use F))
  2417. answer))
  2418. ((patternvar? P)
  2419. (cons (cons P F) answer))
  2420. ((ellipsis-pattern? P)
  2421. (match1 F P answer (+ rank 1)))
  2422. ((vector? P)
  2423. (and (vector? F)
  2424. (match (vector->list F) (vector-ref P 0) answer rank)))
  2425. (else (and (equal? F P) answer))))
  2426. (define (match1 F P answer rank)
  2427. (cond ((not (list? F)) #f)
  2428. ((null? F)
  2429. (append (map (lambda (var) (cons var '()))
  2430. (ellipsis-pattern-vars P))
  2431. answer))
  2432. (else
  2433. (let* ((P1 (ellipsis-pattern P))
  2434. (answers (map (lambda (F) (match F P1 answer rank))
  2435. F)))
  2436. (if (every1? (lambda (answer) answer) answers)
  2437. (append (map (lambda (var)
  2438. (cons var
  2439. (map (lambda (answer)
  2440. (cdr (assq var answer)))
  2441. answers)))
  2442. (ellipsis-pattern-vars P))
  2443. answer)
  2444. #f)))))
  2445. (match F P empty-pattern-variable-environment 0))
  2446. (define (m-rewrite T alist)
  2447. (define (rewrite T alist rank)
  2448. (cond ((null? T) '())
  2449. ((pair? T)
  2450. ((if (ellipsis-pattern? (car T))
  2451. append
  2452. cons)
  2453. (rewrite (car T) alist rank)
  2454. (rewrite (cdr T) alist rank)))
  2455. ((symbol? T) (cdr (assq T alist)))
  2456. ((patternvar? T) (cdr (assq T alist)))
  2457. ((ellipsis-template? T)
  2458. (rewrite1 T alist (+ rank 1)))
  2459. ((vector? T)
  2460. (list->vector (rewrite (vector-ref T 0) alist rank)))
  2461. (else T)))
  2462. (define (rewrite1 T alist rank)
  2463. (let* ((T1 (ellipsis-template T))
  2464. (vars (ellipsis-template-vars T))
  2465. (rows (map (lambda (var) (cdr (assq var alist)))
  2466. vars)))
  2467. (map (lambda (alist) (rewrite T1 alist rank))
  2468. (make-columns vars rows alist))))
  2469. (define (make-columns vars rows alist)
  2470. (define (loop rows)
  2471. (if (null? (car rows))
  2472. '()
  2473. (cons (append (map (lambda (var row)
  2474. (cons var (car row)))
  2475. vars
  2476. rows)
  2477. alist)
  2478. (loop (map cdr rows)))))
  2479. (if (or (null? (cdr rows))
  2480. (apply = (map length rows)))
  2481. (loop rows)
  2482. (m-error "Use of macro is not consistent with definition"
  2483. vars
  2484. rows)))
  2485. (rewrite T alist 0))
  2486. ; Given a use of a macro, the syntactic environment of the use,
  2487. ; a continuation that expects a transcribed expression and
  2488. ; a new environment in which to continue expansion, and a boolean
  2489. ; that is true if this transcription is for an inline procedure,
  2490. ; does the right thing.
  2491. (define (m-transcribe0 exp env-use k inline?)
  2492. (let* ((m (syntactic-lookup env-use (car exp)))
  2493. (rules (macro-rules m))
  2494. (env-def (macro-env m))
  2495. (F (cdr exp)))
  2496. (define (loop rules)
  2497. (if (null? rules)
  2498. (if inline?
  2499. (k exp env-use)
  2500. (m-error "Use of macro does not match definition" exp))
  2501. (let* ((rule (car rules))
  2502. (pattern (car rule))
  2503. (alist (m-match F pattern env-def env-use)))
  2504. (if alist
  2505. (let* ((template (cadr rule))
  2506. (inserted (caddr rule))
  2507. (alist2 (rename-vars inserted))
  2508. (newexp (m-rewrite template (append alist2 alist))))
  2509. (k newexp
  2510. (syntactic-alias env-use alist2 env-def)))
  2511. (loop (cdr rules))))))
  2512. (if (procedure? rules)
  2513. (m-transcribe-low-level exp env-use k rules env-def)
  2514. (loop rules))))
  2515. (define (m-transcribe exp env-use k)
  2516. (m-transcribe0 exp env-use k #f))
  2517. (define (m-transcribe-inline exp env-use k)
  2518. (m-transcribe0 exp env-use k #t))
  2519. ; Copyright 1998 William Clinger
  2520. ;
  2521. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  2522. ;
  2523. ; Low-level macro facility based on explicit renaming. See
  2524. ; William D Clinger. Hygienic macros through explicit renaming.
  2525. ; In Lisp Pointers IV(4), 25-28, December 1991.
  2526. ($$trace "lowlevel")
  2527. (define (m-transcribe-low-level exp env-use k transformer env-def)
  2528. (let ((rename0 (make-rename-procedure))
  2529. (renamed '())
  2530. (ok #t))
  2531. (define (lookup sym)
  2532. (let loop ((alist renamed))
  2533. (cond ((null? alist)
  2534. (syntactic-lookup env-use sym))
  2535. ((eq? sym (cdr (car alist)))
  2536. (syntactic-lookup env-def (car (car alist))))
  2537. (else
  2538. (loop (cdr alist))))))
  2539. (let ((rename
  2540. (lambda (sym)
  2541. (if ok
  2542. (let ((probe (assq sym renamed)))
  2543. (if probe
  2544. (cdr probe)
  2545. (let ((sym2 (rename0 sym)))
  2546. (set! renamed (cons (cons sym sym2) renamed))
  2547. sym2)))
  2548. (m-error "Illegal use of a rename procedure" sym))))
  2549. (compare
  2550. (lambda (sym1 sym2)
  2551. (same-denotation? (lookup sym1) (lookup sym2)))))
  2552. (let ((exp2 (transformer exp rename compare)))
  2553. (set! ok #f)
  2554. (k exp2
  2555. (syntactic-alias env-use renamed env-def))))))
  2556. (define identifier? symbol?)
  2557. (define (identifier->symbol id)
  2558. (m-strip id))
  2559. ; Copyright 1992 William Clinger
  2560. ;
  2561. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  2562. ;
  2563. ; 22 April 1999
  2564. ($$trace "expand")
  2565. ; This procedure sets the default scope of global macro definitions.
  2566. (define define-syntax-scope
  2567. (let ((flag 'letrec))
  2568. (lambda args
  2569. (cond ((null? args) flag)
  2570. ((not (null? (cdr args)))
  2571. (apply m-warn
  2572. "Too many arguments passed to define-syntax-scope"
  2573. args))
  2574. ((memq (car args) '(letrec letrec* let*))
  2575. (set! flag (car args)))
  2576. (else (m-warn "Unrecognized argument to define-syntax-scope"
  2577. (car args)))))))
  2578. ; The main entry point.
  2579. ; The outermost lambda allows known procedures to be lifted outside
  2580. ; all local variables.
  2581. (define (macro-expand def-or-exp)
  2582. (call-with-current-continuation
  2583. (lambda (k)
  2584. (set! m-quit k)
  2585. (set! renaming-counter 0)
  2586. (make-call
  2587. (make-lambda '() ; formals
  2588. '() ; definitions
  2589. '() ; R
  2590. '() ; F
  2591. '() ; G
  2592. '() ; declarations
  2593. #f ; documentation
  2594. (desugar-definitions def-or-exp
  2595. global-syntactic-environment
  2596. make-toplevel-definition))
  2597. '()))))
  2598. (define (desugar-definitions exp env make-toplevel-definition)
  2599. (letrec
  2600. ((define-loop
  2601. (lambda (exp rest first env)
  2602. (cond ((and (pair? exp)
  2603. (symbol? (car exp))
  2604. (eq? (syntactic-lookup env (car exp))
  2605. denotation-of-begin)
  2606. (pair? (cdr exp)))
  2607. (define-loop (cadr exp) (append (cddr exp) rest) first env))
  2608. ((and (pair? exp)
  2609. (symbol? (car exp))
  2610. (eq? (syntactic-lookup env (car exp))
  2611. denotation-of-define))
  2612. (let ((exp (desugar-define exp env)))
  2613. (cond ((and (null? first) (null? rest))
  2614. exp)
  2615. ((null? rest)
  2616. (make-begin (reverse (cons exp first))))
  2617. (else (define-loop (car rest)
  2618. (cdr rest)
  2619. (cons exp first)
  2620. env)))))
  2621. ((and (pair? exp)
  2622. (symbol? (car exp))
  2623. (or (eq? (syntactic-lookup env (car exp))
  2624. denotation-of-define-syntax)
  2625. (eq? (syntactic-lookup env (car exp))
  2626. denotation-of-define-inline))
  2627. (null? first))
  2628. (define-syntax-loop exp rest env))
  2629. ((and (pair? exp)
  2630. (symbol? (car exp))
  2631. (macro-denotation? (syntactic-lookup env (car exp))))
  2632. (m-transcribe exp
  2633. env
  2634. (lambda (exp env)
  2635. (define-loop exp rest first env))))
  2636. ((and (null? first) (null? rest))
  2637. (m-expand exp env))
  2638. ((null? rest)
  2639. (make-begin (reverse (cons (m-expand exp env) first))))
  2640. (else (make-begin
  2641. (append (reverse first)
  2642. (map (lambda (exp) (m-expand exp env))
  2643. (cons exp rest))))))))
  2644. (define-syntax-loop
  2645. (lambda (exp rest env)
  2646. (cond ((and (pair? exp)
  2647. (symbol? (car exp))
  2648. (eq? (syntactic-lookup env (car exp))
  2649. denotation-of-begin)
  2650. (pair? (cdr exp)))
  2651. (define-syntax-loop (cadr exp) (append (cddr exp) rest) env))
  2652. ((and (pair? exp)
  2653. (symbol? (car exp))
  2654. (eq? (syntactic-lookup env (car exp))
  2655. denotation-of-define-syntax))
  2656. (if (pair? (cdr exp))
  2657. (redefinition (cadr exp)))
  2658. (if (null? rest)
  2659. (m-define-syntax exp env)
  2660. (begin (m-define-syntax exp env)
  2661. (define-syntax-loop (car rest) (cdr rest) env))))
  2662. ((and (pair? exp)
  2663. (symbol? (car exp))
  2664. (eq? (syntactic-lookup env (car exp))
  2665. denotation-of-define-inline))
  2666. (if (pair? (cdr exp))
  2667. (redefinition (cadr exp)))
  2668. (if (null? rest)
  2669. (m-define-inline exp env)
  2670. (begin (m-define-inline exp env)
  2671. (define-syntax-loop (car rest) (cdr rest) env))))
  2672. ((and (pair? exp)
  2673. (symbol? (car exp))
  2674. (macro-denotation? (syntactic-lookup env (car exp))))
  2675. (m-transcribe exp
  2676. env
  2677. (lambda (exp env)
  2678. (define-syntax-loop exp rest env))))
  2679. ((and (pair? exp)
  2680. (symbol? (car exp))
  2681. (eq? (syntactic-lookup env (car exp))
  2682. denotation-of-define))
  2683. (define-loop exp rest '() env))
  2684. ((null? rest)
  2685. (m-expand exp env))
  2686. (else (make-begin
  2687. (map (lambda (exp) (m-expand exp env))
  2688. (cons exp rest)))))))
  2689. (desugar-define
  2690. (lambda (exp env)
  2691. (cond
  2692. ((null? (cdr exp)) (m-error "Malformed definition" exp))
  2693. ; (define foo) syntax is transformed into (define foo (undefined)).
  2694. ((null? (cddr exp))
  2695. (let ((id (cadr exp)))
  2696. (if (or (null? pass1-block-inlines)
  2697. (not (memq id pass1-block-inlines)))
  2698. (begin
  2699. (redefinition id)
  2700. (syntactic-bind-globally! id (make-identifier-denotation id))))
  2701. (make-toplevel-definition id (make-undefined))))
  2702. ((pair? (cadr exp))
  2703. (desugar-define
  2704. (let* ((def (car exp))
  2705. (pattern (cadr exp))
  2706. (f (car pattern))
  2707. (args (cdr pattern))
  2708. (body (cddr exp)))
  2709. (if (and (symbol? (car (cadr exp)))
  2710. (benchmark-mode)
  2711. (list? (cadr exp)))
  2712. `(,def ,f
  2713. (,lambda0 ,args
  2714. ((,lambda0 (,f)
  2715. (,set!0 ,f (,lambda0 ,args ,@body))
  2716. ,pattern)
  2717. 0)))
  2718. `(,def ,f (,lambda0 ,args ,@body))))
  2719. env))
  2720. ((> (length exp) 3) (m-error "Malformed definition" exp))
  2721. (else (let ((id (cadr exp)))
  2722. (if (or (null? pass1-block-inlines)
  2723. (not (memq id pass1-block-inlines)))
  2724. (begin
  2725. (redefinition id)
  2726. (syntactic-bind-globally! id (make-identifier-denotation id))))
  2727. (make-toplevel-definition id (m-expand (caddr exp) env)))))))
  2728. (redefinition
  2729. (lambda (id)
  2730. (if (symbol? id)
  2731. (if (not (identifier-denotation?
  2732. (syntactic-lookup global-syntactic-environment id)))
  2733. (if (issue-warnings)
  2734. (m-warn "Redefining " id)))
  2735. (m-error "Malformed variable or keyword" id)))))
  2736. ; body of letrec
  2737. (define-loop exp '() '() env)))
  2738. ; Given an expression and a syntactic environment,
  2739. ; returns an expression in core Scheme.
  2740. (define (m-expand exp env)
  2741. (cond ((not (pair? exp))
  2742. (m-atom exp env))
  2743. ((not (symbol? (car exp)))
  2744. (m-application exp env))
  2745. (else
  2746. (let ((keyword (syntactic-lookup env (car exp))))
  2747. (case (denotation-class keyword)
  2748. ((special)
  2749. (cond
  2750. ((eq? keyword denotation-of-quote) (m-quote exp))
  2751. ((eq? keyword denotation-of-lambda) (m-lambda exp env))
  2752. ((eq? keyword denotation-of-if) (m-if exp env))
  2753. ((eq? keyword denotation-of-set!) (m-set exp env))
  2754. ((eq? keyword denotation-of-begin) (m-begin exp env))
  2755. ((eq? keyword denotation-of-let-syntax)
  2756. (m-let-syntax exp env))
  2757. ((eq? keyword denotation-of-letrec-syntax)
  2758. (m-letrec-syntax exp env))
  2759. ((or (eq? keyword denotation-of-define)
  2760. (eq? keyword denotation-of-define-syntax)
  2761. (eq? keyword denotation-of-define-inline))
  2762. (m-error "Definition out of context" exp))
  2763. (else (m-bug "Bug detected in m-expand" exp env))))
  2764. ((macro) (m-macro exp env))
  2765. ((inline) (m-inline exp env))
  2766. ((identifier) (m-application exp env))
  2767. (else (m-bug "Bug detected in m-expand" exp env)))))))
  2768. (define (m-atom exp env)
  2769. (cond ((not (symbol? exp))
  2770. ; Here exp ought to be a boolean, number, character, or string.
  2771. ; I'll warn about other things but treat them as if quoted.
  2772. ;
  2773. ; I'm turning off some of the warnings because notably procedures
  2774. ; and #!unspecified can occur in loaded files and it's a major
  2775. ; pain if a warning is printed for each. --lars
  2776. (if (and (not (boolean? exp))
  2777. (not (number? exp))
  2778. (not (char? exp))
  2779. (not (string? exp))
  2780. (not (procedure? exp))
  2781. (not (eq? exp (unspecified))))
  2782. (m-warn "Malformed constant -- should be quoted" exp))
  2783. (make-constant exp))
  2784. (else (let ((denotation (syntactic-lookup env exp)))
  2785. (case (denotation-class denotation)
  2786. ((special macro)
  2787. (m-warn "Syntactic keyword used as a variable" exp)
  2788. ; Syntactic keywords used as variables are treated as #t.
  2789. (make-constant #t))
  2790. ((inline)
  2791. (make-variable (inline-name denotation)))
  2792. ((identifier)
  2793. (let ((var (make-variable (identifier-name denotation)))
  2794. (R-entry (identifier-R-entry denotation)))
  2795. (R-entry.references-set!
  2796. R-entry
  2797. (cons var (R-entry.references R-entry)))
  2798. var))
  2799. (else (m-bug "Bug detected by m-atom" exp env)))))))
  2800. (define (m-quote exp)
  2801. (if (and (pair? (cdr exp))
  2802. (null? (cddr exp)))
  2803. (make-constant (m-strip (cadr exp)))
  2804. (m-error "Malformed quoted constant" exp)))
  2805. (define (m-lambda exp env)
  2806. (if (> (safe-length exp) 2)
  2807. (let* ((formals (cadr exp))
  2808. (alist (rename-vars formals))
  2809. (env (syntactic-rename env alist))
  2810. (body (cddr exp)))
  2811. (do ((alist alist (cdr alist)))
  2812. ((null? alist))
  2813. (if (assq (caar alist) (cdr alist))
  2814. (m-error "Malformed parameter list" formals)))
  2815. ; To simplify the run-time system, there's a limit on how many
  2816. ; fixed arguments can be followed by a rest argument.
  2817. ; That limit is removed here.
  2818. ; Bug: documentation slot isn't right when this happens.
  2819. ; Bug: this generates extremely inefficient code.
  2820. (if (and (not (list? formals))
  2821. (> (length alist) @maxargs-with-rest-arg@))
  2822. (let ((TEMP (car (rename-vars '(temp)))))
  2823. (m-lambda
  2824. `(,lambda0 ,TEMP
  2825. ((,lambda0 ,(map car alist)
  2826. ,@(cddr exp))
  2827. ,@(do ((actuals '() (cons (list name:CAR path)
  2828. actuals))
  2829. (path TEMP (list name:CDR path))
  2830. (formals formals (cdr formals)))
  2831. ((symbol? formals)
  2832. (append (reverse actuals) (list path))))))
  2833. env))
  2834. (make-lambda (rename-formals formals alist)
  2835. '() ; no definitions yet
  2836. (map (lambda (entry)
  2837. (cdr (syntactic-lookup env (cdr entry))))
  2838. alist) ; R
  2839. '() ; F
  2840. '() ; G
  2841. '() ; decls
  2842. (make-doc #f
  2843. (if (list? formals)
  2844. (length alist)
  2845. (exact->inexact (- (length alist) 1)))
  2846. (if (include-variable-names)
  2847. formals
  2848. #f)
  2849. (if (include-source-code)
  2850. exp
  2851. #f)
  2852. source-file-name
  2853. source-file-position)
  2854. (m-body body env))))
  2855. (m-error "Malformed lambda expression" exp)))
  2856. (define (m-body body env)
  2857. (define (loop body env defs)
  2858. (if (null? body)
  2859. (m-error "Empty body"))
  2860. (let ((exp (car body)))
  2861. (if (and (pair? exp)
  2862. (symbol? (car exp)))
  2863. (let ((denotation (syntactic-lookup env (car exp))))
  2864. (case (denotation-class denotation)
  2865. ((special)
  2866. (cond ((eq? denotation denotation-of-begin)
  2867. (loop (append (cdr exp) (cdr body)) env defs))
  2868. ((eq? denotation denotation-of-define)
  2869. (loop (cdr body) env (cons exp defs)))
  2870. (else (finalize-body body env defs))))
  2871. ((macro)
  2872. (m-transcribe exp
  2873. env
  2874. (lambda (exp env)
  2875. (loop (cons exp (cdr body))
  2876. env
  2877. defs))))
  2878. ((inline identifier)
  2879. (finalize-body body env defs))
  2880. (else (m-bug "Bug detected in m-body" body env))))
  2881. (finalize-body body env defs))))
  2882. (loop body env '()))
  2883. (define (finalize-body body env defs)
  2884. (if (null? defs)
  2885. (let ((body (map (lambda (exp) (m-expand exp env))
  2886. body)))
  2887. (if (null? (cdr body))
  2888. (car body)
  2889. (make-begin body)))
  2890. (let ()
  2891. (define (sort-defs defs)
  2892. (let* ((augmented
  2893. (map (lambda (def)
  2894. (let ((rhs (cadr def)))
  2895. (if (not (pair? rhs))
  2896. (cons 'trivial def)
  2897. (let ((denotation
  2898. (syntactic-lookup env (car rhs))))
  2899. (cond ((eq? denotation
  2900. denotation-of-lambda)
  2901. (cons 'procedure def))
  2902. ((eq? denotation
  2903. denotation-of-quote)
  2904. (cons 'trivial def))
  2905. (else
  2906. (cons 'miscellaneous def)))))))
  2907. defs))
  2908. (sorted (twobit-sort (lambda (x y)
  2909. (or (eq? (car x) 'procedure)
  2910. (eq? (car y) 'miscellaneous)))
  2911. augmented)))
  2912. (map cdr sorted)))
  2913. (define (desugar-definition def)
  2914. (if (> (safe-length def) 2)
  2915. (cond ((pair? (cadr def))
  2916. (desugar-definition
  2917. `(,(car def)
  2918. ,(car (cadr def))
  2919. (,lambda0
  2920. ,(cdr (cadr def))
  2921. ,@(cddr def)))))
  2922. ((and (= (length def) 3)
  2923. (symbol? (cadr def)))
  2924. (cdr def))
  2925. (else (m-error "Malformed definition" def)))
  2926. (m-error "Malformed definition" def)))
  2927. (define (expand-letrec bindings body)
  2928. (make-call
  2929. (m-expand
  2930. `(,lambda0 ,(map car bindings)
  2931. ,@(map (lambda (binding)
  2932. `(,set!0 ,(car binding)
  2933. ,(cadr binding)))
  2934. bindings)
  2935. ,@body)
  2936. env)
  2937. (map (lambda (binding) (make-unspecified)) bindings)))
  2938. (expand-letrec (sort-defs (map desugar-definition
  2939. (reverse defs)))
  2940. body))))
  2941. (define (m-if exp env)
  2942. (let ((n (safe-length exp)))
  2943. (if (or (= n 3) (= n 4))
  2944. (make-conditional (m-expand (cadr exp) env)
  2945. (m-expand (caddr exp) env)
  2946. (if (= n 3)
  2947. (make-unspecified)
  2948. (m-expand (cadddr exp) env)))
  2949. (m-error "Malformed if expression" exp))))
  2950. (define (m-set exp env)
  2951. (if (= (safe-length exp) 3)
  2952. (let ((lhs (m-expand (cadr exp) env))
  2953. (rhs (m-expand (caddr exp) env)))
  2954. (if (variable? lhs)
  2955. (let* ((x (variable.name lhs))
  2956. (assignment (make-assignment x rhs))
  2957. (denotation (syntactic-lookup env x)))
  2958. (if (identifier-denotation? denotation)
  2959. (let ((R-entry (identifier-R-entry denotation)))
  2960. (R-entry.references-set!
  2961. R-entry
  2962. (remq lhs (R-entry.references R-entry)))
  2963. (R-entry.assignments-set!
  2964. R-entry
  2965. (cons assignment (R-entry.assignments R-entry)))))
  2966. (if (and (lambda? rhs)
  2967. (include-procedure-names))
  2968. (let ((doc (lambda.doc rhs)))
  2969. (doc.name-set! doc x)))
  2970. (if pass1-block-compiling?
  2971. (set! pass1-block-assignments
  2972. (cons x pass1-block-assignments)))
  2973. assignment)
  2974. (m-error "Malformed assignment" exp)))
  2975. (m-error "Malformed assignment" exp)))
  2976. (define (m-begin exp env)
  2977. (cond ((> (safe-length exp) 1)
  2978. (make-begin (map (lambda (exp) (m-expand exp env)) (cdr exp))))
  2979. ((= (safe-length exp) 1)
  2980. (m-warn "Non-standard begin expression" exp)
  2981. (make-unspecified))
  2982. (else
  2983. (m-error "Malformed begin expression" exp))))
  2984. (define (m-application exp env)
  2985. (if (> (safe-length exp) 0)
  2986. (let* ((proc (m-expand (car exp) env))
  2987. (args (map (lambda (exp) (m-expand exp env))
  2988. (cdr exp)))
  2989. (call (make-call proc args)))
  2990. (if (variable? proc)
  2991. (let* ((procname (variable.name proc))
  2992. (entry
  2993. (and (not (null? args))
  2994. (constant? (car args))
  2995. (integrate-usual-procedures)
  2996. (every1? constant? args)
  2997. (let ((entry (constant-folding-entry procname)))
  2998. (and entry
  2999. (let ((predicates
  3000. (constant-folding-predicates entry)))
  3001. (and (= (length args)
  3002. (length predicates))
  3003. (let loop ((args args)
  3004. (predicates predicates))
  3005. (cond ((null? args) entry)
  3006. (((car predicates)
  3007. (constant.value (car args)))
  3008. (loop (cdr args)
  3009. (cdr predicates)))
  3010. (else #f))))))))))
  3011. (if entry
  3012. (make-constant (apply (constant-folding-folder entry)
  3013. (map constant.value args)))
  3014. (let ((denotation (syntactic-lookup env procname)))
  3015. (if (identifier-denotation? denotation)
  3016. (let ((R-entry (identifier-R-entry denotation)))
  3017. (R-entry.calls-set!
  3018. R-entry
  3019. (cons call (R-entry.calls R-entry)))))
  3020. call)))
  3021. call))
  3022. (m-error "Malformed application" exp)))
  3023. ; The environment argument should always be global here.
  3024. (define (m-define-inline exp env)
  3025. (cond ((and (= (safe-length exp) 3)
  3026. (symbol? (cadr exp)))
  3027. (let ((name (cadr exp)))
  3028. (m-define-syntax1 name
  3029. (caddr exp)
  3030. env
  3031. (define-syntax-scope))
  3032. (let ((denotation
  3033. (syntactic-lookup global-syntactic-environment name)))
  3034. (syntactic-bind-globally!
  3035. name
  3036. (make-inline-denotation name
  3037. (macro-rules denotation)
  3038. (macro-env denotation))))
  3039. (make-constant name)))
  3040. (else
  3041. (m-error "Malformed define-inline" exp))))
  3042. ; The environment argument should always be global here.
  3043. (define (m-define-syntax exp env)
  3044. (cond ((and (= (safe-length exp) 3)
  3045. (symbol? (cadr exp)))
  3046. (m-define-syntax1 (cadr exp)
  3047. (caddr exp)
  3048. env
  3049. (define-syntax-scope)))
  3050. ((and (= (safe-length exp) 4)
  3051. (symbol? (cadr exp))
  3052. ; FIXME: should use denotations here
  3053. (memq (caddr exp) '(letrec letrec* let*)))
  3054. (m-define-syntax1 (cadr exp)
  3055. (cadddr exp)
  3056. env
  3057. (caddr exp)))
  3058. (else (m-error "Malformed define-syntax" exp))))
  3059. (define (m-define-syntax1 keyword spec env scope)
  3060. (if (and (pair? spec)
  3061. (symbol? (car spec)))
  3062. (let* ((transformer-keyword (car spec))
  3063. (denotation (syntactic-lookup env transformer-keyword)))
  3064. (cond ((eq? denotation denotation-of-syntax-rules)
  3065. (case scope
  3066. ((letrec) (m-define-syntax-letrec keyword spec env))
  3067. ((letrec*) (m-define-syntax-letrec* keyword spec env))
  3068. ((let*) (m-define-syntax-let* keyword spec env))
  3069. (else (m-bug "Weird scope" scope))))
  3070. ((same-denotation? denotation denotation-of-transformer)
  3071. ; FIXME: no error checking here
  3072. (syntactic-bind-globally!
  3073. keyword
  3074. (make-macro-denotation (eval (cadr spec)) env)))
  3075. (else
  3076. (m-error "Malformed syntax transformer" spec))))
  3077. (m-error "Malformed syntax transformer" spec))
  3078. (make-constant keyword))
  3079. (define (m-define-syntax-letrec keyword spec env)
  3080. (syntactic-bind-globally!
  3081. keyword
  3082. (m-compile-transformer-spec spec env)))
  3083. (define (m-define-syntax-letrec* keyword spec env)
  3084. (let* ((env (syntactic-extend (syntactic-copy env)
  3085. (list keyword)
  3086. '((fake denotation))))
  3087. (transformer (m-compile-transformer-spec spec env)))
  3088. (syntactic-assign! env keyword transformer)
  3089. (syntactic-bind-globally! keyword transformer)))
  3090. (define (m-define-syntax-let* keyword spec env)
  3091. (syntactic-bind-globally!
  3092. keyword
  3093. (m-compile-transformer-spec spec (syntactic-copy env))))
  3094. (define (m-let-syntax exp env)
  3095. (if (and (> (safe-length exp) 2)
  3096. (every1? (lambda (binding)
  3097. (and (pair? binding)
  3098. (symbol? (car binding))
  3099. (pair? (cdr binding))
  3100. (null? (cddr binding))))
  3101. (cadr exp)))
  3102. (m-body (cddr exp)
  3103. (syntactic-extend env
  3104. (map car (cadr exp))
  3105. (map (lambda (spec)
  3106. (m-compile-transformer-spec
  3107. spec
  3108. env))
  3109. (map cadr (cadr exp)))))
  3110. (m-error "Malformed let-syntax" exp)))
  3111. (define (m-letrec-syntax exp env)
  3112. (if (and (> (safe-length exp) 2)
  3113. (every1? (lambda (binding)
  3114. (and (pair? binding)
  3115. (symbol? (car binding))
  3116. (pair? (cdr binding))
  3117. (null? (cddr binding))))
  3118. (cadr exp)))
  3119. (let ((env (syntactic-extend env
  3120. (map car (cadr exp))
  3121. (map (lambda (id)
  3122. '(fake denotation))
  3123. (cadr exp)))))
  3124. (for-each (lambda (id spec)
  3125. (syntactic-assign!
  3126. env
  3127. id
  3128. (m-compile-transformer-spec spec env)))
  3129. (map car (cadr exp))
  3130. (map cadr (cadr exp)))
  3131. (m-body (cddr exp) env))
  3132. (m-error "Malformed let-syntax" exp)))
  3133. (define (m-macro exp env)
  3134. (m-transcribe exp
  3135. env
  3136. (lambda (exp env)
  3137. (m-expand exp env))))
  3138. (define (m-inline exp env)
  3139. (if (integrate-usual-procedures)
  3140. (m-transcribe-inline exp
  3141. env
  3142. (lambda (newexp env)
  3143. (if (eq? exp newexp)
  3144. (m-application exp env)
  3145. (m-expand newexp env))))
  3146. (m-application exp env)))
  3147. (define m-quit ; assigned by macro-expand
  3148. (lambda (v) v))
  3149. ; To do:
  3150. ; Clean up alist hacking et cetera.
  3151. ; Declarations.
  3152. ; Integrable procedures.
  3153. ; New semantics for body of LET-SYNTAX and LETREC-SYNTAX.
  3154. ; Copyright 1992 William Clinger
  3155. ;
  3156. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  3157. ;
  3158. ; 5 April 1999.
  3159. ($$trace "usual")
  3160. ; The usual macros, adapted from Jonathan's Version 2 implementation.
  3161. ; DEFINE is handled primitively, since top-level DEFINE has a side
  3162. ; effect on the global syntactic environment, and internal definitions
  3163. ; have to be handled specially anyway.
  3164. ;
  3165. ; Some extensions are noted, as are some optimizations.
  3166. ;
  3167. ; The LETREC* scope rule is used here to protect these macros against
  3168. ; redefinition of LAMBDA etc. The scope rule is changed to LETREC at
  3169. ; the end of this file.
  3170. (define-syntax-scope 'letrec*)
  3171. (for-each (lambda (form)
  3172. (macro-expand form))
  3173. '(
  3174. ; Named LET is defined later, after LETREC has been defined.
  3175. (define-syntax let
  3176. (syntax-rules ()
  3177. ((let ((?name ?val) ...) ?body ?body1 ...)
  3178. ((lambda (?name ...) ?body ?body1 ...) ?val ...))))
  3179. (define-syntax let*
  3180. (syntax-rules ()
  3181. ((let* () ?body ?body1 ...)
  3182. (let () ?body ?body1 ...))
  3183. ((let* ((?name1 ?val1) (?name ?val) ...) ?body ?body1 ...)
  3184. (let ((?name1 ?val1)) (let* ((?name ?val) ...) ?body ?body1 ...)))))
  3185. ; Internal definitions have to be handled specially anyway,
  3186. ; so we might as well rely on them here.
  3187. (define-syntax letrec
  3188. (syntax-rules (lambda quote)
  3189. ((letrec ((?name ?val) ...) ?body ?body2 ...)
  3190. ((lambda ()
  3191. (define ?name ?val) ...
  3192. ?body ?body2 ...)))))
  3193. ; This definition of named LET extends the prior definition of LET.
  3194. ; The first rule is non-circular, thanks to the LET* scope that is
  3195. ; specified for this use of DEFINE-SYNTAX.
  3196. (define-syntax let let*
  3197. (syntax-rules ()
  3198. ((let (?bindings ...) . ?body)
  3199. (let (?bindings ...) . ?body))
  3200. ((let ?tag ((?name ?val) ...) ?body ?body1 ...)
  3201. (let ((?name ?val) ...)
  3202. (letrec ((?tag (lambda (?name ...) ?body ?body1 ...)))
  3203. (?tag ?name ...))))))
  3204. (define-syntax and
  3205. (syntax-rules ()
  3206. ((and) #t)
  3207. ((and ?e) ?e)
  3208. ((and ?e1 ?e2 ?e3 ...)
  3209. (if ?e1 (and ?e2 ?e3 ...) #f))))
  3210. (define-syntax or
  3211. (syntax-rules ()
  3212. ((or) #f)
  3213. ((or ?e) ?e)
  3214. ((or ?e1 ?e2 ?e3 ...)
  3215. (let ((temp ?e1))
  3216. (if temp temp (or ?e2 ?e3 ...))))))
  3217. (define-syntax cond
  3218. (syntax-rules (else =>)
  3219. ((cond (else ?result ?result2 ...))
  3220. (begin ?result ?result2 ...))
  3221. ((cond (?test => ?result))
  3222. (let ((temp ?test))
  3223. (if temp (?result temp))))
  3224. ((cond (?test)) ?test)
  3225. ((cond (?test ?result ?result2 ...))
  3226. (if ?test (begin ?result ?result2 ...)))
  3227. ((cond (?test => ?result) ?clause ?clause2 ...)
  3228. (let ((temp ?test))
  3229. (if temp (?result temp) (cond ?clause ?clause2 ...))))
  3230. ((cond (?test) ?clause ?clause2 ...)
  3231. (or ?test (cond ?clause ?clause2 ...)))
  3232. ((cond (?test ?result ?result2 ...)
  3233. ?clause ?clause2 ...)
  3234. (if ?test
  3235. (begin ?result ?result2 ...)
  3236. (cond ?clause ?clause2 ...)))))
  3237. ; The R4RS says a <step> may be omitted.
  3238. ; That's a good excuse for a macro-defining macro that uses LETREC-SYNTAX
  3239. ; and the ... escape.
  3240. (define-syntax do
  3241. (syntax-rules ()
  3242. ((do (?bindings0 ...) (?test) ?body0 ...)
  3243. (do (?bindings0 ...) (?test (if #f #f)) ?body0 ...))
  3244. ((do (?bindings0 ...) ?clause0 ?body0 ...)
  3245. (letrec-syntax
  3246. ((do-aux
  3247. (... (syntax-rules ()
  3248. ((do-aux () ((?name ?init ?step) ...) ?clause ?body ...)
  3249. (letrec ((loop (lambda (?name ...)
  3250. (cond ?clause
  3251. (else
  3252. (begin #t ?body ...)
  3253. (loop ?step ...))))))
  3254. (loop ?init ...)))
  3255. ((do-aux ((?name ?init ?step) ?todo ...)
  3256. (?bindings ...)
  3257. ?clause
  3258. ?body ...)
  3259. (do-aux (?todo ...)
  3260. (?bindings ... (?name ?init ?step))
  3261. ?clause
  3262. ?body ...))
  3263. ((do-aux ((?name ?init) ?todo ...)
  3264. (?bindings ...)
  3265. ?clause
  3266. ?body ...)
  3267. (do-aux (?todo ...)
  3268. (?bindings ... (?name ?init ?name))
  3269. ?clause
  3270. ?body ...))))))
  3271. (do-aux (?bindings0 ...) () ?clause0 ?body0 ...)))))
  3272. (define-syntax delay
  3273. (syntax-rules ()
  3274. ((delay ?e) (.make-promise (lambda () ?e)))))
  3275. ; Another use of LETREC-SYNTAX and the escape extension.
  3276. (define-syntax case
  3277. (syntax-rules (else)
  3278. ((case ?e1 (else ?body ?body2 ...))
  3279. (begin ?e1 ?body ?body2 ...))
  3280. ((case ?e1 (?z ?body ?body2 ...))
  3281. (if (memv ?e1 '?z) (begin ?body ?body2 ...)))
  3282. ((case ?e1 ?clause1 ?clause2 ?clause3 ...)
  3283. (letrec-syntax
  3284. ((case-aux
  3285. (... (syntax-rules (else)
  3286. ((case-aux ?temp (else ?body ?body2 ...))
  3287. (begin ?body ?body2 ...))
  3288. ((case-aux ?temp ((?z ...) ?body ?body2 ...))
  3289. (if (memv ?temp '(?z ...)) (begin ?body ?body2 ...)))
  3290. ((case-aux ?temp ((?z ...) ?body ?body2 ...) ?c1 ?c2 ...)
  3291. (if (memv ?temp '(?z ...))
  3292. (begin ?body ?body2 ...)
  3293. (case-aux ?temp ?c1 ?c2 ...)))
  3294. ; a popular extension
  3295. ((case-aux ?temp (?z ?body ...) ?c1 ...)
  3296. (case-aux ?temp ((?z) ?body ...) ?c1 ...))))))
  3297. (let ((temp ?e1))
  3298. (case-aux temp ?clause1 ?clause2 ?clause3 ...))))))
  3299. ; A complete implementation of quasiquote, obtained by translating
  3300. ; Jonathan Rees's implementation that was posted to RRRS-AUTHORS
  3301. ; on 22 December 1986.
  3302. ; Unfortunately, the use of LETREC scope means that it is vulnerable
  3303. ; to top-level redefinitions of QUOTE etc. That could be fixed, but
  3304. ; it has hair enough already.
  3305. (begin
  3306. (define-syntax .finalize-quasiquote letrec
  3307. (syntax-rules (quote unquote unquote-splicing)
  3308. ((.finalize-quasiquote quote ?arg ?return)
  3309. (.interpret-continuation ?return (quote ?arg)))
  3310. ((.finalize-quasiquote unquote ?arg ?return)
  3311. (.interpret-continuation ?return ?arg))
  3312. ((.finalize-quasiquote unquote-splicing ?arg ?return)
  3313. (syntax-error ",@ in illegal context" ?arg))
  3314. ((.finalize-quasiquote ?mode ?arg ?return)
  3315. (.interpret-continuation ?return (?mode . ?arg)))))
  3316. ; The first two "arguments" to .descend-quasiquote and to
  3317. ; .descend-quasiquote-pair are always identical.
  3318. (define-syntax .descend-quasiquote letrec
  3319. (syntax-rules (quasiquote unquote unquote-splicing)
  3320. ((.descend-quasiquote `?y ?x ?level ?return)
  3321. (.descend-quasiquote-pair ?x ?x (?level) ?return))
  3322. ((.descend-quasiquote ,?y ?x () ?return)
  3323. (.interpret-continuation ?return unquote ?y))
  3324. ((.descend-quasiquote ,?y ?x (?level) ?return)
  3325. (.descend-quasiquote-pair ?x ?x ?level ?return))
  3326. ((.descend-quasiquote ,@?y ?x () ?return)
  3327. (.interpret-continuation ?return unquote-splicing ?y))
  3328. ((.descend-quasiquote ,@?y ?x (?level) ?return)
  3329. (.descend-quasiquote-pair ?x ?x ?level ?return))
  3330. ((.descend-quasiquote (?y . ?z) ?x ?level ?return)
  3331. (.descend-quasiquote-pair ?x ?x ?level ?return))
  3332. ((.descend-quasiquote #(?y ...) ?x ?level ?return)
  3333. (.descend-quasiquote-vector ?x ?x ?level ?return))
  3334. ((.descend-quasiquote ?y ?x ?level ?return)
  3335. (.interpret-continuation ?return quote ?x))))
  3336. (define-syntax .descend-quasiquote-pair letrec
  3337. (syntax-rules (quote unquote unquote-splicing)
  3338. ((.descend-quasiquote-pair (?carx . ?cdrx) ?x ?level ?return)
  3339. (.descend-quasiquote ?carx ?carx ?level (1 ?cdrx ?x ?level ?return)))))
  3340. (define-syntax .descend-quasiquote-vector letrec
  3341. (syntax-rules (quote)
  3342. ((.descend-quasiquote-vector #(?y ...) ?x ?level ?return)
  3343. (.descend-quasiquote (?y ...) (?y ...) ?level (6 ?x ?return)))))
  3344. ; Representations for continuations used here.
  3345. ; Continuation types 0, 1, 2, and 6 take a mode and an expression.
  3346. ; Continuation types -1, 3, 4, 5, and 7 take just an expression.
  3347. ;
  3348. ; (-1)
  3349. ; means no continuation
  3350. ; (0)
  3351. ; means to call .finalize-quasiquote with no further continuation
  3352. ; (1 ?cdrx ?x ?level ?return)
  3353. ; means a return from the call to .descend-quasiquote from
  3354. ; .descend-quasiquote-pair
  3355. ; (2 ?car-mode ?car-arg ?x ?return)
  3356. ; means a return from the second call to .descend-quasiquote in
  3357. ; in Jonathan's code for .descend-quasiquote-pair
  3358. ; (3 ?car-arg ?return)
  3359. ; means take the result and return an append of ?car-arg with it
  3360. ; (4 ?cdr-mode ?cdr-arg ?return)
  3361. ; means take the result and call .finalize-quasiquote on ?cdr-mode
  3362. ; and ?cdr-arg with a continuation of type 5
  3363. ; (5 ?car-result ?return)
  3364. ; means take the result and return a cons of ?car-result onto it
  3365. ; (6 ?x ?return)
  3366. ; means a return from the call to .descend-quasiquote from
  3367. ; .descend-quasiquote-vector
  3368. ; (7 ?return)
  3369. ; means take the result and return a call of list->vector on it
  3370. (define-syntax .interpret-continuation letrec
  3371. (syntax-rules (quote unquote unquote-splicing)
  3372. ((.interpret-continuation (-1) ?e) ?e)
  3373. ((.interpret-continuation (0) ?mode ?arg)
  3374. (.finalize-quasiquote ?mode ?arg (-1)))
  3375. ((.interpret-continuation (1 ?cdrx ?x ?level ?return) ?car-mode ?car-arg)
  3376. (.descend-quasiquote ?cdrx
  3377. ?cdrx
  3378. ?level
  3379. (2 ?car-mode ?car-arg ?x ?return)))
  3380. ((.interpret-continuation (2 quote ?car-arg ?x ?return) quote ?cdr-arg)
  3381. (.interpret-continuation ?return quote ?x))
  3382. ((.interpret-continuation (2 unquote-splicing ?car-arg ?x ?return) quote ())
  3383. (.interpret-continuation ?return unquote ?car-arg))
  3384. ((.interpret-continuation (2 unquote-splicing ?car-arg ?x ?return)
  3385. ?cdr-mode ?cdr-arg)
  3386. (.finalize-quasiquote ?cdr-mode ?cdr-arg (3 ?car-arg ?return)))
  3387. ((.interpret-continuation (2 ?car-mode ?car-arg ?x ?return)
  3388. ?cdr-mode ?cdr-arg)
  3389. (.finalize-quasiquote ?car-mode ?car-arg (4 ?cdr-mode ?cdr-arg ?return)))
  3390. ((.interpret-continuation (3 ?car-arg ?return) ?e)
  3391. (.interpret-continuation ?return append (?car-arg ?e)))
  3392. ((.interpret-continuation (4 ?cdr-mode ?cdr-arg ?return) ?e1)
  3393. (.finalize-quasiquote ?cdr-mode ?cdr-arg (5 ?e1 ?return)))
  3394. ((.interpret-continuation (5 ?e1 ?return) ?e2)
  3395. (.interpret-continuation ?return .cons (?e1 ?e2)))
  3396. ((.interpret-continuation (6 ?x ?return) quote ?arg)
  3397. (.interpret-continuation ?return quote ?x))
  3398. ((.interpret-continuation (6 ?x ?return) ?mode ?arg)
  3399. (.finalize-quasiquote ?mode ?arg (7 ?return)))
  3400. ((.interpret-continuation (7 ?return) ?e)
  3401. (.interpret-continuation ?return .list->vector (?e)))))
  3402. (define-syntax quasiquote letrec
  3403. (syntax-rules ()
  3404. ((quasiquote ?x)
  3405. (.descend-quasiquote ?x ?x () (0)))))
  3406. )
  3407. (define-syntax let*-syntax
  3408. (syntax-rules ()
  3409. ((let*-syntax () ?body)
  3410. (let-syntax () ?body))
  3411. ((let*-syntax ((?name1 ?val1) (?name ?val) ...) ?body)
  3412. (let-syntax ((?name1 ?val1)) (let*-syntax ((?name ?val) ...) ?body)))))
  3413. ))
  3414. (define-syntax-scope 'letrec)
  3415. (define standard-syntactic-environment
  3416. (syntactic-copy global-syntactic-environment))
  3417. (define (make-standard-syntactic-environment)
  3418. (syntactic-copy standard-syntactic-environment))
  3419. ; Copyright 1998 William Clinger.
  3420. ;
  3421. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  3422. ;
  3423. ; 25 April 1999
  3424. ;
  3425. ; Given an expression in the subset of Scheme used as an intermediate language
  3426. ; by Twobit, returns a newly allocated copy of the expression in which the
  3427. ; local variables have been renamed and the referencing information has been
  3428. ; recomputed.
  3429. (define (copy-exp exp)
  3430. (define special-names (cons name:IGNORED argument-registers))
  3431. (define original-names (make-hashtable symbol-hash assq))
  3432. (define renaming-counter 0)
  3433. (define (rename-vars vars)
  3434. (let ((rename (make-rename-procedure)))
  3435. (map (lambda (var)
  3436. (cond ((memq var special-names)
  3437. var)
  3438. ((hashtable-get original-names var)
  3439. (rename var))
  3440. (else
  3441. (hashtable-put! original-names var #t)
  3442. var)))
  3443. vars)))
  3444. (define (rename-formals formals newnames)
  3445. (cond ((null? formals) '())
  3446. ((symbol? formals) (car newnames))
  3447. ((memq (car formals) special-names)
  3448. (cons (car formals)
  3449. (rename-formals (cdr formals)
  3450. (cdr newnames))))
  3451. (else (cons (car newnames)
  3452. (rename-formals (cdr formals)
  3453. (cdr newnames))))))
  3454. ; Environments that map symbols to arbitrary information.
  3455. ; This data type is mutable, and uses the shallow binding technique.
  3456. (define (make-env) (make-hashtable symbol-hash assq))
  3457. (define (env-bind! env sym info)
  3458. (let ((stack (hashtable-get env sym)))
  3459. (hashtable-put! env sym (cons info stack))))
  3460. (define (env-unbind! env sym)
  3461. (let ((stack (hashtable-get env sym)))
  3462. (hashtable-put! env sym (cdr stack))))
  3463. (define (env-lookup env sym default)
  3464. (let ((stack (hashtable-get env sym)))
  3465. (if stack
  3466. (car stack)
  3467. default)))
  3468. (define (env-bind-multiple! env symbols infos)
  3469. (for-each (lambda (sym info) (env-bind! env sym info))
  3470. symbols
  3471. infos))
  3472. (define (env-unbind-multiple! env symbols)
  3473. (for-each (lambda (sym) (env-unbind! env sym))
  3474. symbols))
  3475. ;
  3476. (define (lexical-lookup R-table name)
  3477. (assq name R-table))
  3478. (define (copy exp env notepad R-table)
  3479. (cond ((constant? exp) exp)
  3480. ((lambda? exp)
  3481. (let* ((bvl (make-null-terminated (lambda.args exp)))
  3482. (newnames (rename-vars bvl))
  3483. (procnames (map def.lhs (lambda.defs exp)))
  3484. (newprocnames (rename-vars procnames))
  3485. (refinfo (map (lambda (var)
  3486. (make-R-entry var '() '() '()))
  3487. (append newnames newprocnames)))
  3488. (newexp
  3489. (make-lambda
  3490. (rename-formals (lambda.args exp) newnames)
  3491. '()
  3492. refinfo
  3493. '()
  3494. '()
  3495. (lambda.decls exp)
  3496. (lambda.doc exp)
  3497. (lambda.body exp))))
  3498. (env-bind-multiple! env procnames newprocnames)
  3499. (env-bind-multiple! env bvl newnames)
  3500. (for-each (lambda (entry)
  3501. (env-bind! R-table (R-entry.name entry) entry))
  3502. refinfo)
  3503. (notepad-lambda-add! notepad newexp)
  3504. (let ((newnotepad (make-notepad notepad)))
  3505. (for-each (lambda (name rhs)
  3506. (lambda.defs-set!
  3507. newexp
  3508. (cons (make-definition
  3509. name
  3510. (copy rhs env newnotepad R-table))
  3511. (lambda.defs newexp))))
  3512. (reverse newprocnames)
  3513. (map def.rhs
  3514. (reverse (lambda.defs exp))))
  3515. (lambda.body-set!
  3516. newexp
  3517. (copy (lambda.body exp) env newnotepad R-table))
  3518. (lambda.F-set! newexp (notepad-free-variables newnotepad))
  3519. (lambda.G-set! newexp (notepad-captured-variables newnotepad)))
  3520. (env-unbind-multiple! env procnames)
  3521. (env-unbind-multiple! env bvl)
  3522. (for-each (lambda (entry)
  3523. (env-unbind! R-table (R-entry.name entry)))
  3524. refinfo)
  3525. newexp))
  3526. ((assignment? exp)
  3527. (let* ((oldname (assignment.lhs exp))
  3528. (name (env-lookup env oldname oldname))
  3529. (varinfo (env-lookup R-table name #f))
  3530. (newexp
  3531. (make-assignment name
  3532. (copy (assignment.rhs exp) env notepad R-table))))
  3533. (notepad-var-add! notepad name)
  3534. (if varinfo
  3535. (R-entry.assignments-set!
  3536. varinfo
  3537. (cons newexp (R-entry.assignments varinfo))))
  3538. newexp))
  3539. ((conditional? exp)
  3540. (make-conditional (copy (if.test exp) env notepad R-table)
  3541. (copy (if.then exp) env notepad R-table)
  3542. (copy (if.else exp) env notepad R-table)))
  3543. ((begin? exp)
  3544. (make-begin (map (lambda (exp) (copy exp env notepad R-table))
  3545. (begin.exprs exp))))
  3546. ((variable? exp)
  3547. (let* ((oldname (variable.name exp))
  3548. (name (env-lookup env oldname oldname))
  3549. (varinfo (env-lookup R-table name #f))
  3550. (newexp (make-variable name)))
  3551. (notepad-var-add! notepad name)
  3552. (if varinfo
  3553. (R-entry.references-set!
  3554. varinfo
  3555. (cons newexp (R-entry.references varinfo))))
  3556. newexp))
  3557. ((call? exp)
  3558. (let ((newexp (make-call (copy (call.proc exp) env notepad R-table)
  3559. (map (lambda (exp)
  3560. (copy exp env notepad R-table))
  3561. (call.args exp)))))
  3562. (if (variable? (call.proc newexp))
  3563. (let ((varinfo
  3564. (env-lookup R-table
  3565. (variable.name
  3566. (call.proc newexp))
  3567. #f)))
  3568. (if varinfo
  3569. (R-entry.calls-set!
  3570. varinfo
  3571. (cons newexp (R-entry.calls varinfo))))))
  3572. (if (lambda? (call.proc newexp))
  3573. (notepad-nonescaping-add! notepad (call.proc newexp)))
  3574. newexp))
  3575. (else ???)))
  3576. (copy exp (make-env) (make-notepad #f) (make-env)))
  3577. ; For debugging.
  3578. ; Given an expression, traverses the expression to confirm
  3579. ; that the referencing invariants are correct.
  3580. (define (check-referencing-invariants exp . flags)
  3581. (let ((check-free-variables? (memq 'free flags))
  3582. (check-referencing? (memq 'reference flags))
  3583. (first-violation? #t))
  3584. ; env is the list of enclosing lambda expressions,
  3585. ; beginning with the innermost.
  3586. (define (check exp env)
  3587. (cond ((constant? exp) (return exp #t))
  3588. ((lambda? exp)
  3589. (let ((env (cons exp env)))
  3590. (return exp
  3591. (and (every? (lambda (exp)
  3592. (check exp env))
  3593. (map def.rhs (lambda.defs exp)))
  3594. (check (lambda.body exp) env)
  3595. (if (and check-free-variables?
  3596. (not (null? env)))
  3597. (subset? (difference
  3598. (lambda.F exp)
  3599. (make-null-terminated
  3600. (lambda.args exp)))
  3601. (lambda.F (car env)))
  3602. #t)
  3603. (if check-referencing?
  3604. (let ((env (cons exp env))
  3605. (R (lambda.R exp)))
  3606. (every? (lambda (formal)
  3607. (or (ignored? formal)
  3608. (R-entry R formal)))
  3609. (make-null-terminated
  3610. (lambda.args exp))))
  3611. #t)))))
  3612. ((variable? exp)
  3613. (return exp
  3614. (and (if (and check-free-variables?
  3615. (not (null? env)))
  3616. (memq (variable.name exp)
  3617. (lambda.F (car env)))
  3618. #t)
  3619. (if check-referencing?
  3620. (let ((Rinfo (lookup env (variable.name exp))))
  3621. (if Rinfo
  3622. (memq exp (R-entry.references Rinfo))
  3623. #t))
  3624. #t))))
  3625. ((assignment? exp)
  3626. (return exp
  3627. (and (check (assignment.rhs exp) env)
  3628. (if (and check-free-variables?
  3629. (not (null? env)))
  3630. (memq (assignment.lhs exp)
  3631. (lambda.F (car env)))
  3632. #t)
  3633. (if check-referencing?
  3634. (let ((Rinfo (lookup env (assignment.lhs exp))))
  3635. (if Rinfo
  3636. (memq exp (R-entry.assignments Rinfo))
  3637. #t))
  3638. #t))))
  3639. ((conditional? exp)
  3640. (return exp
  3641. (and (check (if.test exp) env)
  3642. (check (if.then exp) env)
  3643. (check (if.else exp) env))))
  3644. ((begin? exp)
  3645. (return exp
  3646. (every? (lambda (exp) (check exp env))
  3647. (begin.exprs exp))))
  3648. ((call? exp)
  3649. (return exp
  3650. (and (check (call.proc exp) env)
  3651. (every? (lambda (exp) (check exp env))
  3652. (call.args exp))
  3653. (if (and check-referencing?
  3654. (variable? (call.proc exp)))
  3655. (let ((Rinfo (lookup env
  3656. (variable.name
  3657. (call.proc exp)))))
  3658. (if Rinfo
  3659. (memq exp (R-entry.calls Rinfo))
  3660. #t))
  3661. #t))))
  3662. (else ???)))
  3663. (define (return exp flag)
  3664. (cond (flag
  3665. #t)
  3666. (first-violation?
  3667. (set! first-violation? #f)
  3668. (display "Violation of referencing invariants")
  3669. (newline)
  3670. (pretty-print (make-readable exp))
  3671. #f)
  3672. (else (pretty-print (make-readable exp))
  3673. #f)))
  3674. (define (lookup env I)
  3675. (if (null? env)
  3676. #f
  3677. (let ((Rinfo (R-entry (lambda.R (car env)) I)))
  3678. (or Rinfo
  3679. (lookup (cdr env) I)))))
  3680. (if (null? flags)
  3681. (begin (set! check-free-variables? #t)
  3682. (set! check-referencing? #t)))
  3683. (check exp '())))
  3684. ; Calculating the free variable information for an expression
  3685. ; as output by pass 2. This should be faster than computing both
  3686. ; the free variables and the referencing information.
  3687. (define (compute-free-variables! exp)
  3688. (define empty-set (make-set '()))
  3689. (define (singleton x) (list x))
  3690. (define (union2 x y) (union x y))
  3691. (define (union3 x y z) (union x y z))
  3692. (define (set->list set) set)
  3693. (define (free exp)
  3694. (cond ((constant? exp) empty-set)
  3695. ((lambda? exp)
  3696. (let* ((defs (lambda.defs exp))
  3697. (formals (make-set
  3698. (make-null-terminated (lambda.args exp))))
  3699. (defined (make-set (map def.lhs defs)))
  3700. (Fdefs
  3701. (apply-union
  3702. (map (lambda (def)
  3703. (free (def.rhs def)))
  3704. defs)))
  3705. (Fbody (free (lambda.body exp)))
  3706. (F (union2 Fdefs Fbody)))
  3707. (lambda.F-set! exp (set->list F))
  3708. (lambda.G-set! exp (set->list F))
  3709. (difference F (union2 formals defined))))
  3710. ((assignment? exp)
  3711. (union2 (make-set (list (assignment.lhs exp)))
  3712. (free (assignment.rhs exp))))
  3713. ((conditional? exp)
  3714. (union3 (free (if.test exp))
  3715. (free (if.then exp))
  3716. (free (if.else exp))))
  3717. ((begin? exp)
  3718. (apply-union
  3719. (map (lambda (exp) (free exp))
  3720. (begin.exprs exp))))
  3721. ((variable? exp)
  3722. (singleton (variable.name exp)))
  3723. ((call? exp)
  3724. (union2 (free (call.proc exp))
  3725. (apply-union
  3726. (map (lambda (exp) (free exp))
  3727. (call.args exp)))))
  3728. (else ???)))
  3729. (free exp))
  3730. ; As above, but representing sets as hashtrees.
  3731. ; This is commented out because it is much slower than the implementation
  3732. ; above. Because the set of free variables is represented as a list
  3733. ; within a lambda expression, this implementation must convert the
  3734. ; representation for every lambda expression, which is quite expensive
  3735. ; for A-normal form.
  3736. (begin
  3737. '
  3738. (define (compute-free-variables! exp)
  3739. (define empty-set (make-hashtree symbol-hash assq))
  3740. (define (singleton x)
  3741. (hashtree-put empty-set x #t))
  3742. (define (make-set values)
  3743. (if (null? values)
  3744. empty-set
  3745. (hashtree-put (make-set (cdr values))
  3746. (car values)
  3747. #t)))
  3748. (define (union2 x y)
  3749. (hashtree-for-each (lambda (key val)
  3750. (set! x (hashtree-put x key #t)))
  3751. y)
  3752. x)
  3753. (define (union3 x y z)
  3754. (union2 (union2 x y) z))
  3755. (define (apply-union sets)
  3756. (cond ((null? sets)
  3757. (make-set '()))
  3758. ((null? (cdr sets))
  3759. (car sets))
  3760. (else
  3761. (union2 (car sets)
  3762. (apply-union (cdr sets))))))
  3763. (define (difference x y)
  3764. (hashtree-for-each (lambda (key val)
  3765. (set! x (hashtree-remove x key)))
  3766. y)
  3767. x)
  3768. (define (set->list set)
  3769. (hashtree-map (lambda (sym val) sym) set))
  3770. (define (free exp)
  3771. (cond ((constant? exp) empty-set)
  3772. ((lambda? exp)
  3773. (let* ((defs (lambda.defs exp))
  3774. (formals (make-set
  3775. (make-null-terminated (lambda.args exp))))
  3776. (defined (make-set (map def.lhs defs)))
  3777. (Fdefs
  3778. (apply-union
  3779. (map (lambda (def)
  3780. (free (def.rhs def)))
  3781. defs)))
  3782. (Fbody (free (lambda.body exp)))
  3783. (F (union2 Fdefs Fbody)))
  3784. (lambda.F-set! exp (set->list F))
  3785. (lambda.G-set! exp (set->list F))
  3786. (difference F (union2 formals defined))))
  3787. ((assignment? exp)
  3788. (union2 (make-set (list (assignment.lhs exp)))
  3789. (free (assignment.rhs exp))))
  3790. ((conditional? exp)
  3791. (union3 (free (if.test exp))
  3792. (free (if.then exp))
  3793. (free (if.else exp))))
  3794. ((begin? exp)
  3795. (apply-union
  3796. (map (lambda (exp) (free exp))
  3797. (begin.exprs exp))))
  3798. ((variable? exp)
  3799. (singleton (variable.name exp)))
  3800. ((call? exp)
  3801. (union2 (free (call.proc exp))
  3802. (apply-union
  3803. (map (lambda (exp) (free exp))
  3804. (call.args exp)))))
  3805. (else ???)))
  3806. (hashtree-map (lambda (sym val) sym)
  3807. (free exp)))
  3808. #t); Copyright 1991 William Clinger
  3809. ;
  3810. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  3811. ;
  3812. ; 24 April 1999
  3813. ;
  3814. ; First pass of the Twobit compiler:
  3815. ; macro expansion, syntax checking, alpha conversion,
  3816. ; preliminary annotation.
  3817. ;
  3818. ; The input to this pass is a Scheme definition or expression.
  3819. ; The output is an expression in the subset of Scheme described
  3820. ; by the following grammar, where the output satisfies certain
  3821. ; additional invariants described below.
  3822. ;
  3823. ; "X ..." means zero or more occurrences of X.
  3824. ;
  3825. ; L --> (lambda (I_1 ...)
  3826. ; (begin D ...)
  3827. ; (quote (R F G <decls> <doc>)
  3828. ; E)
  3829. ; | (lambda (I_1 ... . I_rest)
  3830. ; (begin D ...)
  3831. ; (quote (R F <decls> <doc>))
  3832. ; E)
  3833. ; D --> (define I L)
  3834. ; E --> (quote K) ; constants
  3835. ; | (begin I) ; variable references
  3836. ; | L ; lambda expressions
  3837. ; | (E0 E1 ...) ; calls
  3838. ; | (set! I E) ; assignments
  3839. ; | (if E0 E1 E2) ; conditionals
  3840. ; | (begin E0 E1 E2 ...) ; sequential expressions
  3841. ; I --> <identifier>
  3842. ;
  3843. ; R --> ((I <references> <assignments> <calls>) ...)
  3844. ; F --> (I ...)
  3845. ; G --> (I ...)
  3846. ;
  3847. ; Invariants that hold for the output:
  3848. ; * There are no internal definitions.
  3849. ; * No identifier containing an upper case letter is bound anywhere.
  3850. ; (Change the "name:..." variables if upper case is preferred.)
  3851. ; * No identifier is bound in more than one place.
  3852. ; * Each R contains one entry for every identifier bound in the
  3853. ; formal argument list and the internal definition list that
  3854. ; precede it. Each entry contains a list of pointers to all
  3855. ; references to the identifier, a list of pointers to all
  3856. ; assignments to the identifier, and a list of pointers to all
  3857. ; calls to the identifier.
  3858. ; * Except for constants, the expression does not share structure
  3859. ; with the original input or itself, except that the references
  3860. ; and assignments in R are guaranteed to share structure with
  3861. ; the expression. Thus the expression may be side effected, and
  3862. ; side effects to references or assignments obtained through R
  3863. ; are guaranteed to change the references or assignments pointed
  3864. ; to by R.
  3865. ; * F and G are garbage.
  3866. ($$trace "pass1")
  3867. (define source-file-name #f)
  3868. (define source-file-position #f)
  3869. (define pass1-block-compiling? #f)
  3870. (define pass1-block-assignments '())
  3871. (define pass1-block-inlines '())
  3872. (define (pass1 def-or-exp . rest)
  3873. (set! source-file-name #f)
  3874. (set! source-file-position #f)
  3875. (set! pass1-block-compiling? #f)
  3876. (set! pass1-block-assignments '())
  3877. (set! pass1-block-inlines '())
  3878. (if (not (null? rest))
  3879. (begin (set! source-file-name (car rest))
  3880. (if (not (null? (cdr rest)))
  3881. (set! source-file-position (cadr rest)))))
  3882. (set! renaming-counter 0)
  3883. (macro-expand def-or-exp))
  3884. ; Compiles a whole sequence of top-level forms on the assumption
  3885. ; that no variable that is defined by a form in the sequence is
  3886. ; ever defined or assigned outside of the sequence.
  3887. ;
  3888. ; This is a crock in three parts:
  3889. ;
  3890. ; 1. Macro-expand each form and record assignments.
  3891. ; 2. Find the top-level variables that are defined but not
  3892. ; assigned, give them local names, generate a DEFINE-INLINE
  3893. ; for each of the top-level procedures, and macro-expand
  3894. ; each form again.
  3895. ; 3. Wrap the whole mess in an appropriate LET and recompute
  3896. ; the referencing information by copying it.
  3897. ;
  3898. ; Note that macros get expanded twice, and that all DEFINE-SYNTAX
  3899. ; macros are considered local to the forms.
  3900. ; FIXME: Need to turn off warning messages.
  3901. (define (pass1-block forms . rest)
  3902. (define (part1)
  3903. (set! pass1-block-compiling? #t)
  3904. (set! pass1-block-assignments '())
  3905. (set! pass1-block-inlines '())
  3906. (set! renaming-counter 0)
  3907. (let ((env0 (syntactic-copy global-syntactic-environment))
  3908. (bmode (benchmark-mode))
  3909. (wmode (issue-warnings))
  3910. (defined '()))
  3911. (define (make-toplevel-definition id exp)
  3912. (cond ((memq id defined)
  3913. (set! pass1-block-assignments
  3914. (cons id pass1-block-assignments)))
  3915. ((or (constant? exp)
  3916. (and (lambda? exp)
  3917. (list? (lambda.args exp))))
  3918. (set! defined (cons id defined))))
  3919. (make-begin
  3920. (list (make-assignment id exp)
  3921. (make-constant id))))
  3922. (benchmark-mode #f)
  3923. (issue-warnings #f)
  3924. (for-each (lambda (form)
  3925. (desugar-definitions form
  3926. global-syntactic-environment
  3927. make-toplevel-definition))
  3928. forms)
  3929. (set! global-syntactic-environment env0)
  3930. (benchmark-mode bmode)
  3931. (issue-warnings wmode)
  3932. (part2 (filter (lambda (id)
  3933. (not (memq id pass1-block-assignments)))
  3934. (reverse defined)))))
  3935. (define (part2 defined)
  3936. (set! pass1-block-compiling? #f)
  3937. (set! pass1-block-assignments '())
  3938. (set! pass1-block-inlines '())
  3939. (set! renaming-counter 0)
  3940. (let* ((rename (make-rename-procedure))
  3941. (alist (map (lambda (id)
  3942. (cons id (rename id)))
  3943. defined))
  3944. (definitions0 '()) ; for constants
  3945. (definitions1 '())) ; for lambda expressions
  3946. (define (make-toplevel-definition id exp)
  3947. (if (lambda? exp)
  3948. (doc.name-set! (lambda.doc exp) id))
  3949. (let ((probe (assq id alist)))
  3950. (if probe
  3951. (let ((id1 (cdr probe)))
  3952. (cond ((constant? exp)
  3953. (set! definitions0
  3954. (cons (make-assignment id exp)
  3955. definitions0))
  3956. (make-constant id))
  3957. ((lambda? exp)
  3958. (set! definitions1
  3959. (cons (make-assignment id1 exp)
  3960. definitions1))
  3961. (make-assignment
  3962. id
  3963. (make-lambda (lambda.args exp)
  3964. '() ; no definitions
  3965. '() ; R
  3966. '() ; F
  3967. '() ; G
  3968. '() ; decls
  3969. (lambda.doc exp)
  3970. (make-call
  3971. (make-variable id1)
  3972. (map make-variable
  3973. (lambda.args exp))))))
  3974. (else
  3975. (m-error "Inconsistent macro expansion"
  3976. (make-readable exp)))))
  3977. (make-assignment id exp))))
  3978. (let ((env0 (syntactic-copy global-syntactic-environment))
  3979. (bmode (benchmark-mode))
  3980. (wmode (issue-warnings)))
  3981. (issue-warnings #f)
  3982. (for-each (lambda (pair)
  3983. (let ((id0 (car pair))
  3984. (id1 (cdr pair)))
  3985. (syntactic-bind-globally!
  3986. id0
  3987. (make-inline-denotation
  3988. id0
  3989. (lambda (exp rename compare)
  3990. ; Deliberately non-hygienic!
  3991. (cons id1 (cdr exp)))
  3992. global-syntactic-environment))
  3993. (set! pass1-block-inlines
  3994. (cons id0 pass1-block-inlines))))
  3995. alist)
  3996. (benchmark-mode #f)
  3997. (issue-warnings wmode)
  3998. (let ((forms
  3999. (do ((forms forms (cdr forms))
  4000. (newforms '()
  4001. (cons (desugar-definitions
  4002. (car forms)
  4003. global-syntactic-environment
  4004. make-toplevel-definition)
  4005. newforms)))
  4006. ((null? forms)
  4007. (reverse newforms)))))
  4008. (benchmark-mode bmode)
  4009. (set! global-syntactic-environment env0)
  4010. (part3 alist definitions0 definitions1 forms)))))
  4011. (define (part3 alist definitions0 definitions1 forms)
  4012. (set! pass1-block-compiling? #f)
  4013. (set! pass1-block-assignments '())
  4014. (set! pass1-block-inlines '())
  4015. (let* ((constnames0 (map assignment.lhs definitions0))
  4016. (constnames1 (map (lambda (id0)
  4017. (cdr (assq id0 alist)))
  4018. constnames0))
  4019. (procnames1 (map assignment.lhs definitions1)))
  4020. (copy-exp
  4021. (make-call
  4022. (make-lambda
  4023. constnames1
  4024. '() ; no definitions
  4025. '() ; R
  4026. '() ; F
  4027. '() ; G
  4028. '() ; decls
  4029. #f ; doc
  4030. (make-begin
  4031. (list
  4032. (make-begin
  4033. (cons (make-constant #f)
  4034. (reverse
  4035. (map (lambda (id)
  4036. (make-assignment id (make-variable (cdr (assq id alist)))))
  4037. constnames0))))
  4038. (make-call
  4039. (make-lambda
  4040. constnames0
  4041. '() ; no definitions
  4042. '() ; R
  4043. '() ; F
  4044. '() ; G
  4045. '() ; decls
  4046. #f ; doc
  4047. (make-call
  4048. (make-lambda
  4049. (map assignment.lhs definitions1)
  4050. '() ; no definitions
  4051. '() ; R
  4052. '() ; F
  4053. '() ; G
  4054. '() ; decls
  4055. #f ; doc
  4056. (make-begin (cons (make-constant #f)
  4057. (append definitions1 forms))))
  4058. (map (lambda (ignored) (make-unspecified))
  4059. definitions1)))
  4060. (map make-variable constnames1))
  4061. )))
  4062. (map assignment.rhs definitions0)))))
  4063. (set! source-file-name #f)
  4064. (set! source-file-position #f)
  4065. (if (not (null? rest))
  4066. (begin (set! source-file-name (car rest))
  4067. (if (not (null? (cdr rest)))
  4068. (set! source-file-position (cadr rest)))))
  4069. (part1))
  4070. ; Copyright 1999 William D Clinger.
  4071. ;
  4072. ; Permission to copy this software, in whole or in part, to use this
  4073. ; software for any lawful noncommercial purpose, and to redistribute
  4074. ; this software is granted subject to the restriction that all copies
  4075. ; made of this software must include this copyright notice in full.
  4076. ;
  4077. ; I also request that you send me a copy of any improvements that you
  4078. ; make to this software so that they may be incorporated within it to
  4079. ; the benefit of the Scheme community.
  4080. ;
  4081. ; 7 June 1999.
  4082. ;
  4083. ; Support for intraprocedural value numbering:
  4084. ; set of available expressions
  4085. ; miscellaneous
  4086. ;
  4087. ; The set of available expressions is represented as a
  4088. ; mutable abstract data type Available with these operations:
  4089. ;
  4090. ; make-available-table: -> Available
  4091. ; copy-available-table: Available -> Available
  4092. ; available-expression: Available x Expr -> (symbol + {#f})
  4093. ; available-variable: Available x symbol -> Expr
  4094. ; available-extend!: Available x symbol x Expr x Killer ->
  4095. ; available-kill!: Available x Killer ->
  4096. ;
  4097. ; where Expr is of the form
  4098. ;
  4099. ; Expr --> W
  4100. ; | (W_0 W_1 ...)
  4101. ;
  4102. ; W --> (quote K)
  4103. ; | (begin I)
  4104. ;
  4105. ; and Killer is a fixnum, as defined later in this file.
  4106. ;
  4107. ; (make-available-table)
  4108. ; returns an empty table of available expressions.
  4109. ; (copy-available-table available)
  4110. ; copies the given table.
  4111. ; (available-expression available E)
  4112. ; returns the name of E if it is available in the table, else #f.
  4113. ; (available-variable available T)
  4114. ; returns a constant or variable to use in place of T, else #f.
  4115. ; (available-extend! available T E K)
  4116. ; adds the binding (T E) to the table, with Killer K.
  4117. ; If E is a variable and this binding is never killed, then copy
  4118. ; propagation will replace uses of T by uses of E; otherwise
  4119. ; commoning will replace uses of E by uses of T, until the
  4120. ; binding is killed.
  4121. ; (available-kill! available K)
  4122. ; removes all bindings whose Killer intersects K.
  4123. ;
  4124. ; (available-extend! available T E K) is very fast if the previous
  4125. ; operation on the table was (available-expression available E).
  4126. ; Implementation.
  4127. ;
  4128. ; Quick and dirty.
  4129. ; The available expressions are represented as a vector of 2 association
  4130. ; lists. The first list is used for common subexpression elimination,
  4131. ; and the second is used for copy and constant propagation.
  4132. ;
  4133. ; Each element of the first list is a binding of
  4134. ; a symbol T to an expression E, with killer K,
  4135. ; represented by the list (E T K).
  4136. ;
  4137. ; Each element of the second list is a binding of
  4138. ; a symbol T to an expression E, with killer K,
  4139. ; represented by the list (T E K).
  4140. ; The expression E will be a constant or variable.
  4141. (define (make-available-table)
  4142. (vector '() '()))
  4143. (define (copy-available-table available)
  4144. (vector (vector-ref available 0)
  4145. (vector-ref available 1)))
  4146. (define (available-expression available E)
  4147. (let ((binding (assoc E (vector-ref available 0))))
  4148. (if binding
  4149. (cadr binding)
  4150. #f)))
  4151. (define (available-variable available T)
  4152. (let ((binding (assq T (vector-ref available 1))))
  4153. (if binding
  4154. (cadr binding)
  4155. #f)))
  4156. (define (available-extend! available T E K)
  4157. (cond ((constant? E)
  4158. (vector-set! available
  4159. 1
  4160. (cons (list T E K)
  4161. (vector-ref available 1))))
  4162. ((and (variable? E)
  4163. (eq? K available:killer:none))
  4164. (vector-set! available
  4165. 1
  4166. (cons (list T E K)
  4167. (vector-ref available 1))))
  4168. (else
  4169. (vector-set! available
  4170. 0
  4171. (cons (list E T K)
  4172. (vector-ref available 0))))))
  4173. (define (available-kill! available K)
  4174. (vector-set! available
  4175. 0
  4176. (filter (lambda (binding)
  4177. (zero?
  4178. (logand K
  4179. (caddr binding))))
  4180. (vector-ref available 0)))
  4181. (vector-set! available
  4182. 1
  4183. (filter (lambda (binding)
  4184. (zero?
  4185. (logand K
  4186. (caddr binding))))
  4187. (vector-ref available 1))))
  4188. (define (available-intersect! available0 available1 available2)
  4189. (vector-set! available0
  4190. 0
  4191. (intersection (vector-ref available1 0)
  4192. (vector-ref available2 0)))
  4193. (vector-set! available0
  4194. 1
  4195. (intersection (vector-ref available1 1)
  4196. (vector-ref available2 1))))
  4197. ; The Killer concrete data type, represented as a fixnum.
  4198. ;
  4199. ; The set of side effects that can kill an available expression
  4200. ; are a subset of
  4201. ;
  4202. ; assignments to global variables
  4203. ; uses of SET-CAR!
  4204. ; uses of SET-CDR!
  4205. ; uses of STRING-SET!
  4206. ; uses of VECTOR-SET!
  4207. ;
  4208. ; This list is not complete. If we were trying to perform common
  4209. ; subexpression elimination on calls to PEEK-CHAR, for example,
  4210. ; then those calls would be killed by reads.
  4211. (define available:killer:globals 2)
  4212. (define available:killer:car 4)
  4213. (define available:killer:cdr 8)
  4214. (define available:killer:string 16) ; also bytevectors etc
  4215. (define available:killer:vector 32) ; also structures etc
  4216. (define available:killer:cell 64)
  4217. (define available:killer:io 128)
  4218. (define available:killer:none 0) ; none of the above
  4219. (define available:killer:all 1022) ; all of the above
  4220. (define available:killer:immortal 0) ; never killed
  4221. (define available:killer:dead 1023) ; never available
  4222. (define (available:killer-combine k1 k2)
  4223. (logior k1 k2))
  4224. ; Miscellaneous.
  4225. ; A simple lambda expression has no internal definitions at its head
  4226. ; and no declarations aside from A-normal form.
  4227. (define (simple-lambda? L)
  4228. (and (null? (lambda.defs L))
  4229. (every? (lambda (decl)
  4230. (eq? decl A-normal-form-declaration))
  4231. (lambda.decls L))))
  4232. ; A real call is a call whose procedure expression is
  4233. ; neither a lambda expression nor a primop.
  4234. (define (real-call? E)
  4235. (and (call? E)
  4236. (let ((proc (call.proc E)))
  4237. (and (not (lambda? proc))
  4238. (or (not (variable? proc))
  4239. (let ((f (variable.name proc)))
  4240. (or (not (integrate-usual-procedures))
  4241. (not (prim-entry f)))))))))
  4242. (define (prim-call E)
  4243. (and (call? E)
  4244. (let ((proc (call.proc E)))
  4245. (and (variable? proc)
  4246. (integrate-usual-procedures)
  4247. (prim-entry (variable.name proc))))))
  4248. (define (no-side-effects? E)
  4249. (or (constant? E)
  4250. (variable? E)
  4251. (lambda? E)
  4252. (and (conditional? E)
  4253. (no-side-effects? (if.test E))
  4254. (no-side-effects? (if.then E))
  4255. (no-side-effects? (if.else E)))
  4256. (and (call? E)
  4257. (let ((proc (call.proc E)))
  4258. (and (variable? proc)
  4259. (integrate-usual-procedures)
  4260. (let ((entry (prim-entry (variable.name proc))))
  4261. (and entry
  4262. (not (eq? available:killer:dead
  4263. (prim-lives-until entry))))))))))
  4264. ; Given a local variable, the expression within its scope, and
  4265. ; a list of local variables that are known to be used only once,
  4266. ; returns #t if the variable is used only once.
  4267. ;
  4268. ; The purpose of this routine is to recognize temporaries that
  4269. ; may once have had two or more uses because of CSE, but now have
  4270. ; only one use because of further CSE followed by dead code elimination.
  4271. (define (temporary-used-once? T E used-once)
  4272. (cond ((call? E)
  4273. (let ((proc (call.proc E))
  4274. (args (call.args E)))
  4275. (or (and (lambda? proc)
  4276. (not (memq T (lambda.F proc)))
  4277. (and (pair? args)
  4278. (null? (cdr args))
  4279. (temporary-used-once? T (car args) used-once)))
  4280. (do ((exprs (cons proc (call.args E))
  4281. (cdr exprs))
  4282. (n 0
  4283. (let ((exp (car exprs)))
  4284. (cond ((constant? exp)
  4285. n)
  4286. ((variable? exp)
  4287. (if (eq? T (variable.name exp))
  4288. (+ n 1)
  4289. n))
  4290. (else
  4291. ; Terminate the loop and return #f.
  4292. 2)))))
  4293. ((or (null? exprs)
  4294. (> n 1))
  4295. (= n 1))))))
  4296. (else
  4297. (memq T used-once))))
  4298. ; Register bindings.
  4299. (define (make-regbinding lhs rhs use)
  4300. (list lhs rhs use))
  4301. (define (regbinding.lhs x) (car x))
  4302. (define (regbinding.rhs x) (cadr x))
  4303. (define (regbinding.use x) (caddr x))
  4304. ; Given a list of register bindings, an expression E and its free variables F,
  4305. ; returns two values:
  4306. ; E with the register bindings wrapped around it
  4307. ; the free variables of the wrapped expression
  4308. (define (wrap-with-register-bindings regbindings E F)
  4309. (if (null? regbindings)
  4310. (values E F)
  4311. (let* ((regbinding (car regbindings))
  4312. (R (regbinding.lhs regbinding))
  4313. (x (regbinding.rhs regbinding)))
  4314. (wrap-with-register-bindings
  4315. (cdr regbindings)
  4316. (make-call (make-lambda (list R)
  4317. '()
  4318. '()
  4319. F
  4320. F
  4321. (list A-normal-form-declaration)
  4322. #f
  4323. E)
  4324. (list (make-variable x)))
  4325. (union (list x)
  4326. (difference F (list R)))))))
  4327. ; Returns two values:
  4328. ; the subset of regbindings that have x as their right hand side
  4329. ; the rest of regbindings
  4330. (define (register-bindings regbindings x)
  4331. (define (loop regbindings to-x others)
  4332. (cond ((null? regbindings)
  4333. (values to-x others))
  4334. ((eq? x (regbinding.rhs (car regbindings)))
  4335. (loop (cdr regbindings)
  4336. (cons (car regbindings) to-x)
  4337. others))
  4338. (else
  4339. (loop (cdr regbindings)
  4340. to-x
  4341. (cons (car regbindings) others)))))
  4342. (loop regbindings '() '()))
  4343. ; This procedure is called when the compiler can tell that an assertion
  4344. ; is never true.
  4345. (define (declaration-error E)
  4346. (if (issue-warnings)
  4347. (begin (display "WARNING: Assertion is false: ")
  4348. (write (make-readable E #t))
  4349. (newline))))
  4350. ; Representations, which form a subtype hierarchy.
  4351. ;
  4352. ; <rep> ::= <fixnum> | (<fixnum> <datum> ...)
  4353. ;
  4354. ; (<rep> <datum> ...) is a subtype of <rep>, but the non-fixnum
  4355. ; representations are otherwise interpreted by arbitrary code.
  4356. (define *nreps* 0)
  4357. (define *rep-encodings* '())
  4358. (define *rep-decodings* '())
  4359. (define *rep-subtypes* '())
  4360. (define *rep-joins* (make-bytevector 0))
  4361. (define *rep-meets* (make-bytevector 0))
  4362. (define *rep-joins-special* '#())
  4363. (define *rep-meets-special* '#())
  4364. (define (representation-error msg . stuff)
  4365. (apply error
  4366. (if (string? msg)
  4367. (string-append "Bug in flow analysis: " msg)
  4368. msg)
  4369. stuff))
  4370. (define (symbol->rep sym)
  4371. (let ((probe (assq sym *rep-encodings*)))
  4372. (if probe
  4373. (cdr probe)
  4374. (let ((rep *nreps*))
  4375. (set! *nreps* (+ *nreps* 1))
  4376. (if (> *nreps* 255)
  4377. (representation-error "Too many representation types"))
  4378. (set! *rep-encodings*
  4379. (cons (cons sym rep)
  4380. *rep-encodings*))
  4381. (set! *rep-decodings*
  4382. (cons (cons rep sym)
  4383. *rep-decodings*))
  4384. rep))))
  4385. (define (rep->symbol rep)
  4386. (if (pair? rep)
  4387. (cons (rep->symbol (car rep)) (cdr rep))
  4388. (let ((probe (assv rep *rep-decodings*)))
  4389. (if probe
  4390. (cdr probe)
  4391. 'unknown))))
  4392. (define (representation-table table)
  4393. (map (lambda (row)
  4394. (map (lambda (x)
  4395. (if (list? x)
  4396. (map symbol->rep x)
  4397. x))
  4398. row))
  4399. table))
  4400. ; DEFINE-SUBTYPE is how representation types are defined.
  4401. (define (define-subtype sym1 sym2)
  4402. (let* ((rep2 (symbol->rep sym2))
  4403. (rep1 (symbol->rep sym1)))
  4404. (set! *rep-subtypes*
  4405. (cons (cons rep1 rep2)
  4406. *rep-subtypes*))
  4407. sym1))
  4408. ; COMPUTE-TYPE-STRUCTURE! must be called before DEFINE-INTERSECTION.
  4409. (define (define-intersection sym1 sym2 sym3)
  4410. (let ((rep1 (symbol->rep sym1))
  4411. (rep2 (symbol->rep sym2))
  4412. (rep3 (symbol->rep sym3)))
  4413. (representation-aset! *rep-meets* rep1 rep2 rep3)
  4414. (representation-aset! *rep-meets* rep2 rep1 rep3)))
  4415. ;
  4416. (define (representation-aref bv i j)
  4417. (bytevector-ref bv (+ (* *nreps* i) j)))
  4418. (define (representation-aset! bv i j x)
  4419. (bytevector-set! bv (+ (* *nreps* i) j) x))
  4420. (define (compute-unions!)
  4421. ; Always define a bottom element.
  4422. (for-each (lambda (sym)
  4423. (define-subtype 'bottom sym))
  4424. (map car *rep-encodings*))
  4425. (let* ((debugging? #f)
  4426. (n *nreps*)
  4427. (n^2 (* n n))
  4428. (matrix (make-bytevector n^2)))
  4429. ; This code assumes there will always be a top element.
  4430. (define (lub rep1 rep2 subtype?)
  4431. (do ((i 0 (+ i 1))
  4432. (bounds '()
  4433. (if (and (subtype? rep1 i)
  4434. (subtype? rep2 i))
  4435. (cons i bounds)
  4436. bounds)))
  4437. ((= i n)
  4438. (car (twobit-sort subtype? bounds)))))
  4439. (define (join i j)
  4440. (lub i j (lambda (rep1 rep2)
  4441. (= 1 (representation-aref matrix rep1 rep2)))))
  4442. (define (compute-transitive-closure!)
  4443. (let ((changed? #f))
  4444. (define (loop)
  4445. (do ((i 0 (+ i 1)))
  4446. ((= i n))
  4447. (do ((k 0 (+ k 1)))
  4448. ((= k n))
  4449. (do ((j 0 (+ j 1))
  4450. (sum 0
  4451. (logior sum
  4452. (logand
  4453. (representation-aref matrix i j)
  4454. (representation-aref matrix j k)))))
  4455. ((= j n)
  4456. (if (> sum 0)
  4457. (let ((x (representation-aref matrix i k)))
  4458. (if (zero? x)
  4459. (begin
  4460. (set! changed? #t)
  4461. (representation-aset! matrix i k 1)))))))))
  4462. (if changed?
  4463. (begin (set! changed? #f)
  4464. (loop))))
  4465. (loop)))
  4466. (define (compute-joins!)
  4467. (let ((default (lambda (x y)
  4468. (error "Compiler bug: special meet or join" x y))))
  4469. (set! *rep-joins-special* (make-vector n default))
  4470. (set! *rep-meets-special* (make-vector n default)))
  4471. (set! *rep-joins* (make-bytevector n^2))
  4472. (set! *rep-meets* (make-bytevector n^2))
  4473. (do ((i 0 (+ i 1)))
  4474. ((= i n))
  4475. (do ((j 0 (+ j 1)))
  4476. ((= j n))
  4477. (representation-aset! *rep-joins*
  4478. i
  4479. j
  4480. (join i j)))))
  4481. (do ((i 0 (+ i 1)))
  4482. ((= i n))
  4483. (do ((j 0 (+ j 1)))
  4484. ((= j n))
  4485. (representation-aset! matrix i j 0))
  4486. (representation-aset! matrix i i 1))
  4487. (for-each (lambda (subtype)
  4488. (let ((rep1 (car subtype))
  4489. (rep2 (cdr subtype)))
  4490. (representation-aset! matrix rep1 rep2 1)))
  4491. *rep-subtypes*)
  4492. (compute-transitive-closure!)
  4493. (if debugging?
  4494. (do ((i 0 (+ i 1)))
  4495. ((= i n))
  4496. (do ((j 0 (+ j 1)))
  4497. ((= j n))
  4498. (write-char #\space)
  4499. (write (representation-aref matrix i j)))
  4500. (newline)))
  4501. (compute-joins!)
  4502. (set! *rep-subtypes* '())))
  4503. ; Intersections are not dual to unions because a conservative analysis
  4504. ; must always err on the side of the larger subtype.
  4505. ; COMPUTE-UNIONS! must be called before COMPUTE-INTERSECTIONS!.
  4506. (define (compute-intersections!)
  4507. (let ((n *nreps*))
  4508. (define (meet i j)
  4509. (let ((k (representation-union i j)))
  4510. (if (= i k)
  4511. j
  4512. i)))
  4513. (do ((i 0 (+ i 1)))
  4514. ((= i n))
  4515. (do ((j 0 (+ j 1)))
  4516. ((= j n))
  4517. (representation-aset! *rep-meets*
  4518. i
  4519. j
  4520. (meet i j))))))
  4521. (define (compute-type-structure!)
  4522. (compute-unions!)
  4523. (compute-intersections!))
  4524. (define (representation-subtype? rep1 rep2)
  4525. (equal? rep2 (representation-union rep1 rep2)))
  4526. (define (representation-union rep1 rep2)
  4527. (if (fixnum? rep1)
  4528. (if (fixnum? rep2)
  4529. (representation-aref *rep-joins* rep1 rep2)
  4530. (representation-union rep1 (car rep2)))
  4531. (if (fixnum? rep2)
  4532. (representation-union (car rep1) rep2)
  4533. (let ((r1 (car rep1))
  4534. (r2 (car rep2)))
  4535. (if (= r1 r2)
  4536. ((vector-ref *rep-joins-special* r1) rep1 rep2)
  4537. (representation-union r1 r2))))))
  4538. (define (representation-intersection rep1 rep2)
  4539. (if (fixnum? rep1)
  4540. (if (fixnum? rep2)
  4541. (representation-aref *rep-meets* rep1 rep2)
  4542. (representation-intersection rep1 (car rep2)))
  4543. (if (fixnum? rep2)
  4544. (representation-intersection (car rep1) rep2)
  4545. (let ((r1 (car rep1))
  4546. (r2 (car rep2)))
  4547. (if (= r1 r2)
  4548. ((vector-ref *rep-meets-special* r1) rep1 rep2)
  4549. (representation-intersection r1 r2))))))
  4550. ; For debugging.
  4551. (define (display-unions-and-intersections)
  4552. (let* ((column-width 10)
  4553. (columns/row (quotient 80 column-width)))
  4554. (define (display-symbol sym)
  4555. (let* ((s (symbol->string sym))
  4556. (n (string-length s)))
  4557. (if (< n column-width)
  4558. (begin (display s)
  4559. (display (make-string (- column-width n) #\space)))
  4560. (begin (display (substring s 0 (- column-width 1)))
  4561. (write-char #\space)))))
  4562. ; Display columns i to n.
  4563. (define (display-matrix f i n)
  4564. (display (make-string column-width #\space))
  4565. (do ((i i (+ i 1)))
  4566. ((= i n))
  4567. (display-symbol (rep->symbol i)))
  4568. (newline)
  4569. (newline)
  4570. (do ((k 0 (+ k 1)))
  4571. ((= k *nreps*))
  4572. (display-symbol (rep->symbol k))
  4573. (do ((i i (+ i 1)))
  4574. ((= i n))
  4575. (display-symbol (rep->symbol (f k i))))
  4576. (newline))
  4577. (newline)
  4578. (newline))
  4579. (display "Unions:")
  4580. (newline)
  4581. (newline)
  4582. (do ((i 0 (+ i columns/row)))
  4583. ((>= i *nreps*))
  4584. (display-matrix representation-union
  4585. i
  4586. (min *nreps* (+ i columns/row))))
  4587. (display "Intersections:")
  4588. (newline)
  4589. (newline)
  4590. (do ((i 0 (+ i columns/row)))
  4591. ((>= i *nreps*))
  4592. (display-matrix representation-intersection
  4593. i
  4594. (min *nreps* (+ i columns/row))))))
  4595. ; Operations that can be specialized.
  4596. ;
  4597. ; Format: (<name> (<arg-rep> ...) <specific-name>)
  4598. (define (rep-specific? f rs)
  4599. (rep-match f rs rep-specific caddr))
  4600. ; Operations whose result has some specific representation.
  4601. ;
  4602. ; Format: (<name> (<arg-rep> ...) (<result-rep>))
  4603. (define (rep-result? f rs)
  4604. (rep-match f rs rep-result caaddr))
  4605. ; Unary predicates that give information about representation.
  4606. ;
  4607. ; Format: (<name> <rep-if-true> <rep-if-false>)
  4608. (define (rep-if-true f rs)
  4609. (rep-match f rs rep-informing caddr))
  4610. (define (rep-if-false f rs)
  4611. (rep-match f rs rep-informing cadddr))
  4612. ; Given the name of an integrable primitive,
  4613. ; the representations of its arguments,
  4614. ; a representation table, and a selector function
  4615. ; finds the most type-specific row of the table that matches both
  4616. ; the name of the primitive and the representations of its arguments,
  4617. ; and returns the result of applying the selector to that row.
  4618. ; If no row matches, then REP-MATCH returns #f.
  4619. ;
  4620. ; FIXME: This should be more efficient, and should prefer the most
  4621. ; specific matches.
  4622. (define (rep-match f rs table selector)
  4623. (let ((n (length rs)))
  4624. (let loop ((entries table))
  4625. (cond ((null? entries)
  4626. #f)
  4627. ((eq? f (car (car entries)))
  4628. (let ((rs0 (cadr (car entries))))
  4629. (if (and (= n (length rs0))
  4630. (every? (lambda (r1+r2)
  4631. (let ((r1 (car r1+r2))
  4632. (r2 (cdr r1+r2)))
  4633. (representation-subtype? r1 r2)))
  4634. (map cons rs rs0)))
  4635. (selector (car entries))
  4636. (loop (cdr entries)))))
  4637. (else
  4638. (loop (cdr entries)))))))
  4639. ; Abstract interpretation with respect to types and constraints.
  4640. ; Returns a representation type.
  4641. (define (aeval E types constraints)
  4642. (cond ((call? E)
  4643. (let ((proc (call.proc E)))
  4644. (if (variable? proc)
  4645. (let* ((op (variable.name proc))
  4646. (argtypes (map (lambda (E)
  4647. (aeval E types constraints))
  4648. (call.args E)))
  4649. (type (rep-result? op argtypes)))
  4650. (if type
  4651. type
  4652. rep:object))
  4653. rep:object)))
  4654. ((variable? E)
  4655. (representation-typeof (variable.name E) types constraints))
  4656. ((constant? E)
  4657. (representation-of-value (constant.value E)))
  4658. (else
  4659. rep:object)))
  4660. ; If x has representation type t0 in the hash table,
  4661. ; and some further constraints
  4662. ;
  4663. ; x = (op y1 ... yn)
  4664. ; x : t1
  4665. ; ...
  4666. ; x : tk
  4667. ;
  4668. ; then
  4669. ;
  4670. ; typeof (x) = op (typeof (y1), ..., typeof (yn))
  4671. ; & t0 & t1 & ... & tk
  4672. ;
  4673. ; where & means intersection and op is the abstraction of op.
  4674. ;
  4675. ; Also if T : true and T = E then E may give information about
  4676. ; the types of other variables. Similarly for T : false.
  4677. (define (representation-typeof name types constraints)
  4678. (let ((t0 (hashtable-fetch types name rep:object))
  4679. (cs (hashtable-fetch (constraints.table constraints) name '())))
  4680. (define (loop type cs)
  4681. (if (null? cs)
  4682. type
  4683. (let* ((c (car cs))
  4684. (cs (cdr cs))
  4685. (E (constraint.rhs c)))
  4686. (cond ((constant? E)
  4687. (loop (representation-intersection type
  4688. (constant.value E))
  4689. cs))
  4690. ((call? E)
  4691. (loop (representation-intersection
  4692. type (aeval E types constraints))
  4693. cs))
  4694. (else
  4695. (loop type cs))))))
  4696. (loop t0 cs)))
  4697. ; Constraints.
  4698. ;
  4699. ; The constraints used by this analysis consist of type constraints
  4700. ; together with the available expressions used for commoning.
  4701. ;
  4702. ; (T E K) T = E until killed by an effect in K
  4703. ; (T '<rep> K) T : <rep> until killed by an effect in K
  4704. (define (make-constraint T E K)
  4705. (list T E K))
  4706. (define (constraint.lhs c)
  4707. (car c))
  4708. (define (constraint.rhs c)
  4709. (cadr c))
  4710. (define (constraint.killer c)
  4711. (caddr c))
  4712. (define (make-type-constraint T type K)
  4713. (make-constraint T
  4714. (make-constant type)
  4715. K))
  4716. ; If the new constraint is of the form T = E until killed by K,
  4717. ; then there shouldn't be any prior constraints.
  4718. ;
  4719. ; Otherwise the new constraint is of the form T : t until killed by K.
  4720. ; Suppose the prior constraints are
  4721. ; T = E until killed by K
  4722. ; T : t1 until killed by K1
  4723. ; ...
  4724. ; T : tn until killed by Kn
  4725. ;
  4726. ; If there exists i such that ti is a subtype of t and Ki a subset of K,
  4727. ; then the new constraint adds no new information and should be ignored.
  4728. ; Otherwise compute t' = t1 & ... & tn and K' = K1 | ... | Kn, where
  4729. ; & indicates intersection and | indicates union.
  4730. ; If K = K' then add the new constraint T : t' until killed by K;
  4731. ; otherwise add two new constraints:
  4732. ; T : t' until killed by K'
  4733. ; T : t until killed by K
  4734. (define (constraints-add! types constraints new)
  4735. (let* ((debugging? #f)
  4736. (T (constraint.lhs new))
  4737. (E (constraint.rhs new))
  4738. (K (constraint.killer new))
  4739. (cs (constraints-for-variable constraints T)))
  4740. (define (loop type K cs newcs)
  4741. (if (null? cs)
  4742. (cons (make-type-constraint T type K) newcs)
  4743. (let* ((c2 (car cs))
  4744. (cs (cdr cs))
  4745. (E2 (constraint.rhs c2))
  4746. (K2 (constraint.killer c2)))
  4747. (if (constant? E2)
  4748. (let* ((type2 (constant.value E2))
  4749. (type3 (representation-intersection type type2)))
  4750. (cond ((eq? type2 type3)
  4751. (if (= K2 (logand K K2))
  4752. (append newcs cs)
  4753. (loop (representation-intersection type type2)
  4754. (available:killer-combine K K2)
  4755. cs
  4756. (cons c2 newcs))))
  4757. ((representation-subtype? type type3)
  4758. (if (= K (logand K K2))
  4759. (loop type K cs newcs)
  4760. (loop type K cs (cons c2 newcs))))
  4761. (else
  4762. (loop type3
  4763. (available:killer-combine K K2)
  4764. cs
  4765. (cons c2 newcs)))))
  4766. (let* ((op (variable.name (call.proc E2)))
  4767. (args (call.args E2))
  4768. (argtypes (map (lambda (exp)
  4769. (aeval exp types constraints))
  4770. args)))
  4771. (cond ((representation-subtype? type rep:true)
  4772. (let ((reps (rep-if-true op argtypes)))
  4773. (if reps
  4774. (record-new-reps! args argtypes reps K2))))
  4775. ((representation-subtype? type rep:false)
  4776. (let ((reps (rep-if-false op argtypes)))
  4777. (if reps
  4778. (record-new-reps! args argtypes reps K2)))))
  4779. (loop type K cs (cons c2 newcs)))))))
  4780. (define (record-new-reps! args argtypes reps K2)
  4781. (if debugging?
  4782. (begin (write (list (map make-readable args)
  4783. (map rep->symbol argtypes)
  4784. (map rep->symbol reps)))
  4785. (newline)))
  4786. (for-each (lambda (arg type0 type1)
  4787. (if (not (representation-subtype? type0 type1))
  4788. (if (variable? arg)
  4789. (let ((name (variable.name arg)))
  4790. ; FIXME: In this context, a variable
  4791. ; should always be local so the hashtable
  4792. ; operation isn't necessary.
  4793. (if (hashtable-get types name)
  4794. (constraints-add!
  4795. types
  4796. constraints
  4797. (make-type-constraint
  4798. name
  4799. type1
  4800. (available:killer-combine K K2)))
  4801. (cerror
  4802. "Compiler bug: unexpected global: "
  4803. name))))))
  4804. args argtypes reps))
  4805. (if (not (zero? K))
  4806. (constraints-add-killedby! constraints T K))
  4807. (let* ((table (constraints.table constraints))
  4808. (cs (hashtable-fetch table T '())))
  4809. (cond ((constant? E)
  4810. ; It's a type constraint.
  4811. (let ((type (constant.value E)))
  4812. (if debugging?
  4813. (begin (display T)
  4814. (display " : ")
  4815. (display (rep->symbol type))
  4816. (newline)))
  4817. (let ((cs (loop type K cs '())))
  4818. (hashtable-put! table T cs)
  4819. constraints)))
  4820. (else
  4821. (if debugging?
  4822. (begin (display T)
  4823. (display " = ")
  4824. (display (make-readable E #t))
  4825. (newline)))
  4826. (if (not (null? cs))
  4827. (begin
  4828. (display "Compiler bug: ")
  4829. (write T)
  4830. (display " has unexpectedly nonempty constraints")
  4831. (newline)))
  4832. (hashtable-put! table T (list (list T E K)))
  4833. constraints)))))
  4834. ; Sets of constraints.
  4835. ;
  4836. ; The set of constraints is represented as (<hashtable> <killedby>),
  4837. ; where <hashtable> is a hashtable mapping variables to lists of
  4838. ; constraints as above, and <killedby> is a vector mapping basic killers
  4839. ; to lists of variables that need to be examined for constraints that
  4840. ; are killed by that basic killer.
  4841. (define number-of-basic-killers
  4842. (do ((i 0 (+ i 1))
  4843. (k 1 (+ k k)))
  4844. ((> k available:killer:dead)
  4845. i)))
  4846. (define (constraints.table constraints) (car constraints))
  4847. (define (constraints.killed constraints) (cadr constraints))
  4848. (define (make-constraints-table)
  4849. (list (make-hashtable symbol-hash assq)
  4850. (make-vector number-of-basic-killers '())))
  4851. (define (copy-constraints-table constraints)
  4852. (list (hashtable-copy (constraints.table constraints))
  4853. (list->vector (vector->list (constraints.killed constraints)))))
  4854. (define (constraints-for-variable constraints T)
  4855. (hashtable-fetch (constraints.table constraints) T '()))
  4856. (define (constraints-add-killedby! constraints T K0)
  4857. (if (not (zero? K0))
  4858. (let ((v (constraints.killed constraints)))
  4859. (do ((i 0 (+ i 1))
  4860. (k 1 (+ k k)))
  4861. ((= i number-of-basic-killers))
  4862. (if (not (zero? (logand k K0)))
  4863. (vector-set! v i (cons T (vector-ref v i))))))))
  4864. (define (constraints-kill! constraints K)
  4865. (if (not (zero? K))
  4866. (let ((table (constraints.table constraints))
  4867. (killed (constraints.killed constraints)))
  4868. (define (examine! T)
  4869. (let ((cs (filter (lambda (c)
  4870. (zero? (logand (constraint.killer c) K)))
  4871. (hashtable-fetch table T '()))))
  4872. (if (null? cs)
  4873. (hashtable-remove! table T)
  4874. (hashtable-put! table T cs))))
  4875. (do ((i 0 (+ i 1))
  4876. (j 1 (+ j j)))
  4877. ((= i number-of-basic-killers))
  4878. (if (not (zero? (logand j K)))
  4879. (begin (for-each examine! (vector-ref killed i))
  4880. (vector-set! killed i '())))))))
  4881. (define (constraints-intersect! constraints0 constraints1 constraints2)
  4882. (let ((table0 (constraints.table constraints0))
  4883. (table1 (constraints.table constraints1))
  4884. (table2 (constraints.table constraints2)))
  4885. (if (eq? table0 table1)
  4886. ; FIXME: Which is more efficient: to update the killed vector,
  4887. ; or not to update it? Both are safe.
  4888. (hashtable-for-each (lambda (T cs)
  4889. (if (not (null? cs))
  4890. (hashtable-put!
  4891. table0
  4892. T
  4893. (cs-intersect
  4894. (hashtable-fetch table2 T '())
  4895. cs))))
  4896. table1)
  4897. ; This case shouldn't ever happen, so it can be slow.
  4898. (begin
  4899. (constraints-intersect! constraints0 constraints0 constraints1)
  4900. (constraints-intersect! constraints0 constraints0 constraints2)))))
  4901. (define (cs-intersect cs1 cs2)
  4902. (define (loop cs init rep Krep)
  4903. (if (null? cs)
  4904. (values init rep Krep)
  4905. (let* ((c (car cs))
  4906. (cs (cdr cs))
  4907. (E2 (constraint.rhs c))
  4908. (K2 (constraint.killer c)))
  4909. (cond ((constant? E2)
  4910. (loop cs
  4911. init
  4912. (representation-intersection rep (constant.value E2))
  4913. (available:killer-combine Krep K2)))
  4914. ((call? E2)
  4915. (if init
  4916. (begin (display "Compiler bug in cs-intersect")
  4917. (break))
  4918. (loop cs c rep Krep)))
  4919. (else
  4920. (error "Compiler bug in cs-intersect"))))))
  4921. (call-with-values
  4922. (lambda ()
  4923. (loop cs1 #f rep:object available:killer:none))
  4924. (lambda (c1 rep1 Krep1)
  4925. (call-with-values
  4926. (lambda ()
  4927. (loop cs2 #f rep:object available:killer:none))
  4928. (lambda (c2 rep2 Krep2)
  4929. (let ((c (if (equal? c1 c2) c1 #f))
  4930. (rep (representation-union rep1 rep2))
  4931. (Krep (available:killer-combine Krep1 Krep2)))
  4932. (if (eq? rep rep:object)
  4933. (if c (list c) '())
  4934. (let ((T (constraint.lhs (car cs1))))
  4935. (if c
  4936. (list c (make-type-constraint T rep Krep))
  4937. (list (make-type-constraint T rep Krep)))))))))))
  4938. ; DO NOT EDIT THIS FILE. Edit the config file and rerun "config".
  4939. (define $gc.ephemeral 0)
  4940. (define $gc.tenuring 1)
  4941. (define $gc.full 2)
  4942. (define $mstat.wallocated-hi 0)
  4943. (define $mstat.wallocated-lo 1)
  4944. (define $mstat.wcollected-hi 2)
  4945. (define $mstat.wcollected-lo 3)
  4946. (define $mstat.wcopied-hi 4)
  4947. (define $mstat.wcopied-lo 5)
  4948. (define $mstat.gctime 6)
  4949. (define $mstat.wlive 7)
  4950. (define $mstat.gc-last-gen 8)
  4951. (define $mstat.gc-last-type 9)
  4952. (define $mstat.generations 10)
  4953. (define $mstat.g-gc-count 0)
  4954. (define $mstat.g-prom-count 1)
  4955. (define $mstat.g-gctime 2)
  4956. (define $mstat.g-wlive 3)
  4957. (define $mstat.g-np-youngp 4)
  4958. (define $mstat.g-np-oldp 5)
  4959. (define $mstat.g-np-j 6)
  4960. (define $mstat.g-np-k 7)
  4961. (define $mstat.g-alloc 8)
  4962. (define $mstat.g-target 9)
  4963. (define $mstat.g-promtime 10)
  4964. (define $mstat.remsets 11)
  4965. (define $mstat.r-apool 0)
  4966. (define $mstat.r-upool 1)
  4967. (define $mstat.r-ahash 2)
  4968. (define $mstat.r-uhash 3)
  4969. (define $mstat.r-hrec-hi 4)
  4970. (define $mstat.r-hrec-lo 5)
  4971. (define $mstat.r-hrem-hi 6)
  4972. (define $mstat.r-hrem-lo 7)
  4973. (define $mstat.r-hscan-hi 8)
  4974. (define $mstat.r-hscan-lo 9)
  4975. (define $mstat.r-wscan-hi 10)
  4976. (define $mstat.r-wscan-lo 11)
  4977. (define $mstat.r-ssbrec-hi 12)
  4978. (define $mstat.r-ssbrec-lo 13)
  4979. (define $mstat.r-np-p 14)
  4980. (define $mstat.fflushed-hi 12)
  4981. (define $mstat.fflushed-lo 13)
  4982. (define $mstat.wflushed-hi 14)
  4983. (define $mstat.wflushed-lo 15)
  4984. (define $mstat.stk-created 16)
  4985. (define $mstat.frestored-hi 17)
  4986. (define $mstat.frestored-lo 18)
  4987. (define $mstat.words-heap 19)
  4988. (define $mstat.words-remset 20)
  4989. (define $mstat.words-rts 21)
  4990. (define $mstat.swb-assign 22)
  4991. (define $mstat.swb-lhs-ok 23)
  4992. (define $mstat.swb-rhs-const 24)
  4993. (define $mstat.swb-not-xgen 25)
  4994. (define $mstat.swb-trans 26)
  4995. (define $mstat.rtime 27)
  4996. (define $mstat.stime 28)
  4997. (define $mstat.utime 29)
  4998. (define $mstat.minfaults 30)
  4999. (define $mstat.majfaults 31)
  5000. (define $mstat.np-remsetp 32)
  5001. (define $mstat.max-heap 33)
  5002. (define $mstat.promtime 34)
  5003. (define $mstat.wmoved-hi 35)
  5004. (define $mstat.wmoved-lo 36)
  5005. (define $mstat.vsize 37)
  5006. (define $g.reg0 12)
  5007. (define $r.reg8 44)
  5008. (define $r.reg9 48)
  5009. (define $r.reg10 52)
  5010. (define $r.reg11 56)
  5011. (define $r.reg12 60)
  5012. (define $r.reg13 64)
  5013. (define $r.reg14 68)
  5014. (define $r.reg15 72)
  5015. (define $r.reg16 76)
  5016. (define $r.reg17 80)
  5017. (define $r.reg18 84)
  5018. (define $r.reg19 88)
  5019. (define $r.reg20 92)
  5020. (define $r.reg21 96)
  5021. (define $r.reg22 100)
  5022. (define $r.reg23 104)
  5023. (define $r.reg24 108)
  5024. (define $r.reg25 112)
  5025. (define $r.reg26 116)
  5026. (define $r.reg27 120)
  5027. (define $r.reg28 124)
  5028. (define $r.reg29 128)
  5029. (define $r.reg30 132)
  5030. (define $r.reg31 136)
  5031. (define $g.stkbot 180)
  5032. (define $g.gccnt 420)
  5033. (define $m.alloc 1024)
  5034. (define $m.alloci 1032)
  5035. (define $m.gc 1040)
  5036. (define $m.addtrans 1048)
  5037. (define $m.stkoflow 1056)
  5038. (define $m.stkuflow 1072)
  5039. (define $m.creg 1080)
  5040. (define $m.creg-set! 1088)
  5041. (define $m.add 1096)
  5042. (define $m.subtract 1104)
  5043. (define $m.multiply 1112)
  5044. (define $m.quotient 1120)
  5045. (define $m.remainder 1128)
  5046. (define $m.divide 1136)
  5047. (define $m.modulo 1144)
  5048. (define $m.negate 1152)
  5049. (define $m.numeq 1160)
  5050. (define $m.numlt 1168)
  5051. (define $m.numle 1176)
  5052. (define $m.numgt 1184)
  5053. (define $m.numge 1192)
  5054. (define $m.zerop 1200)
  5055. (define $m.complexp 1208)
  5056. (define $m.realp 1216)
  5057. (define $m.rationalp 1224)
  5058. (define $m.integerp 1232)
  5059. (define $m.exactp 1240)
  5060. (define $m.inexactp 1248)
  5061. (define $m.exact->inexact 1256)
  5062. (define $m.inexact->exact 1264)
  5063. (define $m.make-rectangular 1272)
  5064. (define $m.real-part 1280)
  5065. (define $m.imag-part 1288)
  5066. (define $m.sqrt 1296)
  5067. (define $m.round 1304)
  5068. (define $m.truncate 1312)
  5069. (define $m.apply 1320)
  5070. (define $m.varargs 1328)
  5071. (define $m.typetag 1336)
  5072. (define $m.typetag-set 1344)
  5073. (define $m.break 1352)
  5074. (define $m.eqv 1360)
  5075. (define $m.partial-list->vector 1368)
  5076. (define $m.timer-exception 1376)
  5077. (define $m.exception 1384)
  5078. (define $m.singlestep 1392)
  5079. (define $m.syscall 1400)
  5080. (define $m.bvlcmp 1408)
  5081. (define $m.enable-interrupts 1416)
  5082. (define $m.disable-interrupts 1424)
  5083. (define $m.alloc-bv 1432)
  5084. (define $m.global-ex 1440)
  5085. (define $m.invoke-ex 1448)
  5086. (define $m.global-invoke-ex 1456)
  5087. (define $m.argc-ex 1464)
  5088. ; DO NOT EDIT THIS FILE. Edit the config file and rerun "config".
  5089. (define $r.g0 0)
  5090. (define $r.g1 1)
  5091. (define $r.g2 2)
  5092. (define $r.g3 3)
  5093. (define $r.g4 4)
  5094. (define $r.g5 5)
  5095. (define $r.g6 6)
  5096. (define $r.g7 7)
  5097. (define $r.o0 8)
  5098. (define $r.o1 9)
  5099. (define $r.o2 10)
  5100. (define $r.o3 11)
  5101. (define $r.o4 12)
  5102. (define $r.o5 13)
  5103. (define $r.o6 14)
  5104. (define $r.o7 15)
  5105. (define $r.l0 16)
  5106. (define $r.l1 17)
  5107. (define $r.l2 18)
  5108. (define $r.l3 19)
  5109. (define $r.l4 20)
  5110. (define $r.l5 21)
  5111. (define $r.l6 22)
  5112. (define $r.l7 23)
  5113. (define $r.i0 24)
  5114. (define $r.i1 25)
  5115. (define $r.i2 26)
  5116. (define $r.i3 27)
  5117. (define $r.i4 28)
  5118. (define $r.i5 29)
  5119. (define $r.i6 30)
  5120. (define $r.i7 31)
  5121. (define $r.result $r.o0)
  5122. (define $r.argreg2 $r.o1)
  5123. (define $r.argreg3 $r.o2)
  5124. (define $r.stkp $r.o3)
  5125. (define $r.stklim $r.i0)
  5126. (define $r.tmp1 $r.o4)
  5127. (define $r.tmp2 $r.o5)
  5128. (define $r.tmp0 $r.g1)
  5129. (define $r.e-top $r.i0)
  5130. (define $r.e-limit $r.o3)
  5131. (define $r.timer $r.i4)
  5132. (define $r.millicode $r.i7)
  5133. (define $r.globals $r.i7)
  5134. (define $r.reg0 $r.l0)
  5135. (define $r.reg1 $r.l1)
  5136. (define $r.reg2 $r.l2)
  5137. (define $r.reg3 $r.l3)
  5138. (define $r.reg4 $r.l4)
  5139. (define $r.reg5 $r.l5)
  5140. (define $r.reg6 $r.l6)
  5141. (define $r.reg7 $r.l7)
  5142. ; DO NOT EDIT THIS FILE. Edit the config file and rerun "config".
  5143. (define $ex.car 0)
  5144. (define $ex.cdr 1)
  5145. (define $ex.setcar 2)
  5146. (define $ex.setcdr 3)
  5147. (define $ex.add 10)
  5148. (define $ex.sub 11)
  5149. (define $ex.mul 12)
  5150. (define $ex.div 13)
  5151. (define $ex.lessp 14)
  5152. (define $ex.lesseqp 15)
  5153. (define $ex.equalp 16)
  5154. (define $ex.greatereqp 17)
  5155. (define $ex.greaterp 18)
  5156. (define $ex.quotient 19)
  5157. (define $ex.remainder 20)
  5158. (define $ex.modulo 21)
  5159. (define $ex.logior 22)
  5160. (define $ex.logand 23)
  5161. (define $ex.logxor 24)
  5162. (define $ex.lognot 25)
  5163. (define $ex.lsh 26)
  5164. (define $ex.rsha 27)
  5165. (define $ex.rshl 28)
  5166. (define $ex.e2i 29)
  5167. (define $ex.i2e 30)
  5168. (define $ex.exactp 31)
  5169. (define $ex.inexactp 32)
  5170. (define $ex.round 33)
  5171. (define $ex.trunc 34)
  5172. (define $ex.zerop 35)
  5173. (define $ex.neg 36)
  5174. (define $ex.abs 37)
  5175. (define $ex.realpart 38)
  5176. (define $ex.imagpart 39)
  5177. (define $ex.vref 40)
  5178. (define $ex.vset 41)
  5179. (define $ex.vlen 42)
  5180. (define $ex.pref 50)
  5181. (define $ex.pset 51)
  5182. (define $ex.plen 52)
  5183. (define $ex.sref 60)
  5184. (define $ex.sset 61)
  5185. (define $ex.slen 62)
  5186. (define $ex.bvref 70)
  5187. (define $ex.bvset 71)
  5188. (define $ex.bvlen 72)
  5189. (define $ex.bvlref 80)
  5190. (define $ex.bvlset 81)
  5191. (define $ex.bvllen 82)
  5192. (define $ex.vlref 90)
  5193. (define $ex.vlset 91)
  5194. (define $ex.vllen 92)
  5195. (define $ex.typetag 100)
  5196. (define $ex.typetagset 101)
  5197. (define $ex.apply 102)
  5198. (define $ex.argc 103)
  5199. (define $ex.vargc 104)
  5200. (define $ex.nonproc 105)
  5201. (define $ex.undef-global 106)
  5202. (define $ex.dump 107)
  5203. (define $ex.dumpfail 108)
  5204. (define $ex.timer 109)
  5205. (define $ex.unsupported 110)
  5206. (define $ex.int2char 111)
  5207. (define $ex.char2int 112)
  5208. (define $ex.mkbvl 113)
  5209. (define $ex.mkvl 114)
  5210. (define $ex.char<? 115)
  5211. (define $ex.char<=? 116)
  5212. (define $ex.char=? 117)
  5213. (define $ex.char>? 118)
  5214. (define $ex.char>=? 119)
  5215. (define $ex.bvfill 120)
  5216. (define $ex.enable-interrupts 121)
  5217. (define $ex.keyboard-interrupt 122)
  5218. (define $ex.arithmetic-exception 123)
  5219. (define $ex.global-invoke 124)
  5220. (define $ex.fx+ 140)
  5221. (define $ex.fx- 141)
  5222. (define $ex.fx-- 142)
  5223. (define $ex.fx= 143)
  5224. (define $ex.fx< 144)
  5225. (define $ex.fx<= 145)
  5226. (define $ex.fx> 146)
  5227. (define $ex.fx>= 147)
  5228. (define $ex.fxpositive? 148)
  5229. (define $ex.fxnegative? 149)
  5230. (define $ex.fxzero? 150)
  5231. (define $ex.fx* 151)
  5232. ; DO NOT EDIT THIS FILE. Edit the config file and rerun "config".
  5233. (define $tag.tagmask 7)
  5234. (define $tag.pair-tag 1)
  5235. (define $tag.vector-tag 3)
  5236. (define $tag.bytevector-tag 5)
  5237. (define $tag.procedure-tag 7)
  5238. (define $imm.vector-header 162)
  5239. (define $imm.bytevector-header 194)
  5240. (define $imm.procedure-header 254)
  5241. (define $imm.true 6)
  5242. (define $imm.false 2)
  5243. (define $imm.null 10)
  5244. (define $imm.unspecified 278)
  5245. (define $imm.eof 534)
  5246. (define $imm.undefined 790)
  5247. (define $imm.character 38)
  5248. (define $tag.vector-typetag 0)
  5249. (define $tag.rectnum-typetag 4)
  5250. (define $tag.ratnum-typetag 8)
  5251. (define $tag.symbol-typetag 12)
  5252. (define $tag.port-typetag 16)
  5253. (define $tag.structure-typetag 20)
  5254. (define $tag.bytevector-typetag 0)
  5255. (define $tag.string-typetag 4)
  5256. (define $tag.flonum-typetag 8)
  5257. (define $tag.compnum-typetag 12)
  5258. (define $tag.bignum-typetag 16)
  5259. (define $hdr.port 178)
  5260. (define $hdr.struct 182)
  5261. (define $p.codevector -3)
  5262. (define $p.constvector 1)
  5263. (define $p.linkoffset 5)
  5264. (define $p.reg0 5)
  5265. (define $p.codeoffset -1)
  5266. ; Copyright 1991 William Clinger
  5267. ;
  5268. ; Relatively target-independent information for Twobit's backend.
  5269. ;
  5270. ; 24 April 1999 / wdc
  5271. ;
  5272. ; Most of the definitions in this file can be extended or overridden by
  5273. ; target-specific definitions.
  5274. (define twobit-sort
  5275. (lambda (less? list) (compat:sort list less?)))
  5276. (define renaming-prefix ".")
  5277. ; The prefix used for cells introduced by the compiler.
  5278. (define cell-prefix (string-append renaming-prefix "CELL:"))
  5279. ; Names of global procedures that cannot be redefined or assigned
  5280. ; by ordinary code.
  5281. ; The expansion of quasiquote uses .cons and .list directly, so these
  5282. ; should not be changed willy-nilly.
  5283. ; Others may be used directly by a DEFINE-INLINE.
  5284. (define name:CHECK! '.check!)
  5285. (define name:CONS '.cons)
  5286. (define name:LIST '.list)
  5287. (define name:MAKE-CELL '.make-cell)
  5288. (define name:CELL-REF '.cell-ref)
  5289. (define name:CELL-SET! '.cell-set!)
  5290. (define name:IGNORED (string->symbol "IGNORED"))
  5291. (define name:CAR '.car)
  5292. (define name:CDR '.cdr)
  5293. ;(begin (eval `(define ,name:CONS cons))
  5294. ; (eval `(define ,name:LIST list))
  5295. ; (eval `(define ,name:MAKE-CELL list))
  5296. ; (eval `(define ,name:CELL-REF car))
  5297. ; (eval `(define ,name:CELL-SET! set-car!)))
  5298. ; If (INTEGRATE-USUAL-PROCEDURES) is true, then control optimization
  5299. ; recognizes calls to these procedures.
  5300. (define name:NOT 'not)
  5301. (define name:MEMQ 'memq)
  5302. (define name:MEMV 'memv)
  5303. ; If (INTEGRATE-USUAL-PROCEDURES) is true, then control optimization
  5304. ; recognizes calls to these procedures and also creates calls to them.
  5305. (define name:EQ? 'eq?)
  5306. (define name:EQV? 'eqv?)
  5307. ; Control optimization creates calls to these procedures,
  5308. ; which do not need to check their arguments.
  5309. (define name:FIXNUM? 'fixnum?)
  5310. (define name:CHAR? 'char?)
  5311. (define name:SYMBOL? 'symbol?)
  5312. (define name:FX< '<:fix:fix)
  5313. (define name:FX- 'fx-) ; non-checking version
  5314. (define name:CHAR->INTEGER 'char->integer) ; non-checking version
  5315. (define name:VECTOR-REF 'vector-ref:trusted)
  5316. ; Constant folding.
  5317. ; Prototype, will probably change in the future.
  5318. (define (constant-folding-entry name)
  5319. (assq name $usual-constant-folding-procedures$))
  5320. (define constant-folding-predicates cadr)
  5321. (define constant-folding-folder caddr)
  5322. (define $usual-constant-folding-procedures$
  5323. (let ((always? (lambda (x) #t))
  5324. (charcode? (lambda (n)
  5325. (and (number? n)
  5326. (exact? n)
  5327. (<= 0 n)
  5328. (< n 128))))
  5329. (ratnum? (lambda (n)
  5330. (and (number? n)
  5331. (exact? n)
  5332. (rational? n))))
  5333. ; smallint? is defined later.
  5334. (smallint? (lambda (n) (smallint? n))))
  5335. `(
  5336. ; This makes some assumptions about the host system.
  5337. (integer->char (,charcode?) ,integer->char)
  5338. (char->integer (,char?) ,char->integer)
  5339. (zero? (,ratnum?) ,zero?)
  5340. (< (,ratnum? ,ratnum?) ,<)
  5341. (<= (,ratnum? ,ratnum?) ,<=)
  5342. (= (,ratnum? ,ratnum?) ,=)
  5343. (>= (,ratnum? ,ratnum?) ,>=)
  5344. (> (,ratnum? ,ratnum?) ,>)
  5345. (+ (,ratnum? ,ratnum?) ,+)
  5346. (- (,ratnum? ,ratnum?) ,-)
  5347. (* (,ratnum? ,ratnum?) ,*)
  5348. (-- (,ratnum?) ,(lambda (x) (- 0 x)))
  5349. (eq? (,always? ,always?) ,eq?)
  5350. (eqv? (,always? ,always?) ,eqv?)
  5351. (equal? (,always? ,always?) ,equal?)
  5352. (memq (,always? ,list?) ,memq)
  5353. (memv (,always? ,list?) ,memv)
  5354. (member (,always? ,list?) ,member)
  5355. (assq (,always? ,list?) ,assq)
  5356. (assv (,always? ,list?) ,assv)
  5357. (assoc (,always? ,list?) ,assoc)
  5358. (length (,list?) ,length)
  5359. (fixnum? (,smallint?) ,smallint?)
  5360. (=:fix:fix (,smallint? ,smallint?) ,=)
  5361. (<:fix:fix (,smallint? ,smallint?) ,<)
  5362. (<=:fix:fix (,smallint? ,smallint?) ,<=)
  5363. (>:fix:fix (,smallint? ,smallint?) ,>)
  5364. (>=:fix:fix (,smallint? ,smallint?) ,>=)
  5365. )))
  5366. (begin '
  5367. (define (.check! flag exn . args)
  5368. (if (not flag)
  5369. (apply error "Runtime check exception: " exn args)))
  5370. #t)
  5371. ; Order matters. If f and g are both inlined, and the definition of g
  5372. ; uses f, then f should be defined before g.
  5373. (for-each pass1
  5374. `(
  5375. (define-inline car
  5376. (syntax-rules ()
  5377. ((car x0)
  5378. (let ((x x0))
  5379. (.check! (pair? x) ,$ex.car x)
  5380. (car:pair x)))))
  5381. (define-inline cdr
  5382. (syntax-rules ()
  5383. ((car x0)
  5384. (let ((x x0))
  5385. (.check! (pair? x) ,$ex.cdr x)
  5386. (cdr:pair x)))))
  5387. (define-inline vector-length
  5388. (syntax-rules ()
  5389. ((vector-length v0)
  5390. (let ((v v0))
  5391. (.check! (vector? v) ,$ex.vlen v)
  5392. (vector-length:vec v)))))
  5393. (define-inline vector-ref
  5394. (syntax-rules ()
  5395. ((vector-ref v0 i0)
  5396. (let ((v v0)
  5397. (i i0))
  5398. (.check! (fixnum? i) ,$ex.vref v i)
  5399. (.check! (vector? v) ,$ex.vref v i)
  5400. (.check! (<:fix:fix i (vector-length:vec v)) ,$ex.vref v i)
  5401. (.check! (>=:fix:fix i 0) ,$ex.vref v i)
  5402. (vector-ref:trusted v i)))))
  5403. (define-inline vector-set!
  5404. (syntax-rules ()
  5405. ((vector-set! v0 i0 x0)
  5406. (let ((v v0)
  5407. (i i0)
  5408. (x x0))
  5409. (.check! (fixnum? i) ,$ex.vset v i x)
  5410. (.check! (vector? v) ,$ex.vset v i x)
  5411. (.check! (<:fix:fix i (vector-length:vec v)) ,$ex.vset v i x)
  5412. (.check! (>=:fix:fix i 0) ,$ex.vset v i x)
  5413. (vector-set!:trusted v i x)))))
  5414. ; This transformation must make sure the entire list is freshly
  5415. ; allocated when an argument to LIST returns more than once.
  5416. (define-inline list
  5417. (syntax-rules ()
  5418. ((list)
  5419. '())
  5420. ((list ?e)
  5421. (cons ?e '()))
  5422. ((list ?e1 ?e2 ...)
  5423. (let* ((t1 ?e1)
  5424. (t2 (list ?e2 ...)))
  5425. (cons t1 t2)))))
  5426. ; This transformation must make sure the entire list is freshly
  5427. ; allocated when an argument to VECTOR returns more than once.
  5428. (define-inline vector
  5429. (syntax-rules ()
  5430. ((vector)
  5431. '#())
  5432. ((vector ?e)
  5433. (make-vector 1 ?e))
  5434. ((vector ?e1 ?e2 ...)
  5435. (letrec-syntax
  5436. ((vector-aux1
  5437. (... (syntax-rules ()
  5438. ((vector-aux1 () ?n ?exps ?indexes ?temps)
  5439. (vector-aux2 ?n ?exps ?indexes ?temps))
  5440. ((vector-aux1 (?exp1 ?exp2 ...) ?n ?exps ?indexes ?temps)
  5441. (vector-aux1 (?exp2 ...)
  5442. (+ ?n 1)
  5443. (?exp1 . ?exps)
  5444. (?n . ?indexes)
  5445. (t . ?temps))))))
  5446. (vector-aux2
  5447. (... (syntax-rules ()
  5448. ((vector-aux2 ?n (?exp1 ?exp2 ...) (?n1 ?n2 ...) (?t1 ?t2 ...))
  5449. (let* ((?t1 ?exp1)
  5450. (?t2 ?exp2)
  5451. ...
  5452. (v (make-vector ?n ?t1)))
  5453. (vector-set! v ?n2 ?t2)
  5454. ...
  5455. v))))))
  5456. (vector-aux1 (?e1 ?e2 ...) 0 () () ())))))
  5457. (define-inline cadddr
  5458. (syntax-rules ()
  5459. ((cadddr ?e)
  5460. (car (cdr (cdr (cdr ?e)))))))
  5461. (define-inline cddddr
  5462. (syntax-rules ()
  5463. ((cddddr ?e)
  5464. (cdr (cdr (cdr (cdr ?e)))))))
  5465. (define-inline cdddr
  5466. (syntax-rules ()
  5467. ((cdddr ?e)
  5468. (cdr (cdr (cdr ?e))))))
  5469. (define-inline caddr
  5470. (syntax-rules ()
  5471. ((caddr ?e)
  5472. (car (cdr (cdr ?e))))))
  5473. (define-inline cddr
  5474. (syntax-rules ()
  5475. ((cddr ?e)
  5476. (cdr (cdr ?e)))))
  5477. (define-inline cdar
  5478. (syntax-rules ()
  5479. ((cdar ?e)
  5480. (cdr (car ?e)))))
  5481. (define-inline cadr
  5482. (syntax-rules ()
  5483. ((cadr ?e)
  5484. (car (cdr ?e)))))
  5485. (define-inline caar
  5486. (syntax-rules ()
  5487. ((caar ?e)
  5488. (car (car ?e)))))
  5489. (define-inline make-vector
  5490. (syntax-rules ()
  5491. ((make-vector ?n)
  5492. (make-vector ?n '()))))
  5493. (define-inline make-string
  5494. (syntax-rules ()
  5495. ((make-string ?n)
  5496. (make-string ?n #\space))))
  5497. (define-inline =
  5498. (syntax-rules ()
  5499. ((= ?e1 ?e2 ?e3 ?e4 ...)
  5500. (let ((t ?e2))
  5501. (and (= ?e1 t)
  5502. (= t ?e3 ?e4 ...))))))
  5503. (define-inline <
  5504. (syntax-rules ()
  5505. ((< ?e1 ?e2 ?e3 ?e4 ...)
  5506. (let ((t ?e2))
  5507. (and (< ?e1 t)
  5508. (< t ?e3 ?e4 ...))))))
  5509. (define-inline >
  5510. (syntax-rules ()
  5511. ((> ?e1 ?e2 ?e3 ?e4 ...)
  5512. (let ((t ?e2))
  5513. (and (> ?e1 t)
  5514. (> t ?e3 ?e4 ...))))))
  5515. (define-inline <=
  5516. (syntax-rules ()
  5517. ((<= ?e1 ?e2 ?e3 ?e4 ...)
  5518. (let ((t ?e2))
  5519. (and (<= ?e1 t)
  5520. (<= t ?e3 ?e4 ...))))))
  5521. (define-inline >=
  5522. (syntax-rules ()
  5523. ((>= ?e1 ?e2 ?e3 ?e4 ...)
  5524. (let ((t ?e2))
  5525. (and (>= ?e1 t)
  5526. (>= t ?e3 ?e4 ...))))))
  5527. (define-inline +
  5528. (syntax-rules ()
  5529. ((+)
  5530. 0)
  5531. ((+ ?e)
  5532. ?e)
  5533. ((+ ?e1 ?e2 ?e3 ?e4 ...)
  5534. (+ (+ ?e1 ?e2) ?e3 ?e4 ...))))
  5535. (define-inline *
  5536. (syntax-rules ()
  5537. ((*)
  5538. 1)
  5539. ((* ?e)
  5540. ?e)
  5541. ((* ?e1 ?e2 ?e3 ?e4 ...)
  5542. (* (* ?e1 ?e2) ?e3 ?e4 ...))))
  5543. (define-inline -
  5544. (syntax-rules ()
  5545. ((- ?e)
  5546. (- 0 ?e))
  5547. ((- ?e1 ?e2 ?e3 ?e4 ...)
  5548. (- (- ?e1 ?e2) ?e3 ?e4 ...))))
  5549. (define-inline /
  5550. (syntax-rules ()
  5551. ((/ ?e)
  5552. (/ 1 ?e))
  5553. ((/ ?e1 ?e2 ?e3 ?e4 ...)
  5554. (/ (/ ?e1 ?e2) ?e3 ?e4 ...))))
  5555. (define-inline abs
  5556. (syntax-rules ()
  5557. ((abs ?z)
  5558. (let ((temp ?z))
  5559. (if (< temp 0)
  5560. (-- temp)
  5561. temp)))))
  5562. (define-inline negative?
  5563. (syntax-rules ()
  5564. ((negative? ?x)
  5565. (< ?x 0))))
  5566. (define-inline positive?
  5567. (syntax-rules ()
  5568. ((positive? ?x)
  5569. (> ?x 0))))
  5570. (define-inline eqv?
  5571. (transformer
  5572. (lambda (exp rename compare)
  5573. (let ((arg1 (cadr exp))
  5574. (arg2 (caddr exp)))
  5575. (define (constant? exp)
  5576. (or (boolean? exp)
  5577. (char? exp)
  5578. (and (pair? exp)
  5579. (= (length exp) 2)
  5580. (identifier? (car exp))
  5581. (compare (car exp) (rename 'quote))
  5582. (symbol? (cadr exp)))))
  5583. (if (or (constant? arg1)
  5584. (constant? arg2))
  5585. (cons (rename 'eq?) (cdr exp))
  5586. exp)))))
  5587. (define-inline memq
  5588. (syntax-rules (quote)
  5589. ((memq ?expr '(?datum ...))
  5590. (letrec-syntax
  5591. ((memq0
  5592. (... (syntax-rules (quote)
  5593. ((memq0 '?xx '(?d ...))
  5594. (let ((t1 '(?d ...)))
  5595. (memq1 '?xx t1 (?d ...))))
  5596. ((memq0 ?e '(?d ...))
  5597. (let ((t0 ?e)
  5598. (t1 '(?d ...)))
  5599. (memq1 t0 t1 (?d ...)))))))
  5600. (memq1
  5601. (... (syntax-rules ()
  5602. ((memq1 ?t0 ?t1 ())
  5603. #f)
  5604. ((memq1 ?t0 ?t1 (?d1 ?d2 ...))
  5605. (if (eq? ?t0 '?d1)
  5606. ?t1
  5607. (let ((?t1 (cdr ?t1)))
  5608. (memq1 ?t0 ?t1 (?d2 ...)))))))))
  5609. (memq0 ?expr '(?datum ...))))))
  5610. (define-inline memv
  5611. (transformer
  5612. (lambda (exp rename compare)
  5613. (let ((arg1 (cadr exp))
  5614. (arg2 (caddr exp)))
  5615. (if (or (boolean? arg1)
  5616. (fixnum? arg1)
  5617. (char? arg1)
  5618. (and (pair? arg1)
  5619. (= (length arg1) 2)
  5620. (identifier? (car arg1))
  5621. (compare (car arg1) (rename 'quote))
  5622. (symbol? (cadr arg1)))
  5623. (and (pair? arg2)
  5624. (= (length arg2) 2)
  5625. (identifier? (car arg2))
  5626. (compare (car arg2) (rename 'quote))
  5627. (every1? (lambda (x)
  5628. (or (boolean? x)
  5629. (fixnum? x)
  5630. (char? x)
  5631. (symbol? x)))
  5632. (cadr arg2))))
  5633. (cons (rename 'memq) (cdr exp))
  5634. exp)))))
  5635. (define-inline assv
  5636. (transformer
  5637. (lambda (exp rename compare)
  5638. (let ((arg1 (cadr exp))
  5639. (arg2 (caddr exp)))
  5640. (if (or (boolean? arg1)
  5641. (char? arg1)
  5642. (and (pair? arg1)
  5643. (= (length arg1) 2)
  5644. (identifier? (car arg1))
  5645. (compare (car arg1) (rename 'quote))
  5646. (symbol? (cadr arg1)))
  5647. (and (pair? arg2)
  5648. (= (length arg2) 2)
  5649. (identifier? (car arg2))
  5650. (compare (car arg2) (rename 'quote))
  5651. (every1? (lambda (y)
  5652. (and (pair? y)
  5653. (let ((x (car y)))
  5654. (or (boolean? x)
  5655. (char? x)
  5656. (symbol? x)))))
  5657. (cadr arg2))))
  5658. (cons (rename 'assq) (cdr exp))
  5659. exp)))))
  5660. (define-inline map
  5661. (syntax-rules (lambda)
  5662. ((map ?proc ?exp1 ?exp2 ...)
  5663. (letrec-syntax
  5664. ((loop
  5665. (... (syntax-rules (lambda)
  5666. ((loop 1 () (?y1 ?y2 ...) ?f ?exprs)
  5667. (loop 2 (?y1 ?y2 ...) ?f ?exprs))
  5668. ((loop 1 (?a1 ?a2 ...) (?y2 ...) ?f ?exprs)
  5669. (loop 1 (?a2 ...) (y1 ?y2 ...) ?f ?exprs))
  5670. ((loop 2 ?ys (lambda ?formals ?body) ?exprs)
  5671. (loop 3 ?ys (lambda ?formals ?body) ?exprs))
  5672. ((loop 2 ?ys (?f1 . ?f2) ?exprs)
  5673. (let ((f (?f1 . ?f2)))
  5674. (loop 3 ?ys f ?exprs)))
  5675. ; ?f must be a constant or variable.
  5676. ((loop 2 ?ys ?f ?exprs)
  5677. (loop 3 ?ys ?f ?exprs))
  5678. ((loop 3 (?y1 ?y2 ...) ?f (?e1 ?e2 ...))
  5679. (do ((?y1 ?e1 (cdr ?y1))
  5680. (?y2 ?e2 (cdr ?y2))
  5681. ...
  5682. (results '() (cons (?f (car ?y1) (car ?y2) ...)
  5683. results)))
  5684. ((or (null? ?y1) (null? ?y2) ...)
  5685. (reverse results))))))))
  5686. (loop 1 (?exp1 ?exp2 ...) () ?proc (?exp1 ?exp2 ...))))))
  5687. (define-inline for-each
  5688. (syntax-rules (lambda)
  5689. ((for-each ?proc ?exp1 ?exp2 ...)
  5690. (letrec-syntax
  5691. ((loop
  5692. (... (syntax-rules (lambda)
  5693. ((loop 1 () (?y1 ?y2 ...) ?f ?exprs)
  5694. (loop 2 (?y1 ?y2 ...) ?f ?exprs))
  5695. ((loop 1 (?a1 ?a2 ...) (?y2 ...) ?f ?exprs)
  5696. (loop 1 (?a2 ...) (y1 ?y2 ...) ?f ?exprs))
  5697. ((loop 2 ?ys (lambda ?formals ?body) ?exprs)
  5698. (loop 3 ?ys (lambda ?formals ?body) ?exprs))
  5699. ((loop 2 ?ys (?f1 . ?f2) ?exprs)
  5700. (let ((f (?f1 . ?f2)))
  5701. (loop 3 ?ys f ?exprs)))
  5702. ; ?f must be a constant or variable.
  5703. ((loop 2 ?ys ?f ?exprs)
  5704. (loop 3 ?ys ?f ?exprs))
  5705. ((loop 3 (?y1 ?y2 ...) ?f (?e1 ?e2 ...))
  5706. (do ((?y1 ?e1 (cdr ?y1))
  5707. (?y2 ?e2 (cdr ?y2))
  5708. ...)
  5709. ((or (null? ?y1) (null? ?y2) ...)
  5710. (if #f #f))
  5711. (?f (car ?y1) (car ?y2) ...)))))))
  5712. (loop 1 (?exp1 ?exp2 ...) () ?proc (?exp1 ?exp2 ...))))))
  5713. ))
  5714. (define extended-syntactic-environment
  5715. (syntactic-copy global-syntactic-environment))
  5716. (define (make-extended-syntactic-environment)
  5717. (syntactic-copy extended-syntactic-environment))
  5718. ; MacScheme machine assembly instructions.
  5719. (define instruction.op car)
  5720. (define instruction.arg1 cadr)
  5721. (define instruction.arg2 caddr)
  5722. (define instruction.arg3 cadddr)
  5723. ; Opcode table.
  5724. (define *mnemonic-names* '()) ; For readify-lap
  5725. (begin
  5726. '
  5727. (define *last-reserved-mnemonic* 32767) ; For consistency check
  5728. '
  5729. (define make-mnemonic
  5730. (let ((count 0))
  5731. (lambda (name)
  5732. (set! count (+ count 1))
  5733. (if (= count *last-reserved-mnemonic*)
  5734. (error "Error in make-mnemonic: conflict: " name))
  5735. (set! *mnemonic-names* (cons (cons count name) *mnemonic-names*))
  5736. count)))
  5737. '
  5738. (define (reserved-mnemonic name value)
  5739. (if (and (> value 0) (< value *last-reserved-mnemonic*))
  5740. (set! *last-reserved-mnemonic* value))
  5741. (set! *mnemonic-names* (cons (cons value name) *mnemonic-names*))
  5742. value)
  5743. #t)
  5744. (define make-mnemonic
  5745. (let ((count 0))
  5746. (lambda (name)
  5747. (set! count (+ count 1))
  5748. (set! *mnemonic-names* (cons (cons count name) *mnemonic-names*))
  5749. count)))
  5750. (define (reserved-mnemonic name ignored)
  5751. (make-mnemonic name))
  5752. (define $.linearize (reserved-mnemonic '.linearize -1)) ; unused?
  5753. (define $.label (reserved-mnemonic '.label 63))
  5754. (define $.proc (reserved-mnemonic '.proc 62)) ; proc entry point
  5755. (define $.cont (reserved-mnemonic '.cont 61)) ; return point
  5756. (define $.align (reserved-mnemonic '.align 60)) ; align code stream
  5757. (define $.asm (reserved-mnemonic '.asm 59)) ; in-line native code
  5758. (define $.proc-doc ; internal def proc info
  5759. (reserved-mnemonic '.proc-doc 58))
  5760. (define $.end ; end of code vector
  5761. (reserved-mnemonic '.end 57)) ; (asm internal)
  5762. (define $.singlestep ; insert singlestep point
  5763. (reserved-mnemonic '.singlestep 56)) ; (asm internal)
  5764. (define $.entry (reserved-mnemonic '.entry 55)) ; procedure entry point
  5765. ; (asm internal)
  5766. (define $op1 (make-mnemonic 'op1)) ; op prim
  5767. (define $op2 (make-mnemonic 'op2)) ; op2 prim,k
  5768. (define $op3 (make-mnemonic 'op3)) ; op3 prim,k1,k2
  5769. (define $op2imm (make-mnemonic 'op2imm)) ; op2imm prim,x
  5770. (define $const (make-mnemonic 'const)) ; const x
  5771. (define $global (make-mnemonic 'global)) ; global x
  5772. (define $setglbl (make-mnemonic 'setglbl)) ; setglbl x
  5773. (define $lexical (make-mnemonic 'lexical)) ; lexical m,n
  5774. (define $setlex (make-mnemonic 'setlex)) ; setlex m,n
  5775. (define $stack (make-mnemonic 'stack)) ; stack n
  5776. (define $setstk (make-mnemonic 'setstk)) ; setstk n
  5777. (define $load (make-mnemonic 'load)) ; load k,n
  5778. (define $store (make-mnemonic 'store)) ; store k,n
  5779. (define $reg (make-mnemonic 'reg)) ; reg k
  5780. (define $setreg (make-mnemonic 'setreg)) ; setreg k
  5781. (define $movereg (make-mnemonic 'movereg)) ; movereg k1,k2
  5782. (define $lambda (make-mnemonic 'lambda)) ; lambda x,n,doc
  5783. (define $lexes (make-mnemonic 'lexes)) ; lexes n,doc
  5784. (define $args= (make-mnemonic 'args=)) ; args= k
  5785. (define $args>= (make-mnemonic 'args>=)) ; args>= k
  5786. (define $invoke (make-mnemonic 'invoke)) ; invoke k
  5787. (define $save (make-mnemonic 'save)) ; save L,k
  5788. (define $setrtn (make-mnemonic 'setrtn)) ; setrtn L
  5789. (define $restore (make-mnemonic 'restore)) ; restore n ; deprecated
  5790. (define $pop (make-mnemonic 'pop)) ; pop k
  5791. (define $popstk (make-mnemonic 'popstk)) ; popstk ; for students
  5792. (define $return (make-mnemonic 'return)) ; return
  5793. (define $mvrtn (make-mnemonic 'mvrtn)) ; mvrtn ; NYI
  5794. (define $apply (make-mnemonic 'apply)) ; apply
  5795. (define $nop (make-mnemonic 'nop)) ; nop
  5796. (define $jump (make-mnemonic 'jump)) ; jump m,o
  5797. (define $skip (make-mnemonic 'skip)) ; skip L ; forward
  5798. (define $branch (make-mnemonic 'branch)) ; branch L
  5799. (define $branchf (make-mnemonic 'branchf)) ; branchf L
  5800. (define $check (make-mnemonic 'check)) ; check k1,k2,k3,L
  5801. (define $trap (make-mnemonic 'trap)) ; trap k1,k2,k3,exn
  5802. ; A peephole optimizer may define more instructions in some
  5803. ; target-specific file.
  5804. ; eof
  5805. ; Copyright 1991 William Clinger
  5806. ;
  5807. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  5808. ;
  5809. ; Larceny -- target-specific information for Twobit's SPARC backend.
  5810. ;
  5811. ; 11 June 1999 / wdc
  5812. ; The maximum number of fixed arguments that may be followed by a rest
  5813. ; argument. This limitation is removed by the macro expander.
  5814. (define @maxargs-with-rest-arg@ 30)
  5815. ; The number of MacScheme machine registers.
  5816. ; (They do not necessarily correspond to hardware registers.)
  5817. (define *nregs* 32)
  5818. (define *lastreg* (- *nregs* 1))
  5819. (define *fullregs* (quotient *nregs* 2))
  5820. ; The number of argument registers that are represented by hardware
  5821. ; registers.
  5822. (define *nhwregs* 8)
  5823. ; Variable names that indicate register targets.
  5824. (define *regnames*
  5825. (do ((alist '() (cons (cons (string->symbol
  5826. (string-append ".REG" (number->string r)))
  5827. r)
  5828. alist))
  5829. (r (- *nhwregs* 1) (- r 1)))
  5830. ((<= r 0)
  5831. alist)))
  5832. ; A non-inclusive upper bound for the instruction encodings.
  5833. (define *number-of-mnemonics* 72)
  5834. ; Integrable procedures and procedure-specific source code transformations.
  5835. ; Every integrable procedure that takes a varying number of arguments must
  5836. ; supply a transformation procedure to map calls into the fixed arity
  5837. ; required by the MacScheme machine instructions.
  5838. ; The table of integrable procedures.
  5839. ; Each entry is a list of the following items:
  5840. ;
  5841. ; procedure name
  5842. ; arity (or -1 for special primops like .check!)
  5843. ; procedure name to be used by the disassembler
  5844. ; predicate for immediate operands (or #f)
  5845. ; primop code in the MacScheme machine (not used by Larceny)
  5846. ; the effects that kill this primop's result
  5847. ; the effects of this primop that kill available expressions
  5848. (define (prim-entry name)
  5849. (assq name $usual-integrable-procedures$))
  5850. (define prim-arity cadr)
  5851. (define prim-opcodename caddr)
  5852. (define prim-immediate? cadddr)
  5853. (define (prim-primcode entry)
  5854. (car (cddddr entry)))
  5855. ; This predicate returns #t iff its argument will be represented
  5856. ; as a fixnum on the target machine.
  5857. (define smallint?
  5858. (let* ((least (- (expt 2 29)))
  5859. (greatest (- (- least) 1)))
  5860. (lambda (x)
  5861. (and (number? x)
  5862. (exact? x)
  5863. (integer? x)
  5864. (<= least x greatest)))))
  5865. (define (sparc-imm? x)
  5866. (and (fixnum? x)
  5867. (<= -1024 x 1023)))
  5868. (define (sparc-eq-imm? x)
  5869. (or (sparc-imm? x)
  5870. (eq? x #t)
  5871. (eq? x #f)
  5872. (eq? x '())))
  5873. (define (valid-typetag? x)
  5874. (and (fixnum? x)
  5875. (<= 0 x 7)))
  5876. (define (fixnum-primitives) #t)
  5877. (define (flonum-primitives) #t)
  5878. ; The table of primitives has been extended with
  5879. ; kill information used for commoning.
  5880. (define (prim-lives-until entry)
  5881. (list-ref entry 5))
  5882. (define (prim-kills entry)
  5883. (list-ref entry 6))
  5884. (define $usual-integrable-procedures$
  5885. (let ((:globals available:killer:globals)
  5886. (:car available:killer:car)
  5887. (:cdr available:killer:cdr)
  5888. (:string available:killer:string)
  5889. (:vector available:killer:vector)
  5890. (:cell available:killer:cell)
  5891. (:io available:killer:io)
  5892. (:none available:killer:none) ; none of the above
  5893. (:all available:killer:all) ; all of the above
  5894. (:immortal available:killer:immortal) ; never killed
  5895. (:dead available:killer:dead) ; never available
  5896. )
  5897. ; external arity internal immediate ignored killed kills
  5898. ; name name predicate by what
  5899. ; kind of
  5900. ; effect
  5901. `((break 0 break #f 3 ,:dead ,:all)
  5902. (creg 0 creg #f 7 ,:dead ,:all)
  5903. (unspecified 0 unspecified #f -1 ,:dead ,:none)
  5904. (undefined 0 undefined #f 8 ,:dead ,:none)
  5905. (eof-object 0 eof-object #f -1 ,:dead ,:none)
  5906. (enable-interrupts 1 enable-interrupts #f -1 ,:dead ,:all)
  5907. (disable-interrupts 0 disable-interrupts #f -1 ,:dead ,:all)
  5908. (typetag 1 typetag #f #x11 ,:dead ,:none)
  5909. (not 1 not #f #x18 ,:immortal ,:none)
  5910. (null? 1 null? #f #x19 ,:immortal ,:none)
  5911. (pair? 1 pair? #f #x1a ,:immortal ,:none)
  5912. (eof-object? 1 eof-object? #f -1 ,:immortal ,:none)
  5913. (port? 1 port? #f -1 ,:dead ,:none)
  5914. (structure? 1 structure? #f -1 ,:dead ,:none)
  5915. (car 1 car #f #x1b ,:car ,:none)
  5916. (,name:CAR 1 car #f #x1b ,:car ,:none)
  5917. (cdr 1 cdr #f #x1c ,:cdr ,:none)
  5918. (,name:CDR 1 cdr #f #x1c ,:cdr ,:none)
  5919. (symbol? 1 symbol? #f #x1f ,:immortal ,:none)
  5920. (number? 1 complex? #f #x20 ,:immortal ,:none)
  5921. (complex? 1 complex? #f #x20 ,:immortal ,:none)
  5922. (real? 1 rational? #f #x21 ,:immortal ,:none)
  5923. (rational? 1 rational? #f #x21 ,:immortal ,:none)
  5924. (integer? 1 integer? #f #x22 ,:immortal ,:none)
  5925. (fixnum? 1 fixnum? #f #x23 ,:immortal ,:none)
  5926. (flonum? 1 flonum? #f -1 ,:immortal ,:none)
  5927. (compnum? 1 compnum? #f -1 ,:immortal ,:none)
  5928. (exact? 1 exact? #f #x24 ,:immortal ,:none)
  5929. (inexact? 1 inexact? #f #x25 ,:immortal ,:none)
  5930. (exact->inexact 1 exact->inexact #f #x26 ,:immortal ,:none)
  5931. (inexact->exact 1 inexact->exact #f #x27 ,:immortal ,:none)
  5932. (round 1 round #f #x28 ,:immortal ,:none)
  5933. (truncate 1 truncate #f #x29 ,:immortal ,:none)
  5934. (zero? 1 zero? #f #x2c ,:immortal ,:none)
  5935. (-- 1 -- #f #x2d ,:immortal ,:none)
  5936. (lognot 1 lognot #f #x2f ,:immortal ,:none)
  5937. (real-part 1 real-part #f #x3e ,:immortal ,:none)
  5938. (imag-part 1 imag-part #f #x3f ,:immortal ,:none)
  5939. (char? 1 char? #f #x40 ,:immortal ,:none)
  5940. (char->integer 1 char->integer #f #x41 ,:immortal ,:none)
  5941. (integer->char 1 integer->char #f #x42 ,:immortal ,:none)
  5942. (string? 1 string? #f #x50 ,:immortal ,:none)
  5943. (string-length 1 string-length #f #x51 ,:immortal ,:none)
  5944. (vector? 1 vector? #f #x52 ,:immortal ,:none)
  5945. (vector-length 1 vector-length #f #x53 ,:immortal ,:none)
  5946. (bytevector? 1 bytevector? #f #x54 ,:immortal ,:none)
  5947. (bytevector-length 1 bytevector-length #f #x55 ,:immortal ,:none)
  5948. (bytevector-fill! 2 bytevector-fill! #f -1 ,:dead ,:string)
  5949. (make-bytevector 1 make-bytevector #f #x56 ,:dead ,:none)
  5950. (procedure? 1 procedure? #f #x58 ,:immortal ,:none)
  5951. (procedure-length 1 procedure-length #f #x59 ,:dead ,:none)
  5952. (make-procedure 1 make-procedure #f #x5a ,:dead ,:none)
  5953. (creg-set! 1 creg-set! #f #x71 ,:dead ,:none)
  5954. (,name:MAKE-CELL 1 make-cell #f #x7e ,:dead ,:none)
  5955. (,name:CELL-REF 1 cell-ref #f #x7f ,:cell ,:none)
  5956. (,name:CELL-SET! 2 cell-set! #f #xdf ,:dead ,:cell)
  5957. (typetag-set! 2 typetag-set! ,valid-typetag? #xa0 ,:dead ,:all)
  5958. (eq? 2 eq? ,sparc-eq-imm? #xa1 ,:immortal ,:none)
  5959. (eqv? 2 eqv? #f #xa2 ,:immortal ,:none)
  5960. (cons 2 cons #f #xa8 ,:dead ,:none)
  5961. (,name:CONS 2 cons #f #xa8 ,:dead ,:none)
  5962. (set-car! 2 set-car! #f #xa9 ,:dead ,:car)
  5963. (set-cdr! 2 set-cdr! #f #xaa ,:dead ,:cdr)
  5964. (+ 2 + ,sparc-imm? #xb0 ,:immortal ,:none)
  5965. (- 2 - ,sparc-imm? #xb1 ,:immortal ,:none)
  5966. (* 2 * ,sparc-imm? #xb2 ,:immortal ,:none)
  5967. (/ 2 / #f #xb3 ,:immortal ,:none)
  5968. (quotient 2 quotient #f #xb4 ,:immortal ,:none)
  5969. (< 2 < ,sparc-imm? #xb5 ,:immortal ,:none)
  5970. (<= 2 <= ,sparc-imm? #xb6 ,:immortal ,:none)
  5971. (= 2 = ,sparc-imm? #xb7 ,:immortal ,:none)
  5972. (> 2 > ,sparc-imm? #xb8 ,:immortal ,:none)
  5973. (>= 2 >= ,sparc-imm? #xb9 ,:immortal ,:none)
  5974. (logand 2 logand #f #xc0 ,:immortal ,:none)
  5975. (logior 2 logior #f #xc1 ,:immortal ,:none)
  5976. (logxor 2 logxor #f #xc2 ,:immortal ,:none)
  5977. (lsh 2 lsh #f #xc3 ,:immortal ,:none)
  5978. (rsha 2 rsha #f -1 ,:immortal ,:none)
  5979. (rshl 2 rshl #f -1 ,:immortal ,:none)
  5980. (rot 2 rot #f #xc4 ,:immortal ,:none)
  5981. (make-string 2 make-string #f -1 ,:dead ,:none)
  5982. (string-ref 2 string-ref ,sparc-imm? #xd1 ,:string ,:none)
  5983. (string-set! 3 string-set! ,sparc-imm? -1 ,:dead ,:string)
  5984. (make-vector 2 make-vector #f #xd2 ,:dead ,:none)
  5985. (vector-ref 2 vector-ref ,sparc-imm? #xd3 ,:vector ,:none)
  5986. (bytevector-ref 2 bytevector-ref ,sparc-imm? #xd5 ,:string ,:none)
  5987. (procedure-ref 2 procedure-ref #f #xd7 ,:dead ,:none)
  5988. (char<? 2 char<? ,char? #xe0 ,:immortal ,:none)
  5989. (char<=? 2 char<=? ,char? #xe1 ,:immortal ,:none)
  5990. (char=? 2 char=? ,char? #xe2 ,:immortal ,:none)
  5991. (char>? 2 char>? ,char? #xe3 ,:immortal ,:none)
  5992. (char>=? 2 char>=? ,char? #xe4 ,:immortal ,:none)
  5993. (sys$partial-list->vector 2 sys$partial-list->vector #f -1 ,:dead ,:all)
  5994. (vector-set! 3 vector-set! #f #xf1 ,:dead ,:vector)
  5995. (bytevector-set! 3 bytevector-set! #f #xf2 ,:dead ,:string)
  5996. (procedure-set! 3 procedure-set! #f #xf3 ,:dead ,:all)
  5997. (bytevector-like? 1 bytevector-like? #f -1 ,:immortal ,:none)
  5998. (vector-like? 1 vector-like? #f -1 ,:immortal ,:none)
  5999. (bytevector-like-ref 2 bytevector-like-ref #f -1 ,:string ,:none)
  6000. (bytevector-like-set! 3 bytevector-like-set! #f -1 ,:dead ,:string)
  6001. (sys$bvlcmp 2 sys$bvlcmp #f -1 ,:dead ,:all)
  6002. (vector-like-ref 2 vector-like-ref #f -1 ,:vector ,:none)
  6003. (vector-like-set! 3 vector-like-set! #f -1 ,:dead ,:vector)
  6004. (vector-like-length 1 vector-like-length #f -1 ,:immortal ,:none)
  6005. (bytevector-like-length 1 bytevector-like-length #f -1 ,:immortal ,:none)
  6006. (remainder 2 remainder #f -1 ,:immortal ,:none)
  6007. (sys$read-char 1 sys$read-char #f -1 ,:dead ,:io)
  6008. (gc-counter 0 gc-counter #f -1 ,:dead ,:none)
  6009. ,@(if (fixnum-primitives)
  6010. `((most-positive-fixnum
  6011. 0 most-positive-fixnum
  6012. #f -1 ,:immortal ,:none)
  6013. (most-negative-fixnum
  6014. 0 most-negative-fixnum
  6015. #f -1 ,:immortal ,:none)
  6016. (fx+ 2 fx+ ,sparc-imm? -1 ,:immortal ,:none)
  6017. (fx- 2 fx- ,sparc-imm? -1 ,:immortal ,:none)
  6018. (fx-- 1 fx-- #f -1 ,:immortal ,:none)
  6019. (fx* 2 fx* #f -1 ,:immortal ,:none)
  6020. (fx= 2 fx= ,sparc-imm? -1 ,:immortal ,:none)
  6021. (fx< 2 fx< ,sparc-imm? -1 ,:immortal ,:none)
  6022. (fx<= 2 fx<= ,sparc-imm? -1 ,:immortal ,:none)
  6023. (fx> 2 fx> ,sparc-imm? -1 ,:immortal ,:none)
  6024. (fx>= 2 fx>= ,sparc-imm? -1 ,:immortal ,:none)
  6025. (fxzero? 1 fxzero? #f -1 ,:immortal ,:none)
  6026. (fxpositive? 1 fxpositive? #f -1 ,:immortal ,:none)
  6027. (fxnegative? 1 fxnegative? #f -1 ,:immortal ,:none))
  6028. '())
  6029. ,@(if (flonum-primitives)
  6030. `((fl+ 2 + #f -1 ,:immortal ,:none)
  6031. (fl- 2 - #f -1 ,:immortal ,:none)
  6032. (fl-- 1 -- #f -1 ,:immortal ,:none)
  6033. (fl* 2 * #f -1 ,:immortal ,:none)
  6034. (fl= 2 = #f -1 ,:immortal ,:none)
  6035. (fl< 2 < #f -1 ,:immortal ,:none)
  6036. (fl<= 2 <= #f -1 ,:immortal ,:none)
  6037. (fl> 2 > #f -1 ,:immortal ,:none)
  6038. (fl>= 2 >= #f -1 ,:immortal ,:none))
  6039. '())
  6040. ; Added for CSE, representation analysis.
  6041. (,name:CHECK! -1 check! #f -1 ,:dead ,:none)
  6042. (vector-length:vec 1 vector-length:vec #f -1 ,:immortal ,:none)
  6043. (vector-ref:trusted 2 vector-ref:trusted ,sparc-imm? -1 ,:vector ,:none)
  6044. (vector-set!:trusted 3 vector-set!:trusted #f -1 ,:dead ,:vector)
  6045. (car:pair 1 car:pair #f -1 ,:car ,:none)
  6046. (cdr:pair 1 cdr:pair #f -1 ,:cdr ,:none)
  6047. (=:fix:fix 2 =:fix:fix ,sparc-imm? -1 ,:immortal ,:none)
  6048. (<:fix:fix 2 <:fix:fix ,sparc-imm? -1 ,:immortal ,:none)
  6049. (<=:fix:fix 2 <=:fix:fix ,sparc-imm? -1 ,:immortal ,:none)
  6050. (>=:fix:fix 2 >=:fix:fix ,sparc-imm? -1 ,:immortal ,:none)
  6051. (>:fix:fix 2 >:fix:fix ,sparc-imm? -1 ,:immortal ,:none)
  6052. ; Not yet implemented.
  6053. (+:idx:idx 2 +:idx:idx #f -1 ,:immortal ,:none)
  6054. (+:fix:fix 2 +:idx:idx #f -1 ,:immortal ,:none)
  6055. (+:exi:exi 2 +:idx:idx #f -1 ,:immortal ,:none)
  6056. (+:flo:flo 2 +:idx:idx #f -1 ,:immortal ,:none)
  6057. (=:flo:flo 2 =:flo:flo #f -1 ,:immortal ,:none)
  6058. (=:obj:flo 2 =:obj:flo #f -1 ,:immortal ,:none)
  6059. (=:flo:obj 2 =:flo:obj #f -1 ,:immortal ,:none)
  6060. )))
  6061. ; Not used by the Sparc assembler; for information only.
  6062. (define $immediate-primops$
  6063. '((typetag-set! #x80)
  6064. (eq? #x81)
  6065. (+ #x82)
  6066. (- #x83)
  6067. (< #x84)
  6068. (<= #x85)
  6069. (= #x86)
  6070. (> #x87)
  6071. (>= #x88)
  6072. (char<? #x89)
  6073. (char<=? #x8a)
  6074. (char=? #x8b)
  6075. (char>? #x8c)
  6076. (char>=? #x8d)
  6077. (string-ref #x90)
  6078. (vector-ref #x91)
  6079. (bytevector-ref #x92)
  6080. (bytevector-like-ref -1)
  6081. (vector-like-ref -1)
  6082. (fx+ -1)
  6083. (fx- -1)
  6084. (fx-- -1)
  6085. (fx= -1)
  6086. (fx< -1)
  6087. (fx<= -1)
  6088. (fx> -1)
  6089. (fx>= -1)))
  6090. ; Operations introduced by peephole optimizer.
  6091. (define $reg/op1/branchf ; reg/op1/branchf prim,k1,L
  6092. (make-mnemonic 'reg/op1/branchf))
  6093. (define $reg/op2/branchf ; reg/op2/branchf prim,k1,k2,L
  6094. (make-mnemonic 'reg/op2/branchf))
  6095. (define $reg/op2imm/branchf ; reg/op2imm/branchf prim,k1,x,L
  6096. (make-mnemonic 'reg/op2imm/branchf))
  6097. (define $reg/op1/check ; reg/op1/check prim,k1,k2,k3,k4,exn
  6098. (make-mnemonic 'reg/op1/check))
  6099. (define $reg/op2/check ; reg/op2/check prim,k1,k2,k3,k4,k5,exn
  6100. (make-mnemonic 'reg/op2/check))
  6101. (define $reg/op2imm/check ; reg/op2imm/check prim,k1,x,k2,k3,k4,exn
  6102. (make-mnemonic 'reg/op2imm/check))
  6103. (define $reg/op1/setreg ; reg/op1/setreg prim,k1,kr
  6104. (make-mnemonic 'reg/op1/setreg))
  6105. (define $reg/op2/setreg ; reg/op2/setreg prim,k1,k2,kr
  6106. (make-mnemonic 'reg/op2/setreg))
  6107. (define $reg/op2imm/setreg ; reg/op2imm/setreg prim,k1,x,kr
  6108. (make-mnemonic 'reg/op2imm/setreg))
  6109. (define $reg/branchf ; reg/branchf k, L
  6110. (make-mnemonic 'reg/branchf))
  6111. (define $reg/return ; reg/return k
  6112. (make-mnemonic 'reg/return))
  6113. (define $reg/setglbl ; reg/setglbl k,x
  6114. (make-mnemonic 'reg/setglbl))
  6115. (define $reg/op3 ; reg/op3 prim,k1,k2,k3
  6116. (make-mnemonic 'reg/op3))
  6117. (define $const/setreg ; const/setreg const,k
  6118. (make-mnemonic 'const/setreg))
  6119. (define $const/return ; const/return const
  6120. (make-mnemonic 'const/return))
  6121. (define $global/setreg ; global/setreg x,k
  6122. (make-mnemonic 'global/setreg))
  6123. (define $setrtn/branch ; setrtn/branch L,doc
  6124. (make-mnemonic 'setrtn/branch))
  6125. (define $setrtn/invoke ; setrtn/invoke L
  6126. (make-mnemonic 'setrtn/invoke))
  6127. (define $global/invoke ; global/invoke global,n
  6128. (make-mnemonic 'global/invoke))
  6129. ; misc
  6130. (define $cons 'cons)
  6131. (define $car:pair 'car)
  6132. (define $cdr:pair 'cdr)
  6133. ; eof
  6134. ; Target-specific representations.
  6135. ;
  6136. ; A few of these representation types must be specified for every target:
  6137. ; rep:object
  6138. ; rep:procedure
  6139. ; rep:true
  6140. ; rep:false
  6141. ; rep:bottom
  6142. (define-subtype 'true 'object) ; values that count as true
  6143. (define-subtype 'eqtype 'object) ; can use EQ? instead of EQV?
  6144. (define-subtype 'nonpointer 'eqtype) ; can omit write barrier
  6145. (define-subtype 'eqtype1 'eqtype) ; eqtypes excluding #f
  6146. (define-subtype 'boolean 'nonpointer)
  6147. (define-subtype 'truth 'eqtype1) ; { #t }
  6148. (define-subtype 'truth 'boolean)
  6149. (define-subtype 'false 'boolean) ; { #f }
  6150. (define-subtype 'eqtype1 'true)
  6151. (define-subtype 'procedure 'true)
  6152. (define-subtype 'vector 'true)
  6153. (define-subtype 'bytevector 'true)
  6154. (define-subtype 'string 'true)
  6155. (define-subtype 'pair 'true)
  6156. (define-subtype 'emptylist 'eqtype1)
  6157. (define-subtype 'emptylist 'nonpointer)
  6158. (define-subtype 'symbol 'eqtype1)
  6159. (define-subtype 'char 'eqtype1)
  6160. (define-subtype 'char 'nonpointer)
  6161. (define-subtype 'number 'true)
  6162. (define-subtype 'inexact 'number)
  6163. (define-subtype 'flonum 'inexact)
  6164. (define-subtype 'integer 'number)
  6165. (define-subtype 'exact 'number)
  6166. (define-subtype 'exactint 'integer)
  6167. (define-subtype 'exactint 'exact)
  6168. (define-subtype 'fixnum 'exactint)
  6169. (define-subtype '!fixnum 'fixnum) ; 0 <= n
  6170. (define-subtype 'fixnum! 'fixnum) ; n <= largest index
  6171. (define-subtype 'index '!fixnum)
  6172. (define-subtype 'index 'fixnum!)
  6173. (define-subtype 'zero 'index)
  6174. (define-subtype 'fixnum 'eqtype1)
  6175. (define-subtype 'fixnum 'nonpointer)
  6176. (compute-type-structure!)
  6177. ; If the intersection of rep1 and rep2 is known precisely,
  6178. ; but neither is a subtype of the other, then their intersection
  6179. ; should be declared explicitly.
  6180. ; Otherwise a conservative approximation will be used.
  6181. (define-intersection 'true 'eqtype 'eqtype1)
  6182. (define-intersection 'true 'boolean 'truth)
  6183. (define-intersection 'exact 'integer 'exactint)
  6184. (define-intersection '!fixnum 'fixnum! 'index)
  6185. ;(display-unions-and-intersections)
  6186. ; Parameters.
  6187. (define rep:min_fixnum (- (expt 2 29)))
  6188. (define rep:max_fixnum (- (expt 2 29) 1))
  6189. (define rep:max_index (- (expt 2 24) 1))
  6190. ; The representations we'll recognize for now.
  6191. (define rep:object (symbol->rep 'object))
  6192. (define rep:true (symbol->rep 'true))
  6193. (define rep:truth (symbol->rep 'truth))
  6194. (define rep:false (symbol->rep 'false))
  6195. (define rep:boolean (symbol->rep 'boolean))
  6196. (define rep:pair (symbol->rep 'pair))
  6197. (define rep:symbol (symbol->rep 'symbol))
  6198. (define rep:number (symbol->rep 'number))
  6199. (define rep:zero (symbol->rep 'zero))
  6200. (define rep:index (symbol->rep 'index))
  6201. (define rep:fixnum (symbol->rep 'fixnum))
  6202. (define rep:exactint (symbol->rep 'exactint))
  6203. (define rep:flonum (symbol->rep 'flonum))
  6204. (define rep:exact (symbol->rep 'exact))
  6205. (define rep:inexact (symbol->rep 'inexact))
  6206. (define rep:integer (symbol->rep 'integer))
  6207. ;(define rep:real (symbol->rep 'real))
  6208. (define rep:char (symbol->rep 'char))
  6209. (define rep:string (symbol->rep 'string))
  6210. (define rep:vector (symbol->rep 'vector))
  6211. (define rep:procedure (symbol->rep 'procedure))
  6212. (define rep:bottom (symbol->rep 'bottom))
  6213. ; Given the value of a quoted constant, return its representation.
  6214. (define (representation-of-value x)
  6215. (cond ((boolean? x)
  6216. (if x
  6217. rep:truth
  6218. rep:false))
  6219. ((pair? x)
  6220. rep:pair)
  6221. ((symbol? x)
  6222. rep:symbol)
  6223. ((number? x)
  6224. (cond ((and (exact? x)
  6225. (integer? x))
  6226. (cond ((zero? x)
  6227. rep:zero)
  6228. ((<= 0 x rep:max_index)
  6229. rep:index)
  6230. ((<= rep:min_fixnum
  6231. x
  6232. rep:max_fixnum)
  6233. rep:fixnum)
  6234. (else
  6235. rep:exactint)))
  6236. ((and (inexact? x)
  6237. (real? x))
  6238. rep:flonum)
  6239. (else
  6240. ; We're not tracking other numbers yet.
  6241. rep:number)))
  6242. ((char? x)
  6243. rep:char)
  6244. ((string? x)
  6245. rep:string)
  6246. ((vector? x)
  6247. rep:vector)
  6248. ; Everything counts as true except for #f.
  6249. (else
  6250. rep:true)))
  6251. ; Tables that express the representation-specific operations,
  6252. ; and the information about representations that are implied
  6253. ; by certain operations.
  6254. ; FIXME: Currently way incomplete, but good enough for testing.
  6255. (define rep-specific
  6256. (representation-table
  6257. ; When the procedure in the first column is called with
  6258. ; arguments described in the middle column, then the procedure
  6259. ; in the last column can be called instead.
  6260. '(
  6261. ;(+ (index index) +:idx:idx)
  6262. ;(+ (fixnum fixnum) +:fix:fix)
  6263. ;(- (index index) -:idx:idx)
  6264. ;(- (fixnum fixnum) -:fix:fix)
  6265. (= (fixnum fixnum) =:fix:fix)
  6266. (< (fixnum fixnum) <:fix:fix)
  6267. (<= (fixnum fixnum) <=:fix:fix)
  6268. (> (fixnum fixnum) >:fix:fix)
  6269. (>= (fixnum fixnum) >=:fix:fix)
  6270. ;(+ (flonum flonum) +:flo:flo)
  6271. ;(- (flonum flonum) -:flo:flo)
  6272. ;(= (flonum flonum) =:flo:flo)
  6273. ;(< (flonum flonum) <:flo:flo)
  6274. ;(<= (flonum flonum) <=:flo:flo)
  6275. ;(> (flonum flonum) >:flo:flo)
  6276. ;(>= (flonum flonum) >=:flo:flo)
  6277. ;(vector-set!:trusted (vector fixnum nonpointer) vector-set!:trusted:imm)
  6278. )))
  6279. (define rep-result
  6280. (representation-table
  6281. ; When the procedure in the first column is called with
  6282. ; arguments described in the middle column, then the result
  6283. ; is described by the last column.
  6284. '((fixnum? (fixnum) (truth))
  6285. (vector? (vector) (truth))
  6286. (<= (zero !fixnum) (truth))
  6287. (>= (!fixnum zero) (truth))
  6288. (<=:fix:fix (zero !fixnum) (truth))
  6289. (>=:fix:fix (!fixnum zero) (truth))
  6290. (+ (index index) (!fixnum))
  6291. (+ (fixnum fixnum) (exactint))
  6292. (- (index index) (fixnum!))
  6293. (- (fixnum fixnum) (exactint))
  6294. (+ (flonum flonum) (flonum))
  6295. (- (flonum flonum) (flonum))
  6296. ;(+:idx:idx (index index) (!fixnum))
  6297. ;(-:idx:idx (index index) (fixnum!))
  6298. ;(+:fix:fix (index index) (exactint))
  6299. ;(+:fix:fix (fixnum fixnum) (exactint))
  6300. ;(-:idx:idx (index index) (fixnum))
  6301. ;(-:fix:fix (fixnum fixnum) (exactint))
  6302. (make-vector (object object) (vector))
  6303. (vector-length:vec (vector) (index))
  6304. (cons (object object) (pair))
  6305. ; Is it really all that useful to know that the result
  6306. ; of these comparisons is a boolean?
  6307. (= (number number) (boolean))
  6308. (< (number number) (boolean))
  6309. (<= (number number) (boolean))
  6310. (> (number number) (boolean))
  6311. (>= (number number) (boolean))
  6312. (=:fix:fix (fixnum fixnum) (boolean))
  6313. (<:fix:fix (fixnum fixnum) (boolean))
  6314. (<=:fix:fix (fixnum fixnum) (boolean))
  6315. (>:fix:fix (fixnum fixnum) (boolean))
  6316. (>=:fix:fix (fixnum fixnum) (boolean))
  6317. )))
  6318. (define rep-informing
  6319. (representation-table
  6320. ; When the predicate in the first column is called in the test position
  6321. ; of a conditional expression, on arguments described by the second
  6322. ; column, then the arguments are described by the third column if the
  6323. ; predicate returns true, and by the fourth column if the predicate
  6324. ; returns false.
  6325. '(
  6326. (fixnum? (object) (fixnum) (object))
  6327. (flonum? (object) (flonum) (object))
  6328. (vector? (object) (vector) (object))
  6329. (pair? (object) (pair) (object))
  6330. (= (exactint index) (index index) (exactint index))
  6331. (= (index exactint) (index index) (index exactint))
  6332. (= (exactint !fixnum) (!fixnum !fixnum) (exactint !fixnum))
  6333. (= (!fixnum exactint) (!fixnum !fixnum) (!fixnum exactint))
  6334. (= (exactint fixnum!) (fixnum! fixnum!) (exactint fixnum!))
  6335. (= (fixnum! exactint) (fixnum! fixnum!) (fixnum! exactint))
  6336. (< (!fixnum fixnum!) (index index) (!fixnum fixnum!))
  6337. (< (fixnum fixnum!) (fixnum! fixnum!) (fixnum fixnum!))
  6338. (< (!fixnum fixnum) (!fixnum !fixnum) (!fixnum fixnum))
  6339. (< (fixnum! !fixnum) (fixnum! !fixnum) (index index))
  6340. (<= (!fixnum fixnum!) (index index) (!fixnum fixnum!))
  6341. (<= (fixnum! !fixnum) (fixnum! !fixnum) (index index))
  6342. (<= (fixnum fixnum!) (fixnum! fixnum!) (fixnum fixnum!))
  6343. (<= (!fixnum fixnum) (!fixnum !fixnum) (!fixnum fixnum))
  6344. (> (!fixnum fixnum!) (!fixnum fixnum!) (index index))
  6345. (> (fixnum! !fixnum) (index index) (fixnum! !fixnum))
  6346. (> (fixnum fixnum!) (fixnum fixnum!) (fixnum! fixnum!))
  6347. (> (!fixnum fixnum) (!fixnum fixnum) (!fixnum !fixnum))
  6348. (>= (!fixnum fixnum!) (!fixnum fixnum!) (index index))
  6349. (>= (fixnum! !fixnum) (index index) (fixnum! !fixnum))
  6350. (>= (fixnum fixnum!) (fixnum fixnum!) (fixnum! fixnum!))
  6351. (>= (!fixnum fixnum) (!fixnum fixnum) (!fixnum !fixnum))
  6352. (=:fix:fix (exactint index) (index index) (exactint index))
  6353. (=:fix:fix (index exactint) (index index) (index exactint))
  6354. (=:fix:fix (exactint !fixnum) (!fixnum !fixnum) (exactint !fixnum))
  6355. (=:fix:fix (!fixnum exactint) (!fixnum !fixnum) (!fixnum exactint))
  6356. (=:fix:fix (exactint fixnum!) (fixnum! fixnum!) (exactint fixnum!))
  6357. (=:fix:fix (fixnum! exactint) (fixnum! fixnum!) (fixnum! exactint))
  6358. (<:fix:fix (!fixnum fixnum!) (index index) (!fixnum fixnum!))
  6359. (<:fix:fix (fixnum! !fixnum) (fixnum! !fixnum) (index index))
  6360. (<:fix:fix (fixnum fixnum!) (fixnum! fixnum!) (fixnum fixnum!))
  6361. (<:fix:fix (!fixnum fixnum) (!fixnum !fixnum) (!fixnum fixnum))
  6362. (<=:fix:fix (!fixnum fixnum!) (index index) (!fixnum fixnum!))
  6363. (<=:fix:fix (fixnum! !fixnum) (fixnum! !fixnum) (index index))
  6364. (<=:fix:fix (fixnum fixnum!) (fixnum! fixnum!) (fixnum fixnum!))
  6365. (<=:fix:fix (!fixnum fixnum) (!fixnum !fixnum) (!fixnum fixnum))
  6366. (>:fix:fix (!fixnum fixnum!) (!fixnum fixnum!) (index index))
  6367. (>:fix:fix (fixnum! !fixnum) (index index) (fixnum! !fixnum))
  6368. (>:fix:fix (fixnum fixnum!) (fixnum fixnum!) (fixnum! fixnum!))
  6369. (>:fix:fix (!fixnum fixnum) (!fixnum fixnum) (!fixnum !fixnum))
  6370. (>=:fix:fix (!fixnum fixnum!) (!fixnum fixnum!) (index index))
  6371. (>=:fix:fix (fixnum! !fixnum) (index index) (fixnum! !fixnum))
  6372. (>=:fix:fix (fixnum fixnum!) (fixnum fixnum!) (fixnum! fixnum!))
  6373. (>=:fix:fix (!fixnum fixnum) (!fixnum fixnum) (!fixnum !fixnum))
  6374. )))
  6375. ; Copyright 1991 William D Clinger.
  6376. ;
  6377. ; Permission to copy this software, in whole or in part, to use this
  6378. ; software for any lawful noncommercial purpose, and to redistribute
  6379. ; this software is granted subject to the restriction that all copies
  6380. ; made of this software must include this copyright notice in full.
  6381. ;
  6382. ; I also request that you send me a copy of any improvements that you
  6383. ; make to this software so that they may be incorporated within it to
  6384. ; the benefit of the Scheme community.
  6385. ;
  6386. ; 25 April 1999.
  6387. ;
  6388. ; Second pass of the Twobit compiler:
  6389. ; single assignment analysis, local source transformations,
  6390. ; assignment elimination, and lambda lifting.
  6391. ; The code for assignment elimination and lambda lifting
  6392. ; are in a separate file.
  6393. ;
  6394. ; This pass operates as a source-to-source transformation on
  6395. ; expressions written in the subset of Scheme described by the
  6396. ; following grammar, where the input and output expressions
  6397. ; satisfy certain additional invariants described below.
  6398. ;
  6399. ; "X ..." means zero or more occurrences of X.
  6400. ;
  6401. ; L --> (lambda (I_1 ...)
  6402. ; (begin D ...)
  6403. ; (quote (R F G <decls> <doc>)
  6404. ; E)
  6405. ; | (lambda (I_1 ... . I_rest)
  6406. ; (begin D ...)
  6407. ; (quote (R F G <decls> <doc>))
  6408. ; E)
  6409. ; D --> (define I L)
  6410. ; E --> (quote K) ; constants
  6411. ; | (begin I) ; variable references
  6412. ; | L ; lambda expressions
  6413. ; | (E0 E1 ...) ; calls
  6414. ; | (set! I E) ; assignments
  6415. ; | (if E0 E1 E2) ; conditionals
  6416. ; | (begin E0 E1 E2 ...) ; sequential expressions
  6417. ; I --> <identifier>
  6418. ;
  6419. ; R --> ((I <references> <assignments> <calls>) ...)
  6420. ; F --> (I ...)
  6421. ; G --> (I ...)
  6422. ;
  6423. ; Invariants that hold for the input only:
  6424. ; * There are no internal definitions.
  6425. ; * No identifier containing an upper case letter is bound anywhere.
  6426. ; (Change the "name:..." variables if upper case is preferred.)
  6427. ; * No identifier is bound in more than one place.
  6428. ; * Each R contains one entry for every identifier bound in the
  6429. ; formal argument list and the internal definition list that
  6430. ; precede it. Each entry contains a list of pointers to all
  6431. ; references to the identifier, a list of pointers to all
  6432. ; assignments to the identifier, and a list of pointers to all
  6433. ; calls to the identifier.
  6434. ; * Except for constants, the expression does not share structure
  6435. ; with the original input or itself, except that the references
  6436. ; and assignments in R are guaranteed to share structure with
  6437. ; the expression. Thus the expression may be side effected, and
  6438. ; side effects to references or assignments obtained through R
  6439. ; are guaranteed to change the references or assignments pointed
  6440. ; to by R.
  6441. ;
  6442. ; Invariants that hold for the output only:
  6443. ; * There are no assignments except to global variables.
  6444. ; * If I is declared by an internal definition, then the right hand
  6445. ; side of the internal definition is a lambda expression and I
  6446. ; is referenced only in the procedure position of a call.
  6447. ; * Each R contains one entry for every identifier bound in the
  6448. ; formal argument list and the internal definition list that
  6449. ; precede it. Each entry contains a list of pointers to all
  6450. ; references to the identifier, a list of pointers to all
  6451. ; assignments to the identifier, and a list of pointers to all
  6452. ; calls to the identifier.
  6453. ; * For each lambda expression, the associated F is a list of all
  6454. ; the identifiers that occur free in the body of that lambda
  6455. ; expression, and possibly a few extra identifiers that were
  6456. ; once free but have been removed by optimization.
  6457. ; * For each lambda expression, the associated G is a subset of F
  6458. ; that contains every identifier that occurs free within some
  6459. ; inner lambda expression that escapes, and possibly a few that
  6460. ; don't. (Assignment-elimination does not calculate G exactly.)
  6461. ; * Variables named IGNORED are neither referenced nor assigned.
  6462. ; * Except for constants, the expression does not share structure
  6463. ; with the original input or itself, except that the references
  6464. ; and assignments in R are guaranteed to share structure with
  6465. ; the expression. Thus the expression may be side effected, and
  6466. ; side effects to references or assignments obtained through R
  6467. ; are guaranteed to change the references or assignments pointed
  6468. ; to by R.
  6469. (define (pass2 exp)
  6470. (simplify exp (make-notepad #f)))
  6471. ; Given an expression and a "notepad" data structure that conveys
  6472. ; inherited attributes, performs the appropriate optimizations and
  6473. ; destructively modifies the notepad to record various attributes
  6474. ; that it synthesizes while traversing the expression. In particular,
  6475. ; any nested lambda expressions and any variable references will be
  6476. ; noted in the notepad.
  6477. (define (simplify exp notepad)
  6478. (case (car exp)
  6479. ((quote) exp)
  6480. ((lambda) (simplify-lambda exp notepad))
  6481. ((set!) (simplify-assignment exp notepad))
  6482. ((if) (simplify-conditional exp notepad))
  6483. ((begin) (if (variable? exp)
  6484. (begin (notepad-var-add! notepad (variable.name exp))
  6485. exp)
  6486. (simplify-sequential exp notepad)))
  6487. (else (simplify-call exp notepad))))
  6488. ; Most optimization occurs here.
  6489. ; The right hand sides of internal definitions are simplified,
  6490. ; as is the body.
  6491. ; Internal definitions of enclosed lambda expressions may
  6492. ; then be lifted to this one.
  6493. ; Single assignment analysis creates internal definitions.
  6494. ; Single assignment elimination converts single assignments
  6495. ; to bindings where possible, and renames arguments whose value
  6496. ; is ignored.
  6497. ; Assignment elimination then replaces all remaining assigned
  6498. ; variables by heap-allocated cells.
  6499. (define (simplify-lambda exp notepad)
  6500. (notepad-lambda-add! notepad exp)
  6501. (let ((defs (lambda.defs exp))
  6502. (body (lambda.body exp))
  6503. (newnotepad (make-notepad exp)))
  6504. (for-each (lambda (def)
  6505. (simplify-lambda (def.rhs def) newnotepad))
  6506. defs)
  6507. (lambda.body-set! exp (simplify body newnotepad))
  6508. (lambda.F-set! exp (notepad-free-variables newnotepad))
  6509. (lambda.G-set! exp (notepad-captured-variables newnotepad))
  6510. (single-assignment-analysis exp newnotepad)
  6511. (let ((known-lambdas (notepad.nonescaping newnotepad)))
  6512. (for-each (lambda (L)
  6513. (if (memq L known-lambdas)
  6514. (lambda-lifting L exp)
  6515. (lambda-lifting L L)))
  6516. (notepad.lambdas newnotepad))))
  6517. (single-assignment-elimination exp notepad)
  6518. (assignment-elimination exp)
  6519. (if (not (notepad.parent notepad))
  6520. ; This is an outermost lambda expression.
  6521. (lambda-lifting exp exp))
  6522. exp)
  6523. ; SIMPLIFY-ASSIGNMENT performs this transformation:
  6524. ;
  6525. ; (set! I (begin ... E))
  6526. ; -> (begin ... (set! I E))
  6527. (define (simplify-assignment exp notepad)
  6528. (notepad-var-add! notepad (assignment.lhs exp))
  6529. (let ((rhs (simplify (assignment.rhs exp) notepad)))
  6530. (cond ((begin? rhs)
  6531. (let ((exprs (reverse (begin.exprs rhs))))
  6532. (assignment.rhs-set! exp (car exprs))
  6533. (post-simplify-begin
  6534. (make-begin (reverse (cons exp (cdr exprs))))
  6535. notepad)))
  6536. (else (assignment.rhs-set! exp rhs) exp))))
  6537. (define (simplify-sequential exp notepad)
  6538. (let ((exprs (map (lambda (exp) (simplify exp notepad))
  6539. (begin.exprs exp))))
  6540. (begin.exprs-set! exp exprs)
  6541. (post-simplify-begin exp notepad)))
  6542. ; Given (BEGIN E0 E1 E2 ...) where the E_i are simplified expressions,
  6543. ; flattens any nested BEGINs and removes trivial expressions that
  6544. ; don't appear in the last position. The second argument is used only
  6545. ; if a lambda expression is removed.
  6546. ; This procedure is careful to return E instead of (BEGIN E).
  6547. ; Fairly harmless bug: a variable reference removed by this procedure
  6548. ; may remain on the notepad when it shouldn't.
  6549. (define (post-simplify-begin exp notepad)
  6550. (let ((unspecified-expression (make-unspecified)))
  6551. ; (flatten exprs '()) returns the flattened exprs in reverse order.
  6552. (define (flatten exprs flattened)
  6553. (cond ((null? exprs) flattened)
  6554. ((begin? (car exprs))
  6555. (flatten (cdr exprs)
  6556. (flatten (begin.exprs (car exprs)) flattened)))
  6557. (else (flatten (cdr exprs) (cons (car exprs) flattened)))))
  6558. (define (filter exprs filtered)
  6559. (if (null? exprs)
  6560. filtered
  6561. (let ((exp (car exprs)))
  6562. (cond ((constant? exp) (filter (cdr exprs) filtered))
  6563. ((variable? exp) (filter (cdr exprs) filtered))
  6564. ((lambda? exp)
  6565. (notepad.lambdas-set!
  6566. notepad
  6567. (remq exp (notepad.lambdas notepad)))
  6568. (filter (cdr exprs) filtered))
  6569. ((equal? exp unspecified-expression)
  6570. (filter (cdr exprs) filtered))
  6571. (else (filter (cdr exprs) (cons exp filtered)))))))
  6572. (let ((exprs (flatten (begin.exprs exp) '())))
  6573. (begin.exprs-set! exp (filter (cdr exprs) (list (car exprs))))
  6574. (if (null? (cdr (begin.exprs exp)))
  6575. (car (begin.exprs exp))
  6576. exp))))
  6577. ; SIMPLIFY-CALL performs this transformation:
  6578. ;
  6579. ; (... (begin ... E) ...)
  6580. ; -> (begin ... (... E ...))
  6581. ;
  6582. ; It also takes care of LET transformations.
  6583. (define (simplify-call exp notepad)
  6584. (define (loop args newargs exprs)
  6585. (cond ((null? args)
  6586. (finish newargs exprs))
  6587. ((begin? (car args))
  6588. (let ((newexprs (reverse (begin.exprs (car args)))))
  6589. (loop (cdr args)
  6590. (cons (car newexprs) newargs)
  6591. (append (cdr newexprs) exprs))))
  6592. (else (loop (cdr args) (cons (car args) newargs) exprs))))
  6593. (define (finish newargs exprs)
  6594. (call.args-set! exp (reverse newargs))
  6595. (let* ((newexp
  6596. (if (lambda? (call.proc exp))
  6597. (simplify-let exp notepad)
  6598. (begin
  6599. (call.proc-set! exp
  6600. (simplify (call.proc exp) notepad))
  6601. exp)))
  6602. (newexp
  6603. (if (and (call? newexp)
  6604. (variable? (call.proc newexp)))
  6605. (let* ((procname (variable.name (call.proc newexp)))
  6606. (args (call.args newexp))
  6607. (entry
  6608. (and (not (null? args))
  6609. (constant? (car args))
  6610. (integrate-usual-procedures)
  6611. (every? constant? args)
  6612. (let ((entry (constant-folding-entry procname)))
  6613. (and entry
  6614. (let ((predicates
  6615. (constant-folding-predicates entry)))
  6616. (and (= (length args)
  6617. (length predicates))
  6618. (let loop ((args args)
  6619. (predicates predicates))
  6620. (cond ((null? args) entry)
  6621. (((car predicates)
  6622. (constant.value
  6623. (car args)))
  6624. (loop (cdr args)
  6625. (cdr predicates)))
  6626. (else #f))))))))))
  6627. (if entry
  6628. (make-constant (apply (constant-folding-folder entry)
  6629. (map constant.value args)))
  6630. newexp))
  6631. newexp)))
  6632. (cond ((and (call? newexp)
  6633. (begin? (call.proc newexp)))
  6634. (let ((exprs0 (reverse (begin.exprs (call.proc newexp)))))
  6635. (call.proc-set! newexp (car exprs0))
  6636. (post-simplify-begin
  6637. (make-begin (reverse
  6638. (cons newexp
  6639. (append (cdr exprs0) exprs))))
  6640. notepad)))
  6641. ((null? exprs)
  6642. newexp)
  6643. (else
  6644. (post-simplify-begin
  6645. (make-begin (reverse (cons newexp exprs)))
  6646. notepad)))))
  6647. (call.args-set! exp (map (lambda (arg) (simplify arg notepad))
  6648. (call.args exp)))
  6649. (loop (call.args exp) '() '()))
  6650. ; SIMPLIFY-LET performs these transformations:
  6651. ;
  6652. ; ((lambda (I_1 ... I_k . I_rest) ---) E1 ... Ek Ek+1 ...)
  6653. ; -> ((lambda (I_1 ... I_k I_rest) ---) E1 ... Ek (LIST Ek+1 ...))
  6654. ;
  6655. ; ((lambda (I1 I2 ...) (begin D ...) (quote ...) E) L ...)
  6656. ; -> ((lambda (I2 ...) (begin (define I1 L) D ...) (quote ...) E) ...)
  6657. ;
  6658. ; provided I1 is not assigned and each reference to I1 is in call position.
  6659. ;
  6660. ; ((lambda (I1)
  6661. ; (begin)
  6662. ; (quote ((I1 ((begin I1)) () ())))
  6663. ; (begin I1))
  6664. ; E1)
  6665. ;
  6666. ; -> E1
  6667. ;
  6668. ; ((lambda (I1)
  6669. ; (begin)
  6670. ; (quote ((I1 ((begin I1)) () ())))
  6671. ; (if (begin I1) E2 E3))
  6672. ; E1)
  6673. ;
  6674. ; -> (if E1 E2 E3)
  6675. ;
  6676. ; (Together with SIMPLIFY-CONDITIONAL, this cleans up the output of the OR
  6677. ; macro and enables certain control optimizations.)
  6678. ;
  6679. ; ((lambda (I1 I2 ...)
  6680. ; (begin D ...)
  6681. ; (quote (... (I <references> () <calls>) ...) ...)
  6682. ; E)
  6683. ; K ...)
  6684. ; -> ((lambda (I2 ...)
  6685. ; (begin D' ...)
  6686. ; (quote (... ...) ...)
  6687. ; E')
  6688. ; ...)
  6689. ;
  6690. ; where D' ... and E' ... are obtained from D ... and E ...
  6691. ; by replacing all references to I1 by K. This transformation
  6692. ; applies if K is a constant that can be duplicated without changing
  6693. ; its EQV? behavior.
  6694. ;
  6695. ; ((lambda () (begin) (quote ...) E)) -> E
  6696. ;
  6697. ; ((lambda (IGNORED I2 ...) ---) E1 E2 ...)
  6698. ; -> (begin E1 ((lambda (I2 ...) ---) E2 ...))
  6699. ;
  6700. ; (Single assignment analysis, performed by the simplifier for lambda
  6701. ; expressions, detects unused arguments and replaces them in the argument
  6702. ; list by the special identifier IGNORED.)
  6703. (define (simplify-let exp notepad)
  6704. (define proc (call.proc exp))
  6705. ; Loop1 operates before simplification of the lambda body.
  6706. (define (loop1 formals actuals processed-formals processed-actuals)
  6707. (cond ((null? formals)
  6708. (if (not (null? actuals))
  6709. (pass2-error p2error:wna exp))
  6710. (return1 processed-formals processed-actuals))
  6711. ((symbol? formals)
  6712. (return1 (cons formals processed-formals)
  6713. (cons (make-call-to-LIST actuals) processed-actuals)))
  6714. ((null? actuals)
  6715. (pass2-error p2error:wna exp)
  6716. (return1 processed-formals
  6717. processed-actuals))
  6718. ((and (lambda? (car actuals))
  6719. (let ((Rinfo (R-lookup (lambda.R proc) (car formals))))
  6720. (and (null? (R-entry.assignments Rinfo))
  6721. (= (length (R-entry.references Rinfo))
  6722. (length (R-entry.calls Rinfo))))))
  6723. (let ((I (car formals))
  6724. (L (car actuals)))
  6725. (notepad-nonescaping-add! notepad L)
  6726. (lambda.defs-set! proc
  6727. (cons (make-definition I L)
  6728. (lambda.defs proc)))
  6729. (standardize-known-calls L
  6730. (R-entry.calls
  6731. (R-lookup (lambda.R proc) I)))
  6732. (lambda.F-set! proc (union (lambda.F proc)
  6733. (free-variables L)))
  6734. (lambda.G-set! proc (union (lambda.G proc) (lambda.G L))))
  6735. (loop1 (cdr formals)
  6736. (cdr actuals)
  6737. processed-formals
  6738. processed-actuals))
  6739. ((and (constant? (car actuals))
  6740. (let ((x (constant.value (car actuals))))
  6741. (or (boolean? x)
  6742. (number? x)
  6743. (symbol? x)
  6744. (char? x))))
  6745. (let* ((I (car formals))
  6746. (Rinfo (R-lookup (lambda.R proc) I)))
  6747. (if (null? (R-entry.assignments Rinfo))
  6748. (begin
  6749. (for-each (lambda (ref)
  6750. (variable-set! ref (car actuals)))
  6751. (R-entry.references Rinfo))
  6752. (lambda.R-set! proc (remq Rinfo (lambda.R proc)))
  6753. (lambda.F-set! proc (remq I (lambda.F proc)))
  6754. (lambda.G-set! proc (remq I (lambda.G proc)))
  6755. (loop1 (cdr formals)
  6756. (cdr actuals)
  6757. processed-formals
  6758. processed-actuals))
  6759. (loop1 (cdr formals)
  6760. (cdr actuals)
  6761. (cons (car formals) processed-formals)
  6762. (cons (car actuals) processed-actuals)))))
  6763. (else (if (null? actuals)
  6764. (pass2-error p2error:wna exp))
  6765. (loop1 (cdr formals)
  6766. (cdr actuals)
  6767. (cons (car formals) processed-formals)
  6768. (cons (car actuals) processed-actuals)))))
  6769. (define (return1 rev-formals rev-actuals)
  6770. (let ((formals (reverse rev-formals))
  6771. (actuals (reverse rev-actuals)))
  6772. (lambda.args-set! proc formals)
  6773. (if (and (not (null? formals))
  6774. (null? (cdr formals))
  6775. (let* ((x (car formals))
  6776. (R (lambda.R proc))
  6777. (refs (references R x)))
  6778. (and (= 1 (length refs))
  6779. (null? (assignments R x)))))
  6780. (let ((x (car formals))
  6781. (body (lambda.body proc)))
  6782. (cond ((and (variable? body)
  6783. (eq? x (variable.name body)))
  6784. (simplify (car actuals) notepad))
  6785. ((and (conditional? body)
  6786. (let ((B0 (if.test body)))
  6787. (variable? B0)
  6788. (eq? x (variable.name B0))))
  6789. (if.test-set! body (car actuals))
  6790. (simplify body notepad))
  6791. (else
  6792. (return1-finish formals actuals))))
  6793. (return1-finish formals actuals))))
  6794. (define (return1-finish formals actuals)
  6795. (simplify-lambda proc notepad)
  6796. (loop2 formals actuals '() '() '()))
  6797. ; Loop2 operates after simplification of the lambda body.
  6798. (define (loop2 formals actuals processed-formals processed-actuals for-effect)
  6799. (cond ((null? formals)
  6800. (return2 processed-formals processed-actuals for-effect))
  6801. ((ignored? (car formals))
  6802. (loop2 (cdr formals)
  6803. (cdr actuals)
  6804. processed-formals
  6805. processed-actuals
  6806. (cons (car actuals) for-effect)))
  6807. (else (loop2 (cdr formals)
  6808. (cdr actuals)
  6809. (cons (car formals) processed-formals)
  6810. (cons (car actuals) processed-actuals)
  6811. for-effect))))
  6812. (define (return2 rev-formals rev-actuals rev-for-effect)
  6813. (let ((formals (reverse rev-formals))
  6814. (actuals (reverse rev-actuals))
  6815. (for-effect (reverse rev-for-effect)))
  6816. (lambda.args-set! proc formals)
  6817. (call.args-set! exp actuals)
  6818. (let ((exp (if (and (null? actuals)
  6819. (or (null? (lambda.defs proc))
  6820. (and (notepad.parent notepad)
  6821. (POLICY:LIFT? proc
  6822. (notepad.parent notepad)
  6823. (map (lambda (def) '())
  6824. (lambda.defs proc))))))
  6825. (begin (for-each (lambda (I)
  6826. (notepad-var-add! notepad I))
  6827. (lambda.F proc))
  6828. (if (not (null? (lambda.defs proc)))
  6829. (let ((parent (notepad.parent notepad))
  6830. (defs (lambda.defs proc))
  6831. (R (lambda.R proc)))
  6832. (lambda.defs-set!
  6833. parent
  6834. (append defs (lambda.defs parent)))
  6835. (lambda.defs-set! proc '())
  6836. (lambda.R-set!
  6837. parent
  6838. (append (map (lambda (def)
  6839. (R-lookup R (def.lhs def)))
  6840. defs)
  6841. (lambda.R parent)))))
  6842. (lambda.body proc))
  6843. exp)))
  6844. (if (null? for-effect)
  6845. exp
  6846. (post-simplify-begin (make-begin (append for-effect (list exp)))
  6847. notepad)))))
  6848. (notepad-nonescaping-add! notepad proc)
  6849. (loop1 (lambda.args proc) (call.args exp) '() '()))
  6850. ; Single assignment analysis performs the transformation
  6851. ;
  6852. ; (lambda (... I ...)
  6853. ; (begin D ...)
  6854. ; (quote (... (I <references> ((set! I L)) <calls>) ...) ...)
  6855. ; (begin (set! I L) E1 ...))
  6856. ; -> (lambda (... IGNORED ...)
  6857. ; (begin (define I L) D ...)
  6858. ; (quote (... (I <references> () <calls>) ...) ...)
  6859. ; (begin E1 ...))
  6860. ;
  6861. ; For best results, pass 1 should sort internal definitions and LETRECs so
  6862. ; that procedure definitions/bindings come first.
  6863. ;
  6864. ; This procedure operates by side effect.
  6865. (define (single-assignment-analysis L notepad)
  6866. (let ((formals (lambda.args L))
  6867. (defs (lambda.defs L))
  6868. (R (lambda.R L))
  6869. (body (lambda.body L)))
  6870. (define (finish! exprs escapees)
  6871. (begin.exprs-set! body
  6872. (append (reverse escapees)
  6873. exprs))
  6874. (lambda.body-set! L (post-simplify-begin body '())))
  6875. (if (begin? body)
  6876. (let loop ((exprs (begin.exprs body))
  6877. (escapees '()))
  6878. (let ((first (car exprs)))
  6879. (if (and (assignment? first)
  6880. (not (null? (cdr exprs))))
  6881. (let ((I (assignment.lhs first))
  6882. (rhs (assignment.rhs first)))
  6883. (if (and (lambda? rhs)
  6884. (local? R I)
  6885. (= 1 (length (assignments R I))))
  6886. (if (= (length (calls R I))
  6887. (length (references R I)))
  6888. (begin (notepad-nonescaping-add! notepad rhs)
  6889. (flag-as-ignored I L)
  6890. (lambda.defs-set! L
  6891. (cons (make-definition I rhs)
  6892. (lambda.defs L)))
  6893. (assignments-set! R I '())
  6894. (standardize-known-calls
  6895. rhs
  6896. (R-entry.calls (R-lookup R I)))
  6897. (loop (cdr exprs) escapees))
  6898. (loop (cdr exprs)
  6899. (cons (car exprs) escapees)))
  6900. (finish! exprs escapees)))
  6901. (finish! exprs escapees)))))))
  6902. (define (standardize-known-calls L calls)
  6903. (let ((formals (lambda.args L)))
  6904. (cond ((not (list? formals))
  6905. (let* ((newformals (make-null-terminated formals))
  6906. (n (- (length newformals) 1)))
  6907. (lambda.args-set! L newformals)
  6908. (for-each (lambda (call)
  6909. (if (>= (length (call.args call)) n)
  6910. (call.args-set!
  6911. call
  6912. (append (list-head (call.args call) n)
  6913. (list
  6914. (make-call-to-LIST
  6915. (list-tail (call.args call) n)))))
  6916. (pass2-error p2error:wna call)))
  6917. calls)))
  6918. (else (let ((n (length formals)))
  6919. (for-each (lambda (call)
  6920. (if (not (= (length (call.args call)) n))
  6921. (pass2-error p2error:wna call)))
  6922. calls))))))
  6923. ; Copyright 1991 William D Clinger.
  6924. ;
  6925. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  6926. ;
  6927. ; 13 November 1998
  6928. ;
  6929. ; Second pass of the Twobit compiler, part 2:
  6930. ; single assignment elimination, assignment elimination,
  6931. ; and lambda lifting.
  6932. ;
  6933. ; See part 1 for further documentation.
  6934. ; Single assignment elimination performs the transformation
  6935. ;
  6936. ; (lambda (... I1 ... In ...)
  6937. ; (begin D ...)
  6938. ; (begin (set! I1 E1)
  6939. ; ...
  6940. ; (set! In En)
  6941. ; E ...))
  6942. ; -> (lambda (... IGNORED ... IGNORED ...)
  6943. ; (let* ((I1 E1) ... (In En))
  6944. ; (begin D ...)
  6945. ; (begin E ...)))
  6946. ;
  6947. ; provided for each k:
  6948. ;
  6949. ; 1. Ik does not occur in E1, ..., Ek.
  6950. ; 2. Either E1 through Ek contain no procedure calls
  6951. ; or Ik is not referenced by an escaping lambda expression.
  6952. ; 3. Ik is assigned only once.
  6953. ;
  6954. ; I doubt whether the third condition is really necessary, but
  6955. ; dropping it would involve a more complex calculation of the
  6956. ; revised referencing information.
  6957. ;
  6958. ; A more precise description of the transformation:
  6959. ;
  6960. ; (lambda (... I1 ... In ...)
  6961. ; (begin (define F1 L1) ...)
  6962. ; (quote (... (I1 <references> ((set! I1 E1)) <calls>) ...
  6963. ; (In <references> ((set! In En)) <calls>)
  6964. ; (F1 <references> () <calls>) ...) ...)
  6965. ; (begin (set! I1 E1) ... (set! In En) E ...))
  6966. ; -> (lambda (... IGNORED ... IGNORED ...)
  6967. ; (begin)
  6968. ; (quote (...) ...)
  6969. ; ((lambda (I1)
  6970. ; (begin)
  6971. ; (quote ((I1 <references> () <calls>)) ...)
  6972. ; ...
  6973. ; ((lambda (In)
  6974. ; (begin (define F1 L1) ...)
  6975. ; (quote (... (In <references> () <calls>)
  6976. ; (F1 <references> () <calls>) ...) ...)
  6977. ; (begin E ...))
  6978. ; En)
  6979. ; ...)
  6980. ; E1))
  6981. ;
  6982. ; For best results, pass 1 should sort internal definitions and LETRECs
  6983. ; so that procedure definitions/bindings come first, followed by
  6984. ; definitions/bindings whose right hand side contains no calls,
  6985. ; followed by definitions/bindings of variables that do not escape,
  6986. ; followed by all other definitions/bindings.
  6987. ;
  6988. ; Pass 1 can't tell which variables escape, however. Pass 2 can't tell
  6989. ; which variables escape either until all enclosed lambda expressions
  6990. ; have been simplified and the first transformation above has been
  6991. ; performed. That is why single assignment analysis precedes single
  6992. ; assignment elimination. As implemented here, an assignment that does
  6993. ; not satisfy the conditions above will prevent the transformation from
  6994. ; being applied to any subsequent assignments.
  6995. ;
  6996. ; This procedure operates by side effect.
  6997. (define (single-assignment-elimination L notepad)
  6998. (if (begin? (lambda.body L))
  6999. (let* ((formals (make-null-terminated (lambda.args L)))
  7000. (defined (map def.lhs (lambda.defs L)))
  7001. (escaping (intersection formals
  7002. (notepad-captured-variables notepad)))
  7003. (R (lambda.R L)))
  7004. ; Given:
  7005. ; exprs that remain in the body;
  7006. ; assigns that will be replaced by let* variables;
  7007. ; call-has-occurred?, a boolean;
  7008. ; free variables of the assigns;
  7009. ; Performs the transformation described above.
  7010. (define (loop exprs assigns call-has-occurred? free)
  7011. (cond ((null? (cdr exprs))
  7012. (return exprs assigns))
  7013. ((assignment? (car exprs))
  7014. (let ((I1 (assignment.lhs (car exprs)))
  7015. (E1 (assignment.rhs (car exprs))))
  7016. (if (and (memq I1 formals)
  7017. (= (length (assignments R I1)) 1)
  7018. (not (and call-has-occurred?
  7019. (memq I1 escaping))))
  7020. (let* ((free-in-E1 (free-variables E1))
  7021. (newfree (union free-in-E1 free)))
  7022. (if (or (memq I1 newfree)
  7023. (not
  7024. (empty-set?
  7025. (intersection free-in-E1 defined))))
  7026. (return exprs assigns)
  7027. (loop (cdr exprs)
  7028. (cons (car exprs) assigns)
  7029. (or call-has-occurred?
  7030. (might-return-twice? E1))
  7031. newfree)))
  7032. (return exprs assigns))))
  7033. (else (return exprs assigns))))
  7034. (define (return exprs assigns)
  7035. (if (not (null? assigns))
  7036. (let ((I (assignment.lhs (car assigns)))
  7037. (E (assignment.rhs (car assigns)))
  7038. (defs (lambda.defs L))
  7039. (F (lambda.F L))
  7040. (G (lambda.G L)))
  7041. (flag-as-ignored I L)
  7042. (assignments-set! R I '())
  7043. (let ((L2 (make-lambda (list I)
  7044. defs
  7045. (cons (R-entry R I)
  7046. (map (lambda (def)
  7047. (R-entry R (def.lhs def)))
  7048. defs))
  7049. F
  7050. G
  7051. (lambda.decls L)
  7052. (lambda.doc L)
  7053. (make-begin exprs))))
  7054. (lambda.defs-set! L '())
  7055. (for-each (lambda (entry)
  7056. (lambda.R-set! L (remq entry R)))
  7057. (lambda.R L2))
  7058. (return-loop (cdr assigns) (make-call L2 (list E)))))))
  7059. (define (return-loop assigns body)
  7060. (if (null? assigns)
  7061. (let ((L3 (call.proc body)))
  7062. (lambda.body-set! L body)
  7063. (lambda-lifting L3 L))
  7064. (let* ((I (assignment.lhs (car assigns)))
  7065. (E (assignment.rhs (car assigns)))
  7066. (L3 (call.proc body))
  7067. (F (remq I (lambda.F L3)))
  7068. (G (remq I (lambda.G L3))))
  7069. (flag-as-ignored I L)
  7070. (assignments-set! R I '())
  7071. (let ((L2 (make-lambda (list I)
  7072. '()
  7073. (list (R-entry R I))
  7074. F
  7075. G
  7076. (lambda.decls L)
  7077. (lambda.doc L)
  7078. body)))
  7079. (lambda.R-set! L (remq (R-entry R I) R))
  7080. (lambda-lifting L3 L2)
  7081. (return-loop (cdr assigns) (make-call L2 (list E)))))))
  7082. (loop (begin.exprs (lambda.body L)) '() #f '())))
  7083. L)
  7084. ; Temporary definitions.
  7085. (define (free-variables exp)
  7086. (case (car exp)
  7087. ((quote) '())
  7088. ((lambda) (difference (lambda.F exp)
  7089. (make-null-terminated (lambda.args exp))))
  7090. ((set!) (union (list (assignment.lhs exp))
  7091. (free-variables (assignment.rhs exp))))
  7092. ((if) (union (free-variables (if.test exp))
  7093. (free-variables (if.then exp))
  7094. (free-variables (if.else exp))))
  7095. ((begin) (if (variable? exp)
  7096. (list (variable.name exp))
  7097. (apply union (map free-variables (begin.exprs exp)))))
  7098. (else (apply union (map free-variables exp)))))
  7099. (define (might-return-twice? exp)
  7100. (case (car exp)
  7101. ((quote) #f)
  7102. ((lambda) #f)
  7103. ((set!) (might-return-twice? (assignment.rhs exp)))
  7104. ((if) (or (might-return-twice? (if.test exp))
  7105. (might-return-twice? (if.then exp))
  7106. (might-return-twice? (if.else exp))))
  7107. ((begin) (if (variable? exp)
  7108. #f
  7109. (some? might-return-twice? (begin.exprs exp))))
  7110. (else #t)))
  7111. ; Assignment elimination replaces variables that appear on the left
  7112. ; hand side of an assignment by data structures. This is necessary
  7113. ; to avoid some nasty complications with lambda lifting.
  7114. ;
  7115. ; This procedure operates by side effect.
  7116. (define (assignment-elimination L)
  7117. (let ((R (lambda.R L)))
  7118. ; Given a list of entries, return those for assigned variables.
  7119. (define (loop entries assigned)
  7120. (cond ((null? entries)
  7121. (if (not (null? assigned))
  7122. (eliminate assigned)))
  7123. ((not (null? (R-entry.assignments (car entries))))
  7124. (loop (cdr entries) (cons (car entries) assigned)))
  7125. ((null? (R-entry.references (car entries)))
  7126. (flag-as-ignored (R-entry.name (car entries)) L)
  7127. (loop (cdr entries) assigned))
  7128. (else (loop (cdr entries) assigned))))
  7129. ; Given a list of entries for assigned variables I1 ...,
  7130. ; remove the assignments by replacing the body by a LET of the form
  7131. ; ((LAMBDA (V1 ...) ...) (MAKE-CELL I1) ...), by replacing references
  7132. ; by calls to CELL-REF, and by replacing assignments by calls to
  7133. ; CELL-SET!.
  7134. (define (eliminate assigned)
  7135. (let* ((oldnames (map R-entry.name assigned))
  7136. (newnames (map generate-new-name oldnames)))
  7137. (let ((augmented-entries (map list newnames assigned))
  7138. (renaming-alist (map cons oldnames newnames))
  7139. (defs (lambda.defs L)))
  7140. (for-each cellify! augmented-entries)
  7141. (for-each (lambda (def)
  7142. (do ((free (lambda.F (def.rhs def)) (cdr free)))
  7143. ((null? free))
  7144. (let ((z (assq (car free) renaming-alist)))
  7145. (if z
  7146. (set-car! free (cdr z))))))
  7147. defs)
  7148. (let ((newbody
  7149. (make-call
  7150. (make-lambda (map car augmented-entries)
  7151. defs
  7152. (union (map (lambda (def)
  7153. (R-entry R (def.lhs def)))
  7154. defs)
  7155. (map new-reference-info augmented-entries))
  7156. (union (list name:CELL-REF name:CELL-SET!)
  7157. newnames
  7158. (difference (lambda.F L) oldnames))
  7159. (union (list name:CELL-REF name:CELL-SET!)
  7160. newnames
  7161. (difference (lambda.G L) oldnames))
  7162. (lambda.decls L)
  7163. (lambda.doc L)
  7164. (lambda.body L))
  7165. (map (lambda (name)
  7166. (make-call (make-variable name:MAKE-CELL)
  7167. (list (make-variable name))))
  7168. (map R-entry.name assigned)))))
  7169. (lambda.F-set! L (union (list name:MAKE-CELL name:CELL-REF name:CELL-SET!)
  7170. (difference (lambda.F L)
  7171. (map def.lhs (lambda.defs L)))))
  7172. (lambda.defs-set! L '())
  7173. (for-each update-old-reference-info!
  7174. (map (lambda (arg)
  7175. (car (call.args arg)))
  7176. (call.args newbody)))
  7177. (lambda.body-set! L newbody)
  7178. (lambda-lifting (call.proc newbody) L)))))
  7179. (define (generate-new-name name)
  7180. (string->symbol (string-append cell-prefix (symbol->string name))))
  7181. ; In addition to replacing references and assignments involving the
  7182. ; old variable by calls to CELL-REF and CELL-SET! on the new, CELLIFY!
  7183. ; uses the old entry to collect the referencing information for the
  7184. ; new variable.
  7185. (define (cellify! augmented-entry)
  7186. (let ((newname (car augmented-entry))
  7187. (entry (cadr augmented-entry)))
  7188. (do ((refs (R-entry.references entry)
  7189. (cdr refs)))
  7190. ((null? refs))
  7191. (let* ((reference (car refs))
  7192. (newref (make-variable newname)))
  7193. (set-car! reference (make-variable name:CELL-REF))
  7194. (set-car! (cdr reference) newref)
  7195. (set-car! refs newref)))
  7196. (do ((assigns (R-entry.assignments entry)
  7197. (cdr assigns)))
  7198. ((null? assigns))
  7199. (let* ((assignment (car assigns))
  7200. (newref (make-variable newname)))
  7201. (set-car! assignment (make-variable name:CELL-SET!))
  7202. (set-car! (cdr assignment) newref)
  7203. (R-entry.references-set! entry
  7204. (cons newref
  7205. (R-entry.references entry)))))
  7206. (R-entry.assignments-set! entry '())))
  7207. ; This procedure creates a brand new entry for a new variable, extracting
  7208. ; the references stored in the old entry by CELLIFY!.
  7209. (define (new-reference-info augmented-entry)
  7210. (make-R-entry (car augmented-entry)
  7211. (R-entry.references (cadr augmented-entry))
  7212. '()
  7213. '()))
  7214. ; This procedure updates the old entry to reflect the fact that it is
  7215. ; now referenced once and never assigned.
  7216. (define (update-old-reference-info! ref)
  7217. (references-set! R (variable.name ref) (list ref))
  7218. (assignments-set! R (variable.name ref) '())
  7219. (calls-set! R (variable.name ref) '()))
  7220. (loop R '())))
  7221. ; Lambda lifting raises internal definitions to outer scopes to avoid
  7222. ; having to choose between creating a closure or losing tail recursion.
  7223. ; If L is not #f, then L2 is a lambda expression nested within L.
  7224. ; Any internal definitions that occur within L2 may be lifted to L
  7225. ; by adding extra arguments to the defined procedure and to all calls to it.
  7226. ; Lambda lifting is not a clear win, because the extra arguments could
  7227. ; easily become more expensive than creating a closure and referring
  7228. ; to the non-local arguments through the closure. The heuristics used
  7229. ; to decide whether to lift a group of internal definitions are isolated
  7230. ; within the POLICY:LIFT? procedure.
  7231. ; L2 can be the same as L, so the order of side effects is critical.
  7232. (define (lambda-lifting L2 L)
  7233. ; The call to sort is optional. It gets the added arguments into
  7234. ; the same order they appear in the formals list, which is an
  7235. ; advantage for register targeting.
  7236. (define (lift L2 L args-to-add)
  7237. (let ((formals (make-null-terminated (lambda.args L2))))
  7238. (do ((defs (lambda.defs L2) (cdr defs))
  7239. (args-to-add args-to-add (cdr args-to-add)))
  7240. ((null? defs))
  7241. (let* ((def (car defs))
  7242. (entry (R-lookup (lambda.R L2) (def.lhs def)))
  7243. (calls (R-entry.calls entry))
  7244. (added (twobit-sort (lambda (x y)
  7245. (let ((xx (memq x formals))
  7246. (yy (memq y formals)))
  7247. (if (and xx yy)
  7248. (> (length xx) (length yy))
  7249. #t)))
  7250. (car args-to-add)))
  7251. (L3 (def.rhs def)))
  7252. ; The flow equation guarantees that these added arguments
  7253. ; will occur free by the time this round of lifting is done.
  7254. (lambda.F-set! L3 (union added (lambda.F L3)))
  7255. (lambda.args-set! L3 (append added (lambda.args L3)))
  7256. (for-each (lambda (call)
  7257. (let ((newargs (map make-variable added)))
  7258. ; The referencing information is made obsolete here!
  7259. (call.args-set! call
  7260. (append newargs (call.args call)))))
  7261. calls)
  7262. (lambda.R-set! L2 (remq entry (lambda.R L2)))
  7263. (lambda.R-set! L (cons entry (lambda.R L)))
  7264. ))
  7265. (if (not (eq? L2 L))
  7266. (begin
  7267. (lambda.defs-set! L (append (lambda.defs L2) (lambda.defs L)))
  7268. (lambda.defs-set! L2 '())))))
  7269. (if L
  7270. (if (not (null? (lambda.defs L2)))
  7271. (let ((args-to-add (compute-added-arguments
  7272. (lambda.defs L2)
  7273. (make-null-terminated (lambda.args L2)))))
  7274. (if (POLICY:LIFT? L2 L args-to-add)
  7275. (lift L2 L args-to-add))))))
  7276. ; Given a list of definitions ((define f1 ...) ...) and a set of formals
  7277. ; N over which the definitions may be lifted, returns a list of the
  7278. ; subsets of N that need to be added to each procedure definition
  7279. ; as new arguments.
  7280. ;
  7281. ; Algorithm: Let F_i be the variables that occur free in the body of
  7282. ; the lambda expression associated with f_i. Construct the call graph.
  7283. ; Solve the flow equations
  7284. ;
  7285. ; A_i = (F_i /\ N) \/ (\/ {A_j | A_i calls A_j})
  7286. ;
  7287. ; where /\ is intersection and \/ is union.
  7288. (define (compute-added-arguments defs formals)
  7289. (let ((procs (map def.lhs defs))
  7290. (freevars (map lambda.F (map def.rhs defs))))
  7291. (let ((callgraph (map (lambda (names)
  7292. (map (lambda (name)
  7293. (position name procs))
  7294. (intersection names procs)))
  7295. freevars))
  7296. (added_0 (map (lambda (names)
  7297. (intersection names formals))
  7298. freevars)))
  7299. (vector->list
  7300. (compute-fixedpoint
  7301. (make-vector (length procs) '())
  7302. (list->vector (map (lambda (term0 indexes)
  7303. (lambda (approximations)
  7304. (union term0
  7305. (apply union
  7306. (map (lambda (i)
  7307. (vector-ref approximations i))
  7308. indexes)))))
  7309. added_0
  7310. callgraph))
  7311. set-equal?)))))
  7312. (define (position x l)
  7313. (cond ((eq? x (car l)) 0)
  7314. (else (+ 1 (position x (cdr l))))))
  7315. ; Given a vector of starting approximations,
  7316. ; a vector of functions that compute a next approximation
  7317. ; as a function of the vector of approximations,
  7318. ; and an equality predicate,
  7319. ; returns a vector of fixed points.
  7320. (define (compute-fixedpoint v functions equiv?)
  7321. (define (loop i flag)
  7322. (if (negative? i)
  7323. (if flag
  7324. (loop (- (vector-length v) 1) #f)
  7325. v)
  7326. (let ((next_i ((vector-ref functions i) v)))
  7327. (if (equiv? next_i (vector-ref v i))
  7328. (loop (- i 1) flag)
  7329. (begin (vector-set! v i next_i)
  7330. (loop (- i 1) #t))))))
  7331. (loop (- (vector-length v) 1) #f))
  7332. ; Given a lambda expression L2, its parent lambda expression
  7333. ; L (which may be the same as L2, or #f), and a list of the
  7334. ; lists of arguments that would need to be added to known
  7335. ; local procedures, returns #t iff lambda lifting should be done.
  7336. ;
  7337. ; Here are some heuristics:
  7338. ;
  7339. ; Don't lift if it means adding too many arguments.
  7340. ; Don't lift large groups of definitions.
  7341. ; In questionable cases it is better to lift to an outer
  7342. ; lambda expression that already contains internal
  7343. ; definitions than to one that doesn't.
  7344. ; It is better not to lift if the body contains a lambda
  7345. ; expression that has to be closed anyway.
  7346. (define (POLICY:LIFT? L2 L args-to-add)
  7347. (and (lambda-optimizations)
  7348. (not (lambda? (lambda.body L2)))
  7349. (every? (lambda (addlist)
  7350. (< (length addlist) 6))
  7351. args-to-add)))
  7352. ; Copyright 1991 William D Clinger (for SIMPLIFY-CONDITIONAL)
  7353. ; Copyright 1999 William D Clinger (for everything else)
  7354. ;
  7355. ; Permission to copy this software, in whole or in part, to use this
  7356. ; software for any lawful noncommercial purpose, and to redistribute
  7357. ; this software is granted subject to the restriction that all copies
  7358. ; made of this software must include this copyright notice in full.
  7359. ;
  7360. ; I also request that you send me a copy of any improvements that you
  7361. ; make to this software so that they may be incorporated within it to
  7362. ; the benefit of the Scheme community.
  7363. ;
  7364. ; 11 April 1999.
  7365. ;
  7366. ; Some source transformations on IF expressions:
  7367. ;
  7368. ; (if '#f E1 E2) E2
  7369. ; (if 'K E1 E2) E1 K != #f
  7370. ; (if (if B0 '#f '#f) E1 E2) (begin B0 E2)
  7371. ; (if (if B0 '#f 'K ) E1 E2) (if B0 E2 E1) K != #f
  7372. ; (if (if B0 'K '#f) E1 E2) (if B0 E1 E2) K != #f
  7373. ; (if (if B0 'K1 'K2) E1 E2) (begin B0 E1) K1, K2 != #f
  7374. ; (if (if B0 (if B1 #t #f) B2) E1 E2) (if (if B0 B1 B2) E1 E2)
  7375. ; (if (if B0 B1 (if B2 #t #f)) E1 E2) (if (if B0 B1 B2) E1 E2)
  7376. ; (if (if X X B0 ) E1 E2) (if (if X #t B0) E1 E2) X a variable
  7377. ; (if (if X B0 X ) E1 E2) (if (if X B0 #f) E1 E2) X a variable
  7378. ; (if ((lambda (X) (if ((lambda (X)
  7379. ; (if X X B2)) B0) (if X #t (if B2 #t #f))) B0)
  7380. ; E1 E2) E1 E2)
  7381. ; (if (begin ... B0) E1 E2) (begin ... (if B0 E1 E2))
  7382. ; (if (not E0) E1 E2) (if E0 E2 E1) not is integrable
  7383. ;
  7384. ; FIXME: Three of the transformations above are intended to clean up
  7385. ; the output of the OR macro. It isn't yet clear how well this works.
  7386. (define (simplify-conditional exp notepad)
  7387. (define (coercion-to-boolean? exp)
  7388. (and (conditional? exp)
  7389. (let ((E1 (if.then exp))
  7390. (E2 (if.else exp)))
  7391. (and (constant? E1)
  7392. (eq? #t (constant.value E1))
  7393. (constant? E2)
  7394. (eq? #f (constant.value E2))))))
  7395. (if (not (control-optimization))
  7396. (begin (if.test-set! exp (simplify (if.test exp) notepad))
  7397. (if.then-set! exp (simplify (if.then exp) notepad))
  7398. (if.else-set! exp (simplify (if.else exp) notepad))
  7399. exp)
  7400. (let* ((test (if.test exp)))
  7401. (if (and (call? test)
  7402. (lambda? (call.proc test))
  7403. (let* ((L (call.proc test))
  7404. (body (lambda.body L)))
  7405. (and (conditional? body)
  7406. (let ((R (lambda.R L))
  7407. (B0 (if.test body))
  7408. (B1 (if.then body)))
  7409. (and (variable? B0)
  7410. (variable? B1)
  7411. (let ((x (variable.name B0)))
  7412. (and (eq? x (variable.name B1))
  7413. (local? R x)
  7414. (= 1 (length R))
  7415. (= 1 (length (call.args test))))))))))
  7416. (let* ((L (call.proc test))
  7417. (R (lambda.R L))
  7418. (body (lambda.body L))
  7419. (ref (if.then body))
  7420. (x (variable.name ref))
  7421. (entry (R-entry R x)))
  7422. (if.then-set! body (make-constant #t))
  7423. (if.else-set! body
  7424. (make-conditional (if.else body)
  7425. (make-constant #t)
  7426. (make-constant #f)))
  7427. (R-entry.references-set! entry
  7428. (remq ref
  7429. (R-entry.references entry)))
  7430. (simplify-conditional exp notepad))
  7431. (let loop ((test (simplify (if.test exp) notepad)))
  7432. (if.test-set! exp test)
  7433. (cond ((constant? test)
  7434. (simplify (if (constant.value test)
  7435. (if.then exp)
  7436. (if.else exp))
  7437. notepad))
  7438. ((and (conditional? test)
  7439. (constant? (if.then test))
  7440. (constant? (if.else test)))
  7441. (cond ((and (constant.value (if.then test))
  7442. (constant.value (if.else test)))
  7443. (post-simplify-begin
  7444. (make-begin (list (if.test test)
  7445. (simplify (if.then exp)
  7446. notepad)))
  7447. notepad))
  7448. ((and (not (constant.value (if.then test)))
  7449. (not (constant.value (if.else test))))
  7450. (post-simplify-begin
  7451. (make-begin (list (if.test test)
  7452. (simplify (if.else exp)
  7453. notepad)))
  7454. notepad))
  7455. (else (if (not (constant.value (if.then test)))
  7456. (let ((temp (if.then exp)))
  7457. (if.then-set! exp (if.else exp))
  7458. (if.else-set! exp temp)))
  7459. (if.test-set! exp (if.test test))
  7460. (loop (if.test exp)))))
  7461. ((and (conditional? test)
  7462. (or (coercion-to-boolean? (if.then test))
  7463. (coercion-to-boolean? (if.else test))))
  7464. (if (coercion-to-boolean? (if.then test))
  7465. (if.then-set! test (if.test (if.then test)))
  7466. (if.else-set! test (if.test (if.else test))))
  7467. (loop test))
  7468. ((and (conditional? test)
  7469. (variable? (if.test test))
  7470. (let ((x (variable.name (if.test test))))
  7471. (or (and (variable? (if.then test))
  7472. (eq? x (variable.name (if.then test)))
  7473. 1)
  7474. (and (variable? (if.else test))
  7475. (eq? x (variable.name (if.else test)))
  7476. 2))))
  7477. =>
  7478. (lambda (n)
  7479. (case n
  7480. ((1) (if.then-set! test (make-constant #t)))
  7481. ((2) (if.else-set! test (make-constant #f))))
  7482. (loop test)))
  7483. ((begin? test)
  7484. (let ((exprs (reverse (begin.exprs test))))
  7485. (if.test-set! exp (car exprs))
  7486. (post-simplify-begin
  7487. (make-begin (reverse (cons (loop (car exprs))
  7488. (cdr exprs))))
  7489. notepad)))
  7490. ((and (call? test)
  7491. (variable? (call.proc test))
  7492. (eq? (variable.name (call.proc test)) name:NOT)
  7493. (integrable? name:NOT)
  7494. (integrate-usual-procedures)
  7495. (= (length (call.args test)) 1))
  7496. (let ((temp (if.then exp)))
  7497. (if.then-set! exp (if.else exp))
  7498. (if.else-set! exp temp))
  7499. (loop (car (call.args test))))
  7500. (else
  7501. (simplify-case exp notepad))))))))
  7502. ; Given a conditional expression whose test has been simplified,
  7503. ; simplifies the then and else parts while applying optimizations
  7504. ; for CASE expressions.
  7505. ; Precondition: (control-optimization) is true.
  7506. (define (simplify-case exp notepad)
  7507. (let ((E0 (if.test exp)))
  7508. (if (and (call? E0)
  7509. (variable? (call.proc E0))
  7510. (let ((name (variable.name (call.proc E0))))
  7511. ; FIXME: Should ensure that the name is integrable,
  7512. ; but MEMQ and MEMV probably aren't according to the
  7513. ; INTEGRABLE? predicate.
  7514. (or (eq? name name:EQ?)
  7515. (eq? name name:EQV?)
  7516. (eq? name name:MEMQ)
  7517. (eq? name name:MEMV)))
  7518. (integrate-usual-procedures)
  7519. (= (length (call.args E0)) 2)
  7520. (variable? (car (call.args E0)))
  7521. (constant? (cadr (call.args E0))))
  7522. (simplify-case-clauses (variable.name (car (call.args E0)))
  7523. exp
  7524. notepad)
  7525. (begin (if.then-set! exp (simplify (if.then exp) notepad))
  7526. (if.else-set! exp (simplify (if.else exp) notepad))
  7527. exp))))
  7528. ; Code generation for case expressions.
  7529. ;
  7530. ; A case expression turns into a conditional expression
  7531. ; of the form
  7532. ;
  7533. ; CASE{I} ::= E | (if (PRED I K) E CASE{I})
  7534. ; PRED ::= memv | memq | eqv? | eq?
  7535. ;
  7536. ; The memq and eq? predicates are used when the constant
  7537. ; is a (list of) boolean, fixnum, char, empty list, or symbol.
  7538. ; The constants will almost always be of these types.
  7539. ;
  7540. ; The first step is to remove duplicated constants and to
  7541. ; collect all the case clauses, sorting them into the following
  7542. ; categories based on their simplified list of constants:
  7543. ; constants are fixnums
  7544. ; constants are characters
  7545. ; constants are symbols
  7546. ; constants are of mixed or other type
  7547. ; After duplicated constants have been removed, the predicates
  7548. ; for these clauses can be tested in any order.
  7549. ; Given the name of an arbitrary variable, an expression that
  7550. ; has not yet been simplified or can safely be simplified again,
  7551. ; and a notepad, returns the expression after simplification.
  7552. ; If the expression is equivalent to a case expression that dispatches
  7553. ; on the given variable, then case-optimization will be applied.
  7554. (define (simplify-case-clauses var0 E notepad)
  7555. (define notepad2 (make-notepad (notepad.parent notepad)))
  7556. (define (collect-clauses E fix chr sym other constants)
  7557. (if (not (conditional? E))
  7558. (analyze (simplify E notepad2)
  7559. fix chr sym other constants)
  7560. (let ((test (simplify (if.test E) notepad2))
  7561. (code (simplify (if.then E) notepad2)))
  7562. (if.test-set! E test)
  7563. (if.then-set! E code)
  7564. (if (not (call? test))
  7565. (finish E fix chr sym other constants)
  7566. (let ((proc (call.proc test))
  7567. (args (call.args test)))
  7568. (if (not (and (variable? proc)
  7569. (let ((name (variable.name proc)))
  7570. ; FIXME: See note above.
  7571. (or (eq? name name:EQ?)
  7572. (eq? name name:EQV?)
  7573. (eq? name name:MEMQ)
  7574. (eq? name name:MEMV)))
  7575. (= (length args) 2)
  7576. (variable? (car args))
  7577. (eq? (variable.name (car args)) var0)
  7578. (constant? (cadr args))))
  7579. (finish E fix chr sym other constants)
  7580. (let ((pred (variable.name proc))
  7581. (datum (constant.value (cadr args))))
  7582. ; FIXME
  7583. (if (or (and (or (eq? pred name:MEMV)
  7584. (eq? pred name:MEMQ))
  7585. (not (list? datum)))
  7586. (and (eq? pred name:EQ?)
  7587. (not (eqv-is-ok? datum)))
  7588. (and (eq? pred name:MEMQ)
  7589. (not (every? (lambda (datum)
  7590. (eqv-is-ok? datum))
  7591. datum))))
  7592. (finish E fix chr sym other constants)
  7593. (call-with-values
  7594. (lambda ()
  7595. (remove-duplicates (if (or (eq? pred name:EQV?)
  7596. (eq? pred name:EQ?))
  7597. (list datum)
  7598. datum)
  7599. constants))
  7600. (lambda (data constants)
  7601. (let ((clause (list data code))
  7602. (E2 (if.else E)))
  7603. (cond ((every? smallint? data)
  7604. (collect-clauses E2
  7605. (cons clause fix)
  7606. chr
  7607. sym
  7608. other
  7609. constants))
  7610. ((every? char? data)
  7611. (collect-clauses E2
  7612. fix
  7613. (cons clause chr)
  7614. sym
  7615. other
  7616. constants))
  7617. ((every? symbol? data)
  7618. (collect-clauses E2
  7619. fix
  7620. chr
  7621. (cons clause sym)
  7622. other
  7623. constants))
  7624. (else
  7625. (collect-clauses E2
  7626. fix
  7627. chr
  7628. sym
  7629. (cons clause other)
  7630. constants))))))))))))))
  7631. (define (remove-duplicates data set)
  7632. (let loop ((originals data)
  7633. (data '())
  7634. (set set))
  7635. (if (null? originals)
  7636. (values data set)
  7637. (let ((x (car originals))
  7638. (originals (cdr originals)))
  7639. (if (memv x set)
  7640. (loop originals data set)
  7641. (loop originals (cons x data) (cons x set)))))))
  7642. (define (finish E fix chr sym other constants)
  7643. (if.else-set! E (simplify (if.else E) notepad2))
  7644. (analyze E fix chr sym other constants))
  7645. (define (analyze default fix chr sym other constants)
  7646. (notepad-var-add! notepad2 var0)
  7647. (for-each (lambda (L)
  7648. (notepad-lambda-add! notepad L))
  7649. (notepad.lambdas notepad2))
  7650. (for-each (lambda (L)
  7651. (notepad-nonescaping-add! notepad L))
  7652. (notepad.nonescaping notepad2))
  7653. (for-each (lambda (var)
  7654. (notepad-var-add! notepad var))
  7655. (append (list name:FIXNUM?
  7656. name:CHAR?
  7657. name:SYMBOL?
  7658. name:FX<
  7659. name:FX-
  7660. name:CHAR->INTEGER
  7661. name:VECTOR-REF)
  7662. (notepad.vars notepad2)))
  7663. (analyze-clauses (notepad.vars notepad2)
  7664. var0
  7665. default
  7666. (reverse fix)
  7667. (reverse chr)
  7668. (reverse sym)
  7669. (reverse other)
  7670. constants))
  7671. (collect-clauses E '() '() '() '() '()))
  7672. ; Returns true if EQ? and EQV? behave the same on x.
  7673. (define (eqv-is-ok? x)
  7674. (or (smallint? x)
  7675. (char? x)
  7676. (symbol? x)
  7677. (boolean? x)))
  7678. ; Returns true if EQ? and EQV? behave the same on x.
  7679. (define (eq-is-ok? x)
  7680. (eqv-is-ok? x))
  7681. ; Any case expression that dispatches on a variable var0 and whose
  7682. ; constants are disjoint can be compiled as
  7683. ;
  7684. ; (let ((n (cond ((eq? var0 'K1) ...) ; miscellaneous constants
  7685. ; ...
  7686. ; ((fixnum? var0)
  7687. ; <dispatch-on-fixnum>)
  7688. ; ((char? var0)
  7689. ; <dispatch-on-char>)
  7690. ; ((symbol? var0)
  7691. ; <dispatch-on-symbols>)
  7692. ; (else 0))))
  7693. ; <dispatch-on-case-number>)
  7694. ;
  7695. ; where the <dispatch-on-case-number> uses binary search within
  7696. ; the interval [0, p+1), where p is the number of non-default cases.
  7697. ;
  7698. ; On the SPARC, sequential search is faster if there are fewer than
  7699. ; 8 constants, and sequential search uses less than half the space
  7700. ; if there are fewer than 10 constants. Most target machines should
  7701. ; similar, so I'm hard-wiring this constant.
  7702. ; FIXME: The hardwired constant is annoying.
  7703. (define (analyze-clauses F var0 default fix chr sym other constants)
  7704. (cond ((or (and (null? fix)
  7705. (null? chr))
  7706. (< (length constants) 12))
  7707. (implement-clauses-by-sequential-search var0
  7708. default
  7709. (append fix chr sym other)))
  7710. (else
  7711. (implement-clauses F var0 default fix chr sym other constants))))
  7712. ; Implements the general technique described above.
  7713. (define (implement-clauses F var0 default fix chr sym other constants)
  7714. (let* ((name:n ((make-rename-procedure) 'n))
  7715. ; Referencing information is destroyed by pass 2.
  7716. (entry (make-R-entry name:n '() '() '()))
  7717. (F (union (make-set (list name:n)) F))
  7718. (L (make-lambda
  7719. (list name:n)
  7720. '()
  7721. '() ; entry
  7722. F
  7723. '()
  7724. '()
  7725. #f
  7726. (implement-case-dispatch
  7727. name:n
  7728. (cons default
  7729. (map cadr
  7730. ; The order here must match the order
  7731. ; used by IMPLEMENT-DISPATCH.
  7732. (append other fix chr sym)))))))
  7733. (make-call L
  7734. (list (implement-dispatch 0
  7735. var0
  7736. (map car other)
  7737. (map car fix)
  7738. (map car chr)
  7739. (map car sym))))))
  7740. (define (implement-case-dispatch var0 exprs)
  7741. (implement-intervals var0
  7742. (map (lambda (n code)
  7743. (list n (+ n 1) code))
  7744. (iota (length exprs))
  7745. exprs)))
  7746. ; Given the number of prior clauses,
  7747. ; the variable on which to dispatch,
  7748. ; a list of constant lists for mixed or miscellaneous clauses,
  7749. ; a list of constant lists for the fixnum clauses,
  7750. ; a list of constant lists for the character clauses, and
  7751. ; a list of constant lists for the symbol clauses,
  7752. ; returns code that computes the index of the selected clause.
  7753. ; The mixed/miscellaneous clauses must be tested first because
  7754. ; Twobit's SMALLINT? predicate might not be true of all fixnums
  7755. ; on the target machine, which means that Twobit might classify
  7756. ; some fixnums as miscellaneous.
  7757. (define (implement-dispatch prior var0 other fix chr sym)
  7758. (cond ((not (null? other))
  7759. (implement-dispatch-other
  7760. (implement-dispatch (+ prior (length other))
  7761. var0 fix chr sym '())
  7762. prior var other))
  7763. ((not (null? fix))
  7764. (make-conditional (make-call (make-variable name:FIXNUM?)
  7765. (list (make-variable var0)))
  7766. (implement-dispatch-fixnum prior var0 fix)
  7767. (implement-dispatch (+ prior (length fix))
  7768. var0 '() chr sym other)))
  7769. ((not (null? chr))
  7770. (make-conditional (make-call (make-variable name:CHAR?)
  7771. (list (make-variable var0)))
  7772. (implement-dispatch-char prior var0 chr)
  7773. (implement-dispatch (+ prior (length chr))
  7774. var0 fix '() sym other)))
  7775. ((not (null? sym))
  7776. (make-conditional (make-call (make-variable name:SYMBOL?)
  7777. (list (make-variable var0)))
  7778. (implement-dispatch-symbol prior var0 sym)
  7779. (implement-dispatch (+ prior (length sym))
  7780. var0 fix chr '() other)))
  7781. (else
  7782. (make-constant 0))))
  7783. ; The value of var0 will be known to be a fixnum.
  7784. ; Can use table lookup, binary search, or sequential search.
  7785. ; FIXME: Never uses sequential search, which is best when
  7786. ; there are only a few constants, with gaps between them.
  7787. (define (implement-dispatch-fixnum prior var0 lists)
  7788. (define (calculate-intervals n lists)
  7789. (define (loop n lists intervals)
  7790. (if (null? lists)
  7791. (twobit-sort (lambda (interval1 interval2)
  7792. (< (car interval1) (car interval2)))
  7793. intervals)
  7794. (let ((constants (twobit-sort < (car lists))))
  7795. (loop (+ n 1)
  7796. (cdr lists)
  7797. (append (extract-intervals n constants)
  7798. intervals)))))
  7799. (loop n lists '()))
  7800. (define (extract-intervals n constants)
  7801. (if (null? constants)
  7802. '()
  7803. (let ((k0 (car constants)))
  7804. (do ((constants (cdr constants) (cdr constants))
  7805. (k1 (+ k0 1) (+ k1 1)))
  7806. ((or (null? constants)
  7807. (not (= k1 (car constants))))
  7808. (cons (list k0 k1 (make-constant n))
  7809. (extract-intervals n constants)))))))
  7810. (define (complete-intervals intervals)
  7811. (cond ((null? intervals)
  7812. intervals)
  7813. ((null? (cdr intervals))
  7814. intervals)
  7815. (else
  7816. (let* ((i1 (car intervals))
  7817. (i2 (cadr intervals))
  7818. (end1 (cadr i1))
  7819. (start2 (car i2))
  7820. (intervals (complete-intervals (cdr intervals))))
  7821. (if (= end1 start2)
  7822. (cons i1 intervals)
  7823. (cons i1
  7824. (cons (list end1 start2 (make-constant 0))
  7825. intervals)))))))
  7826. (let* ((intervals (complete-intervals
  7827. (calculate-intervals (+ prior 1) lists)))
  7828. (lo (car (car intervals)))
  7829. (hi (car (car (reverse intervals))))
  7830. (p (length intervals)))
  7831. (make-conditional
  7832. (make-call (make-variable name:FX<)
  7833. (list (make-variable var0)
  7834. (make-constant lo)))
  7835. (make-constant 0)
  7836. (make-conditional
  7837. (make-call (make-variable name:FX<)
  7838. (list (make-variable var0)
  7839. (make-constant (+ hi 1))))
  7840. ; The static cost of table lookup is about hi - lo words.
  7841. ; The static cost of binary search is about 5 SPARC instructions
  7842. ; per interval.
  7843. (if (< (- hi lo) (* 5 p))
  7844. (implement-table-lookup var0 (+ prior 1) lists lo hi)
  7845. (implement-intervals var0 intervals))
  7846. (make-constant 0)))))
  7847. (define (implement-dispatch-char prior var0 lists)
  7848. (let* ((lists (map (lambda (constants)
  7849. (map compat:char->integer constants))
  7850. lists))
  7851. (name:n ((make-rename-procedure) 'n))
  7852. ; Referencing information is destroyed by pass 2.
  7853. ;(entry (make-R-entry name:n '() '() '()))
  7854. (F (list name:n name:EQ? name:FX< name:FX- name:VECTOR-REF))
  7855. (L (make-lambda
  7856. (list name:n)
  7857. '()
  7858. '() ; entry
  7859. F
  7860. '()
  7861. '()
  7862. #f
  7863. (implement-dispatch-fixnum prior name:n lists))))
  7864. (make-call L
  7865. (make-call (make-variable name:CHAR->INTEGER)
  7866. (list (make-variable var0))))))
  7867. (define (implement-dispatch-symbol prior var0 lists)
  7868. (implement-dispatch-other (make-constant 0) prior var0 lists))
  7869. (define (implement-dispatch-other default prior var0 lists)
  7870. (if (null? lists)
  7871. default
  7872. (let* ((constants (car lists))
  7873. (lists (cdr lists))
  7874. (n (+ prior 1)))
  7875. (make-conditional (make-call-to-memv var0 constants)
  7876. (make-constant n)
  7877. (implement-dispatch-other default n var0 lists)))))
  7878. (define (make-call-to-memv var0 constants)
  7879. (cond ((null? constants)
  7880. (make-constant #f))
  7881. ((null? (cdr constants))
  7882. (make-call-to-eqv var0 (car constants)))
  7883. (else
  7884. (make-conditional (make-call-to-eqv var0 (car constants))
  7885. (make-constant #t)
  7886. (make-call-to-memv var0 (cdr constants))))))
  7887. (define (make-call-to-eqv var0 constant)
  7888. (make-call (make-variable
  7889. (if (eq-is-ok? constant)
  7890. name:EQ?
  7891. name:EQV?))
  7892. (list (make-variable var0)
  7893. (make-constant constant))))
  7894. ; Given a variable whose value is known to be a fixnum,
  7895. ; the clause index for the first fixnum clause,
  7896. ; an ordered list of lists of constants for fixnum-only clauses,
  7897. ; and the least and greatest constants in those lists,
  7898. ; returns code for a table lookup.
  7899. (define (implement-table-lookup var0 index lists lo hi)
  7900. (let ((v (make-vector (+ 1 (- hi lo)) 0)))
  7901. (do ((index index (+ index 1))
  7902. (lists lists (cdr lists)))
  7903. ((null? lists))
  7904. (for-each (lambda (k)
  7905. (vector-set! v (- k lo) index))
  7906. (car lists)))
  7907. (make-call (make-variable name:VECTOR-REF)
  7908. (list (make-constant v)
  7909. (make-call (make-variable name:FX-)
  7910. (list (make-variable var0)
  7911. (make-constant lo)))))))
  7912. ; Given a variable whose value is known to lie within the
  7913. ; half-open interval [m0, mk), and an ordered complete
  7914. ; list of intervals of the form
  7915. ;
  7916. ; ((m0 m1 code0)
  7917. ; (m1 m2 code1)
  7918. ; ...
  7919. ; (m{k-1} mk code{k-1})
  7920. ; )
  7921. ;
  7922. ; returns an expression that finds the unique i such that
  7923. ; var0 lies within [mi, m{i+1}), and then executes code{i}.
  7924. (define (implement-intervals var0 intervals)
  7925. (if (null? (cdr intervals))
  7926. (caddr (car intervals))
  7927. (let ((n (quotient (length intervals) 2)))
  7928. (do ((n n (- n 1))
  7929. (intervals1 '() (cons (car intervals2) intervals1))
  7930. (intervals2 intervals (cdr intervals2)))
  7931. ((zero? n)
  7932. (let ((intervals1 (reverse intervals1))
  7933. (m (car (car intervals2))))
  7934. (make-conditional (make-call (make-variable name:FX<)
  7935. (list
  7936. (make-variable var0)
  7937. (make-constant m)))
  7938. (implement-intervals var0 intervals1)
  7939. (implement-intervals var0 intervals2))))))))
  7940. ; The brute force approach.
  7941. ; Given the variable on which the dispatch is being performed, and
  7942. ; actual (simplified) code for the default clause and
  7943. ; for all other clauses,
  7944. ; returns code to perform the dispatch by sequential search.
  7945. (define *memq-threshold* 20)
  7946. (define *memv-threshold* 4)
  7947. (define (implement-clauses-by-sequential-search var0 default clauses)
  7948. (if (null? clauses)
  7949. default
  7950. (let* ((case1 (car clauses))
  7951. (clauses (cdr clauses))
  7952. (constants1 (car case1))
  7953. (code1 (cadr case1)))
  7954. (make-conditional (make-call-to-memv var0 constants1)
  7955. code1
  7956. (implement-clauses-by-sequential-search
  7957. var0 default clauses)))))
  7958. ; Copyright 1999 William D Clinger.
  7959. ;
  7960. ; Permission to copy this software, in whole or in part, to use this
  7961. ; software for any lawful noncommercial purpose, and to redistribute
  7962. ; this software is granted subject to the restriction that all copies
  7963. ; made of this software must include this copyright notice in full.
  7964. ;
  7965. ; I also request that you send me a copy of any improvements that you
  7966. ; make to this software so that they may be incorporated within it to
  7967. ; the benefit of the Scheme community.
  7968. ;
  7969. ; 13 April 1999.
  7970. ;
  7971. ; The tail and non-tail call graphs of known and unknown procedures.
  7972. ;
  7973. ; Given an expression E returned by pass 2 of Twobit,
  7974. ; returns a list of the following form:
  7975. ;
  7976. ; ((#t L () <tailcalls> <nontailcalls> <size> #f)
  7977. ; (<name> L <vars> <tailcalls> <nontailcalls> <size> #f)
  7978. ; ...)
  7979. ;
  7980. ; where
  7981. ;
  7982. ; Each L is a lambda expression that occurs within E
  7983. ; as either an escaping lambda expression or as a known
  7984. ; procedure. If L is a known procedure, then <name> is
  7985. ; its name; otherwise <name> is #f.
  7986. ;
  7987. ; <vars> is a list of the non-global variables within whose
  7988. ; scope L occurs.
  7989. ;
  7990. ; <tailcalls> is a complete list of names of known local procedures
  7991. ; that L calls tail-recursively, disregarding calls from other known
  7992. ; procedures or escaping lambda expressions that occur within L.
  7993. ;
  7994. ; <nontailcalls> is a complete list of names of known local procedures
  7995. ; that L calls non-tail-recursively, disregarding calls from other
  7996. ; known procedures or escaping lambda expressions that occur within L.
  7997. ;
  7998. ; <size> is a measure of the size of L, including known procedures
  7999. ; and escaping lambda expressions that occur within L.
  8000. (define (callgraphnode.name x) (car x))
  8001. (define (callgraphnode.code x) (cadr x))
  8002. (define (callgraphnode.vars x) (caddr x))
  8003. (define (callgraphnode.tailcalls x) (cadddr x))
  8004. (define (callgraphnode.nontailcalls x) (car (cddddr x)))
  8005. (define (callgraphnode.size x) (cadr (cddddr x)))
  8006. (define (callgraphnode.info x) (caddr (cddddr x)))
  8007. (define (callgraphnode.size! x v) (set-car! (cdr (cddddr x)) v) #f)
  8008. (define (callgraphnode.info! x v) (set-car! (cddr (cddddr x)) v) #f)
  8009. (define (callgraph exp)
  8010. ; Returns (union (list x) z).
  8011. (define (adjoin x z)
  8012. (if (memq x z)
  8013. z
  8014. (cons x z)))
  8015. (let ((result '()))
  8016. ; Given a <name> as described above, a lambda expression, a list
  8017. ; of variables that are in scope, and a list of names of known
  8018. ; local procedure that are in scope, computes an entry for L and
  8019. ; entries for any nested known procedures or escaping lambda
  8020. ; expressions, and adds them to the result.
  8021. (define (add-vertex! name L vars known)
  8022. (let ((tailcalls '())
  8023. (nontailcalls '())
  8024. (size 0))
  8025. ; Given an expression, a list of variables that are in scope,
  8026. ; a list of names of known local procedures that are in scope,
  8027. ; and a boolean indicating whether the expression occurs in a
  8028. ; tail context, adds any tail or non-tail calls to known
  8029. ; procedures that occur within the expression to the list
  8030. ; variables declared above.
  8031. (define (graph! exp vars known tail?)
  8032. (set! size (+ size 1))
  8033. (case (car exp)
  8034. ((quote) #f)
  8035. ((lambda) (add-vertex! #f exp vars known)
  8036. (set! size
  8037. (+ size
  8038. (callgraphnode.size (car result)))))
  8039. ((set!) (graph! (assignment.rhs exp) vars known #f))
  8040. ((if) (graph! (if.test exp) vars known #f)
  8041. (graph! (if.then exp) vars known tail?)
  8042. (graph! (if.else exp) vars known tail?))
  8043. ((begin) (if (not (variable? exp))
  8044. (do ((exprs (begin.exprs exp) (cdr exprs)))
  8045. ((null? (cdr exprs))
  8046. (graph! (car exprs) vars known tail?))
  8047. (graph! (car exprs) vars known #f))))
  8048. (else (let ((proc (call.proc exp)))
  8049. (cond ((variable? proc)
  8050. (let ((name (variable.name proc)))
  8051. (if (memq name known)
  8052. (if tail?
  8053. (set! tailcalls
  8054. (adjoin name tailcalls))
  8055. (set! nontailcalls
  8056. (adjoin name nontailcalls))))))
  8057. ((lambda? proc)
  8058. (graph-lambda! proc vars known tail?))
  8059. (else
  8060. (graph! proc vars known #f)))
  8061. (for-each (lambda (exp)
  8062. (graph! exp vars known #f))
  8063. (call.args exp))))))
  8064. (define (graph-lambda! L vars known tail?)
  8065. (let* ((defs (lambda.defs L))
  8066. (newknown (map def.lhs defs))
  8067. (vars (append newknown
  8068. (make-null-terminated
  8069. (lambda.args L))
  8070. vars))
  8071. (known (append newknown known)))
  8072. (for-each (lambda (def)
  8073. (add-vertex! (def.lhs def)
  8074. (def.rhs def)
  8075. vars
  8076. known)
  8077. (set! size
  8078. (+ size
  8079. (callgraphnode.size (car result)))))
  8080. defs)
  8081. (graph! (lambda.body L) vars known tail?)))
  8082. (graph-lambda! L vars known #t)
  8083. (set! result
  8084. (cons (list name L vars tailcalls nontailcalls size #f)
  8085. result))))
  8086. (add-vertex! #t
  8087. (make-lambda '() '() '() '() '() '() '() exp)
  8088. '()
  8089. '())
  8090. result))
  8091. ; Displays the callgraph, for debugging.
  8092. (define (view-callgraph g)
  8093. (for-each (lambda (entry)
  8094. (let ((name (callgraphnode.name entry))
  8095. (exp (callgraphnode.code entry))
  8096. (vars (callgraphnode.vars entry))
  8097. (tail (callgraphnode.tailcalls entry))
  8098. (nt (callgraphnode.nontailcalls entry))
  8099. (size (callgraphnode.size entry)))
  8100. (cond ((symbol? name)
  8101. (write name))
  8102. (name
  8103. (display "TOP LEVEL EXPRESSION"))
  8104. (else
  8105. (display "ESCAPING LAMBDA EXPRESSION")))
  8106. (display ":")
  8107. (newline)
  8108. (display "Size: ")
  8109. (write size)
  8110. (newline)
  8111. ;(newline)
  8112. ;(display "Variables in scope: ")
  8113. ;(write vars)
  8114. ;(newline)
  8115. (display "Tail calls: ")
  8116. (write tail)
  8117. (newline)
  8118. (display "Non-tail calls: ")
  8119. (write nt)
  8120. (newline)
  8121. ;(newline)
  8122. ;(pretty-print (make-readable exp))
  8123. ;(newline)
  8124. ;(newline)
  8125. (newline)))
  8126. g))
  8127. ; Copyright 1999 William D Clinger.
  8128. ;
  8129. ; Permission to copy this software, in whole or in part, to use this
  8130. ; software for any lawful noncommercial purpose, and to redistribute
  8131. ; this software is granted subject to the restriction that all copies
  8132. ; made of this software must include this copyright notice in full.
  8133. ;
  8134. ; I also request that you send me a copy of any improvements that you
  8135. ; make to this software so that they may be incorporated within it to
  8136. ; the benefit of the Scheme community.
  8137. ;
  8138. ; 14 April 1999.
  8139. ;
  8140. ; Inlining of known local procedures.
  8141. ;
  8142. ; First find the known and escaping procedures and compute the call graph.
  8143. ;
  8144. ; If a known local procedure is not called at all, then delete its code.
  8145. ;
  8146. ; If a known local procedure is called exactly once,
  8147. ; then inline its code at the call site and delete the
  8148. ; known local procedure. Change the size of the code
  8149. ; at the call site by adding the size of the inlined code.
  8150. ;
  8151. ; Divide the remaining known and escaping procedures into categories:
  8152. ; 1. makes no calls to known local procedures
  8153. ; 2. known procedures that call known procedures;
  8154. ; within this category, try to sort so that procedures do not
  8155. ; call procedures that come later in the sequence; or sort by
  8156. ; number of calls and/or size
  8157. ; 3. escaping procedures that call known procedures
  8158. ;
  8159. ; Approve each procedure in category 1 for inlining if its code size
  8160. ; is less than some threshold.
  8161. ;
  8162. ; For each procedure in categories 2 and 3, traverse its code, inlining
  8163. ; where it seems like a good idea. The compiler should be more aggressive
  8164. ; about inlining non-tail calls than tail calls because:
  8165. ;
  8166. ; Inlining a non-tail call can eliminate a stack frame
  8167. ; or expose the inlined code to loop optimizations.
  8168. ;
  8169. ; The main reason for inlining a tail call is to enable
  8170. ; intraprocedural optimizations or to unroll a loop.
  8171. ;
  8172. ; After inlining has been performed on a known local procedure,
  8173. ; then approve it for inlining if its size is less than some threshold.
  8174. ;
  8175. ; FIXME:
  8176. ; This strategy avoids infinite unrolling, but it also avoids finite
  8177. ; unrolling of loops.
  8178. ; Parameters to control inlining.
  8179. ; These can be tuned later.
  8180. (define *tail-threshold* 10)
  8181. (define *nontail-threshold* 20)
  8182. (define *multiplier* 300)
  8183. ; Given a callgraph, performs inlining of known local procedures
  8184. ; by side effect. The original expression must then be copied to
  8185. ; reinstate Twobit's invariants.
  8186. ; FIXME: This code doesn't yet do the right thing with known local
  8187. ; procedures that aren't called or are called in exactly one place.
  8188. (define (inline-using-callgraph! g)
  8189. (let ((known (make-hashtable))
  8190. (category2 '())
  8191. (category3 '()))
  8192. (for-each (lambda (node)
  8193. (let ((name (callgraphnode.name node))
  8194. (tcalls (callgraphnode.tailcalls node))
  8195. (ncalls (callgraphnode.nontailcalls node)))
  8196. (if (symbol? name)
  8197. (hashtable-put! known name node))
  8198. (if (and (null? tcalls)
  8199. (null? ncalls))
  8200. (if (< (callgraphnode.size node)
  8201. *nontail-threshold*)
  8202. (callgraphnode.info! node #t))
  8203. (if (symbol? name)
  8204. (set! category2 (cons node category2))
  8205. (set! category3 (cons node category3))))))
  8206. g)
  8207. (set! category2 (twobit-sort (lambda (x y)
  8208. (< (callgraphnode.size x)
  8209. (callgraphnode.size y)))
  8210. category2))
  8211. (for-each (lambda (node)
  8212. (inline-node! node known))
  8213. category2)
  8214. (for-each (lambda (node)
  8215. (inline-node! node known))
  8216. category3)
  8217. ; FIXME:
  8218. ; Inlining destroys the callgraph, so maybe this cleanup is useless.
  8219. (hashtable-for-each (lambda (name node) (callgraphnode.info! node #f))
  8220. known)))
  8221. ; Given a node of the callgraph and a hash table of nodes for
  8222. ; known local procedures, performs inlining by side effect.
  8223. (define (inline-node! node known)
  8224. (let* ((debugging? #f)
  8225. (name (callgraphnode.name node))
  8226. (exp (callgraphnode.code node))
  8227. (size0 (callgraphnode.size node))
  8228. (budget (quotient (* (- *multiplier* 100) size0) 100))
  8229. (tail-threshold *tail-threshold*)
  8230. (nontail-threshold *nontail-threshold*))
  8231. ; Given an expression,
  8232. ; a boolean indicating whether the expression is in a tail context,
  8233. ; a list of procedures that should not be inlined,
  8234. ; and a size budget,
  8235. ; performs inlining by side effect and returns the unused budget.
  8236. (define (inline exp tail? budget)
  8237. (if (positive? budget)
  8238. (case (car exp)
  8239. ((quote lambda)
  8240. budget)
  8241. ((set!)
  8242. (inline (assignment.rhs exp) #f budget))
  8243. ((if)
  8244. (let* ((budget (inline (if.test exp) #f budget))
  8245. (budget (inline (if.then exp) tail? budget))
  8246. (budget (inline (if.else exp) tail? budget)))
  8247. budget))
  8248. ((begin)
  8249. (if (variable? exp)
  8250. budget
  8251. (do ((exprs (begin.exprs exp) (cdr exprs))
  8252. (budget budget
  8253. (inline (car exprs) #f budget)))
  8254. ((null? (cdr exprs))
  8255. (inline (car exprs) tail? budget)))))
  8256. (else
  8257. (let ((budget (do ((exprs (call.args exp) (cdr exprs))
  8258. (budget budget
  8259. (inline (car exprs) #f budget)))
  8260. ((null? exprs)
  8261. budget))))
  8262. (let ((proc (call.proc exp)))
  8263. (cond ((variable? proc)
  8264. (let* ((procname (variable.name proc))
  8265. (procnode (hashtable-get known procname)))
  8266. (if procnode
  8267. (let ((size (callgraphnode.size procnode))
  8268. (info (callgraphnode.info procnode)))
  8269. (if (and info
  8270. (<= size budget)
  8271. (<= size
  8272. (if tail?
  8273. tail-threshold
  8274. nontail-threshold)))
  8275. (begin
  8276. (if debugging?
  8277. (begin
  8278. (display " Inlining ")
  8279. (write (variable.name proc))
  8280. (newline)))
  8281. (call.proc-set!
  8282. exp
  8283. (copy-exp
  8284. (callgraphnode.code procnode)))
  8285. (callgraphnode.size!
  8286. node
  8287. (+ (callgraphnode.size node) size))
  8288. (- budget size))
  8289. (begin
  8290. (if (and #f debugging?)
  8291. (begin
  8292. (display " Declining to inline ")
  8293. (write (variable.name proc))
  8294. (newline)))
  8295. budget)))
  8296. budget)))
  8297. ((lambda? proc)
  8298. (inline (lambda.body proc) tail? budget))
  8299. (else
  8300. (inline proc #f budget)))))))
  8301. -1))
  8302. (if (and #f debugging?)
  8303. (begin
  8304. (display "Processing ")
  8305. (write name)
  8306. (newline)))
  8307. (let ((budget (inline (if (lambda? exp)
  8308. (lambda.body exp)
  8309. exp)
  8310. #t
  8311. budget)))
  8312. (if (and (negative? budget)
  8313. debugging?)
  8314. ; This shouldn't happen very often.
  8315. (begin (display "Ran out of inlining budget for ")
  8316. (write (callgraphnode.name node))
  8317. (newline)))
  8318. (if (<= (callgraphnode.size node) nontail-threshold)
  8319. (callgraphnode.info! node #t))
  8320. #f)))
  8321. ; For testing.
  8322. (define (test-inlining test0)
  8323. (begin (define exp0 (begin (display "Compiling...")
  8324. (newline)
  8325. (pass2 (pass1 test0))))
  8326. (define g0 (begin (display "Computing call graph...")
  8327. (newline)
  8328. (callgraph exp0))))
  8329. (display "Inlining...")
  8330. (newline)
  8331. (inline-using-callgraph! g0)
  8332. (pretty-print (make-readable (copy-exp exp0))))
  8333. ; Copyright 1999 William D Clinger.
  8334. ;
  8335. ; Permission to copy this software, in whole or in part, to use this
  8336. ; software for any lawful noncommercial purpose, and to redistribute
  8337. ; this software is granted subject to the restriction that all copies
  8338. ; made of this software must include this copyright notice in full.
  8339. ;
  8340. ; I also request that you send me a copy of any improvements that you
  8341. ; make to this software so that they may be incorporated within it to
  8342. ; the benefit of the Scheme community.
  8343. ;
  8344. ; 14 April 1999.
  8345. ;
  8346. ; Interprocedural constant propagation and folding.
  8347. ;
  8348. ; Constant propagation must converge before constant folding can be
  8349. ; performed. Constant folding creates more constants that can be
  8350. ; propagated, so these two optimizations must be iterated, but it
  8351. ; is safe to stop at any time.
  8352. ;
  8353. ; Abstract interpretation for constant folding.
  8354. ;
  8355. ; The abstract values are
  8356. ; bottom (represented here by #f)
  8357. ; constants (represented by quoted literals)
  8358. ; top (represented here by #t)
  8359. ;
  8360. ; Let [[ E ]] be the abstract interpretation of E over that domain
  8361. ; of abstract values, with respect to some arbitrary set of abstract
  8362. ; values for local variables.
  8363. ;
  8364. ; If a is a global variable or a formal parameter of an escaping
  8365. ; lambda expression, then [[ a ]] = #t.
  8366. ;
  8367. ; If x is the ith formal parameter of a known local procedure f,
  8368. ; then [[ x ]] = \join_{(f E1 ... En)} [[ Ei ]].
  8369. ;
  8370. ; [[ K ]] = K
  8371. ; [[ L ]] = #t
  8372. ; [[ (begin E1 ... En) ]] = [[ En ]]
  8373. ; [[ (set! I E) ]] = #f
  8374. ;
  8375. ; If [[ E0 ]] = #t, then [[ (if E0 E1 E2) ]] = [[ E1 ]] \join [[ E2 ]]
  8376. ; else if [[ E0 ]] = K, then [[ (if E0 E1 E2) ]] = [[ E1 ]]
  8377. ; or [[ (if E0 E1 E2) ]] = [[ E2 ]]
  8378. ; depending upon K
  8379. ; else [[ (if E0 E1 E2) ]] = #f
  8380. ;
  8381. ; If f is a known local procedure with body E,
  8382. ; then [[ (f E1 ... En) ]] = [[ E ]]
  8383. ;
  8384. ; If g is a foldable integrable procedure, then:
  8385. ; if there is some i for which [[ Ei ]] = #t,
  8386. ; then [[ (g E1 ... En) ]] = #t
  8387. ; else if [[ E1 ]] = K1, ..., [[ En ]] = Kn,
  8388. ; then [[ (g E1 ... En) ]] = (g K1 ... Kn)
  8389. ; else [[ (g E1 ... En) ]] = #f
  8390. ;
  8391. ; Symbolic representations of abstract values.
  8392. ; (Can be thought of as mappings from abstract environments to
  8393. ; abstract values.)
  8394. ;
  8395. ; <symbolic> ::= #t | ( <expressions> )
  8396. ; <expressions> ::= <empty> | <expression> <expressions>
  8397. ; Parameter to limit constant propagation and folding.
  8398. ; This parameter can be tuned later.
  8399. (define *constant-propagation-limit* 5)
  8400. ; Given an expression as output by pass 2, performs constant
  8401. ; propagation and folding.
  8402. (define (constant-propagation exp)
  8403. (define (constant-propagation exp i)
  8404. (if (< i *constant-propagation-limit*)
  8405. (begin
  8406. ;(display "Performing constant propagation and folding...")
  8407. ;(newline)
  8408. (let* ((g (callgraph exp))
  8409. (L (callgraphnode.code (car g)))
  8410. (variables (constant-propagation-using-callgraph g))
  8411. (changed? (constant-folding! L variables)))
  8412. (if changed?
  8413. (constant-propagation (lambda.body L) (+ i 1))
  8414. (lambda.body L))))))
  8415. (constant-propagation exp 0))
  8416. ; Given a callgraph, returns a hashtable of abstract values for
  8417. ; all local variables.
  8418. (define (constant-propagation-using-callgraph g)
  8419. (let ((debugging? #f)
  8420. (folding? (integrate-usual-procedures))
  8421. (known (make-hashtable))
  8422. (variables (make-hashtable))
  8423. (counter 0))
  8424. ; Computes joins of abstract values.
  8425. (define (join x y)
  8426. (cond ((boolean? x)
  8427. (if x #t y))
  8428. ((boolean? y)
  8429. (join y x))
  8430. ((equal? x y)
  8431. x)
  8432. (else #t)))
  8433. ; Given a <symbolic> and a vector of abstract values,
  8434. ; evaluates the <symbolic> and returns its abstract value.
  8435. (define (aeval rep env)
  8436. (cond ((eq? rep #t)
  8437. #t)
  8438. ((null? rep)
  8439. #f)
  8440. ((null? (cdr rep))
  8441. (aeval1 (car rep) env))
  8442. (else
  8443. (join (aeval1 (car rep) env)
  8444. (aeval (cdr rep) env)))))
  8445. (define (aeval1 exp env)
  8446. (case (car exp)
  8447. ((quote)
  8448. exp)
  8449. ((lambda)
  8450. #t)
  8451. ((set!)
  8452. #f)
  8453. ((begin)
  8454. (if (variable? exp)
  8455. (let* ((name (variable.name exp))
  8456. (i (hashtable-get variables name)))
  8457. (if i
  8458. (vector-ref env i)
  8459. #t))
  8460. (aeval1-error)))
  8461. ((if)
  8462. (let* ((val0 (aeval1 (if.test exp) env))
  8463. (val1 (aeval1 (if.then exp) env))
  8464. (val2 (aeval1 (if.else exp) env)))
  8465. (cond ((eq? val0 #t)
  8466. (join val1 val2))
  8467. ((pair? val0)
  8468. (if (constant.value val0)
  8469. val1
  8470. val2))
  8471. (else
  8472. #f))))
  8473. (else
  8474. (do ((exprs (reverse (call.args exp)) (cdr exprs))
  8475. (vals '() (cons (aeval1 (car exprs) env) vals)))
  8476. ((null? exprs)
  8477. (let ((proc (call.proc exp)))
  8478. (cond ((variable? proc)
  8479. (let* ((procname (variable.name proc))
  8480. (procnode (hashtable-get known procname))
  8481. (entry (if folding?
  8482. (constant-folding-entry procname)
  8483. #f)))
  8484. (cond (procnode
  8485. (vector-ref env
  8486. (hashtable-get variables
  8487. procname)))
  8488. (entry
  8489. ; FIXME: No constant folding
  8490. #t)
  8491. (else (aeval1-error)))))
  8492. (else
  8493. (aeval1-error)))))))))
  8494. (define (aeval1-error)
  8495. (error "Compiler bug: constant propagation (aeval1)"))
  8496. ; Combines two <symbolic>s.
  8497. (define (combine-symbolic rep1 rep2)
  8498. (cond ((eq? rep1 #t) #t)
  8499. ((eq? rep2 #t) #t)
  8500. (else
  8501. (append rep1 rep2))))
  8502. ; Given an expression, returns a <symbolic> that represents
  8503. ; a list of expressions whose abstract values can be joined
  8504. ; to obtain the abstract value of the given expression.
  8505. ; As a side effect, enters local variables into variables.
  8506. (define (collect! exp)
  8507. (case (car exp)
  8508. ((quote)
  8509. (list exp))
  8510. ((lambda)
  8511. #t)
  8512. ((set!)
  8513. (collect! (assignment.rhs exp))
  8514. '())
  8515. ((begin)
  8516. (if (variable? exp)
  8517. (list exp)
  8518. (do ((exprs (begin.exprs exp) (cdr exprs)))
  8519. ((null? (cdr exprs))
  8520. (collect! (car exprs)))
  8521. (collect! (car exprs)))))
  8522. ((if)
  8523. (collect! (if.test exp))
  8524. (collect! (if.then exp))
  8525. (collect! (if.else exp))
  8526. #t)
  8527. (else
  8528. (do ((exprs (reverse (call.args exp)) (cdr exprs))
  8529. (reps '() (cons (collect! (car exprs)) reps)))
  8530. ((null? exprs)
  8531. (let ((proc (call.proc exp)))
  8532. (define (put-args! args reps)
  8533. (cond ((pair? args)
  8534. (let ((v (car args))
  8535. (rep (car reps)))
  8536. (hashtable-put! variables v rep)
  8537. (put-args! (cdr args) (cdr reps))))
  8538. ((symbol? args)
  8539. (hashtable-put! variables args #t))
  8540. (else #f)))
  8541. (cond ((variable? proc)
  8542. (let* ((procname (variable.name proc))
  8543. (procnode (hashtable-get known procname))
  8544. (entry (if folding?
  8545. (constant-folding-entry procname)
  8546. #f)))
  8547. (cond (procnode
  8548. (for-each (lambda (v rep)
  8549. (hashtable-put!
  8550. variables
  8551. v
  8552. (combine-symbolic
  8553. rep (hashtable-get variables v))))
  8554. (lambda.args
  8555. (callgraphnode.code procnode))
  8556. reps)
  8557. (list (make-variable procname)))
  8558. (entry
  8559. ; FIXME: No constant folding
  8560. #t)
  8561. (else #t))))
  8562. ((lambda? proc)
  8563. (put-args! (lambda.args proc) reps)
  8564. (collect! (lambda.body proc)))
  8565. (else
  8566. (collect! proc)
  8567. #t))))))))
  8568. (for-each (lambda (node)
  8569. (let* ((name (callgraphnode.name node))
  8570. (code (callgraphnode.code node))
  8571. (known? (symbol? name))
  8572. (rep (if known? '() #t)))
  8573. (if known?
  8574. (hashtable-put! known name node))
  8575. (if (lambda? code)
  8576. (for-each (lambda (var)
  8577. (hashtable-put! variables var rep))
  8578. (make-null-terminated (lambda.args code))))))
  8579. g)
  8580. (for-each (lambda (node)
  8581. (let ((name (callgraphnode.name node))
  8582. (code (callgraphnode.code node)))
  8583. (cond ((symbol? name)
  8584. (hashtable-put! variables
  8585. name
  8586. (collect! (lambda.body code))))
  8587. (else
  8588. (collect! (lambda.body code))))))
  8589. g)
  8590. (if (and #f debugging?)
  8591. (begin
  8592. (hashtable-for-each (lambda (v rep)
  8593. (write v)
  8594. (display ": ")
  8595. (write rep)
  8596. (newline))
  8597. variables)
  8598. (display "----------------------------------------")
  8599. (newline)))
  8600. ;(trace aeval aeval1)
  8601. (let* ((n (hashtable-size variables))
  8602. (vars (hashtable-map (lambda (v rep) v) variables))
  8603. (reps (map (lambda (v) (hashtable-get variables v)) vars))
  8604. (init (make-vector n #f))
  8605. (next (make-vector n)))
  8606. (do ((i 0 (+ i 1))
  8607. (vars vars (cdr vars))
  8608. (reps reps (cdr reps)))
  8609. ((= i n))
  8610. (hashtable-put! variables (car vars) i)
  8611. (vector-set! next
  8612. i
  8613. (let ((rep (car reps)))
  8614. (lambda (env)
  8615. (aeval rep env)))))
  8616. (compute-fixedpoint init next equal?)
  8617. (for-each (lambda (v)
  8618. (let* ((i (hashtable-get variables v))
  8619. (aval (vector-ref init i)))
  8620. (hashtable-put! variables v aval)
  8621. (if (and debugging?
  8622. (not (eq? aval #t)))
  8623. (begin (write v)
  8624. (display ": ")
  8625. (write aval)
  8626. (newline)))))
  8627. vars)
  8628. variables)))
  8629. ; Given a lambda expression, performs constant propagation, folding,
  8630. ; and simplifications by side effect, using the abstract values in the
  8631. ; hash table of variables.
  8632. ; Returns #t if any new constants were created by constant folding,
  8633. ; otherwise returns #f.
  8634. (define (constant-folding! L variables)
  8635. (let ((debugging? #f)
  8636. (msg1 " Propagating constant value for ")
  8637. (msg2 " Folding: ")
  8638. (msg3 " ==> ")
  8639. (folding? (integrate-usual-procedures))
  8640. (changed? #f))
  8641. ; Given a known lambda expression L, its original formal parameters,
  8642. ; and a list of all calls to L, deletes arguments that are now
  8643. ; ignored because of constant propagation.
  8644. (define (delete-ignored-args! L formals0 calls)
  8645. (let ((formals1 (lambda.args L)))
  8646. (for-each (lambda (call)
  8647. (do ((formals0 formals0 (cdr formals0))
  8648. (formals1 formals1 (cdr formals1))
  8649. (args (call.args call)
  8650. (cdr args))
  8651. (newargs '()
  8652. (if (and (eq? (car formals1) name:IGNORED)
  8653. (pair?
  8654. (hashtable-get variables
  8655. (car formals0))))
  8656. newargs
  8657. (cons (car args) newargs))))
  8658. ((null? formals0)
  8659. (call.args-set! call (reverse newargs)))))
  8660. calls)
  8661. (do ((formals0 formals0 (cdr formals0))
  8662. (formals1 formals1 (cdr formals1))
  8663. (formals2 '()
  8664. (if (and (not (eq? (car formals0)
  8665. (car formals1)))
  8666. (eq? (car formals1) name:IGNORED)
  8667. (pair?
  8668. (hashtable-get variables
  8669. (car formals0))))
  8670. formals2
  8671. (cons (car formals1) formals2))))
  8672. ((null? formals0)
  8673. (lambda.args-set! L (reverse formals2))))))
  8674. (define (fold! exp)
  8675. (case (car exp)
  8676. ((quote) exp)
  8677. ((lambda)
  8678. (let ((Rinfo (lambda.R exp))
  8679. (known (map def.lhs (lambda.defs exp))))
  8680. (for-each (lambda (entry)
  8681. (let* ((v (R-entry.name entry))
  8682. (aval (hashtable-fetch variables v #t)))
  8683. (if (and (pair? aval)
  8684. (not (memq v known)))
  8685. (let ((x (constant.value aval)))
  8686. (if (or (boolean? x)
  8687. (null? x)
  8688. (symbol? x)
  8689. (number? x)
  8690. (char? x)
  8691. (and (vector? x)
  8692. (zero? (vector-length x))))
  8693. (let ((refs (R-entry.references entry)))
  8694. (for-each (lambda (ref)
  8695. (variable-set! ref aval))
  8696. refs)
  8697. ; Do not try to use Rinfo in place of
  8698. ; (lambda.R exp) below!
  8699. (lambda.R-set!
  8700. exp
  8701. (remq entry (lambda.R exp)))
  8702. (flag-as-ignored v exp)
  8703. (if debugging?
  8704. (begin (display msg1)
  8705. (write v)
  8706. (display ": ")
  8707. (write aval)
  8708. (newline)))))))))
  8709. Rinfo)
  8710. (for-each (lambda (def)
  8711. (let* ((name (def.lhs def))
  8712. (rhs (def.rhs def))
  8713. (entry (R-lookup Rinfo name))
  8714. (calls (R-entry.calls entry)))
  8715. (if (null? calls)
  8716. (begin (lambda.defs-set!
  8717. exp
  8718. (remq def (lambda.defs exp)))
  8719. ; Do not try to use Rinfo in place of
  8720. ; (lambda.R exp) below!
  8721. (lambda.R-set!
  8722. exp
  8723. (remq entry (lambda.R exp))))
  8724. (let* ((formals0 (append (lambda.args rhs) '()))
  8725. (L (fold! rhs))
  8726. (formals1 (lambda.args L)))
  8727. (if (not (equal? formals0 formals1))
  8728. (delete-ignored-args! L formals0 calls))))))
  8729. (lambda.defs exp))
  8730. (lambda.body-set!
  8731. exp
  8732. (fold! (lambda.body exp)))
  8733. exp))
  8734. ((set!)
  8735. (assignment.rhs-set! exp (fold! (assignment.rhs exp)))
  8736. exp)
  8737. ((begin)
  8738. (if (variable? exp)
  8739. exp
  8740. (post-simplify-begin (make-begin (map fold! (begin.exprs exp)))
  8741. (make-notepad #f))))
  8742. ((if)
  8743. (let ((exp0 (fold! (if.test exp)))
  8744. (exp1 (fold! (if.then exp)))
  8745. (exp2 (fold! (if.else exp))))
  8746. (if (constant? exp0)
  8747. (let ((newexp (if (constant.value exp0)
  8748. exp1
  8749. exp2)))
  8750. (if debugging?
  8751. (begin (display msg2)
  8752. (write (make-readable exp))
  8753. (display msg3)
  8754. (write (make-readable newexp))
  8755. (newline)))
  8756. (set! changed? #t)
  8757. newexp)
  8758. (make-conditional exp0 exp1 exp2))))
  8759. (else
  8760. (let ((args (map fold! (call.args exp)))
  8761. (proc (fold! (call.proc exp))))
  8762. (cond ((and folding?
  8763. (variable? proc)
  8764. (every? constant? args)
  8765. (let ((entry
  8766. (constant-folding-entry (variable.name proc))))
  8767. (and entry
  8768. (let ((preds
  8769. (constant-folding-predicates entry)))
  8770. (and (= (length args) (length preds))
  8771. (every?
  8772. (lambda (x) x)
  8773. (map (lambda (f v) (f v))
  8774. (constant-folding-predicates entry)
  8775. (map constant.value args))))))))
  8776. (set! changed? #t)
  8777. (let ((result
  8778. (make-constant
  8779. (apply (constant-folding-folder
  8780. (constant-folding-entry
  8781. (variable.name proc)))
  8782. (map constant.value args)))))
  8783. (if debugging?
  8784. (begin (display msg2)
  8785. (write (make-readable (make-call proc args)))
  8786. (display msg3)
  8787. (write result)
  8788. (newline)))
  8789. result))
  8790. ((and (lambda? proc)
  8791. (list? (lambda.args proc)))
  8792. ; FIXME: Folding should be done even if there is
  8793. ; a rest argument.
  8794. (let loop ((formals (reverse (lambda.args proc)))
  8795. (actuals (reverse args))
  8796. (processed-formals '())
  8797. (processed-actuals '())
  8798. (for-effect '()))
  8799. (cond ((null? formals)
  8800. (lambda.args-set! proc processed-formals)
  8801. (call.args-set! exp processed-actuals)
  8802. (let ((call (if (and (null? processed-formals)
  8803. (null? (lambda.defs proc)))
  8804. (lambda.body proc)
  8805. exp)))
  8806. (if (null? for-effect)
  8807. call
  8808. (post-simplify-begin
  8809. (make-begin
  8810. (reverse (cons call for-effect)))
  8811. (make-notepad #f)))))
  8812. ((ignored? (car formals))
  8813. (loop (cdr formals)
  8814. (cdr actuals)
  8815. processed-formals
  8816. processed-actuals
  8817. (cons (car actuals) for-effect)))
  8818. (else
  8819. (loop (cdr formals)
  8820. (cdr actuals)
  8821. (cons (car formals) processed-formals)
  8822. (cons (car actuals) processed-actuals)
  8823. for-effect)))))
  8824. (else
  8825. (call.proc-set! exp proc)
  8826. (call.args-set! exp args)
  8827. exp))))))
  8828. (fold! L)
  8829. changed?))
  8830. ; Copyright 1998 William D Clinger.
  8831. ;
  8832. ; Permission to copy this software, in whole or in part, to use this
  8833. ; software for any lawful noncommercial purpose, and to redistribute
  8834. ; this software is granted subject to the restriction that all copies
  8835. ; made of this software must include this copyright notice in full.
  8836. ;
  8837. ; I also request that you send me a copy of any improvements that you
  8838. ; make to this software so that they may be incorporated within it to
  8839. ; the benefit of the Scheme community.
  8840. ;
  8841. ; 7 June 1999.
  8842. ;
  8843. ; Conversion to A-normal form, with heuristics for
  8844. ; choosing a good order of evaluation.
  8845. ;
  8846. ; This pass operates as a source-to-source transformation on
  8847. ; expressions written in the subset of Scheme described by the
  8848. ; following grammar, where the input and output expressions
  8849. ; satisfy certain additional invariants described below.
  8850. ;
  8851. ; "X ..." means zero or more occurrences of X.
  8852. ;
  8853. ; L --> (lambda (I_1 ...)
  8854. ; (begin D ...)
  8855. ; (quote (R F G <decls> <doc>)
  8856. ; E)
  8857. ; | (lambda (I_1 ... . I_rest)
  8858. ; (begin D ...)
  8859. ; (quote (R F G <decls> <doc>))
  8860. ; E)
  8861. ; D --> (define I L)
  8862. ; E --> (quote K) ; constants
  8863. ; | (begin I) ; variable references
  8864. ; | L ; lambda expressions
  8865. ; | (E0 E1 ...) ; calls
  8866. ; | (set! I E) ; assignments
  8867. ; | (if E0 E1 E2) ; conditionals
  8868. ; | (begin E0 E1 E2 ...) ; sequential expressions
  8869. ; I --> <identifier>
  8870. ;
  8871. ; R --> ((I <references> <assignments> <calls>) ...)
  8872. ; F --> (I ...)
  8873. ; G --> (I ...)
  8874. ;
  8875. ; Invariants that hold for the input only:
  8876. ; * There are no assignments except to global variables.
  8877. ; * If I is declared by an internal definition, then the right hand
  8878. ; side of the internal definition is a lambda expression and I
  8879. ; is referenced only in the procedure position of a call.
  8880. ; * For each lambda expression, the associated F is a list of all
  8881. ; the identifiers that occur free in the body of that lambda
  8882. ; expression, and possibly a few extra identifiers that were
  8883. ; once free but have been removed by optimization.
  8884. ; * For each lambda expression, the associated G is a subset of F
  8885. ; that contains every identifier that occurs free within some
  8886. ; inner lambda expression that escapes, and possibly a few that
  8887. ; don't. (Assignment-elimination does not calculate G exactly.)
  8888. ; * Variables named IGNORED are neither referenced nor assigned.
  8889. ;
  8890. ; Invariants that hold for the output only:
  8891. ; * There are no assignments except to global variables.
  8892. ; * If I is declared by an internal definition, then the right hand
  8893. ; side of the internal definition is a lambda expression and I
  8894. ; is referenced only in the procedure position of a call.
  8895. ; * R, F, and G are garbage.
  8896. ; * There are no sequential expressions.
  8897. ; * The output is an expression E with syntax
  8898. ;
  8899. ; E --> A
  8900. ; | (L)
  8901. ; | (L A)
  8902. ;
  8903. ; A --> W
  8904. ; | L
  8905. ; | (W_0 W_1 ...)
  8906. ; | (set! I W)
  8907. ; | (if W E1 E2)
  8908. ;
  8909. ; W --> (quote K)
  8910. ; | (begin I)
  8911. ;
  8912. ; In other words:
  8913. ; An expression is a LET* such that the rhs of every binding is
  8914. ; a conditional with the test already evaluated, or
  8915. ; an expression that can be evaluated in one step
  8916. ; (treating function calls as a single step)
  8917. ;
  8918. ; A-normal form corresponds to the control flow graph for a lambda
  8919. ; expression.
  8920. ; Algorithm: repeated use of these rules:
  8921. ;
  8922. ; (E0 E1 ...) ((lambda (T0 T1 ...) (T0 T1 ...))
  8923. ; E0 E1 ...)
  8924. ; (set! I E) ((lambda (T) (set! I T)) E)
  8925. ; (if E0 E1 E2) ((lambda (T) (if T E1 E2)) E0)
  8926. ; (begin E0 E1 E2 ...) ((lambda (T) (begin E1 E2 ...)) E0)
  8927. ;
  8928. ; ((lambda (I1 I2 I3 ...) E) ((lambda (I1)
  8929. ; E1 E2 E3) ((lambda (I2 I3 ...) E)
  8930. ; E2 E3))
  8931. ; E1)
  8932. ;
  8933. ; ((lambda (I2) E) ((lambda (I1)
  8934. ; ((lambda (I1) E2) ((lambda (I2) E)
  8935. ; E1)) E2)
  8936. ; E1)
  8937. ;
  8938. ; In other words:
  8939. ; Introduce a temporary name for every expression except:
  8940. ; tail expressions
  8941. ; the alternatives of a non-tail conditional
  8942. ; Convert every LET into a LET*.
  8943. ; Get rid of LET* on the right hand side of a binding.
  8944. ; Given an expression E in the representation output by pass 2,
  8945. ; returns an A-normal form for E in that representation.
  8946. ; Except for quoted values, the A-normal form does not share
  8947. ; mutable structure with the original expression E.
  8948. ;
  8949. ; KNOWN BUG:
  8950. ;
  8951. ; If you call A-normal on a form that has already been converted
  8952. ; to A-normal form, then the same temporaries will be generated
  8953. ; twice. An optional argument lets you specify a different prefix
  8954. ; for temporaries the second time around. Example:
  8955. ;
  8956. ; (A-normal-form (A-normal-form E ".T")
  8957. ; ".U")
  8958. ; This is the declaration that is used to indicate A-normal form.
  8959. (define A-normal-form-declaration (list 'anf))
  8960. (define (A-normal-form E . rest)
  8961. (define (A-normal-form E)
  8962. (anf-make-let* (anf E '() '())))
  8963. ; New temporaries.
  8964. (define temp-counter 0)
  8965. (define temp-prefix
  8966. (if (or (null? rest)
  8967. (not (string? (car rest))))
  8968. (string-append renaming-prefix "T")
  8969. (car rest)))
  8970. (define (newtemp)
  8971. (set! temp-counter (+ temp-counter 1))
  8972. (string->symbol
  8973. (string-append temp-prefix
  8974. (number->string temp-counter))))
  8975. ; Given an expression E as output by pass 2,
  8976. ; a list of surrounding LET* bindings,
  8977. ; and an ordered list of likely register variables,
  8978. ; return a non-empty list of LET* bindings
  8979. ; whose first binding associates a dummy variable
  8980. ; with an A-expression giving the value for E.
  8981. (define (anf E bindings regvars)
  8982. (case (car E)
  8983. ((quote) (anf-bind-dummy E bindings))
  8984. ((begin) (if (variable? E)
  8985. (anf-bind-dummy E bindings)
  8986. (anf-sequential E bindings regvars)))
  8987. ((lambda) (anf-lambda E bindings regvars))
  8988. ((set!) (anf-assignment E bindings regvars))
  8989. ((if) (anf-conditional E bindings regvars))
  8990. (else (anf-call E bindings regvars))))
  8991. (define anf:dummy (string->symbol "RESULT"))
  8992. (define (anf-bind-dummy E bindings)
  8993. (cons (list anf:dummy E)
  8994. bindings))
  8995. ; Unlike anf-bind-dummy, anf-bind-name and anf-bind convert
  8996. ; their expression argument to A-normal form.
  8997. ; Don't change anf-bind to call anf-bind-name, because that
  8998. ; would name the temporaries in an aesthetically bad order.
  8999. (define (anf-bind-name name E bindings regvars)
  9000. (let ((bindings (anf E bindings regvars)))
  9001. (cons (list name (cadr (car bindings)))
  9002. (cdr bindings))))
  9003. (define (anf-bind E bindings regvars)
  9004. (let ((bindings (anf E bindings regvars)))
  9005. (cons (list (newtemp) (cadr (car bindings)))
  9006. (cdr bindings))))
  9007. (define (anf-result bindings)
  9008. (make-variable (car (car bindings))))
  9009. (define (anf-make-let* bindings)
  9010. (define (loop bindings body)
  9011. (if (null? bindings)
  9012. body
  9013. (let ((T1 (car (car bindings)))
  9014. (E1 (cadr (car bindings))))
  9015. (loop (cdr bindings)
  9016. (make-call (make-lambda (list T1)
  9017. '()
  9018. '()
  9019. '()
  9020. '()
  9021. (list A-normal-form-declaration)
  9022. '()
  9023. body)
  9024. (list E1))))))
  9025. (loop (cdr bindings)
  9026. (cadr (car bindings))))
  9027. (define (anf-sequential E bindings regvars)
  9028. (do ((bindings bindings
  9029. (anf-bind (car exprs) bindings regvars))
  9030. (exprs (begin.exprs E)
  9031. (cdr exprs)))
  9032. ((null? (cdr exprs))
  9033. (anf (car exprs) bindings regvars))))
  9034. ; Heuristic: the formal parameters of an escaping lambda or
  9035. ; known local procedure are kept in REG1, REG2, et cetera.
  9036. (define (anf-lambda L bindings regvars)
  9037. (anf-bind-dummy
  9038. (make-lambda (lambda.args L)
  9039. (map (lambda (def)
  9040. (make-definition
  9041. (def.lhs def)
  9042. (A-normal-form (def.rhs def))))
  9043. (lambda.defs L))
  9044. '()
  9045. '()
  9046. '()
  9047. (cons A-normal-form-declaration
  9048. (lambda.decls L))
  9049. (lambda.doc L)
  9050. (anf-make-let*
  9051. (anf (lambda.body L)
  9052. '()
  9053. (make-null-terminated (lambda.args L)))))
  9054. bindings))
  9055. (define (anf-assignment E bindings regvars)
  9056. (let ((I (assignment.lhs E))
  9057. (E1 (assignment.rhs E)))
  9058. (if (variable? E1)
  9059. (anf-bind-dummy E bindings)
  9060. (let* ((bindings (anf-bind E1 bindings regvars))
  9061. (T1 (anf-result bindings)))
  9062. (anf-bind-dummy (make-assignment I T1) bindings)))))
  9063. (define (anf-conditional E bindings regvars)
  9064. (let ((E0 (if.test E))
  9065. (E1 (if.then E))
  9066. (E2 (if.else E)))
  9067. (if (variable? E0)
  9068. (let ((E1 (anf-make-let* (anf E1 '() regvars)))
  9069. (E2 (anf-make-let* (anf E2 '() regvars))))
  9070. (anf-bind-dummy
  9071. (make-conditional E0 E1 E2)
  9072. bindings))
  9073. (let* ((bindings (anf-bind E0 bindings regvars))
  9074. (E1 (anf-make-let* (anf E1 '() regvars)))
  9075. (E2 (anf-make-let* (anf E2 '() regvars))))
  9076. (anf-bind-dummy
  9077. (make-conditional (anf-result bindings) E1 E2)
  9078. bindings)))))
  9079. (define (anf-call E bindings regvars)
  9080. (let* ((proc (call.proc E))
  9081. (args (call.args E)))
  9082. ; Evaluates the exprs and returns both a list of bindings and
  9083. ; a list of the temporaries that name the results of the exprs.
  9084. ; If rename-always? is true, then temporaries are generated even
  9085. ; for constants and temporaries.
  9086. (define (loop exprs bindings names rename-always?)
  9087. (if (null? exprs)
  9088. (values bindings (reverse names))
  9089. (let ((E (car exprs)))
  9090. (if (or rename-always?
  9091. (not (or (constant? E)
  9092. (variable? E))))
  9093. (let* ((bindings
  9094. (anf-bind (car exprs) bindings regvars)))
  9095. (loop (cdr exprs)
  9096. bindings
  9097. (cons (anf-result bindings) names)
  9098. rename-always?))
  9099. (loop (cdr exprs)
  9100. bindings
  9101. (cons E names)
  9102. rename-always?)))))
  9103. ; Evaluates the exprs, binding them to the vars, and returns
  9104. ; a list of bindings.
  9105. ;
  9106. ; Although LET variables are likely to be kept in registers,
  9107. ; trying to guess which register will be allocated is likely
  9108. ; to do more harm than good.
  9109. (define (let-loop exprs bindings regvars vars)
  9110. (if (null? exprs)
  9111. (if (null? (lambda.defs proc))
  9112. (anf (lambda.body proc)
  9113. bindings
  9114. regvars)
  9115. (let ((bindings
  9116. (anf-bind
  9117. (make-lambda '()
  9118. (lambda.defs proc)
  9119. '()
  9120. '()
  9121. '()
  9122. (cons A-normal-form-declaration
  9123. (lambda.decls proc))
  9124. (lambda.doc proc)
  9125. (lambda.body proc))
  9126. bindings
  9127. '())))
  9128. (anf-bind-dummy
  9129. (make-call (anf-result bindings) '())
  9130. bindings)))
  9131. (let-loop (cdr exprs)
  9132. (anf-bind-name (car vars)
  9133. (car exprs)
  9134. bindings
  9135. regvars)
  9136. regvars
  9137. (cdr vars))))
  9138. (cond ((lambda? proc)
  9139. (let ((formals (lambda.args proc)))
  9140. (if (list? formals)
  9141. (let* ((pi (anf-order-of-evaluation args regvars #f))
  9142. (exprs (permute args pi))
  9143. (names (permute (lambda.args proc) pi)))
  9144. (let-loop (reverse exprs) bindings regvars (reverse names)))
  9145. (anf-call (normalize-let E) bindings regvars))))
  9146. ((not (variable? proc))
  9147. (let ((pi (anf-order-of-evaluation args regvars #f)))
  9148. (call-with-values
  9149. (lambda () (loop (permute args pi) bindings '() #t))
  9150. (lambda (bindings names)
  9151. (let ((bindings (anf-bind proc bindings regvars)))
  9152. (anf-bind-dummy
  9153. (make-call (anf-result bindings)
  9154. (unpermute names pi))
  9155. bindings))))))
  9156. ((and (integrate-usual-procedures)
  9157. (prim-entry (variable.name proc)))
  9158. (let ((pi (anf-order-of-evaluation args regvars #t)))
  9159. (call-with-values
  9160. (lambda () (loop (permute args pi) bindings '() #t))
  9161. (lambda (bindings names)
  9162. (anf-bind-dummy
  9163. (make-call proc (unpermute names pi))
  9164. bindings)))))
  9165. ((memq (variable.name proc) regvars)
  9166. (let* ((exprs (cons proc args))
  9167. (pi (anf-order-of-evaluation
  9168. exprs
  9169. (cons name:IGNORED regvars)
  9170. #f)))
  9171. (call-with-values
  9172. (lambda () (loop (permute exprs pi) bindings '() #t))
  9173. (lambda (bindings names)
  9174. (let ((names (unpermute names pi)))
  9175. (anf-bind-dummy
  9176. (make-call (car names) (cdr names))
  9177. bindings))))))
  9178. (else
  9179. (let ((pi (anf-order-of-evaluation args regvars #f)))
  9180. (call-with-values
  9181. (lambda () (loop (permute args pi) bindings '() #t))
  9182. (lambda (bindings names)
  9183. (anf-bind-dummy
  9184. (make-call proc (unpermute names pi))
  9185. bindings))))))))
  9186. ; Given a list of expressions, a list of likely register contents,
  9187. ; and a switch telling whether these are arguments for a primop
  9188. ; or something else (such as the arguments for a real call),
  9189. ; try to choose a good order in which to evaluate the expressions.
  9190. ;
  9191. ; Heuristic: If none of the expressions is a call to a non-primop,
  9192. ; then parallel assignment optimization gives a good order if the
  9193. ; regvars are right, and should do no worse than a random order if
  9194. ; the regvars are wrong.
  9195. ;
  9196. ; Heuristic: If the expressions are arguments to a primop, and
  9197. ; none are a call to a non-primop, then the register contents
  9198. ; are irrelevant, and the first argument should be evaluated last.
  9199. ;
  9200. ; Heuristic: If one or more of the expressions is a call to a
  9201. ; non-primop, then the following should be a good order:
  9202. ;
  9203. ; expressions that are neither a constant, variable, or a call
  9204. ; calls to non-primops
  9205. ; constants and variables
  9206. (define (anf-order-of-evaluation exprs regvars for-primop?)
  9207. (define (ordering targets exprs alist)
  9208. (let ((para
  9209. (parallel-assignment targets alist exprs)))
  9210. (or para
  9211. ; Evaluate left to right until a parallel assignment is found.
  9212. (cons (car targets)
  9213. (ordering (cdr targets)
  9214. (cdr exprs)
  9215. alist)))))
  9216. (if (parallel-assignment-optimization)
  9217. (cond ((null? exprs) '())
  9218. ((null? (cdr exprs)) '(0))
  9219. (else
  9220. (let* ((contains-call? #f)
  9221. (vexprs (list->vector exprs))
  9222. (vindexes (list->vector
  9223. (iota (vector-length vexprs))))
  9224. (contains-call? #f)
  9225. (categories
  9226. (list->vector
  9227. (map (lambda (E)
  9228. (cond ((constant? E)
  9229. 2)
  9230. ((variable? E)
  9231. 2)
  9232. ((complicated? E)
  9233. (set! contains-call? #t)
  9234. 1)
  9235. (else
  9236. 0)))
  9237. exprs))))
  9238. (cond (contains-call?
  9239. (twobit-sort (lambda (i j)
  9240. (< (vector-ref categories i)
  9241. (vector-ref categories j)))
  9242. (iota (length exprs))))
  9243. (for-primop?
  9244. (reverse (iota (length exprs))))
  9245. (else
  9246. (let ((targets (iota (length exprs))))
  9247. (define (pairup regvars targets)
  9248. (if (or (null? targets)
  9249. (null? regvars))
  9250. '()
  9251. (cons (cons (car regvars)
  9252. (car targets))
  9253. (pairup (cdr regvars)
  9254. (cdr targets)))))
  9255. (ordering targets
  9256. exprs
  9257. (pairup regvars targets))))))))
  9258. (iota (length exprs))))
  9259. (define (permute things pi)
  9260. (let ((v (list->vector things)))
  9261. (map (lambda (i) (vector-ref v i))
  9262. pi)))
  9263. (define (unpermute things pi)
  9264. (let* ((v0 (list->vector things))
  9265. (v1 (make-vector (vector-length v0))))
  9266. (do ((pi pi (cdr pi))
  9267. (k 0 (+ k 1)))
  9268. ((null? pi)
  9269. (vector->list v1))
  9270. (vector-set! v1 (car pi) (vector-ref v0 k)))))
  9271. ; Given a call whose procedure is a lambda expression that has
  9272. ; a rest argument, return a genuine let expression.
  9273. (define (normalize-let-error exp)
  9274. (if (issue-warnings)
  9275. (begin (display "WARNING from compiler: ")
  9276. (display "Wrong number of arguments ")
  9277. (display "to lambda expression")
  9278. (newline)
  9279. (pretty-print (make-readable exp) #t)
  9280. (newline))))
  9281. (define (normalize-let exp)
  9282. (let* ((L (call.proc exp)))
  9283. (let loop ((formals (lambda.args L))
  9284. (args (call.args exp))
  9285. (newformals '())
  9286. (newargs '()))
  9287. (cond ((null? formals)
  9288. (if (null? args)
  9289. (begin (lambda.args-set! L (reverse newformals))
  9290. (call.args-set! exp (reverse newargs)))
  9291. (begin (normalize-let-error exp)
  9292. (loop (list (newtemp))
  9293. args
  9294. newformals
  9295. newargs))))
  9296. ((pair? formals)
  9297. (if (pair? args)
  9298. (loop (cdr formals)
  9299. (cdr args)
  9300. (cons (car formals) newformals)
  9301. (cons (car args) newargs))
  9302. (begin (normalize-let-error exp)
  9303. (loop formals
  9304. (cons (make-constant 0)
  9305. args)
  9306. newformals
  9307. newargs))))
  9308. (else
  9309. (loop (list formals)
  9310. (list (make-call-to-list args))
  9311. newformals
  9312. newargs))))))
  9313. ; For heuristic use only.
  9314. ; An expression is complicated unless it can probably be evaluated
  9315. ; without saving and restoring any registers, even if it occurs in
  9316. ; a non-tail position.
  9317. (define (complicated? exp)
  9318. ; Let's not spend all day on this.
  9319. (let ((budget 10))
  9320. (define (complicated? exp)
  9321. (set! budget (- budget 1))
  9322. (if (zero? budget)
  9323. #t
  9324. (case (car exp)
  9325. ((quote) #f)
  9326. ((lambda) #f)
  9327. ((set!) (complicated? (assignment.rhs exp)))
  9328. ((if) (or (complicated? (if.test exp))
  9329. (complicated? (if.then exp))
  9330. (complicated? (if.else exp))))
  9331. ((begin) (if (variable? exp)
  9332. #f
  9333. (some? complicated?
  9334. (begin.exprs exp))))
  9335. (else (let ((proc (call.proc exp)))
  9336. (if (and (variable? proc)
  9337. (integrate-usual-procedures)
  9338. (prim-entry (variable.name proc)))
  9339. (some? complicated?
  9340. (call.args exp))
  9341. #t))))))
  9342. (complicated? exp)))
  9343. (A-normal-form E))
  9344. (define (post-simplify-anf L0 T1 E0 E1 free regbindings L2)
  9345. (define (return-normally)
  9346. (values (make-call L0 (list E1))
  9347. free
  9348. regbindings))
  9349. (return-normally))
  9350. ; Copyright 1999 William D Clinger.
  9351. ;
  9352. ; Permission to copy this software, in whole or in part, to use this
  9353. ; software for any lawful noncommercial purpose, and to redistribute
  9354. ; this software is granted subject to the restriction that all copies
  9355. ; made of this software must include this copyright notice in full.
  9356. ;
  9357. ; I also request that you send me a copy of any improvements that you
  9358. ; make to this software so that they may be incorporated within it to
  9359. ; the benefit of the Scheme community.
  9360. ;
  9361. ; 7 June 1999.
  9362. ;
  9363. ; Intraprocedural common subexpression elimination, constant propagation,
  9364. ; copy propagation, dead code elimination, and register targeting.
  9365. ;
  9366. ; (intraprocedural-commoning E 'commoning)
  9367. ;
  9368. ; Given an A-normal form E (alpha-converted, with correct free
  9369. ; variables and referencing information), returns an optimized
  9370. ; A-normal form with correct free variables but incorrect referencing
  9371. ; information.
  9372. ;
  9373. ; (intraprocedural-commoning E 'target-registers)
  9374. ;
  9375. ; Given an A-normal form E (alpha-converted, with correct free
  9376. ; variables and referencing information), returns an A-normal form
  9377. ; with correct free variables but incorrect referencing information,
  9378. ; and in which MacScheme machine register names are used as temporary
  9379. ; variables. The result is alpha-converted except for register names.
  9380. ;
  9381. ; (intraprocedural-commoning E 'commoning 'target-registers)
  9382. ; (intraprocedural-commoning E)
  9383. ;
  9384. ; Given an A-normal form as described above, returns an optimized
  9385. ; form in which register names are used as temporary variables.
  9386. ; Semantics of .check!:
  9387. ;
  9388. ; (.check! b exn x ...) faults with code exn and arguments x ...
  9389. ; if b is #f.
  9390. ; The list of argument registers.
  9391. ; This can't go in pass3commoning.aux.sch because that file must be
  9392. ; loaded before the target-specific file that defines *nregs*.
  9393. (define argument-registers
  9394. (do ((n (- *nregs* 2) (- n 1))
  9395. (regs '()
  9396. (cons (string->symbol
  9397. (string-append ".REG" (number->string n)))
  9398. regs)))
  9399. ((zero? n)
  9400. regs)))
  9401. (define (intraprocedural-commoning E . flags)
  9402. (define target-registers? (or (null? flags) (memq 'target-registers flags)))
  9403. (define commoning? (or (null? flags) (memq 'commoning flags)))
  9404. (define debugging? #f)
  9405. (call-with-current-continuation
  9406. (lambda (return)
  9407. (define (error . stuff)
  9408. (display "Bug detected during intraprocedural optimization")
  9409. (newline)
  9410. (for-each (lambda (s)
  9411. (display s) (newline))
  9412. stuff)
  9413. (return (make-constant #f)))
  9414. ; Given an expression, an environment, the available expressions,
  9415. ; and an ordered list of likely register variables (used heuristically),
  9416. ; returns the transformed expression and its set of free variables.
  9417. (define (scan-body E env available regvars)
  9418. ; The local variables are those that are bound by a LET within
  9419. ; this procedure. The formals of a lambda expression and the
  9420. ; known local procedures are counted as non-global, not local,
  9421. ; because there is no let-binding for a formal that can be
  9422. ; renamed during register targeting.
  9423. ; For each local variable, we keep track of how many times it
  9424. ; is referenced. This information is not accurate until we
  9425. ; are backing out of the recursion, and does not have to be.
  9426. (define local-variables (make-hashtable symbol-hash assq))
  9427. (define (local-variable? sym)
  9428. (hashtable-get local-variables sym))
  9429. (define (local-variable-not-used? sym)
  9430. (= 0 (hashtable-fetch local-variables sym -1)))
  9431. (define (local-variable-used-once? sym)
  9432. (= 1 (hashtable-fetch local-variables sym 0)))
  9433. (define (record-local-variable! sym)
  9434. (hashtable-put! local-variables sym 0))
  9435. (define (used-local-variable! sym)
  9436. (adjust-local-variable! sym 1))
  9437. (define (adjust-local-variable! sym n)
  9438. (let ((m (hashtable-get local-variables sym)))
  9439. (if debugging?
  9440. (if (and m (> m 0))
  9441. (begin (write (list sym (+ m n)))
  9442. (newline))))
  9443. (if m
  9444. (hashtable-put! local-variables
  9445. sym
  9446. (+ m n)))))
  9447. (define (closed-over-local-variable! sym)
  9448. ; Set its reference count to infinity so it won't be optimized away.
  9449. ; FIXME: One million isn't infinity.
  9450. (hashtable-put! local-variables sym 1000000))
  9451. (define (used-variable! sym)
  9452. (used-local-variable! sym))
  9453. (define (abandon-expression! E)
  9454. (cond ((variable? E)
  9455. (adjust-local-variable! (variable.name E) -1))
  9456. ((conditional? E)
  9457. (abandon-expression! (if.test E))
  9458. (abandon-expression! (if.then E))
  9459. (abandon-expression! (if.else E)))
  9460. ((call? E)
  9461. (for-each (lambda (exp)
  9462. (if (variable? exp)
  9463. (let ((name (variable.name exp)))
  9464. (if (local-variable? name)
  9465. (adjust-local-variable! name -1)))))
  9466. (cons (call.proc E)
  9467. (call.args E))))))
  9468. ; Environments are represented as hashtrees.
  9469. (define (make-empty-environment)
  9470. (make-hashtree symbol-hash assq))
  9471. (define (environment-extend env sym)
  9472. (hashtree-put env sym #t))
  9473. (define (environment-extend* env symbols)
  9474. (if (null? symbols)
  9475. env
  9476. (environment-extend* (hashtree-put env (car symbols) #t)
  9477. (cdr symbols))))
  9478. (define (environment-lookup env sym)
  9479. (hashtree-get env sym))
  9480. (define (global? x)
  9481. (cond ((local-variable? x)
  9482. #f)
  9483. ((environment-lookup env x)
  9484. #f)
  9485. (else
  9486. #t)))
  9487. ;
  9488. (define (available-add! available T E)
  9489. (cond ((constant? E)
  9490. (available-extend! available T E available:killer:immortal))
  9491. ((variable? E)
  9492. (available-extend! available
  9493. T
  9494. E
  9495. (if (global? (variable.name E))
  9496. available:killer:globals
  9497. available:killer:immortal)))
  9498. (else
  9499. (let ((entry (prim-call E)))
  9500. (if entry
  9501. (let ((killer (prim-lives-until entry)))
  9502. (if (not (eq? killer available:killer:dead))
  9503. (do ((args (call.args E) (cdr args))
  9504. (k killer
  9505. (let ((arg (car args)))
  9506. (if (and (variable? arg)
  9507. (global? (variable.name arg)))
  9508. available:killer:globals
  9509. k))))
  9510. ((null? args)
  9511. (available-extend!
  9512. available
  9513. T
  9514. E
  9515. (logior killer k)))))))))))
  9516. ; Given an expression E,
  9517. ; an environment containing all variables that are in scope,
  9518. ; and a table of available expressions,
  9519. ; returns multiple values:
  9520. ; the transformed E
  9521. ; the free variables of E
  9522. ; the register bindings to be inserted; each binding has the form
  9523. ; (R x (begin R)), where (begin R) is a reference to R.
  9524. ;
  9525. ; Side effects E.
  9526. (define (scan E env available)
  9527. (if (not (call? E))
  9528. (scan-rhs E env available)
  9529. (let ((proc (call.proc E)))
  9530. (if (not (lambda? proc))
  9531. (scan-rhs E env available)
  9532. (let ((vars (lambda.args proc)))
  9533. (cond ((null? vars)
  9534. (scan-let0 E env available))
  9535. ((null? (cdr vars))
  9536. (scan-binding E env available))
  9537. (else
  9538. (error (make-readable E)))))))))
  9539. ; E has the form of (let ((T1 E1)) E0).
  9540. (define (scan-binding E env available)
  9541. (let* ((L (call.proc E))
  9542. (T1 (car (lambda.args L)))
  9543. (E1 (car (call.args E)))
  9544. (E0 (lambda.body L)))
  9545. (record-local-variable! T1)
  9546. (call-with-values
  9547. (lambda () (scan-rhs E1 env available))
  9548. (lambda (E1 F1 regbindings1)
  9549. (available-add! available T1 E1)
  9550. (let* ((env (let ((formals
  9551. (make-null-terminated (lambda.args L))))
  9552. (environment-extend*
  9553. (environment-extend* env formals)
  9554. (map def.lhs (lambda.defs L)))))
  9555. (Fdefs (scan-defs L env available)))
  9556. (call-with-values
  9557. (lambda () (scan E0 env available))
  9558. (lambda (E0 F0 regbindings0)
  9559. (lambda.body-set! L E0)
  9560. (if target-registers?
  9561. (scan-binding-phase2
  9562. L T1 E0 E1 F0 F1 Fdefs regbindings0 regbindings1)
  9563. (scan-binding-phase3
  9564. L E0 E1 (union F0 Fdefs)
  9565. F1 regbindings0 regbindings1)))))))))
  9566. ; Given the lambda expression for a let expression that binds
  9567. ; a single variable T1, the transformed body E0 and right hand side E1,
  9568. ; their sets of free variables F0 and F1, the set of free variables
  9569. ; for the internal definitions of L, and the sets of register
  9570. ; bindings that need to be wrapped around E0 and E1, returns the
  9571. ; transformed let expression, its free variables, and register
  9572. ; bindings.
  9573. ;
  9574. ; This phase is concerned exclusively with register bindings,
  9575. ; and is bypassed unless the target-registers flag is specified.
  9576. (define (scan-binding-phase2
  9577. L T1 E0 E1 F0 F1 Fdefs regbindings0 regbindings1)
  9578. ; T1 can't be a register because we haven't
  9579. ; yet inserted register bindings that high up.
  9580. ; Classify the register bindings that need to wrapped around E0:
  9581. ; 1. those that have T1 as their rhs
  9582. ; 2. those whose lhs is a register that is likely to hold
  9583. ; a variable that occurs free in E1
  9584. ; 3. all others
  9585. (define (phase2a)
  9586. (do ((rvars regvars (cdr rvars))
  9587. (regs argument-registers (cdr regs))
  9588. (regs1 '() (if (memq (car rvars) F1)
  9589. (cons (car regs) regs1)
  9590. regs1)))
  9591. ((or (null? rvars)
  9592. (null? regs))
  9593. ; regs1 is the set of registers that are live for E1
  9594. (let loop ((regbindings regbindings0)
  9595. (rb1 '())
  9596. (rb2 '())
  9597. (rb3 '()))
  9598. (if (null? regbindings)
  9599. (phase2b rb1 rb2 rb3)
  9600. (let* ((binding (car regbindings))
  9601. (regbindings (cdr regbindings))
  9602. (lhs (regbinding.lhs binding))
  9603. (rhs (regbinding.rhs binding)))
  9604. (cond ((eq? rhs T1)
  9605. (loop regbindings
  9606. (cons binding rb1)
  9607. rb2
  9608. rb3))
  9609. ((memq lhs regs1)
  9610. (loop regbindings
  9611. rb1
  9612. (cons binding rb2)
  9613. rb3))
  9614. (else
  9615. (loop regbindings
  9616. rb1
  9617. rb2
  9618. (cons binding rb3))))))))))
  9619. ; Determine which categories of register bindings should be
  9620. ; wrapped around E0.
  9621. ; Always wrap the register bindings in category 2.
  9622. ; If E1 is a conditional or a real call, then wrap category 3.
  9623. ; If T1 might be used more than once, then wrap category 1.
  9624. (define (phase2b rb1 rb2 rb3)
  9625. (if (or (conditional? E1)
  9626. (real-call? E1))
  9627. (phase2c (append rb2 rb3) rb1 '())
  9628. (phase2c rb2 rb1 rb3)))
  9629. (define (phase2c towrap rb1 regbindings0)
  9630. (cond ((and (not (null? rb1))
  9631. (local-variable-used-once? T1))
  9632. (phase2d towrap rb1 regbindings0))
  9633. (else
  9634. (phase2e (append rb1 towrap) regbindings0))))
  9635. ; T1 is used only once, and there is a register binding (R T1).
  9636. ; Change T1 to R.
  9637. (define (phase2d towrap regbindings-T1 regbindings0)
  9638. (if (not (null? (cdr regbindings-T1)))
  9639. (error "incorrect number of uses" T1))
  9640. (let* ((regbinding (car regbindings-T1))
  9641. (R (regbinding.lhs regbinding)))
  9642. (lambda.args-set! L (list R))
  9643. (phase2e towrap regbindings0)))
  9644. ; Wrap the selected register bindings around E0.
  9645. (define (phase2e towrap regbindings0)
  9646. (call-with-values
  9647. (lambda ()
  9648. (wrap-with-register-bindings towrap E0 F0))
  9649. (lambda (E0 F0)
  9650. (let ((F (union Fdefs F0)))
  9651. (scan-binding-phase3
  9652. L E0 E1 F F1 regbindings0 regbindings1)))))
  9653. (phase2a))
  9654. ; This phase, with arguments as above, constructs the result.
  9655. (define (scan-binding-phase3 L E0 E1 F F1 regbindings0 regbindings1)
  9656. (let* ((args (lambda.args L))
  9657. (T1 (car args))
  9658. (free (union F1 (difference F args)))
  9659. (simple-let? (simple-lambda? L))
  9660. (regbindings
  9661. ; At least one of regbindings0 and regbindings1
  9662. ; is the empty list.
  9663. (cond ((null? regbindings0)
  9664. regbindings1)
  9665. ((null? regbindings1)
  9666. regbindings0)
  9667. (else
  9668. (error 'scan-binding 'regbindings)))))
  9669. (lambda.body-set! L E0)
  9670. (lambda.F-set! L F)
  9671. (lambda.G-set! L F)
  9672. (cond ((and simple-let?
  9673. (not (memq T1 F))
  9674. (no-side-effects? E1))
  9675. (abandon-expression! E1)
  9676. (values E0 F regbindings0))
  9677. ((and target-registers?
  9678. simple-let?
  9679. (local-variable-used-once? T1))
  9680. (post-simplify-anf L T1 E0 E1 free regbindings #f))
  9681. (else
  9682. (values (make-call L (list E1))
  9683. free
  9684. regbindings)))))
  9685. (define (scan-let0 E env available)
  9686. (let ((L (call.proc E)))
  9687. (if (simple-lambda? L)
  9688. (scan (lambda.body L) env available)
  9689. (let ((T1 (make-variable name:IGNORED)))
  9690. (lambda.args-set! L (list T1))
  9691. (call-with-values
  9692. (lambda () (scan (make-call L (list (make-constant 0)))
  9693. env
  9694. available))
  9695. (lambda (E F regbindings)
  9696. (lambda.args-set! L '())
  9697. (values (make-call L '())
  9698. F
  9699. regbindings)))))))
  9700. ; Optimizes the internal definitions of L and returns their
  9701. ; free variables.
  9702. (define (scan-defs L env available)
  9703. (let loop ((defs (lambda.defs L))
  9704. (newdefs '())
  9705. (Fdefs '()))
  9706. (if (null? defs)
  9707. (begin (lambda.defs-set! L (reverse newdefs))
  9708. Fdefs)
  9709. (let ((def (car defs)))
  9710. (call-with-values
  9711. (lambda ()
  9712. (let* ((Ldef (def.rhs def))
  9713. (Lformals (make-null-terminated (lambda.args Ldef)))
  9714. (Lenv (environment-extend*
  9715. (environment-extend* env Lformals)
  9716. (map def.lhs (lambda.defs Ldef)))))
  9717. (scan Ldef Lenv available)))
  9718. (lambda (rhs Frhs empty)
  9719. (if (not (null? empty))
  9720. (error 'scan-binding 'def))
  9721. (loop (cdr defs)
  9722. (cons (make-definition (def.lhs def) rhs)
  9723. newdefs)
  9724. (union Frhs Fdefs))))))))
  9725. ; Given the right-hand side of a let-binding, an environment,
  9726. ; and a table of available expressions, returns the transformed
  9727. ; expression, its free variables, and the register bindings that
  9728. ; need to be wrapped around it.
  9729. (define (scan-rhs E env available)
  9730. (cond
  9731. ((constant? E)
  9732. (values E (empty-set) '()))
  9733. ((variable? E)
  9734. (let* ((name (variable.name E))
  9735. (Enew (and commoning?
  9736. (if (global? name)
  9737. (let ((T (available-expression
  9738. available E)))
  9739. (if T
  9740. (make-variable T)
  9741. #f))
  9742. (available-variable available name)))))
  9743. (if Enew
  9744. (scan-rhs Enew env available)
  9745. (begin (used-variable! name)
  9746. (values E (list name) '())))))
  9747. ((lambda? E)
  9748. (let* ((formals (make-null-terminated (lambda.args E)))
  9749. (env (environment-extend*
  9750. (environment-extend* env formals)
  9751. (map def.lhs (lambda.defs E))))
  9752. (Fdefs (scan-defs E env available)))
  9753. (call-with-values
  9754. (lambda ()
  9755. (let ((available (copy-available-table available)))
  9756. (available-kill! available available:killer:all)
  9757. (scan-body (lambda.body E)
  9758. env
  9759. available
  9760. formals)))
  9761. (lambda (E0 F0 regbindings0)
  9762. (call-with-values
  9763. (lambda ()
  9764. (wrap-with-register-bindings regbindings0 E0 F0))
  9765. (lambda (E0 F0)
  9766. (lambda.body-set! E E0)
  9767. (let ((F (union Fdefs F0)))
  9768. (for-each (lambda (x)
  9769. (closed-over-local-variable! x))
  9770. F)
  9771. (lambda.F-set! E F)
  9772. (lambda.G-set! E F)
  9773. (values E
  9774. (difference F
  9775. (make-null-terminated
  9776. (lambda.args E)))
  9777. '()))))))))
  9778. ((conditional? E)
  9779. (let ((E0 (if.test E))
  9780. (E1 (if.then E))
  9781. (E2 (if.else E)))
  9782. (if (constant? E0)
  9783. ; FIXME: E1 and E2 might not be a legal rhs,
  9784. ; so we can't just return the simplified E1 or E2.
  9785. (let ((E1 (if (constant.value E0) E1 E2)))
  9786. (call-with-values
  9787. (lambda () (scan E1 env available))
  9788. (lambda (E1 F1 regbindings1)
  9789. (cond ((or (not (call? E1))
  9790. (not (lambda? (call.proc E1))))
  9791. (values E1 F1 regbindings1))
  9792. (else
  9793. ; FIXME: Must return a valid rhs.
  9794. (values (make-conditional
  9795. (make-constant #t)
  9796. E1
  9797. (make-constant 0))
  9798. F1
  9799. regbindings1))))))
  9800. (call-with-values
  9801. (lambda () (scan E0 env available))
  9802. (lambda (E0 F0 regbindings0)
  9803. (if (not (null? regbindings0))
  9804. (error 'scan-rhs 'if))
  9805. (if (not (eq? E0 (if.test E)))
  9806. (scan-rhs (make-conditional E0 E1 E2)
  9807. env available)
  9808. (let ((available1
  9809. (copy-available-table available))
  9810. (available2
  9811. (copy-available-table available)))
  9812. (if (variable? E0)
  9813. (let ((T0 (variable.name E0)))
  9814. (available-add!
  9815. available2 T0 (make-constant #f)))
  9816. (error (make-readable E #t)))
  9817. (call-with-values
  9818. (lambda () (scan E1 env available1))
  9819. (lambda (E1 F1 regbindings1)
  9820. (call-with-values
  9821. (lambda ()
  9822. (wrap-with-register-bindings
  9823. regbindings1 E1 F1))
  9824. (lambda (E1 F1)
  9825. (call-with-values
  9826. (lambda () (scan E2 env available2))
  9827. (lambda (E2 F2 regbindings2)
  9828. (call-with-values
  9829. (lambda ()
  9830. (wrap-with-register-bindings
  9831. regbindings2 E2 F2))
  9832. (lambda (E2 F2)
  9833. (let ((E (make-conditional
  9834. E0 E1 E2))
  9835. (F (union F0 F1 F2)))
  9836. (available-intersect!
  9837. available
  9838. available1
  9839. available2)
  9840. (values E F '())))))))))))))))))
  9841. ((assignment? E)
  9842. (call-with-values
  9843. (lambda () (scan-rhs (assignment.rhs E) env available))
  9844. (lambda (E1 F1 regbindings1)
  9845. (if (not (null? regbindings1))
  9846. (error 'scan-rhs 'set!))
  9847. (available-kill! available available:killer:globals)
  9848. (values (make-assignment (assignment.lhs E) E1)
  9849. (union (list (assignment.lhs E)) F1)
  9850. '()))))
  9851. ((begin? E)
  9852. ; Shouldn't occur in A-normal form.
  9853. (error 'scan-rhs 'begin))
  9854. ((real-call? E)
  9855. (let* ((E0 (call.proc E))
  9856. (args (call.args E))
  9857. (regcontents (append regvars
  9858. (map (lambda (x) #f) args))))
  9859. (let loop ((args args)
  9860. (regs argument-registers)
  9861. (regcontents regcontents)
  9862. (newargs '())
  9863. (regbindings '())
  9864. (F (if (variable? E0)
  9865. (let ((f (variable.name E0)))
  9866. (used-variable! f)
  9867. (list f))
  9868. (empty-set))))
  9869. (cond ((null? args)
  9870. (available-kill! available available:killer:all)
  9871. (values (make-call E0 (reverse newargs))
  9872. F
  9873. regbindings))
  9874. ((null? regs)
  9875. (let ((arg (car args)))
  9876. (loop (cdr args)
  9877. '()
  9878. (cdr regcontents)
  9879. (cons arg newargs)
  9880. regbindings
  9881. (if (variable? arg)
  9882. (let ((name (variable.name arg)))
  9883. (used-variable! name)
  9884. (union (list name) F))
  9885. F))))
  9886. ((and commoning?
  9887. (variable? (car args))
  9888. (available-variable
  9889. available
  9890. (variable.name (car args))))
  9891. (let* ((name (variable.name (car args)))
  9892. (Enew (available-variable available name)))
  9893. (loop (cons Enew (cdr args))
  9894. regs regcontents newargs regbindings F)))
  9895. ((and target-registers?
  9896. (variable? (car args))
  9897. (let ((x (variable.name (car args))))
  9898. ; We haven't yet recorded this use.
  9899. (or (local-variable-not-used? x)
  9900. (and (memq x regvars)
  9901. (not (eq? x (car regcontents)))))))
  9902. (let* ((x (variable.name (car args)))
  9903. (R (car regs))
  9904. (newarg (make-variable R)))
  9905. (used-variable! x)
  9906. (loop (cdr args)
  9907. (cdr regs)
  9908. (cdr regcontents)
  9909. (cons newarg newargs)
  9910. (cons (make-regbinding R x newarg)
  9911. regbindings)
  9912. (union (list R) F))))
  9913. (else
  9914. (let ((E1 (car args)))
  9915. (loop (cdr args)
  9916. (cdr regs)
  9917. (cdr regcontents)
  9918. (cons E1 newargs)
  9919. regbindings
  9920. (if (variable? E1)
  9921. (let ((name (variable.name E1)))
  9922. (used-variable! name)
  9923. (union (list name) F))
  9924. F))))))))
  9925. ((call? E)
  9926. ; Must be a call to a primop.
  9927. (let* ((E0 (call.proc E))
  9928. (f0 (variable.name E0)))
  9929. (let loop ((args (call.args E))
  9930. (newargs '())
  9931. (F (list f0)))
  9932. (cond ((null? args)
  9933. (let* ((E (make-call E0 (reverse newargs)))
  9934. (T (and commoning?
  9935. (available-expression
  9936. available E))))
  9937. (if T
  9938. (begin (abandon-expression! E)
  9939. (scan-rhs (make-variable T) env available))
  9940. (begin
  9941. (available-kill!
  9942. available
  9943. (prim-kills (prim-entry f0)))
  9944. (cond ((eq? f0 name:check!)
  9945. (let ((x (car (call.args E))))
  9946. (cond ((not (runtime-safety-checking))
  9947. (abandon-expression! E)
  9948. ;(values x '() '())
  9949. (scan-rhs x env available))
  9950. ((variable? x)
  9951. (available-add!
  9952. available
  9953. (variable.name x)
  9954. (make-constant #t))
  9955. (values E F '()))
  9956. ((constant.value x)
  9957. (abandon-expression! E)
  9958. (values x '() '()))
  9959. (else
  9960. (declaration-error E)
  9961. (values E F '())))))
  9962. (else
  9963. (values E F '())))))))
  9964. ((variable? (car args))
  9965. (let* ((E1 (car args))
  9966. (x (variable.name E1))
  9967. (Enew
  9968. (and commoning?
  9969. (available-variable available x))))
  9970. (if Enew
  9971. ; All of the arguments are constants or
  9972. ; variables, so if the variable is replaced
  9973. ; here it will be replaced throughout the call.
  9974. (loop (cons Enew (cdr args))
  9975. newargs
  9976. (remq x F))
  9977. (begin
  9978. (used-variable! x)
  9979. (loop (cdr args)
  9980. (cons (car args) newargs)
  9981. (union (list x) F))))))
  9982. (else
  9983. (loop (cdr args)
  9984. (cons (car args) newargs)
  9985. F))))))
  9986. (else
  9987. (error 'scan-rhs (make-readable E)))))
  9988. (call-with-values
  9989. (lambda () (scan E env available))
  9990. (lambda (E F regbindings)
  9991. (call-with-values
  9992. (lambda () (wrap-with-register-bindings regbindings E F))
  9993. (lambda (E F)
  9994. (values E F '()))))))
  9995. (call-with-values
  9996. (lambda ()
  9997. (scan-body E
  9998. (make-hashtree symbol-hash assq)
  9999. (make-available-table)
  10000. '()))
  10001. (lambda (E F regbindings)
  10002. (if (not (null? regbindings))
  10003. (error 'scan-body))
  10004. E)))))
  10005. ; Copyright 1999 William D Clinger.
  10006. ;
  10007. ; Permission to copy this software, in whole or in part, to use this
  10008. ; software for any lawful noncommercial purpose, and to redistribute
  10009. ; this software is granted subject to the restriction that all copies
  10010. ; made of this software must include this copyright notice in full.
  10011. ;
  10012. ; I also request that you send me a copy of any improvements that you
  10013. ; make to this software so that they may be incorporated within it to
  10014. ; the benefit of the Scheme community.
  10015. ;
  10016. ; 16 June 1999.
  10017. ;
  10018. ; Intraprocedural representation inference.
  10019. (define (representation-analysis exp)
  10020. (let* ((debugging? #f)
  10021. (integrate-usual? (integrate-usual-procedures))
  10022. (known (make-hashtable symbol-hash assq))
  10023. (types (make-hashtable symbol-hash assq))
  10024. (g (callgraph exp))
  10025. (schedule (list (callgraphnode.code (car g))))
  10026. (changed? #f)
  10027. (mutate? #f))
  10028. ; known is a hashtable that maps the name of a known local procedure
  10029. ; to a list of the form (tv1 ... tvN), where tv1, ..., tvN
  10030. ; are type variables that stand for the representation types of its
  10031. ; arguments. The type variable that stands for the representation
  10032. ; type of the result of the procedure has the same name as the
  10033. ; procedure itself.
  10034. ; types is a hashtable that maps local variables and the names
  10035. ; of known local procedures to an approximation of their
  10036. ; representation type.
  10037. ; For a known local procedure, the representation type is for the
  10038. ; result of the procedure, not the procedure itself.
  10039. ; schedule is a stack of work that needs to be done.
  10040. ; Each entry in the stack is either an escaping lambda expression
  10041. ; or the name of a known local procedure.
  10042. (define (schedule! job)
  10043. (if (not (memq job schedule))
  10044. (begin (set! schedule (cons job schedule))
  10045. (if (not (symbol? job))
  10046. (callgraphnode.info! (lookup-node job) #t)))))
  10047. ; Schedules a known local procedure.
  10048. (define (schedule-known-procedure! name)
  10049. ; Mark every known procedure that can actually be called.
  10050. (callgraphnode.info! (assq name g) #t)
  10051. (schedule! name))
  10052. ; Schedule all code that calls the given known local procedure.
  10053. (define (schedule-callers! name)
  10054. (for-each (lambda (node)
  10055. (if (and (callgraphnode.info node)
  10056. (or (memq name (callgraphnode.tailcalls node))
  10057. (memq name (callgraphnode.nontailcalls node))))
  10058. (let ((caller (callgraphnode.name node)))
  10059. (if caller
  10060. (schedule! caller)
  10061. (schedule! (callgraphnode.code node))))))
  10062. g))
  10063. ; Schedules local procedures of a lambda expression.
  10064. (define (schedule-local-procedures! L)
  10065. (for-each (lambda (def)
  10066. (let ((name (def.lhs def)))
  10067. (if (known-procedure-is-callable? name)
  10068. (schedule! name))))
  10069. (lambda.defs L)))
  10070. ; Returns true iff the given known procedure is known to be callable.
  10071. (define (known-procedure-is-callable? name)
  10072. (callgraphnode.info (assq name g)))
  10073. ; Sets CHANGED? to #t and returns #t if the type variable's
  10074. ; approximation has changed; otherwise returns #f.
  10075. (define (update-typevar! tv type)
  10076. (let* ((type0 (hashtable-get types tv))
  10077. (type0 (or type0
  10078. (begin (hashtable-put! types tv rep:bottom)
  10079. rep:bottom)))
  10080. (type1 (representation-union type0 type)))
  10081. (if (eq? type0 type1)
  10082. #f
  10083. (begin (hashtable-put! types tv type1)
  10084. (set! changed? #t)
  10085. (if (and debugging? mutate?)
  10086. (begin (display "******** Changing type of ")
  10087. (display tv)
  10088. (display " from ")
  10089. (display (rep->symbol type0))
  10090. (display " to ")
  10091. (display (rep->symbol type1))
  10092. (newline)))
  10093. #t))))
  10094. ; GIven the name of a known local procedure, returns its code.
  10095. (define (lookup-code name)
  10096. (callgraphnode.code (assq name g)))
  10097. ; Given a lambda expression, either escaping or the code for
  10098. ; a known local procedure, returns its node in the call graph.
  10099. (define (lookup-node L)
  10100. (let loop ((g g))
  10101. (cond ((null? g)
  10102. (error "Unknown lambda expression" (make-readable L #t)))
  10103. ((eq? L (callgraphnode.code (car g)))
  10104. (car g))
  10105. (else
  10106. (loop (cdr g))))))
  10107. ; Given: a type variable, expression, and a set of constraints.
  10108. ; Side effects:
  10109. ; Update the representation types of all variables that are
  10110. ; bound within the expression.
  10111. ; Update the representation types of all arguments to known
  10112. ; local procedures that are called within the expression.
  10113. ; If the representation type of an argument to a known local
  10114. ; procedure changes, then schedule that procedure's code
  10115. ; for analysis.
  10116. ; Update the constraint set to reflect the constraints that
  10117. ; hold following execution of the expression.
  10118. ; If mutate? is true, then transform the expression to rely
  10119. ; on the representation types that have been inferred.
  10120. ; Return: type of the expression under the current assumptions
  10121. ; and constraints.
  10122. (define (analyze exp constraints)
  10123. (if (and #f debugging?)
  10124. (begin (display "Analyzing: ")
  10125. (newline)
  10126. (pretty-print (make-readable exp #t))
  10127. (newline)))
  10128. (case (car exp)
  10129. ((quote)
  10130. (representation-of-value (constant.value exp)))
  10131. ((begin)
  10132. (let* ((name (variable.name exp)))
  10133. (representation-typeof name types constraints)))
  10134. ((lambda)
  10135. (schedule! exp)
  10136. rep:procedure)
  10137. ((set!)
  10138. (analyze (assignment.rhs exp) constraints)
  10139. (constraints-kill! constraints available:killer:globals)
  10140. rep:object)
  10141. ((if)
  10142. (let* ((E0 (if.test exp))
  10143. (E1 (if.then exp))
  10144. (E2 (if.else exp))
  10145. (type0 (analyze E0 constraints)))
  10146. (if mutate?
  10147. (cond ((representation-subtype? type0 rep:true)
  10148. (if.test-set! exp (make-constant #t)))
  10149. ((representation-subtype? type0 rep:false)
  10150. (if.test-set! exp (make-constant #f)))))
  10151. (cond ((representation-subtype? type0 rep:true)
  10152. (analyze E1 constraints))
  10153. ((representation-subtype? type0 rep:false)
  10154. (analyze E2 constraints))
  10155. ((variable? E0)
  10156. (let* ((T0 (variable.name E0))
  10157. (ignored (analyze E0 constraints))
  10158. (constraints1 (copy-constraints-table constraints))
  10159. (constraints2 (copy-constraints-table constraints)))
  10160. (constraints-add! types
  10161. constraints1
  10162. (make-type-constraint
  10163. T0 rep:true available:killer:immortal))
  10164. (constraints-add! types
  10165. constraints2
  10166. (make-type-constraint
  10167. T0 rep:false available:killer:immortal))
  10168. (let* ((type1 (analyze E1 constraints1))
  10169. (type2 (analyze E2 constraints2))
  10170. (type (representation-union type1 type2)))
  10171. (constraints-intersect! constraints
  10172. constraints1
  10173. constraints2)
  10174. type)))
  10175. (else
  10176. (representation-error "Bad ANF" (make-readable exp #t))))))
  10177. (else
  10178. (let ((proc (call.proc exp))
  10179. (args (call.args exp)))
  10180. (cond ((lambda? proc)
  10181. (cond ((null? args)
  10182. (analyze-let0 exp constraints))
  10183. ((null? (cdr args))
  10184. (analyze-let1 exp constraints))
  10185. (else
  10186. (error "Compiler bug: pass3rep"))))
  10187. ((variable? proc)
  10188. (let* ((procname (variable.name proc)))
  10189. (cond ((hashtable-get known procname)
  10190. =>
  10191. (lambda (vars)
  10192. (analyze-known-call exp constraints vars)))
  10193. (integrate-usual?
  10194. (let ((entry (prim-entry procname)))
  10195. (if entry
  10196. (analyze-primop-call exp constraints entry)
  10197. (analyze-unknown-call exp constraints))))
  10198. (else
  10199. (analyze-unknown-call exp constraints)))))
  10200. (else
  10201. (analyze-unknown-call exp constraints)))))))
  10202. (define (analyze-let0 exp constraints)
  10203. (let ((proc (call.proc exp)))
  10204. (schedule-local-procedures! proc)
  10205. (if (null? (lambda.args proc))
  10206. (analyze (lambda.body exp) constraints)
  10207. (analyze-unknown-call exp constraints))))
  10208. (define (analyze-let1 exp constraints)
  10209. (let* ((proc (call.proc exp))
  10210. (vars (lambda.args proc)))
  10211. (schedule-local-procedures! proc)
  10212. (if (and (pair? vars)
  10213. (null? (cdr vars)))
  10214. (let* ((T1 (car vars))
  10215. (E1 (car (call.args exp))))
  10216. (if (and integrate-usual? (call? E1))
  10217. (let ((proc (call.proc E1))
  10218. (args (call.args E1)))
  10219. (if (variable? proc)
  10220. (let* ((op (variable.name proc))
  10221. (entry (prim-entry op))
  10222. (K1 (if entry
  10223. (prim-lives-until entry)
  10224. available:killer:dead)))
  10225. (if (not (= K1 available:killer:dead))
  10226. ; Must copy the call to avoid problems
  10227. ; with side effects when mutate? is true.
  10228. (constraints-add!
  10229. types
  10230. constraints
  10231. (make-constraint T1
  10232. (make-call proc args)
  10233. K1)))))))
  10234. (update-typevar! T1 (analyze E1 constraints))
  10235. (analyze (lambda.body proc) constraints))
  10236. (analyze-unknown-call exp constraints))))
  10237. (define (analyze-primop-call exp constraints entry)
  10238. (let* ((op (prim-opcodename entry))
  10239. (args (call.args exp))
  10240. (argtypes (map (lambda (arg) (analyze arg constraints))
  10241. args))
  10242. (type (rep-result? op argtypes)))
  10243. (constraints-kill! constraints (prim-kills entry))
  10244. (cond ((and (eq? op 'check!)
  10245. (variable? (car args)))
  10246. (let ((varname (variable.name (car args))))
  10247. (if (and mutate?
  10248. (representation-subtype? (car argtypes) rep:true))
  10249. (call.args-set! exp
  10250. (cons (make-constant #t) (cdr args))))
  10251. (constraints-add! types
  10252. constraints
  10253. (make-type-constraint
  10254. varname
  10255. rep:true
  10256. available:killer:immortal))))
  10257. ((and mutate? (rep-specific? op argtypes))
  10258. =>
  10259. (lambda (newop)
  10260. (call.proc-set! exp (make-variable newop)))))
  10261. (or type rep:object)))
  10262. (define (analyze-known-call exp constraints vars)
  10263. (let* ((procname (variable.name (call.proc exp)))
  10264. (args (call.args exp))
  10265. (argtypes (map (lambda (arg) (analyze arg constraints))
  10266. args)))
  10267. (if (not (known-procedure-is-callable? procname))
  10268. (schedule-known-procedure! procname))
  10269. (for-each (lambda (var type)
  10270. (if (update-typevar! var type)
  10271. (schedule-known-procedure! procname)))
  10272. vars
  10273. argtypes)
  10274. ; FIXME: We aren't analyzing the effects of known local procedures.
  10275. (constraints-kill! constraints available:killer:all)
  10276. (hashtable-get types procname)))
  10277. (define (analyze-unknown-call exp constraints)
  10278. (analyze (call.proc exp) constraints)
  10279. (for-each (lambda (arg) (analyze arg constraints))
  10280. (call.args exp))
  10281. (constraints-kill! constraints available:killer:all)
  10282. rep:object)
  10283. (define (analyze-known-local-procedure name)
  10284. (if debugging?
  10285. (begin (display "Analyzing ")
  10286. (display name)
  10287. (newline)))
  10288. (let ((L (lookup-code name))
  10289. (constraints (make-constraints-table)))
  10290. (schedule-local-procedures! L)
  10291. (let ((type (analyze (lambda.body L) constraints)))
  10292. (if (update-typevar! name type)
  10293. (schedule-callers! name))
  10294. type)))
  10295. (define (analyze-unknown-lambda L)
  10296. (if debugging?
  10297. (begin (display "Analyzing escaping lambda expression")
  10298. (newline)))
  10299. (schedule-local-procedures! L)
  10300. (let ((vars (make-null-terminated (lambda.args L))))
  10301. (for-each (lambda (var)
  10302. (hashtable-put! types var rep:object))
  10303. vars)
  10304. (analyze (lambda.body L)
  10305. (make-constraints-table))))
  10306. ; For debugging.
  10307. (define (display-types)
  10308. (hashtable-for-each (lambda (f vars)
  10309. (write f)
  10310. (display " : returns ")
  10311. (write (rep->symbol (hashtable-get types f)))
  10312. (newline)
  10313. (for-each (lambda (x)
  10314. (display " ")
  10315. (write x)
  10316. (display ": ")
  10317. (write (rep->symbol
  10318. (hashtable-get types x)))
  10319. (newline))
  10320. vars))
  10321. known))
  10322. (define (display-all-types)
  10323. (let* ((vars (hashtable-map (lambda (x type) x) types))
  10324. (vars (twobit-sort (lambda (var1 var2)
  10325. (string<=? (symbol->string var1)
  10326. (symbol->string var2)))
  10327. vars)))
  10328. (for-each (lambda (x)
  10329. (write x)
  10330. (display ": ")
  10331. (write (rep->symbol
  10332. (hashtable-get types x)))
  10333. (newline))
  10334. vars)))
  10335. '
  10336. (if debugging?
  10337. (begin (pretty-print (make-readable (car schedule) #t))
  10338. (newline)))
  10339. (if debugging?
  10340. (view-callgraph g))
  10341. (for-each (lambda (node)
  10342. (let* ((name (callgraphnode.name node))
  10343. (code (callgraphnode.code node))
  10344. (vars (make-null-terminated (lambda.args code)))
  10345. (known? (symbol? name))
  10346. (rep (if known? rep:bottom rep:object)))
  10347. (callgraphnode.info! node #f)
  10348. (if known?
  10349. (begin (hashtable-put! known name vars)
  10350. (hashtable-put! types name rep)))
  10351. (for-each (lambda (var)
  10352. (hashtable-put! types var rep))
  10353. vars)))
  10354. g)
  10355. (let loop ()
  10356. (cond ((not (null? schedule))
  10357. (let ((job (car schedule)))
  10358. (set! schedule (cdr schedule))
  10359. (if (symbol? job)
  10360. (analyze-known-local-procedure job)
  10361. (analyze-unknown-lambda job))
  10362. (loop)))
  10363. (changed?
  10364. (set! changed? #f)
  10365. (set! schedule (list (callgraphnode.code (car g))))
  10366. (if debugging?
  10367. (begin (display-all-types) (newline)))
  10368. (loop))))
  10369. (if debugging?
  10370. (display-types))
  10371. (set! mutate? #t)
  10372. ; We don't want to analyze known procedures that are never called.
  10373. (set! schedule
  10374. (cons (callgraphnode.code (car g))
  10375. (map callgraphnode.name
  10376. (filter (lambda (node)
  10377. (let* ((name (callgraphnode.name node))
  10378. (known? (symbol? name))
  10379. (marked?
  10380. (known-procedure-is-callable? name)))
  10381. (callgraphnode.info! node #f)
  10382. (and known? marked?)))
  10383. g))))
  10384. (let loop ()
  10385. (if (not (null? schedule))
  10386. (let ((job (car schedule)))
  10387. (set! schedule (cdr schedule))
  10388. (if (symbol? job)
  10389. (analyze-known-local-procedure job)
  10390. (analyze-unknown-lambda job))
  10391. (loop))))
  10392. (if changed?
  10393. (error "Compiler bug in representation inference"))
  10394. (if debugging?
  10395. (pretty-print (make-readable (callgraphnode.code (car g)) #t)))
  10396. exp))
  10397. ; Copyright 1999 William D Clinger.
  10398. ;
  10399. ; Permission to copy this software, in whole or in part, to use this
  10400. ; software for any lawful noncommercial purpose, and to redistribute
  10401. ; this software is granted subject to the restriction that all copies
  10402. ; made of this software must include this copyright notice in full.
  10403. ;
  10404. ; I also request that you send me a copy of any improvements that you
  10405. ; make to this software so that they may be incorporated within it to
  10406. ; the benefit of the Scheme community.
  10407. ;
  10408. ; 11 June 1999.
  10409. ;
  10410. ; The third "pass" of the Twobit compiler actually consists of several
  10411. ; passes, which are related by the common theme of flow analysis:
  10412. ; interprocedural inlining of known local procedures
  10413. ; interprocedural constant propagation and folding
  10414. ; intraprocedural commoning, copy propagation, and dead code elimination
  10415. ; representation inference (not yet implemented)
  10416. ; register targeting
  10417. ;
  10418. ; This pass operates as source-to-source transformations on
  10419. ; expressions written in the subset of Scheme described by the
  10420. ; following grammar:
  10421. ;
  10422. ; "X ..." means zero or more occurrences of X.
  10423. ;
  10424. ; L --> (lambda (I_1 ...)
  10425. ; (begin D ...)
  10426. ; (quote (R F G <decls> <doc>)
  10427. ; E)
  10428. ; | (lambda (I_1 ... . I_rest)
  10429. ; (begin D ...)
  10430. ; (quote (R F G <decls> <doc>))
  10431. ; E)
  10432. ; D --> (define I L)
  10433. ; E --> (quote K) ; constants
  10434. ; | (begin I) ; variable references
  10435. ; | L ; lambda expressions
  10436. ; | (E0 E1 ...) ; calls
  10437. ; | (set! I E) ; assignments
  10438. ; | (if E0 E1 E2) ; conditionals
  10439. ; | (begin E0 E1 E2 ...) ; sequential expressions
  10440. ; I --> <identifier>
  10441. ;
  10442. ; R --> ((I <references> <assignments> <calls>) ...)
  10443. ; F --> (I ...)
  10444. ; G --> (I ...)
  10445. ;
  10446. ; Invariants that hold for the input only:
  10447. ; * There are no assignments except to global variables.
  10448. ; * If I is declared by an internal definition, then the right hand
  10449. ; side of the internal definition is a lambda expression and I
  10450. ; is referenced only in the procedure position of a call.
  10451. ; * R, F, and G are garbage.
  10452. ; * Variables named IGNORED are neither referenced nor assigned.
  10453. ; * The expression does not share structure with the original input,
  10454. ; but might share structure with itself.
  10455. ;
  10456. ; Invariants that hold for the output only:
  10457. ; * There are no assignments except to global variables.
  10458. ; * If I is declared by an internal definition, then the right hand
  10459. ; side of the internal definition is a lambda expression and I
  10460. ; is referenced only in the procedure position of a call.
  10461. ; * R is garbage.
  10462. ; * For each lambda expression, the associated F is a list of all
  10463. ; the identifiers that occur free in the body of that lambda
  10464. ; expression, and possibly a few extra identifiers that were
  10465. ; once free but have been removed by optimization.
  10466. ; * If a lambda expression is declared to be in A-normal form (see
  10467. ; pass3anormal.sch), then it really is in A-normal form.
  10468. ;
  10469. ; The phases of pass 3 interact with the referencing information R
  10470. ; and the free variables F as follows:
  10471. ;
  10472. ; Inlining ignores R, ignores F, destroys R, destroys F.
  10473. ; Constant propagation uses R, ignores F, preserves R, preserves F.
  10474. ; Conversion to ANF ignores R, ignores F, destroys R, destroys F.
  10475. ; Commoning ignores R, ignores F, destroys R, computes F.
  10476. ; Register targeting ignores R, ignores F, destroys R, computes F.
  10477. (define (pass3 exp)
  10478. (define (phase1 exp)
  10479. (if (interprocedural-inlining)
  10480. (let ((g (callgraph exp)))
  10481. (inline-using-callgraph! g)
  10482. exp)
  10483. exp))
  10484. (define (phase2 exp)
  10485. (if (interprocedural-constant-propagation)
  10486. (constant-propagation (copy-exp exp))
  10487. exp))
  10488. (define (phase3 exp)
  10489. (if (common-subexpression-elimination)
  10490. (let* ((exp (if (interprocedural-constant-propagation)
  10491. exp
  10492. ; alpha-conversion
  10493. (copy-exp exp)))
  10494. (exp (a-normal-form exp)))
  10495. (if (representation-inference)
  10496. (intraprocedural-commoning exp 'commoning)
  10497. (intraprocedural-commoning exp)))
  10498. exp))
  10499. (define (phase4 exp)
  10500. (if (representation-inference)
  10501. (let ((exp (cond ((common-subexpression-elimination)
  10502. exp)
  10503. ((interprocedural-constant-propagation)
  10504. (a-normal-form exp))
  10505. (else
  10506. ; alpha-conversion
  10507. (a-normal-form (copy-exp exp))))))
  10508. (intraprocedural-commoning
  10509. (representation-analysis exp)))
  10510. exp))
  10511. (define (finish exp)
  10512. (if (and (not (interprocedural-constant-propagation))
  10513. (not (common-subexpression-elimination)))
  10514. (begin (compute-free-variables! exp)
  10515. exp)
  10516. ;(make-begin (list (make-constant 'anf) exp))))
  10517. exp))
  10518. (define (verify exp)
  10519. (check-referencing-invariants exp 'free)
  10520. exp)
  10521. (if (global-optimization)
  10522. (verify (finish (phase4 (phase3 (phase2 (phase1 exp))))))
  10523. (begin (compute-free-variables! exp)
  10524. (verify exp))))
  10525. ; Copyright 1991 Lightship Software, Incorporated.
  10526. ;
  10527. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  10528. ;
  10529. ; 4 June 1999
  10530. ; Implements the following abstract data types.
  10531. ;
  10532. ; labels
  10533. ; (init-labels)
  10534. ; (make-label)
  10535. ; cg-label-counter
  10536. ;
  10537. ; assembly streams
  10538. ; (make-assembly-stream)
  10539. ; (assembly-stream-code as)
  10540. ; (gen! as . instruction)
  10541. ; (gen-instruction! as instruction)
  10542. ; (gen-save! as frame)
  10543. ; (gen-restore! as frame)
  10544. ; (gen-pop! as frame)
  10545. ; (gen-setstk! as frame v)
  10546. ; (gen-store! as frame r v)
  10547. ; (gen-load! as frame r v)
  10548. ; (gen-stack! as frame v)
  10549. ;
  10550. ; temporaries
  10551. ; (init-temps)
  10552. ; (newtemp)
  10553. ; (newtemps)
  10554. ; newtemp-counter
  10555. ;
  10556. ; register environments
  10557. ; (cgreg-initial)
  10558. ; (cgreg-copy regs)
  10559. ; (cgreg-tos regs)
  10560. ; (cgreg-liveregs regs)
  10561. ; (cgreg-live regs r)
  10562. ; (cgreg-vars regs)
  10563. ; (cgreg-bind! regs r v)
  10564. ; (cgreg-bindregs! regs vars)
  10565. ; (cgreg-rename! regs alist)
  10566. ; (cgreg-release! regs r)
  10567. ; (cgreg-clear! regs)
  10568. ; (cgreg-lookup regs var)
  10569. ; (cgreg-lookup-reg regs r)
  10570. ; (cgreg-join! regs1 regs2)
  10571. ;
  10572. ; stack frame environments
  10573. ; (cgframe-initial)
  10574. ; (cgframe-size-cell frame)
  10575. ; (cgframe-size frame)
  10576. ; (cgframe-copy frame)
  10577. ; (cgframe-join! frame1 frame2)
  10578. ; (cgframe-update-stale! frame)
  10579. ; (cgframe-used! frame)
  10580. ; (cgframe-bind! frame n v instruction)
  10581. ; (cgframe-touch! frame v)
  10582. ; (cgframe-rename! frame alist)
  10583. ; (cgframe-release! frame v)
  10584. ; (cgframe-lookup frame v)
  10585. ; (cgframe-spilled? frame v)
  10586. ;
  10587. ; environments
  10588. ; (entry.name entry)
  10589. ; (entry.kind entry)
  10590. ; (entry.rib entry)
  10591. ; (entry.offset entry)
  10592. ; (entry.label entry)
  10593. ; (entry.regnum entry)
  10594. ; (entry.arity entry)
  10595. ; (entry.op entry)
  10596. ; (entry.imm entry)
  10597. ; (cgenv-initial)
  10598. ; (cgenv-lookup env id)
  10599. ; (cgenv-extend env vars procs)
  10600. ; (cgenv-bindprocs env procs)
  10601. ; (var-lookup var regs frame env)
  10602. ; Labels.
  10603. (define (init-labels)
  10604. (set! cg-label-counter 1000))
  10605. (define (make-label)
  10606. (set! cg-label-counter (+ cg-label-counter 1))
  10607. cg-label-counter)
  10608. (define cg-label-counter 1000)
  10609. ; an assembly stream into which instructions should be emitted
  10610. ; an expression
  10611. ; the desired target register ('result, a register number, or '#f)
  10612. ; a register environment [cgreg]
  10613. ; a stack-frame environment [cgframe]
  10614. ; contains size of frame, current top of frame
  10615. ; a compile-time environment [cgenv]
  10616. ; a flag indicating whether the expression is in tail position
  10617. ; Assembly streams, into which instructions are emitted by side effect.
  10618. ; Represented as a list of two things:
  10619. ;
  10620. ; Assembly code, represented as a pair whose car is a nonempty list
  10621. ; whose cdr is a possibly empty list of MacScheme machine assembly
  10622. ; instructions, and whose cdr is the last pair of the car.
  10623. ;
  10624. ; Any Scheme object that the code generator wants to associate with
  10625. ; this code.
  10626. (define (make-assembly-stream)
  10627. (let ((code (list (list 0))))
  10628. (set-cdr! code (car code))
  10629. (list code #f)))
  10630. (define (assembly-stream-code output)
  10631. (if (local-optimizations)
  10632. (filter-basic-blocks (cdar (car output)))
  10633. (cdar (car output))))
  10634. (define (assembly-stream-info output)
  10635. (cadr output))
  10636. (define (assembly-stream-info! output x)
  10637. (set-car! (cdr output) x)
  10638. #f)
  10639. (define (gen-instruction! output instruction)
  10640. (let ((pair (list instruction))
  10641. (code (car output)))
  10642. (set-cdr! (cdr code) pair)
  10643. (set-cdr! code pair)
  10644. output))
  10645. ;
  10646. (define (gen! output . instruction)
  10647. (gen-instruction! output instruction))
  10648. (define (gen-save! output frame t0)
  10649. (let ((size (cgframe-size-cell frame)))
  10650. (gen-instruction! output (cons $save size))
  10651. (gen-store! output frame 0 t0)
  10652. (cgframe:stale-set! frame '())))
  10653. (define (gen-restore! output frame)
  10654. (let ((size (cgframe-size-cell frame)))
  10655. (gen-instruction! output (cons $restore size))))
  10656. (define (gen-pop! output frame)
  10657. (let ((size (cgframe-size-cell frame)))
  10658. (gen-instruction! output (cons $pop size))))
  10659. (define (gen-setstk! output frame tempname)
  10660. (let ((instruction (list $nop $setstk -1)))
  10661. (cgframe-bind! frame tempname instruction)
  10662. (gen-instruction! output instruction)))
  10663. (define (gen-store! output frame r tempname)
  10664. (let ((instruction (list $nop $store r -1)))
  10665. (cgframe-bind! frame tempname instruction)
  10666. (gen-instruction! output instruction)))
  10667. (define (gen-load! output frame r tempname)
  10668. (cgframe-touch! frame tempname)
  10669. (let ((n (entry.slotnum (cgframe-lookup frame tempname))))
  10670. (gen! output $load r n)))
  10671. (define (gen-stack! output frame tempname)
  10672. (cgframe-touch! frame tempname)
  10673. (let ((n (entry.slotnum (cgframe-lookup frame tempname))))
  10674. (gen! output $stack n)))
  10675. ; Returns a temporary name.
  10676. ; Temporaries are compared using EQ?, so the use of small
  10677. ; exact integers as temporary names is implementation-dependent.
  10678. (define (init-temps)
  10679. (set! newtemp-counter 5000))
  10680. (define (newtemp)
  10681. (set! newtemp-counter
  10682. (+ newtemp-counter 1))
  10683. newtemp-counter)
  10684. (define newtemp-counter 5000)
  10685. (define (newtemps n)
  10686. (if (zero? n)
  10687. '()
  10688. (cons (newtemp)
  10689. (newtemps (- n 1)))))
  10690. ; New representation of
  10691. ; Register environments.
  10692. ; Represented as a list of three items:
  10693. ; an exact integer, one more than the highest index of a live register
  10694. ; a mutable vector with *nregs* elements of the form
  10695. ; #f (the register is dead)
  10696. ; #t (the register is live)
  10697. ; v (the register contains variable v)
  10698. ; t (the register contains temporary variable t)
  10699. ; a mutable vector of booleans: true if the register might be stale
  10700. (define (cgreg-makeregs n v1 v2) (list n v1 v2))
  10701. (define (cgreg-liveregs regs)
  10702. (car regs))
  10703. (define (cgreg-contents regs)
  10704. (cadr regs))
  10705. (define (cgreg-stale regs)
  10706. (caddr regs))
  10707. (define (cgreg-liveregs-set! regs n)
  10708. (set-car! regs n)
  10709. regs)
  10710. (define (cgreg-initial)
  10711. (let ((v1 (make-vector *nregs* #f))
  10712. (v2 (make-vector *nregs* #f)))
  10713. (cgreg-makeregs 0 v1 v2)))
  10714. (define (cgreg-copy regs)
  10715. (let* ((newregs (cgreg-initial))
  10716. (v1a (cgreg-contents regs))
  10717. (v2a (cgreg-stale regs))
  10718. (v1 (cgreg-contents newregs))
  10719. (v2 (cgreg-stale newregs))
  10720. (n (vector-length v1a)))
  10721. (cgreg-liveregs-set! newregs (cgreg-liveregs regs))
  10722. (do ((i 0 (+ i 1)))
  10723. ((= i n)
  10724. newregs)
  10725. (vector-set! v1 i (vector-ref v1a i))
  10726. (vector-set! v2 i (vector-ref v2a i)))))
  10727. (define (cgreg-tos regs)
  10728. (- (cgreg-liveregs regs) 1))
  10729. (define (cgreg-live regs r)
  10730. (if (eq? r 'result)
  10731. (cgreg-tos regs)
  10732. (max r (cgreg-tos regs))))
  10733. (define (cgreg-vars regs)
  10734. (let ((m (cgreg-liveregs regs))
  10735. (v (cgreg-contents regs)))
  10736. (do ((i (- m 1) (- i 1))
  10737. (vars '()
  10738. (cons (vector-ref v i)
  10739. vars)))
  10740. ((< i 0)
  10741. vars))))
  10742. (define (cgreg-bind! regs r t)
  10743. (let ((m (cgreg-liveregs regs))
  10744. (v (cgreg-contents regs)))
  10745. (vector-set! v r t)
  10746. (if (>= r m)
  10747. (cgreg-liveregs-set! regs (+ r 1)))))
  10748. (define (cgreg-bindregs! regs vars)
  10749. (do ((m (cgreg-liveregs regs) (+ m 1))
  10750. (v (cgreg-contents regs))
  10751. (vars vars (cdr vars)))
  10752. ((null? vars)
  10753. (cgreg-liveregs-set! regs m)
  10754. regs)
  10755. (vector-set! v m (car vars))))
  10756. (define (cgreg-rename! regs alist)
  10757. (do ((i (- (cgreg-liveregs regs) 1) (- i 1))
  10758. (v (cgreg-contents regs)))
  10759. ((negative? i))
  10760. (let ((var (vector-ref v i)))
  10761. (if var
  10762. (let ((probe (assv var alist)))
  10763. (if probe
  10764. (vector-set! v i (cdr probe))))))))
  10765. (define (cgreg-release! regs r)
  10766. (let ((m (cgreg-liveregs regs))
  10767. (v (cgreg-contents regs)))
  10768. (vector-set! v r #f)
  10769. (vector-set! (cgreg-stale regs) r #t)
  10770. (if (= r (- m 1))
  10771. (do ((m r (- m 1)))
  10772. ((or (negative? m)
  10773. (vector-ref v m))
  10774. (cgreg-liveregs-set! regs (+ m 1)))))))
  10775. (define (cgreg-release-except! regs vars)
  10776. (do ((i (- (cgreg-liveregs regs) 1) (- i 1))
  10777. (v (cgreg-contents regs)))
  10778. ((negative? i))
  10779. (let ((var (vector-ref v i)))
  10780. (if (and var (not (memq var vars)))
  10781. (cgreg-release! regs i)))))
  10782. (define (cgreg-clear! regs)
  10783. (let ((m (cgreg-liveregs regs))
  10784. (v1 (cgreg-contents regs))
  10785. (v2 (cgreg-stale regs)))
  10786. (do ((r 0 (+ r 1)))
  10787. ((= r m)
  10788. (cgreg-liveregs-set! regs 0))
  10789. (vector-set! v1 r #f)
  10790. (vector-set! v2 r #t))))
  10791. (define (cgreg-lookup regs var)
  10792. (let ((m (cgreg-liveregs regs))
  10793. (v (cgreg-contents regs)))
  10794. (define (loop i)
  10795. (cond ((< i 0)
  10796. #f)
  10797. ((eq? var (vector-ref v i))
  10798. (list var 'register i '(object)))
  10799. (else
  10800. (loop (- i 1)))))
  10801. (loop (- m 1))))
  10802. (define (cgreg-lookup-reg regs r)
  10803. (let ((m (cgreg-liveregs regs))
  10804. (v (cgreg-contents regs)))
  10805. (if (<= m r)
  10806. #f
  10807. (vector-ref v r))))
  10808. (define (cgreg-join! regs1 regs2)
  10809. (let ((m1 (cgreg-liveregs regs1))
  10810. (m2 (cgreg-liveregs regs2))
  10811. (v1 (cgreg-contents regs1))
  10812. (v2 (cgreg-contents regs2))
  10813. (stale1 (cgreg-stale regs1)))
  10814. (do ((i (- (max m1 m2) 1) (- i 1)))
  10815. ((< i 0)
  10816. (cgreg-liveregs-set! regs1 (min m1 m2)))
  10817. (let ((x1 (vector-ref v1 i))
  10818. (x2 (vector-ref v2 i)))
  10819. (cond ((eq? x1 x2)
  10820. #t)
  10821. ((not x1)
  10822. (if x2
  10823. (vector-set! stale1 i #t)))
  10824. (else
  10825. (vector-set! v1 i #f)
  10826. (vector-set! stale1 i #t)))))))
  10827. ; New representation of
  10828. ; Stack-frame environments.
  10829. ; Represented as a three-element list.
  10830. ;
  10831. ; Its car is a list whose car is a list of slot entries, each
  10832. ; of the form
  10833. ; (v n instruction stale)
  10834. ; where
  10835. ; v is the name of a variable or temporary,
  10836. ; n is #f or a slot number,
  10837. ; instruction is a possibly phantom store or setstk instruction
  10838. ; that stores v into slot n, and
  10839. ; stale is a list of stale slot entries, each of the form
  10840. ; (#t . n)
  10841. ; or (#f . -1)
  10842. ; where slot n had been allocated, initialized, and released
  10843. ; before the store or setstk instruction was generated.
  10844. ; Slot entries are updated by side effect.
  10845. ;
  10846. ; Its cadr is the list of currently stale slots.
  10847. ;
  10848. ; Its caddr is a list of variables that are free in the continuation,
  10849. ; or #f if that information is unknown.
  10850. ; This information allows a direct-style code generator to know when
  10851. ; a slot becomes stale.
  10852. ;
  10853. ; Its cadddr is the size of the stack frame, which can be
  10854. ; increased but not decreased. The cdddr of the stack frame
  10855. ; environment is shared with the save instruction that
  10856. ; created the frame. What a horrible crock!
  10857. ; This stuff is private to the implementation of stack-frame
  10858. ; environments.
  10859. (define cgframe:slots car)
  10860. (define cgframe:stale cadr)
  10861. (define cgframe:livevars caddr)
  10862. (define cgframe:slot.name car)
  10863. (define cgframe:slot.offset cadr)
  10864. (define cgframe:slot.instruction caddr)
  10865. (define cgframe:slot.stale cadddr)
  10866. (define cgframe:slots-set! set-car!)
  10867. (define (cgframe:stale-set! frame stale)
  10868. (set-car! (cdr frame) stale))
  10869. (define (cgframe:livevars-set! frame vars)
  10870. (set-car! (cddr frame) vars))
  10871. (define cgframe:slot.name-set! set-car!)
  10872. (define (cgframe:slot.offset-set! entry n)
  10873. (let ((instruction (caddr entry)))
  10874. (if (or (not (eq? #f (cadr entry)))
  10875. (not (eq? $nop (car instruction))))
  10876. (error "Compiler bug: cgframe" entry)
  10877. (begin
  10878. (set-car! (cdr entry) n)
  10879. (set-car! instruction (cadr instruction))
  10880. (set-cdr! instruction (cddr instruction))
  10881. (if (eq? $setstk (car instruction))
  10882. (set-car! (cdr instruction) n)
  10883. (set-car! (cddr instruction) n))))))
  10884. ; Reserves a slot offset that was unused where the instruction
  10885. ; of the slot entry was generated, and returns that offset.
  10886. (define (cgframe:unused-slot frame entry)
  10887. (let* ((stale (cgframe:slot.stale entry))
  10888. (probe (assq #t stale)))
  10889. (if probe
  10890. (let ((n (cdr probe)))
  10891. (if (zero? n)
  10892. (cgframe-used! frame))
  10893. (set-car! probe #f)
  10894. n)
  10895. (let* ((cell (cgframe-size-cell frame))
  10896. (n (+ 1 (car cell))))
  10897. (set-car! cell n)
  10898. (if (zero? n)
  10899. (cgframe:unused-slot frame entry)
  10900. n)))))
  10901. ; Public entry points.
  10902. ; The runtime system requires slot 0 of a frame to contain
  10903. ; a closure whose code pointer contains the return address
  10904. ; of the frame.
  10905. ; To prevent slot 0 from being used for some other purpose,
  10906. ; we rely on a complex trick: Slot 0 is initially stale.
  10907. ; Gen-save! generates a store instruction for register 0,
  10908. ; with slot 0 as the only stale slot for that instruction;
  10909. ; then gen-save! clears the frame's set of stale slots, which
  10910. ; prevents other store instructions from using slot 0.
  10911. (define (cgframe-initial)
  10912. (list '()
  10913. (list (cons #t 0))
  10914. '#f
  10915. -1))
  10916. (define cgframe-livevars cgframe:livevars)
  10917. (define cgframe-livevars-set! cgframe:livevars-set!)
  10918. (define (cgframe-size-cell frame)
  10919. (cdddr frame))
  10920. (define (cgframe-size frame)
  10921. (car (cgframe-size-cell frame)))
  10922. (define (cgframe-used! frame)
  10923. (if (negative? (cgframe-size frame))
  10924. (set-car! (cgframe-size-cell frame) 0)))
  10925. ; Called only by gen-store!, gen-setstk!
  10926. (define (cgframe-bind! frame var instruction)
  10927. (cgframe:slots-set! frame
  10928. (cons (list var #f instruction (cgframe:stale frame))
  10929. (cgframe:slots frame))))
  10930. ; Called only by gen-load!, gen-stack!
  10931. (define (cgframe-touch! frame var)
  10932. (let ((entry (assq var (cgframe:slots frame))))
  10933. (if entry
  10934. (let ((n (cgframe:slot.offset entry)))
  10935. (if (eq? #f n)
  10936. (let ((n (cgframe:unused-slot frame entry)))
  10937. (cgframe:slot.offset-set! entry n))))
  10938. (error "Compiler bug: cgframe-touch!" frame var))))
  10939. (define (cgframe-rename! frame alist)
  10940. (for-each (lambda (entry)
  10941. (let ((probe (assq (cgframe:slot.name entry) alist)))
  10942. (if probe
  10943. (cgframe:slot.name-set! entry (cdr probe)))))
  10944. (cgframe:slots frame)))
  10945. (define (cgframe-release! frame var)
  10946. (let* ((slots (cgframe:slots frame))
  10947. (entry (assq var slots)))
  10948. (if entry
  10949. (begin (cgframe:slots-set! frame (remq entry slots))
  10950. (let ((n (cgframe:slot.offset entry)))
  10951. (if (and (not (eq? #f n))
  10952. (not (zero? n)))
  10953. (cgframe:stale-set!
  10954. frame
  10955. (cons (cons #t n)
  10956. (cgframe:stale frame)))))))))
  10957. (define (cgframe-release-except! frame vars)
  10958. (let loop ((slots (reverse (cgframe:slots frame)))
  10959. (newslots '())
  10960. (stale (cgframe:stale frame)))
  10961. (if (null? slots)
  10962. (begin (cgframe:slots-set! frame newslots)
  10963. (cgframe:stale-set! frame stale))
  10964. (let ((slot (car slots)))
  10965. (if (memq (cgframe:slot.name slot) vars)
  10966. (loop (cdr slots)
  10967. (cons slot newslots)
  10968. stale)
  10969. (let ((n (cgframe:slot.offset slot)))
  10970. (cond ((eq? n #f)
  10971. (loop (cdr slots)
  10972. newslots
  10973. stale))
  10974. ((zero? n)
  10975. (loop (cdr slots)
  10976. (cons slot newslots)
  10977. stale))
  10978. (else
  10979. (loop (cdr slots)
  10980. newslots
  10981. (cons (cons #t n) stale))))))))))
  10982. (define (cgframe-lookup frame var)
  10983. (let ((entry (assq var (cgframe:slots frame))))
  10984. (if entry
  10985. (let ((n (cgframe:slot.offset entry)))
  10986. (if (eq? #f n)
  10987. (cgframe-touch! frame var))
  10988. (list var 'frame (cgframe:slot.offset entry) '(object)))
  10989. #f)))
  10990. (define (cgframe-spilled? frame var)
  10991. (let ((entry (assq var (cgframe:slots frame))))
  10992. (if entry
  10993. (let ((n (cgframe:slot.offset entry)))
  10994. (not (eq? #f n)))
  10995. #f)))
  10996. ; For a conditional expression, the then and else parts must be
  10997. ; evaluated using separate copies of the frame environment,
  10998. ; and those copies must be resolved at the join point. The
  10999. ; nature of the resolution depends upon whether the conditional
  11000. ; expression is in a tail position.
  11001. ;
  11002. ; Critical invariant:
  11003. ; Any store instructions that are generated within either arm of the
  11004. ; conditional involve variables and temporaries that are local to the
  11005. ; conditional.
  11006. ;
  11007. ; If the conditional expression is in a tail position, then a slot
  11008. ; that is stale after the test can be allocated independently by the
  11009. ; two arms of the conditional. If the conditional expression is in a
  11010. ; non-tail position, then the slot can be allocated independently
  11011. ; provided it is not a candidate destination for any previous emitted
  11012. ; store instruction.
  11013. (define (cgframe-copy frame)
  11014. (cons (car frame)
  11015. (cons (cadr frame)
  11016. (cons (caddr frame)
  11017. (cdddr frame)))))
  11018. (define (cgframe-update-stale! frame)
  11019. (let* ((n (cgframe-size frame))
  11020. (v (make-vector (+ 1 n) #t))
  11021. (stale (cgframe:stale frame)))
  11022. (for-each (lambda (x)
  11023. (if (car x)
  11024. (let ((i (cdr x)))
  11025. (if (<= i n)
  11026. (vector-set! v i #f)))))
  11027. stale)
  11028. (for-each (lambda (slot)
  11029. (let ((offset (cgframe:slot.offset slot)))
  11030. (if offset
  11031. (vector-set! v offset #f)
  11032. (for-each (lambda (stale)
  11033. (if (car stale)
  11034. (let ((i (cdr stale)))
  11035. (if (< i n)
  11036. (vector-set! v i #f)))))
  11037. (cgframe:slot.stale slot)))))
  11038. (cgframe:slots frame))
  11039. (do ((i n (- i 1))
  11040. (stale (filter car stale)
  11041. (if (vector-ref v i)
  11042. (cons (cons #t i) stale)
  11043. stale)))
  11044. ((<= i 0)
  11045. (cgframe:stale-set! frame stale)))))
  11046. (define (cgframe-join! frame1 frame2)
  11047. (let* ((slots1 (cgframe:slots frame1))
  11048. (slots2 (cgframe:slots frame2))
  11049. (slots (intersection slots1 slots2))
  11050. (deadslots (append (difference slots1 slots)
  11051. (difference slots2 slots)))
  11052. (deadoffsets (make-set
  11053. (filter (lambda (x) (not (eq? x #f)))
  11054. (map cgframe:slot.offset deadslots))))
  11055. (stale1 (cgframe:stale frame1))
  11056. (stale2 (cgframe:stale frame2))
  11057. (stale (intersection stale1 stale2))
  11058. (stale (append (map (lambda (n) (cons #t n))
  11059. deadoffsets)
  11060. stale)))
  11061. (cgframe:slots-set! frame1 slots)
  11062. (cgframe:stale-set! frame1 stale)))
  11063. ; Environments.
  11064. ;
  11065. ; Each identifier has one of the following kinds of entry.
  11066. ;
  11067. ; (<name> register <number> (object))
  11068. ; (<name> frame <slot> (object))
  11069. ; (<name> lexical <rib> <offset> (object))
  11070. ; (<name> procedure <rib> <label> (object))
  11071. ; (<name> integrable <arity> <op> <imm> (object))
  11072. ; (<name> global (object))
  11073. ;
  11074. ; Implementation.
  11075. ;
  11076. ; An environment is represented as a list of the form
  11077. ;
  11078. ; ((<entry> ...) ; lexical rib
  11079. ; ...)
  11080. ;
  11081. ; where each <entry> has one of the forms
  11082. ;
  11083. ; (<name> lexical <offset> (object))
  11084. ; (<name> procedure <rib> <label> (object))
  11085. ; (<name> integrable <arity> <op> <imm> (object))
  11086. (define entry.name car)
  11087. (define entry.kind cadr)
  11088. (define entry.rib caddr)
  11089. (define entry.offset cadddr)
  11090. (define entry.label cadddr)
  11091. (define entry.regnum caddr)
  11092. (define entry.slotnum caddr)
  11093. (define entry.arity caddr)
  11094. (define entry.op cadddr)
  11095. (define (entry.imm entry) (car (cddddr entry)))
  11096. (define (cgenv-initial integrable)
  11097. (list (map (lambda (x)
  11098. (list (car x)
  11099. 'integrable
  11100. (cadr x)
  11101. (caddr x)
  11102. (cadddr x)
  11103. '(object)))
  11104. integrable)))
  11105. (define (cgenv-lookup env id)
  11106. (define (loop ribs m)
  11107. (if (null? ribs)
  11108. (cons id '(global (object)))
  11109. (let ((x (assq id (car ribs))))
  11110. (if x
  11111. (case (cadr x)
  11112. ((lexical)
  11113. (cons id
  11114. (cons (cadr x)
  11115. (cons m (cddr x)))))
  11116. ((procedure)
  11117. (cons id
  11118. (cons (cadr x)
  11119. (cons m (cddr x)))))
  11120. ((integrable)
  11121. (if (integrate-usual-procedures)
  11122. x
  11123. (loop '() m)))
  11124. (else ???))
  11125. (loop (cdr ribs) (+ m 1))))))
  11126. (loop env 0))
  11127. (define (cgenv-extend env vars procs)
  11128. (cons (do ((n 0 (+ n 1))
  11129. (vars vars (cdr vars))
  11130. (rib (map (lambda (id)
  11131. (list id 'procedure (make-label) '(object)))
  11132. procs)
  11133. (cons (list (car vars) 'lexical n '(object)) rib)))
  11134. ((null? vars) rib))
  11135. env))
  11136. (define (cgenv-bindprocs env procs)
  11137. (cons (append (map (lambda (id)
  11138. (list id 'procedure (make-label) '(object)))
  11139. procs)
  11140. (car env))
  11141. (cdr env)))
  11142. (define (var-lookup var regs frame env)
  11143. (or (cgreg-lookup regs var)
  11144. (cgframe-lookup frame var)
  11145. (cgenv-lookup env var)))
  11146. ; Compositions.
  11147. (define compile
  11148. (lambda (x)
  11149. (pass4 (pass3 (pass2 (pass1 x))) $usual-integrable-procedures$)))
  11150. (define compile-block
  11151. (lambda (x)
  11152. (pass4 (pass3 (pass2 (pass1-block x))) $usual-integrable-procedures$)))
  11153. ; For testing.
  11154. (define foo
  11155. (lambda (x)
  11156. (pretty-print (compile x))))
  11157. ; Find the smallest number of registers such that
  11158. ; adding more registers does not affect the code
  11159. ; generated for x (from 4 to 32 registers).
  11160. (define (minregs x)
  11161. (define (defregs R)
  11162. (set! *nregs* R)
  11163. (set! *lastreg* (- *nregs* 1))
  11164. (set! *fullregs* (quotient *nregs* 2)))
  11165. (defregs 32)
  11166. (let ((code (assemble (compile x))))
  11167. (define (binary-search m1 m2)
  11168. (if (= (+ m1 1) m2)
  11169. m2
  11170. (let ((midpt (quotient (+ m1 m2) 2)))
  11171. (defregs midpt)
  11172. (if (equal? code (assemble (compile x)))
  11173. (binary-search m1 midpt)
  11174. (binary-search midpt m2)))))
  11175. (defregs 4)
  11176. (let ((newcode (assemble (compile x))))
  11177. (if (equal? code newcode)
  11178. 4
  11179. (binary-search 4 32)))))
  11180. ; Minimums:
  11181. ; browse 10
  11182. ; triangle 5
  11183. ; traverse 10
  11184. ; destruct 6
  11185. ; puzzle 8,8,10,7
  11186. ; tak 6
  11187. ; fft 28 (changing the named lets to macros didn't matter)
  11188. ; Copyright 1991 William Clinger
  11189. ;
  11190. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  11191. ;
  11192. ; 7 June 1999.
  11193. ;
  11194. ; Fourth pass of the Twobit compiler:
  11195. ; code generation for the MacScheme machine.
  11196. ;
  11197. ; This pass operates on input expressions described by the
  11198. ; following grammar and the invariants that follow it.
  11199. ;
  11200. ; "X ..." means zero or more occurrences of X.
  11201. ;
  11202. ; L --> (lambda (I_1 ...)
  11203. ; (begin D ...)
  11204. ; (quote (R F G <decls> <doc>)
  11205. ; E)
  11206. ; | (lambda (I_1 ... . I_rest)
  11207. ; (begin D ...)
  11208. ; (quote (R F G <decls> <doc>))
  11209. ; E)
  11210. ; D --> (define I L)
  11211. ; E --> (quote K) ; constants
  11212. ; | (begin I) ; variable references
  11213. ; | L ; lambda expressions
  11214. ; | (E0 E1 ...) ; calls
  11215. ; | (set! I E) ; assignments
  11216. ; | (if E0 E1 E2) ; conditionals
  11217. ; | (begin E0 E1 E2 ...) ; sequential expressions
  11218. ; I --> <identifier>
  11219. ;
  11220. ; R --> ((I <references> <assignments> <calls>) ...)
  11221. ; F --> (I ...)
  11222. ; G --> (I ...)
  11223. ;
  11224. ; Invariants that hold for the input
  11225. ; * There are no assignments except to global variables.
  11226. ; * If I is declared by an internal definition, then the right hand
  11227. ; side of the internal definition is a lambda expression and I
  11228. ; is referenced only in the procedure position of a call.
  11229. ; * Every procedure defined by an internal definition takes a
  11230. ; fixed number of arguments.
  11231. ; * Every call to a procedure defined by an internal definition
  11232. ; passes the correct number of arguments.
  11233. ; * For each lambda expression, the associated F is a list of all
  11234. ; the identifiers that occur free in the body of that lambda
  11235. ; expression, and possibly a few extra identifiers that were
  11236. ; once free but have been removed by optimization.
  11237. ; * For each lambda expression, the associated G is a subset of F
  11238. ; that contains every identifier that occurs free within some
  11239. ; inner lambda expression that escapes, and possibly a few that
  11240. ; don't. (Assignment-elimination does not calculate G exactly.)
  11241. ; * Variables named IGNORED are neither referenced nor assigned.
  11242. ; * Any lambda expression that is declared to be in A-normal form
  11243. ; really is in A-normal form.
  11244. ;
  11245. ;
  11246. ; Stack frames are created by "save" instructions.
  11247. ; A save instruction is generated
  11248. ;
  11249. ; * at the beginning of each lambda body
  11250. ; * at the beginning of the code for each arm of a conditional,
  11251. ; provided:
  11252. ; the conditional is in a tail position
  11253. ; the frames that were allocated by the save instructions
  11254. ; that dominate the arms of the conditional have not been
  11255. ; used (those save instructions will be eliminated during
  11256. ; assembly)
  11257. ;
  11258. ; The operand of a save instruction, and of its matching pop instructions,
  11259. ; increases automatically as frame slots are allocated.
  11260. ;
  11261. ; The code generated to return from a procedure is
  11262. ;
  11263. ; pop n
  11264. ; return
  11265. ;
  11266. ; The code generated for a tail call is
  11267. ;
  11268. ; pop n
  11269. ; invoke ...
  11270. ;
  11271. ; Invariant: When the code generator reserves an argument register
  11272. ; to hold a value, that value is named, and is stored into the current
  11273. ; stack frame. These store instructions are eliminated during assembly
  11274. ; unless there is a matching load instruction. If all of the instructions
  11275. ; that store into a stack frame are eliminated, then the stack frame
  11276. ; itself is eliminated.
  11277. ; Exception: An argument register may be used without naming or storing
  11278. ; its value provided the register is not in use and no expressions are
  11279. ; evaluated while it contains the unnamed and unstored value.
  11280. (define (pass4 exp integrable)
  11281. (init-labels)
  11282. (init-temps)
  11283. (let ((output (make-assembly-stream))
  11284. (frame (cgframe-initial))
  11285. (regs (cgreg-initial))
  11286. (t0 (newtemp)))
  11287. (assembly-stream-info! output (make-hashtable equal-hash assoc))
  11288. (cgreg-bind! regs 0 t0)
  11289. (gen-save! output frame t0)
  11290. (cg0 output
  11291. exp
  11292. 'result
  11293. regs
  11294. frame
  11295. (cgenv-initial integrable)
  11296. #t)
  11297. (pass4-code output)))
  11298. (define (pass4-code output)
  11299. (hashtable-for-each (lambda (situation label)
  11300. (cg-trap output situation label))
  11301. (assembly-stream-info output))
  11302. (assembly-stream-code output))
  11303. ; Given:
  11304. ; an assembly stream into which instructions should be emitted
  11305. ; an expression
  11306. ; the target register
  11307. ; ('result, a register number, or '#f; tail position implies 'result)
  11308. ; a register environment [cgreg]
  11309. ; a stack-frame environment [cgframe]
  11310. ; a compile-time environment [cgenv]
  11311. ; a flag indicating whether the expression is in tail position
  11312. ; Returns:
  11313. ; the target register ('result or a register number)
  11314. ; Side effects:
  11315. ; may change the register and stack-frame environments
  11316. ; may increase the size of the stack frame, which changes previously
  11317. ; emitted instructions
  11318. ; writes instructions to the assembly stream
  11319. (define (cg0 output exp target regs frame env tail?)
  11320. (case (car exp)
  11321. ((quote) (gen! output $const (constant.value exp))
  11322. (if tail?
  11323. (begin (gen-pop! output frame)
  11324. (gen! output $return)
  11325. 'result)
  11326. (cg-move output frame regs 'result target)))
  11327. ((lambda) (cg-lambda output exp regs frame env)
  11328. (if tail?
  11329. (begin (gen-pop! output frame)
  11330. (gen! output $return)
  11331. 'result)
  11332. (cg-move output frame regs 'result target)))
  11333. ((set!) (cg0 output (assignment.rhs exp) 'result regs frame env #f)
  11334. (cg-assignment-result output exp target regs frame env tail?))
  11335. ((if) (cg-if output exp target regs frame env tail?))
  11336. ((begin) (if (variable? exp)
  11337. (cg-variable output exp target regs frame env tail?)
  11338. (cg-sequential output exp target regs frame env tail?)))
  11339. (else (cg-call output exp target regs frame env tail?))))
  11340. ; Lambda expressions that evaluate to closures.
  11341. ; This is hard because the MacScheme machine's lambda instruction
  11342. ; closes over the values that are in argument registers 0 through r
  11343. ; (where r can be larger than *nregs*).
  11344. ; The set of free variables is calculated and then sorted to minimize
  11345. ; register shuffling.
  11346. ;
  11347. ; Returns: nothing.
  11348. (define (cg-lambda output exp regs frame env)
  11349. (let* ((args (lambda.args exp))
  11350. (vars (make-null-terminated args))
  11351. (free (difference (lambda.F exp) vars))
  11352. (free (cg-sort-vars free regs frame env))
  11353. (newenv (cgenv-extend env (cons #t free) '()))
  11354. (newoutput (make-assembly-stream)))
  11355. (assembly-stream-info! newoutput (make-hashtable equal-hash assoc))
  11356. (gen! newoutput $.proc)
  11357. (if (list? args)
  11358. (gen! newoutput $args= (length args))
  11359. (gen! newoutput $args>= (- (length vars) 1)))
  11360. (cg-known-lambda newoutput exp newenv)
  11361. (cg-eval-vars output free regs frame env)
  11362. ; FIXME
  11363. '
  11364. (if (not (ignore-space-leaks))
  11365. ; FIXME: Is this the right constant?
  11366. (begin (gen! output $const #f)
  11367. (gen! output $setreg 0)))
  11368. (gen! output
  11369. $lambda
  11370. (pass4-code newoutput)
  11371. (length free)
  11372. (lambda.doc exp))
  11373. ; FIXME
  11374. '
  11375. (if (not (ignore-space-leaks))
  11376. ; FIXME: This load forces a stack frame to be allocated.
  11377. (gen-load! output frame 0 (cgreg-lookup-reg regs 0)))))
  11378. ; Given a list of free variables, filters out the ones that
  11379. ; need to be copied into a closure, and sorts them into an order
  11380. ; that reduces register shuffling. Returns a sorted version of
  11381. ; the list in which the first element (element 0) should go
  11382. ; into register 1, the second into register 2, and so on.
  11383. (define (cg-sort-vars free regs frame env)
  11384. (let* ((free (filter (lambda (var)
  11385. (case (entry.kind
  11386. (var-lookup var regs frame env))
  11387. ((register frame)
  11388. #t)
  11389. ((lexical)
  11390. (not (ignore-space-leaks)))
  11391. (else #f)))
  11392. free))
  11393. (n (length free))
  11394. (m (min n (- *nregs* 1)))
  11395. (vec (make-vector m #f)))
  11396. (define (loop1 free free-notregister)
  11397. (if (null? free)
  11398. (loop2 0 free-notregister)
  11399. (let* ((var (car free))
  11400. (entry (cgreg-lookup regs var)))
  11401. (if entry
  11402. (let ((r (entry.regnum entry)))
  11403. (if (<= r n)
  11404. (begin (vector-set! vec (- r 1) var)
  11405. (loop1 (cdr free)
  11406. free-notregister))
  11407. (loop1 (cdr free)
  11408. (cons var free-notregister))))
  11409. (loop1 (cdr free)
  11410. (cons var free-notregister))))))
  11411. (define (loop2 i free)
  11412. (cond ((null? free)
  11413. (vector->list vec))
  11414. ((= i m)
  11415. (append (vector->list vec) free))
  11416. ((vector-ref vec i)
  11417. (loop2 (+ i 1) free))
  11418. (else
  11419. (vector-set! vec i (car free))
  11420. (loop2 (+ i 1) (cdr free)))))
  11421. (loop1 free '())))
  11422. ; Fetches the given list of free variables into the corresponding
  11423. ; registers in preparation for a $lambda or $lexes instruction.
  11424. (define (cg-eval-vars output free regs frame env)
  11425. (let ((n (length free))
  11426. (R-1 (- *nregs* 1)))
  11427. (if (>= n R-1)
  11428. (begin (gen! output $const '())
  11429. (gen! output $setreg R-1)
  11430. (cgreg-release! regs R-1)))
  11431. (do ((r n (- r 1))
  11432. (vars (reverse free) (cdr vars)))
  11433. ((zero? r))
  11434. (let* ((v (car vars))
  11435. (entry (var-lookup v regs frame env)))
  11436. (case (entry.kind entry)
  11437. ((register)
  11438. (let ((r1 (entry.regnum entry)))
  11439. (if (not (eqv? r r1))
  11440. (if (< r R-1)
  11441. (begin (gen! output $movereg r1 r)
  11442. (cgreg-bind! regs r v))
  11443. (gen! output $reg r1 v)))))
  11444. ((frame)
  11445. (if (< r R-1)
  11446. (begin (gen-load! output frame r v)
  11447. (cgreg-bind! regs r v))
  11448. (gen-stack! output frame v)))
  11449. ((lexical)
  11450. (gen! output $lexical
  11451. (entry.rib entry)
  11452. (entry.offset entry)
  11453. v)
  11454. (if (< r R-1)
  11455. (begin (gen! output $setreg r)
  11456. (cgreg-bind! regs r v)
  11457. (gen-store! output frame r v))))
  11458. (else
  11459. (error "Bug in cg-close-lambda")))
  11460. (if (>= r R-1)
  11461. (begin (gen! output $op2 $cons R-1)
  11462. (gen! output $setreg R-1)))))))
  11463. ; Lambda expressions that appear on the rhs of a definition are
  11464. ; compiled here. They don't need an args= instruction at their head.
  11465. ;
  11466. ; Returns: nothing.
  11467. (define (cg-known-lambda output exp env)
  11468. (let* ((vars (make-null-terminated (lambda.args exp)))
  11469. (regs (cgreg-initial))
  11470. (frame (cgframe-initial))
  11471. (t0 (newtemp)))
  11472. (if (member A-normal-form-declaration (lambda.decls exp))
  11473. (cgframe-livevars-set! frame '()))
  11474. (cgreg-bind! regs 0 t0)
  11475. (gen-save! output frame t0)
  11476. (do ((r 1 (+ r 1))
  11477. (vars vars (cdr vars)))
  11478. ((or (null? vars)
  11479. (= r *lastreg*))
  11480. (if (not (null? vars))
  11481. (begin (gen! output $movereg *lastreg* 1)
  11482. (cgreg-release! regs 1)
  11483. (do ((vars vars (cdr vars)))
  11484. ((null? vars))
  11485. (gen! output $reg 1)
  11486. (gen! output $op1 $car:pair)
  11487. (gen-setstk! output frame (car vars))
  11488. (gen! output $reg 1)
  11489. (gen! output $op1 $cdr:pair)
  11490. (gen! output $setreg 1)))))
  11491. (cgreg-bind! regs r (car vars))
  11492. (gen-store! output frame r (car vars)))
  11493. (cg-body output
  11494. exp
  11495. 'result
  11496. regs
  11497. frame
  11498. env
  11499. #t)))
  11500. ; Compiles a let or lambda body.
  11501. ; The arguments of the lambda expression L are already in
  11502. ; registers or the stack frame, as specified by regs and frame.
  11503. ;
  11504. ; The problem here is that the free variables of an internal
  11505. ; definition must be in a heap-allocated environment, so any
  11506. ; such variables in registers must be copied to the heap.
  11507. ;
  11508. ; Returns: destination register.
  11509. (define (cg-body output L target regs frame env tail?)
  11510. (let* ((exp (lambda.body L))
  11511. (defs (lambda.defs L))
  11512. (free (apply-union
  11513. (map (lambda (def)
  11514. (let ((L (def.rhs def)))
  11515. (difference (lambda.F L)
  11516. (lambda.args L))))
  11517. defs))))
  11518. (cond ((or (null? defs) (constant? exp) (variable? exp))
  11519. (cg0 output exp target regs frame env tail?))
  11520. ((lambda? exp)
  11521. (let* ((free (cg-sort-vars
  11522. (union free
  11523. (difference
  11524. (lambda.F exp)
  11525. (make-null-terminated (lambda.args exp))))
  11526. regs frame env))
  11527. (newenv1 (cgenv-extend env
  11528. (cons #t free)
  11529. (map def.lhs defs)))
  11530. (args (lambda.args exp))
  11531. (vars (make-null-terminated args))
  11532. (newoutput (make-assembly-stream)))
  11533. (assembly-stream-info! newoutput (make-hashtable equal-hash assoc))
  11534. (gen! newoutput $.proc)
  11535. (if (list? args)
  11536. (gen! newoutput $args= (length args))
  11537. (gen! newoutput $args>= (- (length vars) 1)))
  11538. (cg-known-lambda newoutput exp newenv1)
  11539. (cg-defs newoutput defs newenv1)
  11540. (cg-eval-vars output free regs frame env)
  11541. (gen! output
  11542. $lambda
  11543. (pass4-code newoutput)
  11544. (length free)
  11545. (lambda.doc exp))
  11546. (if tail?
  11547. (begin (gen-pop! output frame)
  11548. (gen! output $return)
  11549. 'result)
  11550. (cg-move output frame regs 'result target))))
  11551. ((every? (lambda (def)
  11552. (every? (lambda (v)
  11553. (case (entry.kind
  11554. (var-lookup v regs frame env))
  11555. ((register frame) #f)
  11556. (else #t)))
  11557. (let ((Ldef (def.rhs def)))
  11558. (difference (lambda.F Ldef)
  11559. (lambda.args Ldef)))))
  11560. defs)
  11561. (let* ((newenv (cgenv-bindprocs env (map def.lhs defs)))
  11562. (L (make-label))
  11563. (r (cg0 output exp target regs frame newenv tail?)))
  11564. (if (not tail?)
  11565. (gen! output $skip L (cgreg-live regs r)))
  11566. (cg-defs output defs newenv)
  11567. (if (not tail?)
  11568. (gen! output $.label L))
  11569. r))
  11570. (else
  11571. (let ((free (cg-sort-vars free regs frame env)))
  11572. (cg-eval-vars output free regs frame env)
  11573. ; FIXME: Have to restore it too!
  11574. '
  11575. (if (not (ignore-space-leaks))
  11576. ; FIXME: Is this constant the right one?
  11577. (begin (gen! output $const #f)
  11578. (gen! output $setreg 0)))
  11579. (let ((t0 (cgreg-lookup-reg regs 0))
  11580. (t1 (newtemp))
  11581. (newenv (cgenv-extend env
  11582. (cons #t free)
  11583. (map def.lhs defs)))
  11584. (L (make-label)))
  11585. (gen! output $lexes (length free) free)
  11586. (gen! output $setreg 0)
  11587. (cgreg-bind! regs 0 t1)
  11588. (if tail?
  11589. (begin (cgframe-release! frame t0)
  11590. (gen-store! output frame 0 t1)
  11591. (cg0 output exp 'result regs frame newenv #t)
  11592. (cg-defs output defs newenv)
  11593. 'result)
  11594. (begin (gen-store! output frame 0 t1)
  11595. (cg0 output exp 'result regs frame newenv #f)
  11596. (gen! output $skip L (cgreg-tos regs))
  11597. (cg-defs output defs newenv)
  11598. (gen! output $.label L)
  11599. (gen-load! output frame 0 t0)
  11600. (cgreg-bind! regs 0 t0)
  11601. (cgframe-release! frame t1)
  11602. (cg-move output frame regs 'result target)))))))))
  11603. (define (cg-defs output defs env)
  11604. (for-each (lambda (def)
  11605. (gen! output $.align 4)
  11606. (gen! output $.label
  11607. (entry.label
  11608. (cgenv-lookup env (def.lhs def))))
  11609. (gen! output $.proc)
  11610. (gen! output $.proc-doc (lambda.doc (def.rhs def)))
  11611. (cg-known-lambda output
  11612. (def.rhs def)
  11613. env))
  11614. defs))
  11615. ; The right hand side has already been evaluated into the result register.
  11616. (define (cg-assignment-result output exp target regs frame env tail?)
  11617. (gen! output $setglbl (assignment.lhs exp))
  11618. (if tail?
  11619. (begin (gen-pop! output frame)
  11620. (gen! output $return)
  11621. 'result)
  11622. (cg-move output frame regs 'result target)))
  11623. (define (cg-if output exp target regs frame env tail?)
  11624. ; The test can be a constant, because it is awkward
  11625. ; to remove constant tests from an A-normal form.
  11626. (if (constant? (if.test exp))
  11627. (cg0 output
  11628. (if (constant.value (if.test exp))
  11629. (if.then exp)
  11630. (if.else exp))
  11631. target regs frame env tail?)
  11632. (begin
  11633. (cg0 output (if.test exp) 'result regs frame env #f)
  11634. (cg-if-result output exp target regs frame env tail?))))
  11635. ; The test expression has already been evaluated into the result register.
  11636. (define (cg-if-result output exp target regs frame env tail?)
  11637. (let ((L1 (make-label))
  11638. (L2 (make-label)))
  11639. (gen! output $branchf L1 (cgreg-tos regs))
  11640. (let* ((regs2 (cgreg-copy regs))
  11641. (frame1 (if (and tail?
  11642. (negative? (cgframe-size frame)))
  11643. (cgframe-initial)
  11644. frame))
  11645. (frame2 (if (eq? frame frame1)
  11646. (cgframe-copy frame1)
  11647. (cgframe-initial)))
  11648. (t0 (cgreg-lookup-reg regs 0)))
  11649. (if (not (eq? frame frame1))
  11650. (let ((live (cgframe-livevars frame)))
  11651. (cgframe-livevars-set! frame1 live)
  11652. (cgframe-livevars-set! frame2 live)
  11653. (gen-save! output frame1 t0)
  11654. (cg-saveregs output regs frame1)))
  11655. (let ((r (cg0 output (if.then exp) target regs frame1 env tail?)))
  11656. (if (not tail?)
  11657. (gen! output $skip L2 (cgreg-live regs r)))
  11658. (gen! output $.label L1)
  11659. (if (not (eq? frame frame1))
  11660. (begin (gen-save! output frame2 t0)
  11661. (cg-saveregs output regs2 frame2))
  11662. (cgframe-update-stale! frame2))
  11663. (cg0 output (if.else exp) r regs2 frame2 env tail?)
  11664. (if (not tail?)
  11665. (begin (gen! output $.label L2)
  11666. (cgreg-join! regs regs2)
  11667. (cgframe-join! frame1 frame2)))
  11668. (if (and (not target)
  11669. (not (eq? r 'result))
  11670. (not (cgreg-lookup-reg regs r)))
  11671. (cg-move output frame regs r 'result)
  11672. r)))))
  11673. (define (cg-variable output exp target regs frame env tail?)
  11674. (define (return id)
  11675. (if tail?
  11676. (begin (gen-pop! output frame)
  11677. (gen! output $return)
  11678. 'result)
  11679. (if (and target
  11680. (not (eq? 'result target)))
  11681. (begin (gen! output $setreg target)
  11682. (cgreg-bind! regs target id)
  11683. (gen-store! output frame target id)
  11684. target)
  11685. 'result)))
  11686. ; Same as return, but doesn't emit a store instruction.
  11687. (define (return-nostore id)
  11688. (if tail?
  11689. (begin (gen-pop! output frame)
  11690. (gen! output $return)
  11691. 'result)
  11692. (if (and target
  11693. (not (eq? 'result target)))
  11694. (begin (gen! output $setreg target)
  11695. (cgreg-bind! regs target id)
  11696. target)
  11697. 'result)))
  11698. (let* ((id (variable.name exp))
  11699. (entry (var-lookup id regs frame env)))
  11700. (case (entry.kind entry)
  11701. ((global integrable)
  11702. (gen! output $global id)
  11703. (return (newtemp)))
  11704. ((lexical)
  11705. (let ((m (entry.rib entry))
  11706. (n (entry.offset entry)))
  11707. (gen! output $lexical m n id)
  11708. (if (or (zero? m)
  11709. (negative? (cgframe-size frame)))
  11710. (return-nostore id)
  11711. (return id))))
  11712. ((procedure) (error "Bug in cg-variable" exp))
  11713. ((register)
  11714. (let ((r (entry.regnum entry)))
  11715. (if (or tail?
  11716. (and target (not (eqv? target r))))
  11717. (begin (gen! output $reg (entry.regnum entry) id)
  11718. (return-nostore id))
  11719. r)))
  11720. ((frame)
  11721. (cond ((eq? target 'result)
  11722. (gen-stack! output frame id)
  11723. (return id))
  11724. (target
  11725. ; Must be non-tail.
  11726. (gen-load! output frame target id)
  11727. (cgreg-bind! regs target id)
  11728. target)
  11729. (else
  11730. ; Must be non-tail.
  11731. (let ((r (choose-register regs frame)))
  11732. (gen-load! output frame r id)
  11733. (cgreg-bind! regs r id)
  11734. r))))
  11735. (else (error "Bug in cg-variable" exp)))))
  11736. (define (cg-sequential output exp target regs frame env tail?)
  11737. (cg-sequential-loop output (begin.exprs exp) target regs frame env tail?))
  11738. (define (cg-sequential-loop output exprs target regs frame env tail?)
  11739. (cond ((null? exprs)
  11740. (gen! output $const unspecified)
  11741. (if tail?
  11742. (begin (gen-pop! output frame)
  11743. (gen! output $return)
  11744. 'result)
  11745. (cg-move output frame regs 'result target)))
  11746. ((null? (cdr exprs))
  11747. (cg0 output (car exprs) target regs frame env tail?))
  11748. (else (cg0 output (car exprs) #f regs frame env #f)
  11749. (cg-sequential-loop output
  11750. (cdr exprs)
  11751. target regs frame env tail?))))
  11752. (define (cg-saveregs output regs frame)
  11753. (do ((i 1 (+ i 1))
  11754. (vars (cdr (cgreg-vars regs)) (cdr vars)))
  11755. ((null? vars))
  11756. (let ((t (car vars)))
  11757. (if t
  11758. (gen-store! output frame i t)))))
  11759. (define (cg-move output frame regs src dst)
  11760. (define (bind dst)
  11761. (let ((temp (newtemp)))
  11762. (cgreg-bind! regs dst temp)
  11763. (gen-store! output frame dst temp)
  11764. dst))
  11765. (cond ((not dst)
  11766. src)
  11767. ((eqv? src dst)
  11768. dst)
  11769. ((eq? dst 'result)
  11770. (gen! output $reg src)
  11771. dst)
  11772. ((eq? src 'result)
  11773. (gen! output $setreg dst)
  11774. (bind dst))
  11775. ((and (not (zero? src))
  11776. (not (zero? dst)))
  11777. (gen! output $movereg src dst)
  11778. (bind dst))
  11779. (else
  11780. (gen! output $reg src)
  11781. (gen! output $setreg dst)
  11782. (bind dst))))
  11783. ; On-the-fly register allocator.
  11784. ; Tries to allocate:
  11785. ; a hardware register that isn't being used
  11786. ; a hardware register whose contents have already been spilled
  11787. ; a software register that isn't being used, unless a stack
  11788. ; frame has already been created, in which case it is better to use
  11789. ; a hardware register that is in use and hasn't yet been spilled
  11790. ;
  11791. ; All else equal, it is better to allocate a higher-numbered register
  11792. ; because the lower-numbered registers are targets when arguments
  11793. ; are being evaluated.
  11794. ;
  11795. ; Invariant: Every register that is returned by this allocator
  11796. ; is either not in use or has been spilled.
  11797. (define (choose-register regs frame)
  11798. (car (choose-registers regs frame 1)))
  11799. (define (choose-registers regs frame n)
  11800. ; Find unused hardware registers.
  11801. (define (loop1 i n good)
  11802. (cond ((zero? n)
  11803. good)
  11804. ((zero? i)
  11805. (if (negative? (cgframe-size frame))
  11806. (hardcase)
  11807. (loop2 (- *nhwregs* 1) n good)))
  11808. (else
  11809. (if (cgreg-lookup-reg regs i)
  11810. (loop1 (- i 1) n good)
  11811. (loop1 (- i 1)
  11812. (- n 1)
  11813. (cons i good))))))
  11814. ; Find already spilled hardware registers.
  11815. (define (loop2 i n good)
  11816. (cond ((zero? n)
  11817. good)
  11818. ((zero? i)
  11819. (hardcase))
  11820. (else
  11821. (let ((t (cgreg-lookup-reg regs i)))
  11822. (if (and t (cgframe-spilled? frame t))
  11823. (loop2 (- i 1)
  11824. (- n 1)
  11825. (cons i good))
  11826. (loop2 (- i 1) n good))))))
  11827. ; This is ridiculous.
  11828. ; Fortunately the correctness of the compiler is independent
  11829. ; of the predicate used for this sort.
  11830. (define (hardcase)
  11831. (let* ((frame-exists? (not (negative? (cgframe-size frame))))
  11832. (stufftosort
  11833. (map (lambda (r)
  11834. (let* ((t (cgreg-lookup-reg regs r))
  11835. (spilled?
  11836. (and t
  11837. (cgframe-spilled? frame t))))
  11838. (list r t spilled?)))
  11839. (cdr (iota *nregs*))))
  11840. (registers
  11841. (twobit-sort
  11842. (lambda (x1 x2)
  11843. (let ((r1 (car x1))
  11844. (r2 (car x2))
  11845. (t1 (cadr x1))
  11846. (t2 (cadr x2)))
  11847. (cond ((< r1 *nhwregs*)
  11848. (cond ((not t1) #t)
  11849. ((< r2 *nhwregs*)
  11850. (cond ((not t2) #f)
  11851. ((caddr x1) #t)
  11852. ((caddr x2) #f)
  11853. (else #t)))
  11854. (frame-exists? #t)
  11855. (t2 #t)
  11856. (else #f)))
  11857. ((< r2 *nhwregs*)
  11858. (cond (frame-exists? #f)
  11859. (t1 #f)
  11860. (t2 #t)
  11861. (else #f)))
  11862. (t1
  11863. (if (and (caddr x1)
  11864. t2
  11865. (not (caddr x2)))
  11866. #t
  11867. #f))
  11868. (else #t))))
  11869. stufftosort)))
  11870. ; FIXME: What was this for?
  11871. '
  11872. (for-each (lambda (register)
  11873. (let ((t (cadr register))
  11874. (spilled? (caddr register)))
  11875. (if (and t (not spilled?))
  11876. (cgframe-touch! frame t))))
  11877. registers)
  11878. (do ((sorted (map car registers) (cdr sorted))
  11879. (rs '() (cons (car sorted) rs))
  11880. (n n (- n 1)))
  11881. ((zero? n)
  11882. (reverse rs)))))
  11883. (if (< n *nregs*)
  11884. (loop1 (- *nhwregs* 1) n '())
  11885. (error (string-append "Compiler bug: can't allocate "
  11886. (number->string n)
  11887. " registers on this target."))))
  11888. ; Copyright 1991 William Clinger
  11889. ;
  11890. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  11891. ;
  11892. ; 21 May 1999.
  11893. ; Procedure calls.
  11894. (define (cg-call output exp target regs frame env tail?)
  11895. (let ((proc (call.proc exp)))
  11896. (cond ((and (lambda? proc)
  11897. (list? (lambda.args proc)))
  11898. (cg-let output exp target regs frame env tail?))
  11899. ((not (variable? proc))
  11900. (cg-unknown-call output exp target regs frame env tail?))
  11901. (else (let ((entry
  11902. (var-lookup (variable.name proc) regs frame env)))
  11903. (case (entry.kind entry)
  11904. ((global lexical frame register)
  11905. (cg-unknown-call output
  11906. exp
  11907. target regs frame env tail?))
  11908. ((integrable)
  11909. (cg-integrable-call output
  11910. exp
  11911. target regs frame env tail?))
  11912. ((procedure)
  11913. (cg-known-call output
  11914. exp
  11915. target regs frame env tail?))
  11916. (else (error "Bug in cg-call" exp))))))))
  11917. (define (cg-unknown-call output exp target regs frame env tail?)
  11918. (let* ((proc (call.proc exp))
  11919. (args (call.args exp))
  11920. (n (length args))
  11921. (L (make-label)))
  11922. (cond ((>= (+ n 1) *lastreg*)
  11923. (cg-big-call output exp target regs frame env tail?))
  11924. (else
  11925. (let ((r0 (cgreg-lookup-reg regs 0)))
  11926. (if (variable? proc)
  11927. (let ((entry (cgreg-lookup regs (variable.name proc))))
  11928. (if (and entry
  11929. (<= (entry.regnum entry) n))
  11930. (begin (cg-arguments output
  11931. (iota1 (+ n 1))
  11932. (append args (list proc))
  11933. regs frame env)
  11934. (gen! output $reg (+ n 1)))
  11935. (begin (cg-arguments output
  11936. (iota1 n)
  11937. args
  11938. regs frame env)
  11939. (cg0 output proc 'result regs frame env #f)))
  11940. (if tail?
  11941. (gen-pop! output frame)
  11942. (begin (cgframe-used! frame)
  11943. (gen! output $setrtn L)))
  11944. (gen! output $invoke n))
  11945. (begin (cg-arguments output
  11946. (iota1 (+ n 1))
  11947. (append args (list proc))
  11948. regs frame env)
  11949. (gen! output $reg (+ n 1))
  11950. (if tail?
  11951. (gen-pop! output frame)
  11952. (begin (cgframe-used! frame)
  11953. (gen! output $setrtn L)))
  11954. (gen! output $invoke n)))
  11955. (if tail?
  11956. 'result
  11957. (begin (gen! output $.align 4)
  11958. (gen! output $.label L)
  11959. (gen! output $.cont)
  11960. (cgreg-clear! regs)
  11961. (cgreg-bind! regs 0 r0)
  11962. (gen-load! output frame 0 r0)
  11963. (cg-move output frame regs 'result target))))))))
  11964. (define (cg-known-call output exp target regs frame env tail?)
  11965. (let* ((args (call.args exp))
  11966. (n (length args))
  11967. (L (make-label)))
  11968. (cond ((>= (+ n 1) *lastreg*)
  11969. (cg-big-call output exp target regs frame env tail?))
  11970. (else
  11971. (let ((r0 (cgreg-lookup-reg regs 0)))
  11972. (cg-arguments output (iota1 n) args regs frame env)
  11973. (if tail?
  11974. (gen-pop! output frame)
  11975. (begin (cgframe-used! frame)
  11976. (gen! output $setrtn L)))
  11977. (let* ((entry (cgenv-lookup env (variable.name (call.proc exp))))
  11978. (label (entry.label entry))
  11979. (m (entry.rib entry)))
  11980. (if (zero? m)
  11981. (gen! output $branch label n)
  11982. (gen! output $jump m label n)))
  11983. (if tail?
  11984. 'result
  11985. (begin (gen! output $.align 4)
  11986. (gen! output $.label L)
  11987. (gen! output $.cont)
  11988. (cgreg-clear! regs)
  11989. (cgreg-bind! regs 0 r0)
  11990. (gen-load! output frame 0 r0)
  11991. (cg-move output frame regs 'result target))))))))
  11992. ; Any call can be compiled as follows, even if there are no free registers.
  11993. ;
  11994. ; Let T0, T1, ..., Tn be newly allocated stack temporaries.
  11995. ;
  11996. ; <arg0>
  11997. ; setstk T0
  11998. ; <arg1> -|
  11999. ; setstk T1 |
  12000. ; ... |- evaluate args into stack frame
  12001. ; <argn> |
  12002. ; setstk Tn -|
  12003. ; const ()
  12004. ; setreg R-1
  12005. ; stack Tn -|
  12006. ; op2 cons,R-1 |
  12007. ; setreg R-1 |
  12008. ; ... |- cons up overflow args
  12009. ; stack T_{R-1} |
  12010. ; op2 cons,R-1 |
  12011. ; setreg R-1 -|
  12012. ; stack T_{R-2} -|
  12013. ; setreg R-2 |
  12014. ; ... |- pop remaining args into registers
  12015. ; stack T1 |
  12016. ; setreg 1 -|
  12017. ; stack T0
  12018. ; invoke n
  12019. (define (cg-big-call output exp target regs frame env tail?)
  12020. (let* ((proc (call.proc exp))
  12021. (args (call.args exp))
  12022. (n (length args))
  12023. (argslots (newtemps n))
  12024. (procslot (newtemp))
  12025. (r0 (cgreg-lookup-reg regs 0))
  12026. (R-1 (- *nregs* 1))
  12027. (entry (if (variable? proc)
  12028. (let ((entry
  12029. (var-lookup (variable.name proc)
  12030. regs frame env)))
  12031. (if (eq? (entry.kind entry) 'procedure)
  12032. entry
  12033. #f))
  12034. #f))
  12035. (L (make-label)))
  12036. (if (not entry)
  12037. (begin
  12038. (cg0 output proc 'result regs frame env #f)
  12039. (gen-setstk! output frame procslot)))
  12040. (for-each (lambda (arg argslot)
  12041. (cg0 output arg 'result regs frame env #f)
  12042. (gen-setstk! output frame argslot))
  12043. args
  12044. argslots)
  12045. (cgreg-clear! regs)
  12046. (gen! output $const '())
  12047. (gen! output $setreg R-1)
  12048. (do ((i n (- i 1))
  12049. (slots (reverse argslots) (cdr slots)))
  12050. ((zero? i))
  12051. (if (< i R-1)
  12052. (gen-load! output frame i (car slots))
  12053. (begin (gen-stack! output frame (car slots))
  12054. (gen! output $op2 $cons R-1)
  12055. (gen! output $setreg R-1))))
  12056. (if (not entry)
  12057. (gen-stack! output frame procslot))
  12058. (if tail?
  12059. (gen-pop! output frame)
  12060. (begin (cgframe-used! frame)
  12061. (gen! output $setrtn L)))
  12062. (if entry
  12063. (let ((label (entry.label entry))
  12064. (m (entry.rib entry)))
  12065. (if (zero? m)
  12066. (gen! output $branch label n)
  12067. (gen! output $jump m label n)))
  12068. (gen! output $invoke n))
  12069. (if tail?
  12070. 'result
  12071. (begin (gen! output $.align 4)
  12072. (gen! output $.label L)
  12073. (gen! output $.cont)
  12074. (cgreg-clear! regs) ; redundant, see above
  12075. (cgreg-bind! regs 0 r0)
  12076. (gen-load! output frame 0 r0)
  12077. (cg-move output frame regs 'result target)))))
  12078. (define (cg-integrable-call output exp target regs frame env tail?)
  12079. (let ((args (call.args exp))
  12080. (entry (var-lookup (variable.name (call.proc exp)) regs frame env)))
  12081. (if (= (entry.arity entry) (length args))
  12082. (begin (case (entry.arity entry)
  12083. ((0) (gen! output $op1 (entry.op entry)))
  12084. ((1) (cg0 output (car args) 'result regs frame env #f)
  12085. (gen! output $op1 (entry.op entry)))
  12086. ((2) (cg-integrable-call2 output
  12087. entry
  12088. args
  12089. regs frame env))
  12090. ((3) (cg-integrable-call3 output
  12091. entry
  12092. args
  12093. regs frame env))
  12094. (else (error "Bug detected by cg-integrable-call"
  12095. (make-readable exp))))
  12096. (if tail?
  12097. (begin (gen-pop! output frame)
  12098. (gen! output $return)
  12099. 'result)
  12100. (cg-move output frame regs 'result target)))
  12101. (if (negative? (entry.arity entry))
  12102. (cg-special output exp target regs frame env tail?)
  12103. (error "Wrong number of arguments to integrable procedure"
  12104. (make-readable exp))))))
  12105. (define (cg-integrable-call2 output entry args regs frame env)
  12106. (let ((op (entry.op entry)))
  12107. (if (and (entry.imm entry)
  12108. (constant? (cadr args))
  12109. ((entry.imm entry) (constant.value (cadr args))))
  12110. (begin (cg0 output (car args) 'result regs frame env #f)
  12111. (gen! output $op2imm
  12112. op
  12113. (constant.value (cadr args))))
  12114. (let* ((reg2 (cg0 output (cadr args) #f regs frame env #f))
  12115. (r2 (choose-register regs frame))
  12116. (t2 (if (eq? reg2 'result)
  12117. (let ((t2 (newtemp)))
  12118. (gen! output $setreg r2)
  12119. (cgreg-bind! regs r2 t2)
  12120. (gen-store! output frame r2 t2)
  12121. t2)
  12122. (cgreg-lookup-reg regs reg2))))
  12123. (cg0 output (car args) 'result regs frame env #f)
  12124. (let* ((r2 (or (let ((entry (cgreg-lookup regs t2)))
  12125. (if entry
  12126. (entry.regnum entry)
  12127. #f))
  12128. (let ((r2 (choose-register regs frame)))
  12129. (cgreg-bind! regs r2 t2)
  12130. (gen-load! output frame r2 t2)
  12131. r2))))
  12132. (gen! output $op2 (entry.op entry) r2)
  12133. (if (eq? reg2 'result)
  12134. (begin (cgreg-release! regs r2)
  12135. (cgframe-release! frame t2)))))))
  12136. 'result)
  12137. (define (cg-integrable-call3 output entry args regs frame env)
  12138. (let* ((reg2 (cg0 output (cadr args) #f regs frame env #f))
  12139. (r2 (choose-register regs frame))
  12140. (t2 (if (eq? reg2 'result)
  12141. (let ((t2 (newtemp)))
  12142. (gen! output $setreg r2)
  12143. (cgreg-bind! regs r2 t2)
  12144. (gen-store! output frame r2 t2)
  12145. t2)
  12146. (cgreg-lookup-reg regs reg2)))
  12147. (reg3 (cg0 output (caddr args) #f regs frame env #f))
  12148. (spillregs (choose-registers regs frame 2))
  12149. (t3 (if (eq? reg3 'result)
  12150. (let ((t3 (newtemp))
  12151. (r3 (if (eq? t2 (cgreg-lookup-reg
  12152. regs (car spillregs)))
  12153. (cadr spillregs)
  12154. (car spillregs))))
  12155. (gen! output $setreg r3)
  12156. (cgreg-bind! regs r3 t3)
  12157. (gen-store! output frame r3 t3)
  12158. t3)
  12159. (cgreg-lookup-reg regs reg3))))
  12160. (cg0 output (car args) 'result regs frame env #f)
  12161. (let* ((spillregs (choose-registers regs frame 2))
  12162. (r2 (or (let ((entry (cgreg-lookup regs t2)))
  12163. (if entry
  12164. (entry.regnum entry)
  12165. #f))
  12166. (let ((r2 (car spillregs)))
  12167. (cgreg-bind! regs r2 t2)
  12168. (gen-load! output frame r2 t2)
  12169. r2)))
  12170. (r3 (or (let ((entry (cgreg-lookup regs t3)))
  12171. (if entry
  12172. (entry.regnum entry)
  12173. #f))
  12174. (let ((r3 (if (eq? r2 (car spillregs))
  12175. (cadr spillregs)
  12176. (car spillregs))))
  12177. (cgreg-bind! regs r3 t3)
  12178. (gen-load! output frame r3 t3)
  12179. r3))))
  12180. (gen! output $op3 (entry.op entry) r2 r3)
  12181. (if (eq? reg2 'result)
  12182. (begin (cgreg-release! regs r2)
  12183. (cgframe-release! frame t2)))
  12184. (if (eq? reg3 'result)
  12185. (begin (cgreg-release! regs r3)
  12186. (cgframe-release! frame t3)))))
  12187. 'result)
  12188. ; Given a short list of expressions that can be evaluated in any order,
  12189. ; evaluates the first into the result register and the others into any
  12190. ; register, and returns an ordered list of the registers that contain
  12191. ; the arguments that follow the first.
  12192. ; The number of expressions must be less than the number of argument
  12193. ; registers.
  12194. (define (cg-primop-args output args regs frame env)
  12195. ; Given a list of expressions to evaluate, a list of variables
  12196. ; and temporary names for arguments that have already been
  12197. ; evaluated, in reverse order, and a mask of booleans that
  12198. ; indicate which temporaries should be released before returning,
  12199. ; returns the correct result.
  12200. (define (eval-loop args temps mask)
  12201. (if (null? args)
  12202. (eval-first-into-result temps mask)
  12203. (let ((reg (cg0 output (car args) #f regs frame env #f)))
  12204. (if (eq? reg 'result)
  12205. (let* ((r (choose-register regs frame))
  12206. (t (newtemp)))
  12207. (gen! output $setreg r)
  12208. (cgreg-bind! regs r t)
  12209. (gen-store! output frame r t)
  12210. (eval-loop (cdr args)
  12211. (cons t temps)
  12212. (cons #t mask)))
  12213. (eval-loop (cdr args)
  12214. (cons (cgreg-lookup-reg regs reg) temps)
  12215. (cons #f mask))))))
  12216. (define (eval-first-into-result temps mask)
  12217. (cg0 output (car args) 'result regs frame env #f)
  12218. (finish-loop (choose-registers regs frame (length temps))
  12219. temps
  12220. mask
  12221. '()))
  12222. ; Given a sufficient number of disjoint registers, a list of
  12223. ; variable and temporary names that may need to be loaded into
  12224. ; registers, a mask of booleans that indicates which temporaries
  12225. ; should be released, and a list of registers in forward order,
  12226. ; returns the correct result.
  12227. (define (finish-loop disjoint temps mask registers)
  12228. (if (null? temps)
  12229. registers
  12230. (let* ((t (car temps))
  12231. (entry (cgreg-lookup regs t)))
  12232. (if entry
  12233. (let ((r (entry.regnum entry)))
  12234. (if (car mask)
  12235. (begin (cgreg-release! regs r)
  12236. (cgframe-release! frame t)))
  12237. (finish-loop disjoint
  12238. (cdr temps)
  12239. (cdr mask)
  12240. (cons r registers)))
  12241. (let ((r (car disjoint)))
  12242. (if (memv r registers)
  12243. (finish-loop (cdr disjoint) temps mask registers)
  12244. (begin (gen-load! output frame r t)
  12245. (cgreg-bind! regs r t)
  12246. (if (car mask)
  12247. (begin (cgreg-release! regs r)
  12248. (cgframe-release! frame t)))
  12249. (finish-loop disjoint
  12250. (cdr temps)
  12251. (cdr mask)
  12252. (cons r registers)))))))))
  12253. (if (< (length args) *nregs*)
  12254. (eval-loop (cdr args) '() '())
  12255. (error "Bug detected by cg-primop-args" args)))
  12256. ; Parallel assignment.
  12257. ; Given a list of target registers, a list of expressions, and a
  12258. ; compile-time environment, generates code to evaluate the expressions
  12259. ; into the registers.
  12260. ;
  12261. ; Argument evaluation proceeds as follows:
  12262. ;
  12263. ; 1. Evaluate all but one of the complicated arguments.
  12264. ; 2. Evaluate remaining arguments.
  12265. ; 3. Load spilled arguments from stack.
  12266. (define (cg-arguments output targets args regs frame env)
  12267. ; Sorts the args and their targets into complicated and
  12268. ; uncomplicated args and targets.
  12269. ; Then it calls evalargs.
  12270. (define (sortargs targets args targets1 args1 targets2 args2)
  12271. (if (null? args)
  12272. (evalargs targets1 args1 targets2 args2)
  12273. (let ((target (car targets))
  12274. (arg (car args))
  12275. (targets (cdr targets))
  12276. (args (cdr args)))
  12277. (if (complicated? arg env)
  12278. (sortargs targets
  12279. args
  12280. (cons target targets1)
  12281. (cons arg args1)
  12282. targets2
  12283. args2)
  12284. (sortargs targets
  12285. args
  12286. targets1
  12287. args1
  12288. (cons target targets2)
  12289. (cons arg args2))))))
  12290. ; Given the complicated args1 and their targets1,
  12291. ; and the uncomplicated args2 and their targets2,
  12292. ; evaluates all the arguments into their target registers.
  12293. (define (evalargs targets1 args1 targets2 args2)
  12294. (let* ((temps1 (newtemps (length targets1)))
  12295. (temps2 (newtemps (length targets2))))
  12296. (if (not (null? args1))
  12297. (for-each (lambda (arg temp)
  12298. (cg0 output arg 'result regs frame env #f)
  12299. (gen-setstk! output frame temp))
  12300. (cdr args1)
  12301. (cdr temps1)))
  12302. (if (not (null? args1))
  12303. (evalargs0 (cons (car targets1) targets2)
  12304. (cons (car args1) args2)
  12305. (cons (car temps1) temps2))
  12306. (evalargs0 targets2 args2 temps2))
  12307. (for-each (lambda (r t)
  12308. (let ((temp (cgreg-lookup-reg regs r)))
  12309. (if (not (eq? temp t))
  12310. (let ((entry (var-lookup t regs frame env)))
  12311. (case (entry.kind entry)
  12312. ((register)
  12313. (gen! output $movereg (entry.regnum entry) r))
  12314. ((frame)
  12315. (gen-load! output frame r t)))
  12316. (cgreg-bind! regs r t)))
  12317. (cgframe-release! frame t)))
  12318. (append targets1 targets2)
  12319. (append temps1 temps2))))
  12320. (define (evalargs0 targets args temps)
  12321. (if (not (null? targets))
  12322. (let ((para (let* ((regvars (map (lambda (reg)
  12323. (cgreg-lookup-reg regs reg))
  12324. targets)))
  12325. (parallel-assignment targets
  12326. (map cons regvars targets)
  12327. args))))
  12328. (if para
  12329. (let ((targets para)
  12330. (args (cg-permute args targets para))
  12331. (temps (cg-permute temps targets para)))
  12332. (for-each (lambda (arg r t)
  12333. (cg0 output arg r regs frame env #f)
  12334. (cgreg-bind! regs r t)
  12335. (gen-store! output frame r t))
  12336. args
  12337. para
  12338. temps))
  12339. (let ((r (choose-register regs frame))
  12340. (t (car temps)))
  12341. (cg0 output (car args) r regs frame env #f)
  12342. (cgreg-bind! regs r t)
  12343. (gen-store! output frame r t)
  12344. (evalargs0 (cdr targets)
  12345. (cdr args)
  12346. (cdr temps)))))))
  12347. (if (parallel-assignment-optimization)
  12348. (sortargs (reverse targets) (reverse args) '() '() '() '())
  12349. (cg-evalargs output targets args regs frame env)))
  12350. ; Left-to-right evaluation of arguments directly into targets.
  12351. (define (cg-evalargs output targets args regs frame env)
  12352. (let ((temps (newtemps (length targets))))
  12353. (for-each (lambda (arg r t)
  12354. (cg0 output arg r regs frame env #f)
  12355. (cgreg-bind! regs r t)
  12356. (gen-store! output frame r t))
  12357. args
  12358. targets
  12359. temps)
  12360. (for-each (lambda (r t)
  12361. (let ((temp (cgreg-lookup-reg regs r)))
  12362. (if (not (eq? temp t))
  12363. (begin (gen-load! output frame r t)
  12364. (cgreg-bind! regs r t)))
  12365. (cgframe-release! frame t)))
  12366. targets
  12367. temps)))
  12368. ; For heuristic use only.
  12369. ; An expression is complicated unless it can probably be evaluated
  12370. ; without saving and restoring any registers, even if it occurs in
  12371. ; a non-tail position.
  12372. (define (complicated? exp env)
  12373. (case (car exp)
  12374. ((quote) #f)
  12375. ((lambda) #t)
  12376. ((set!) (complicated? (assignment.rhs exp) env))
  12377. ((if) (or (complicated? (if.test exp) env)
  12378. (complicated? (if.then exp) env)
  12379. (complicated? (if.else exp) env)))
  12380. ((begin) (if (variable? exp)
  12381. #f
  12382. (some? (lambda (exp)
  12383. (complicated? exp env))
  12384. (begin.exprs exp))))
  12385. (else (let ((proc (call.proc exp)))
  12386. (if (and (variable? proc)
  12387. (let ((entry
  12388. (cgenv-lookup env (variable.name proc))))
  12389. (eq? (entry.kind entry) 'integrable)))
  12390. (some? (lambda (exp)
  12391. (complicated? exp env))
  12392. (call.args exp))
  12393. #t)))))
  12394. ; Returns a permutation of the src list, permuted the same way the
  12395. ; key list was permuted to obtain newkey.
  12396. (define (cg-permute src key newkey)
  12397. (let ((alist (map cons key (iota (length key)))))
  12398. (do ((newkey newkey (cdr newkey))
  12399. (dest '()
  12400. (cons (list-ref src (cdr (assq (car newkey) alist)))
  12401. dest)))
  12402. ((null? newkey) (reverse dest)))))
  12403. ; Given a list of register numbers,
  12404. ; an association list with entries of the form (name . regnum) giving
  12405. ; the variable names by which those registers are known in code,
  12406. ; and a list of expressions giving new values for those registers,
  12407. ; returns an ordering of the register assignments that implements a
  12408. ; parallel assignment if one can be found, otherwise returns #f.
  12409. (define parallel-assignment
  12410. (lambda (regnums alist exps)
  12411. (if (null? regnums)
  12412. #t
  12413. (let ((x (toposort (dependency-graph regnums alist exps))))
  12414. (if x (reverse x) #f)))))
  12415. (define dependency-graph
  12416. (lambda (regnums alist exps)
  12417. (let ((names (map car alist)))
  12418. (do ((regnums regnums (cdr regnums))
  12419. (exps exps (cdr exps))
  12420. (l '() (cons (cons (car regnums)
  12421. (map (lambda (var) (cdr (assq var alist)))
  12422. (intersection (freevariables (car exps))
  12423. names)))
  12424. l)))
  12425. ((null? regnums) l)))))
  12426. ; Given a nonempty graph represented as a list of the form
  12427. ; ((node1 . <list of nodes that node1 is less than or equal to>)
  12428. ; (node2 . <list of nodes that node2 is less than or equal to>)
  12429. ; ...)
  12430. ; returns a topological sort of the nodes if one can be found,
  12431. ; otherwise returns #f.
  12432. (define toposort
  12433. (lambda (graph)
  12434. (cond ((null? (cdr graph)) (list (caar graph)))
  12435. (else (toposort2 graph '())))))
  12436. (define toposort2
  12437. (lambda (totry tried)
  12438. (cond ((null? totry) #f)
  12439. ((or (null? (cdr (car totry)))
  12440. (and (null? (cddr (car totry)))
  12441. (eq? (cadr (car totry))
  12442. (car (car totry)))))
  12443. (if (and (null? (cdr totry)) (null? tried))
  12444. (list (caar totry))
  12445. (let* ((node (caar totry))
  12446. (x (toposort2 (map (lambda (y)
  12447. (cons (car y) (remove node (cdr y))))
  12448. (append (cdr totry) tried))
  12449. '())))
  12450. (if x
  12451. (cons node x)
  12452. #f))))
  12453. (else (toposort2 (cdr totry) (cons (car totry) tried))))))
  12454. (define iota (lambda (n) (iota2 n '())))
  12455. (define iota1 (lambda (n) (cdr (iota2 (+ n 1) '()))))
  12456. (define iota2
  12457. (lambda (n l)
  12458. (if (zero? n)
  12459. l
  12460. (let ((n (- n 1)))
  12461. (iota2 n (cons n l))))))
  12462. (define (freevariables exp)
  12463. (freevars2 exp '()))
  12464. (define (freevars2 exp env)
  12465. (cond ((symbol? exp)
  12466. (if (memq exp env) '() (list exp)))
  12467. ((not (pair? exp)) '())
  12468. (else (let ((keyword (car exp)))
  12469. (cond ((eq? keyword 'quote) '())
  12470. ((eq? keyword 'lambda)
  12471. (let ((env (append (make-null-terminated (cadr exp))
  12472. env)))
  12473. (apply-union
  12474. (map (lambda (x) (freevars2 x env))
  12475. (cddr exp)))))
  12476. ((memq keyword '(if set! begin))
  12477. (apply-union
  12478. (map (lambda (x) (freevars2 x env))
  12479. (cdr exp))))
  12480. (else (apply-union
  12481. (map (lambda (x) (freevars2 x env))
  12482. exp))))))))
  12483. ; Copyright 1991 William Clinger (cg-let and cg-let-body)
  12484. ; Copyright 1999 William Clinger (everything else)
  12485. ;
  12486. ; 10 June 1999.
  12487. ; Generates code for a let expression.
  12488. (define (cg-let output exp target regs frame env tail?)
  12489. (let* ((proc (call.proc exp))
  12490. (vars (lambda.args proc))
  12491. (n (length vars))
  12492. (free (lambda.F proc))
  12493. (live (cgframe-livevars frame)))
  12494. (if (and (null? (lambda.defs proc))
  12495. (= n 1))
  12496. (cg-let1 output exp target regs frame env tail?)
  12497. (let* ((args (call.args exp))
  12498. (temps (newtemps n))
  12499. (alist (map cons temps vars)))
  12500. (for-each (lambda (arg t)
  12501. (let ((r (choose-register regs frame)))
  12502. (cg0 output arg r regs frame env #f)
  12503. (cgreg-bind! regs r t)
  12504. (gen-store! output frame r t)))
  12505. args
  12506. temps)
  12507. (cgreg-rename! regs alist)
  12508. (cgframe-rename! frame alist)
  12509. (cg-let-release! free live regs frame tail?)
  12510. (cg-let-body output proc target regs frame env tail?)))))
  12511. ; Given the free variables of a let body, and the variables that are
  12512. ; live after the let expression, and the usual regs, frame, and tail?
  12513. ; arguments, releases any registers and frame slots that don't need
  12514. ; to be preserved across the body of the let.
  12515. (define (cg-let-release! free live regs frame tail?)
  12516. ; The tail case is easy because there are no live temporaries,
  12517. ; and there are no free variables in the context.
  12518. ; The non-tail case assumes A-normal form.
  12519. (cond (tail?
  12520. (let ((keepers (cons (cgreg-lookup-reg regs 0) free)))
  12521. (cgreg-release-except! regs keepers)
  12522. (cgframe-release-except! frame keepers)))
  12523. (live
  12524. (let ((keepers (cons (cgreg-lookup-reg regs 0)
  12525. (union live free))))
  12526. (cgreg-release-except! regs keepers)
  12527. (cgframe-release-except! frame keepers)))))
  12528. ; Generates code for the body of a let.
  12529. (define (cg-let-body output L target regs frame env tail?)
  12530. (let ((vars (lambda.args L))
  12531. (free (lambda.F L))
  12532. (live (cgframe-livevars frame)))
  12533. (let ((r (cg-body output L target regs frame env tail?)))
  12534. (for-each (lambda (v)
  12535. (let ((entry (cgreg-lookup regs v)))
  12536. (if entry
  12537. (cgreg-release! regs (entry.regnum entry)))
  12538. (cgframe-release! frame v)))
  12539. vars)
  12540. (if (and (not target)
  12541. (not (eq? r 'result))
  12542. (not (cgreg-lookup-reg regs r)))
  12543. (cg-move output frame regs r 'result)
  12544. r))))
  12545. ; Generates code for a let expression that binds exactly one variable
  12546. ; and has no internal definitions. These let expressions are very
  12547. ; common in A-normal form, and there are many special cases with
  12548. ; respect to register allocation and order of evaluation.
  12549. (define (cg-let1 output exp target regs frame env tail?)
  12550. (let* ((proc (call.proc exp))
  12551. (v (car (lambda.args proc)))
  12552. (arg (car (call.args exp)))
  12553. (free (lambda.F proc))
  12554. (live (cgframe-livevars frame))
  12555. (body (lambda.body proc)))
  12556. (define (evaluate-into-register r)
  12557. (cg0 output arg r regs frame env #f)
  12558. (cgreg-bind! regs r v)
  12559. (gen-store! output frame r v)
  12560. r)
  12561. (define (release-registers!)
  12562. (cgframe-livevars-set! frame live)
  12563. (cg-let-release! free live regs frame tail?))
  12564. (define (finish)
  12565. (release-registers!)
  12566. (cg-let-body output proc target regs frame env tail?))
  12567. (if live
  12568. (cgframe-livevars-set! frame (union live free)))
  12569. (cond ((assq v *regnames*)
  12570. (evaluate-into-register (cdr (assq v *regnames*)))
  12571. (finish))
  12572. ((not (memq v free))
  12573. (cg0 output arg #f regs frame env #f)
  12574. (finish))
  12575. (live
  12576. (cg0 output arg 'result regs frame env #f)
  12577. (release-registers!)
  12578. (cg-let1-result output exp target regs frame env tail?))
  12579. (else
  12580. (evaluate-into-register (choose-register regs frame))
  12581. (finish)))))
  12582. ; Given a let expression that binds one variable whose value has already
  12583. ; been evaluated into the result register, generates code for the rest
  12584. ; of the let expression.
  12585. ; The main difficulty is an unfortunate interaction between A-normal
  12586. ; form and the MacScheme machine architecture: We don't want to move
  12587. ; a value from the result register into a general register if it has
  12588. ; only one use and can remain in the result register until that use.
  12589. (define (cg-let1-result output exp target regs frame env tail?)
  12590. (let* ((proc (call.proc exp))
  12591. (v (car (lambda.args proc)))
  12592. (free (lambda.F proc))
  12593. (live (cgframe-livevars frame))
  12594. (body (lambda.body proc))
  12595. (pattern (cg-let-used-once v body)))
  12596. (define (move-to-register r)
  12597. (gen! output $setreg r)
  12598. (cgreg-bind! regs r v)
  12599. (gen-store! output frame r v)
  12600. r)
  12601. (define (release-registers!)
  12602. (cgframe-livevars-set! frame live)
  12603. (cg-let-release! free live regs frame tail?))
  12604. ; FIXME: The live variables must be correct in the frame.
  12605. (case pattern
  12606. ((if)
  12607. (cg-if-result output body target regs frame env tail?))
  12608. ((let-if)
  12609. (if live
  12610. (cgframe-livevars-set! frame (union live free)))
  12611. (cg-if-result output
  12612. (car (call.args body))
  12613. 'result regs frame env #f)
  12614. (release-registers!)
  12615. (cg-let1-result output body target regs frame env tail?))
  12616. ((set!)
  12617. (cg-assignment-result output
  12618. body target regs frame env tail?))
  12619. ((let-set!)
  12620. (cg-assignment-result output
  12621. (car (call.args body))
  12622. 'result regs frame env #f)
  12623. (cg-let1-result output body target regs frame env tail?))
  12624. ((primop)
  12625. (cg-primop-result output body target regs frame env tail?))
  12626. ((let-primop)
  12627. (cg-primop-result output
  12628. (car (call.args body))
  12629. 'result regs frame env #f)
  12630. (cg-let1-result output body target regs frame env tail?))
  12631. ; FIXME
  12632. ((_called)
  12633. (cg-call-result output body target regs frame env tail?))
  12634. ; FIXME
  12635. ((_let-called)
  12636. (cg-call-result output
  12637. (car (call.args body))
  12638. 'result regs frame env #f)
  12639. (cg-let1-result output body target regs frame env tail?))
  12640. (else
  12641. ; FIXME: The first case was handled by cg-let1.
  12642. (cond ((assq v *regnames*)
  12643. (move-to-register (cdr (assq v *regnames*))))
  12644. ((memq v free)
  12645. (move-to-register (choose-register regs frame))))
  12646. (cg-let-body output proc target regs frame env tail?)))))
  12647. ; Given a call to a primop whose first argument has already been
  12648. ; evaluated into the result register and whose remaining arguments
  12649. ; consist of constants and variable references, generates code for
  12650. ; the call.
  12651. (define (cg-primop-result output exp target regs frame env tail?)
  12652. (let ((args (call.args exp))
  12653. (entry (var-lookup (variable.name (call.proc exp)) regs frame env)))
  12654. (if (= (entry.arity entry) (length args))
  12655. (begin (case (entry.arity entry)
  12656. ((0) (gen! output $op1 (entry.op entry)))
  12657. ((1) (gen! output $op1 (entry.op entry)))
  12658. ((2) (cg-primop2-result! output entry args regs frame env))
  12659. ((3) (let ((rs (cg-result-args output args regs frame env)))
  12660. (gen! output
  12661. $op3 (entry.op entry) (car rs) (cadr rs))))
  12662. (else (error "Bug detected by cg-primop-result"
  12663. (make-readable exp))))
  12664. (if tail?
  12665. (begin (gen-pop! output frame)
  12666. (gen! output $return)
  12667. 'result)
  12668. (cg-move output frame regs 'result target)))
  12669. (if (negative? (entry.arity entry))
  12670. (cg-special-result output exp target regs frame env tail?)
  12671. (error "Wrong number of arguments to integrable procedure"
  12672. (make-readable exp))))))
  12673. (define (cg-primop2-result! output entry args regs frame env)
  12674. (let ((op (entry.op entry))
  12675. (arg2 (cadr args)))
  12676. (if (and (constant? arg2)
  12677. (entry.imm entry)
  12678. ((entry.imm entry) (constant.value arg2)))
  12679. (gen! output $op2imm op (constant.value arg2))
  12680. (let ((rs (cg-result-args output args regs frame env)))
  12681. (gen! output $op2 op (car rs))))))
  12682. ; Given a short list of constants and variable references to be evaluated
  12683. ; into arbitrary general registers, evaluates them into registers without
  12684. ; disturbing the result register and returns a list of the registers into
  12685. ; which they are evaluated. Before returning, any registers that were
  12686. ; allocated by this routine are released.
  12687. (define (cg-result-args output args regs frame env)
  12688. ; Given a list of unevaluated arguments,
  12689. ; a longer list of disjoint general registers,
  12690. ; the register that holds the first evaluated argument,
  12691. ; a list of registers in reverse order that hold other arguments,
  12692. ; and a list of registers to be released afterwards,
  12693. ; generates code to evaluate the arguments,
  12694. ; deallocates any registers that were evaluated to hold the arguments,
  12695. ; and returns the list of registers that contain the arguments.
  12696. (define (loop args registers rr rs temps)
  12697. (if (null? args)
  12698. (begin (if (not (eq? rr 'result))
  12699. (gen! output $reg rr))
  12700. (for-each (lambda (r) (cgreg-release! regs r))
  12701. temps)
  12702. (reverse rs))
  12703. (let ((arg (car args)))
  12704. (cond ((constant? arg)
  12705. (let ((r (car registers)))
  12706. (gen! output $const/setreg (constant.value arg) r)
  12707. (cgreg-bind! regs r #t)
  12708. (loop (cdr args)
  12709. (cdr registers)
  12710. rr
  12711. (cons r rs)
  12712. (cons r temps))))
  12713. ((variable? arg)
  12714. (let* ((id (variable.name arg))
  12715. (entry (var-lookup id regs frame env)))
  12716. (case (entry.kind entry)
  12717. ((global integrable)
  12718. (if (eq? rr 'result)
  12719. (save-result! args registers rr rs temps)
  12720. (let ((r (car registers)))
  12721. (gen! output $global id)
  12722. (gen! output $setreg r)
  12723. (cgreg-bind! regs r id)
  12724. (loop (cdr args)
  12725. (cdr registers)
  12726. rr
  12727. (cons r rs)
  12728. (cons r temps)))))
  12729. ((lexical)
  12730. (if (eq? rr 'result)
  12731. (save-result! args registers rr rs temps)
  12732. (let ((m (entry.rib entry))
  12733. (n (entry.offset entry))
  12734. (r (car registers)))
  12735. (gen! output $lexical m n id)
  12736. (gen! output $setreg r)
  12737. (cgreg-bind! regs r id)
  12738. (loop (cdr args)
  12739. (cdr registers)
  12740. rr
  12741. (cons r rs)
  12742. (cons r temps)))))
  12743. ((procedure) (error "Bug in cg-variable" arg))
  12744. ((register)
  12745. (let ((r (entry.regnum entry)))
  12746. (loop (cdr args)
  12747. registers
  12748. rr
  12749. (cons r rs)
  12750. temps)))
  12751. ((frame)
  12752. (let ((r (car registers)))
  12753. (gen-load! output frame r id)
  12754. (cgreg-bind! regs r id)
  12755. (loop (cdr args)
  12756. (cdr registers)
  12757. rr
  12758. (cons r rs)
  12759. (cons r temps))))
  12760. (else (error "Bug in cg-result-args" arg)))))
  12761. (else
  12762. (error "Bug in cg-result-args"))))))
  12763. (define (save-result! args registers rr rs temps)
  12764. (let ((r (car registers)))
  12765. (gen! output $setreg r)
  12766. (loop args
  12767. (cdr registers)
  12768. r
  12769. rs
  12770. temps)))
  12771. (loop (cdr args)
  12772. (choose-registers regs frame (length args))
  12773. 'result '() '()))
  12774. ; Given a local variable T1 and an expression in A-normal form,
  12775. ; cg-let-used-once returns a symbol if the local variable is used
  12776. ; exactly once in the expression and the expression matches one of
  12777. ; the patterns below. Otherwise returns #f. The symbol that is
  12778. ; returned is the name of the pattern that is matched.
  12779. ;
  12780. ; pattern symbol returned
  12781. ;
  12782. ; (if T1 ... ...) if
  12783. ;
  12784. ; (<primop> T1 ...) primop
  12785. ;
  12786. ; (T1 ...) called
  12787. ;
  12788. ; (set! ... T1) set!
  12789. ;
  12790. ; (let ((T2 (if T1 ... ...))) let-if
  12791. ; E3)
  12792. ;
  12793. ; (let ((T2 (<primop> T1 ...))) let-primop
  12794. ; E3)
  12795. ;
  12796. ; (let ((T2 (T1 ...))) let-called
  12797. ; E3)
  12798. ;
  12799. ; (let ((T2 (set! ... T1))) let-set!
  12800. ; E3)
  12801. ;
  12802. ; This implementation sometimes returns #f incorrectly, but it always
  12803. ; returns an answer in constant time (assuming A-normal form).
  12804. (define (cg-let-used-once T1 exp)
  12805. (define budget 20)
  12806. (define (cg-let-used-once T1 exp)
  12807. (define (used? T1 exp)
  12808. (set! budget (- budget 1))
  12809. (cond ((negative? budget) #t)
  12810. ((constant? exp) #f)
  12811. ((variable? exp)
  12812. (eq? T1 (variable.name exp)))
  12813. ((lambda? exp)
  12814. (memq T1 (lambda.F exp)))
  12815. ((assignment? exp)
  12816. (used? T1 (assignment.rhs exp)))
  12817. ((call? exp)
  12818. (or (used? T1 (call.proc exp))
  12819. (used-in-args? T1 (call.args exp))))
  12820. ((conditional? exp)
  12821. (or (used? T1 (if.test exp))
  12822. (used? T1 (if.then exp))
  12823. (used? T1 (if.else exp))))
  12824. (else #t)))
  12825. (define (used-in-args? T1 args)
  12826. (if (null? args)
  12827. #f
  12828. (or (used? T1 (car args))
  12829. (used-in-args? T1 (cdr args)))))
  12830. (set! budget (- budget 1))
  12831. (cond ((negative? budget) #f)
  12832. ((call? exp)
  12833. (let ((proc (call.proc exp))
  12834. (args (call.args exp)))
  12835. (cond ((variable? proc)
  12836. (let ((f (variable.name proc)))
  12837. (cond ((eq? f T1)
  12838. (and (not (used-in-args? T1 args))
  12839. 'called))
  12840. ((and (integrable? f)
  12841. (not (null? args))
  12842. (variable? (car args))
  12843. (eq? T1 (variable.name (car args))))
  12844. (and (not (used-in-args? T1 (cdr args)))
  12845. 'primop))
  12846. (else #f))))
  12847. ((lambda? proc)
  12848. (and (not (memq T1 (lambda.F proc)))
  12849. (not (null? args))
  12850. (null? (cdr args))
  12851. (case (cg-let-used-once T1 (car args))
  12852. ((if) 'let-if)
  12853. ((primop) 'let-primop)
  12854. ((called) 'let-called)
  12855. ((set!) 'let-set!)
  12856. (else #f))))
  12857. (else #f))))
  12858. ((conditional? exp)
  12859. (let ((E0 (if.test exp)))
  12860. (and (variable? E0)
  12861. (eq? T1 (variable.name E0))
  12862. (not (used? T1 (if.then exp)))
  12863. (not (used? T1 (if.else exp)))
  12864. 'if)))
  12865. ((assignment? exp)
  12866. (let ((rhs (assignment.rhs exp)))
  12867. (and (variable? rhs)
  12868. (eq? T1 (variable.name rhs))
  12869. 'set!)))
  12870. (else #f)))
  12871. (cg-let-used-once T1 exp))
  12872. ; Given the name of a let-body pattern, an expression that matches that
  12873. ; pattern, and an expression to be substituted for the let variable,
  12874. ; returns the transformed expression.
  12875. ; FIXME: No longer used.
  12876. (define (cg-let-transform pattern exp E1)
  12877. (case pattern
  12878. ((if)
  12879. (make-conditional E1 (if.then exp) (if.else exp)))
  12880. ((primop)
  12881. (make-call (call.proc exp)
  12882. (cons E1 (cdr (call.args exp)))))
  12883. ((called)
  12884. (make-call E1 (call.args exp)))
  12885. ((set!)
  12886. (make-assignment (assignment.lhs exp) E1))
  12887. ((let-if let-primop let-called let-set!)
  12888. (make-call (call.proc exp)
  12889. (list (cg-let-transform (case pattern
  12890. ((let-if) 'if)
  12891. ((let-primop) 'primop)
  12892. ((let-called) 'called)
  12893. ((let-set!) 'set!))
  12894. (car (call.args exp))
  12895. E1))))
  12896. (else
  12897. (error "Unrecognized pattern in cg-let-transform" pattern)))); Copyright 1999 William Clinger
  12898. ;
  12899. ; Code for special primitives, used to generate runtime safety checks,
  12900. ; efficient code for call-with-values, and other weird things.
  12901. ;
  12902. ; 4 June 1999.
  12903. (define (cg-special output exp target regs frame env tail?)
  12904. (let ((name (variable.name (call.proc exp))))
  12905. (cond ((eq? name name:CHECK!)
  12906. (if (runtime-safety-checking)
  12907. (cg-check output exp target regs frame env tail?)))
  12908. (else
  12909. (error "Compiler bug: cg-special" (make-readable exp))))))
  12910. (define (cg-special-result output exp target regs frame env tail?)
  12911. (let ((name (variable.name (call.proc exp))))
  12912. (cond ((eq? name name:CHECK!)
  12913. (if (runtime-safety-checking)
  12914. (cg-check-result output exp target regs frame env tail?)))
  12915. (else
  12916. (error "Compiler bug: cg-special" (make-readable exp))))))
  12917. (define (cg-check output exp target regs frame env tail?)
  12918. (cg0 output (car (call.args exp)) 'result regs frame env #f)
  12919. (cg-check-result output exp target regs frame env tail?))
  12920. (define (cg-check-result output exp target regs frame env tail?)
  12921. (let* ((args (call.args exp))
  12922. (nargs (length args))
  12923. (valexps (cddr args)))
  12924. (if (and (<= 2 nargs 5)
  12925. (constant? (cadr args))
  12926. (every? (lambda (exp)
  12927. (or (constant? exp)
  12928. (variable? exp)))
  12929. valexps))
  12930. (let* ((exn (constant.value (cadr args)))
  12931. (vars (filter variable? valexps))
  12932. (rs (cg-result-args output
  12933. (cons (car args) vars)
  12934. regs frame env)))
  12935. ; Construct the trap situation:
  12936. ; the exception number followed by an ordered list of
  12937. ; register numbers and constant expressions.
  12938. (let loop ((registers rs)
  12939. (exps valexps)
  12940. (operands '()))
  12941. (cond ((null? exps)
  12942. (let* ((situation (cons exn (reverse operands)))
  12943. (ht (assembly-stream-info output))
  12944. (L1 (or (hashtable-get ht situation)
  12945. (let ((L1 (make-label)))
  12946. (hashtable-put! ht situation L1)
  12947. L1))))
  12948. (define (translate r)
  12949. (if (number? r) r 0))
  12950. (case (length operands)
  12951. ((0) (gen! output $check 0 0 0 L1))
  12952. ((1) (gen! output $check
  12953. (translate (car operands))
  12954. 0 0 L1))
  12955. ((2) (gen! output $check
  12956. (translate (car operands))
  12957. (translate (cadr operands))
  12958. 0 L1))
  12959. ((3) (gen! output $check
  12960. (translate (car operands))
  12961. (translate (cadr operands))
  12962. (translate (caddr operands))
  12963. L1)))))
  12964. ((constant? (car exps))
  12965. (loop registers
  12966. (cdr exps)
  12967. (cons (car exps) operands)))
  12968. (else
  12969. (loop (cdr registers)
  12970. (cdr exps)
  12971. (cons (car registers) operands))))))
  12972. (error "Compiler bug: runtime check" (make-readable exp)))))
  12973. ; Given an assembly stream and the description of a trap as recorded
  12974. ; by cg-check above, generates a non-continuable trap at that label for
  12975. ; that trap, passing the operands to the exception handler.
  12976. (define (cg-trap output situation L1)
  12977. (let* ((exn (car situation))
  12978. (operands (cdr situation)))
  12979. (gen! output $.label L1)
  12980. (let ((liveregs (filter number? operands)))
  12981. (define (loop operands registers r)
  12982. (cond ((null? operands)
  12983. (case (length registers)
  12984. ((0) (gen! output $trap 0 0 0 exn))
  12985. ((1) (gen! output $trap (car registers) 0 0 exn))
  12986. ((2) (gen! output $trap
  12987. (car registers)
  12988. (cadr registers)
  12989. 0
  12990. exn))
  12991. ((3) (gen! output $trap
  12992. (car registers)
  12993. (cadr registers)
  12994. (caddr registers)
  12995. exn))
  12996. (else "Compiler bug: trap")))
  12997. ((number? (car operands))
  12998. (loop (cdr operands)
  12999. (cons (car operands) registers)
  13000. r))
  13001. ((memv r liveregs)
  13002. (loop operands registers (+ r 1)))
  13003. (else
  13004. (gen! output $const (constant.value (car operands)))
  13005. (gen! output $setreg r)
  13006. (loop (cdr operands)
  13007. (cons r registers)
  13008. (+ r 1)))))
  13009. (loop (reverse operands) '() 1))))
  13010. ; Given a short list of expressions that can be evaluated in any order,
  13011. ; evaluates the first into the result register and the others into any
  13012. ; register, and returns an ordered list of the registers that contain
  13013. ; the arguments that follow the first.
  13014. ; The number of expressions must be less than the number of argument
  13015. ; registers.
  13016. ; FIXME: No longer used.
  13017. (define (cg-check-args output args regs frame env)
  13018. ; Given a list of expressions to evaluate, a list of variables
  13019. ; and temporary names for arguments that have already been
  13020. ; evaluated, in reverse order, and a mask of booleans that
  13021. ; indicate which temporaries should be released before returning,
  13022. ; returns the correct result.
  13023. (define (eval-loop args temps mask)
  13024. (if (null? args)
  13025. (eval-first-into-result temps mask)
  13026. (let ((reg (cg0 output (car args) #f regs frame env #f)))
  13027. (if (eq? reg 'result)
  13028. (let* ((r (choose-register regs frame))
  13029. (t (newtemp)))
  13030. (gen! output $setreg r)
  13031. (cgreg-bind! regs r t)
  13032. (gen-store! output frame r t)
  13033. (eval-loop (cdr args)
  13034. (cons t temps)
  13035. (cons #t mask)))
  13036. (eval-loop (cdr args)
  13037. (cons (cgreg-lookup-reg regs reg) temps)
  13038. (cons #f mask))))))
  13039. (define (eval-first-into-result temps mask)
  13040. (cg0 output (car args) 'result regs frame env #f)
  13041. (finish-loop (choose-registers regs frame (length temps))
  13042. temps
  13043. mask
  13044. '()))
  13045. ; Given a sufficient number of disjoint registers, a list of
  13046. ; variable and temporary names that may need to be loaded into
  13047. ; registers, a mask of booleans that indicates which temporaries
  13048. ; should be released, and a list of registers in forward order,
  13049. ; returns the correct result.
  13050. (define (finish-loop disjoint temps mask registers)
  13051. (if (null? temps)
  13052. registers
  13053. (let* ((t (car temps))
  13054. (entry (cgreg-lookup regs t)))
  13055. (if entry
  13056. (let ((r (entry.regnum entry)))
  13057. (if (car mask)
  13058. (begin (cgreg-release! regs r)
  13059. (cgframe-release! frame t)))
  13060. (finish-loop disjoint
  13061. (cdr temps)
  13062. (cdr mask)
  13063. (cons r registers)))
  13064. (let ((r (car disjoint)))
  13065. (if (memv r registers)
  13066. (finish-loop (cdr disjoint) temps mask registers)
  13067. (begin (gen-load! output frame r t)
  13068. (cgreg-bind! regs r t)
  13069. (if (car mask)
  13070. (begin (cgreg-release! regs r)
  13071. (cgframe-release! frame t)))
  13072. (finish-loop disjoint
  13073. (cdr temps)
  13074. (cdr mask)
  13075. (cons r registers)))))))))
  13076. (if (< (length args) *nregs*)
  13077. (eval-loop (cdr args) '() '())
  13078. (error "Bug detected by cg-primop-args" args)))
  13079. ; Copyright 1998 William Clinger.
  13080. ;
  13081. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  13082. ;
  13083. ; 5 June 1999.
  13084. ;
  13085. ; Local optimizations for MacScheme machine assembly code.
  13086. ;
  13087. ; Branch tensioning.
  13088. ; Suppress nop instructions.
  13089. ; Suppress save, restore, and pop instructions whose operand is -1.
  13090. ; Suppress redundant stores.
  13091. ; Suppress definitions (primarily loads) of dead registers.
  13092. ;
  13093. ; Note: Twobit never generates a locally redundant load or store,
  13094. ; so this code must be tested with a different code generator.
  13095. ;
  13096. ; To perform these optimizations, the basic block must be traversed
  13097. ; both forwards and backwards.
  13098. ; The forward traversal keeps track of registers that were defined
  13099. ; by a load.
  13100. ; The backward traversal keeps track of live registers.
  13101. (define filter-basic-blocks
  13102. (let* ((suppression-message
  13103. "Local optimization detected a useless instruction.")
  13104. ; Each instruction is mapping to an encoding of the actions
  13105. ; to be performed when it is encountered during the forward
  13106. ; or backward traversal.
  13107. (forward:normal 0)
  13108. (forward:nop 1)
  13109. (forward:ends-block 2)
  13110. (forward:interesting 3)
  13111. (forward:kills-all-registers 4)
  13112. (forward:nop-if-arg1-is-negative 5)
  13113. (backward:normal 0)
  13114. (backward:ends-block 1)
  13115. (backward:begins-block 2)
  13116. (backward:uses-arg1 4)
  13117. (backward:uses-arg2 8)
  13118. (backward:uses-arg3 16)
  13119. (backward:kills-arg1 32)
  13120. (backward:kills-arg2 64)
  13121. (backward:uses-many 128)
  13122. ; largest mnemonic + 1
  13123. (dispatch-table-size *number-of-mnemonics*)
  13124. ; Dispatch table for the forwards traversal.
  13125. (forward-table (make-bytevector dispatch-table-size))
  13126. ; Dispatch table for the backwards traversal.
  13127. (backward-table (make-bytevector dispatch-table-size)))
  13128. (do ((i 0 (+ i 1)))
  13129. ((= i dispatch-table-size))
  13130. (bytevector-set! forward-table i forward:normal)
  13131. (bytevector-set! backward-table i backward:normal))
  13132. (bytevector-set! forward-table $nop forward:nop)
  13133. (bytevector-set! forward-table $invoke forward:ends-block)
  13134. (bytevector-set! forward-table $return forward:ends-block)
  13135. (bytevector-set! forward-table $skip forward:ends-block)
  13136. (bytevector-set! forward-table $branch forward:ends-block)
  13137. (bytevector-set! forward-table $branchf forward:ends-block)
  13138. (bytevector-set! forward-table $jump forward:ends-block)
  13139. (bytevector-set! forward-table $.align forward:ends-block)
  13140. (bytevector-set! forward-table $.proc forward:ends-block)
  13141. (bytevector-set! forward-table $.cont forward:ends-block)
  13142. (bytevector-set! forward-table $.label forward:ends-block)
  13143. (bytevector-set! forward-table $store forward:interesting)
  13144. (bytevector-set! forward-table $load forward:interesting)
  13145. (bytevector-set! forward-table $setstk forward:interesting)
  13146. (bytevector-set! forward-table $setreg forward:interesting)
  13147. (bytevector-set! forward-table $movereg forward:interesting)
  13148. (bytevector-set! forward-table $const/setreg
  13149. forward:interesting)
  13150. (bytevector-set! forward-table $args>= forward:kills-all-registers)
  13151. (bytevector-set! forward-table $popstk forward:kills-all-registers)
  13152. ; These instructions also kill all registers.
  13153. (bytevector-set! forward-table $save forward:nop-if-arg1-is-negative)
  13154. (bytevector-set! forward-table $restore forward:nop-if-arg1-is-negative)
  13155. (bytevector-set! forward-table $pop forward:nop-if-arg1-is-negative)
  13156. (bytevector-set! backward-table $invoke backward:ends-block)
  13157. (bytevector-set! backward-table $return backward:ends-block)
  13158. (bytevector-set! backward-table $skip backward:ends-block)
  13159. (bytevector-set! backward-table $branch backward:ends-block)
  13160. (bytevector-set! backward-table $branchf backward:ends-block)
  13161. (bytevector-set! backward-table $jump backward:begins-block) ; [sic]
  13162. (bytevector-set! backward-table $.align backward:begins-block)
  13163. (bytevector-set! backward-table $.proc backward:begins-block)
  13164. (bytevector-set! backward-table $.cont backward:begins-block)
  13165. (bytevector-set! backward-table $.label backward:begins-block)
  13166. (bytevector-set! backward-table $op2 backward:uses-arg2)
  13167. (bytevector-set! backward-table $op3 (logior backward:uses-arg2
  13168. backward:uses-arg3))
  13169. (bytevector-set! backward-table $check (logior
  13170. backward:uses-arg1
  13171. (logior backward:uses-arg2
  13172. backward:uses-arg3)))
  13173. (bytevector-set! backward-table $trap (logior
  13174. backward:uses-arg1
  13175. (logior backward:uses-arg2
  13176. backward:uses-arg3)))
  13177. (bytevector-set! backward-table $store backward:uses-arg1)
  13178. (bytevector-set! backward-table $reg backward:uses-arg1)
  13179. (bytevector-set! backward-table $load backward:kills-arg1)
  13180. (bytevector-set! backward-table $setreg backward:kills-arg1)
  13181. (bytevector-set! backward-table $movereg (logior backward:uses-arg1
  13182. backward:kills-arg2))
  13183. (bytevector-set! backward-table $const/setreg
  13184. backward:kills-arg2)
  13185. (bytevector-set! backward-table $lambda backward:uses-many)
  13186. (bytevector-set! backward-table $lexes backward:uses-many)
  13187. (bytevector-set! backward-table $args>= backward:uses-many)
  13188. (lambda (instructions)
  13189. (let* ((*nregs* *nregs*) ; locals might be faster than globals
  13190. ; During the forwards traversal:
  13191. ; (vector-ref registers i) = #f
  13192. ; means the content of register i is unknown
  13193. ; (vector-ref registers i) = j
  13194. ; means register was defined by load i,j
  13195. ;
  13196. ; During the backwards traversal:
  13197. ; (vector-ref registers i) = #f means register i is dead
  13198. ; (vector-ref registers i) = #t means register i is live
  13199. (registers (make-vector *nregs* #f))
  13200. ; During the forwards traversal, the label of a block that
  13201. ; falls through into another block or consists of a skip
  13202. ; to another block is mapped to another label.
  13203. ; This mapping is implemented by a hash table.
  13204. ; Before the backwards traversal, the transitive closure
  13205. ; is computed. The graph has no cycles, and the maximum
  13206. ; out-degree is 1, so this is easy.
  13207. (label-table (make-hashtable (lambda (n) n) assv)))
  13208. (define (compute-transitive-closure!)
  13209. (define (lookup x)
  13210. (let ((y (hashtable-get label-table x)))
  13211. (if y
  13212. (lookup y)
  13213. x)))
  13214. (hashtable-for-each (lambda (x y)
  13215. (hashtable-put! label-table x (lookup y)))
  13216. label-table))
  13217. ; Don't use this procedure until the preceding procedure
  13218. ; has been called.
  13219. (define (lookup-label x)
  13220. (hashtable-fetch label-table x x))
  13221. (define (vector-fill! v x)
  13222. (subvector-fill! v 0 (vector-length v) x))
  13223. (define (subvector-fill! v i j x)
  13224. (if (< i j)
  13225. (begin (vector-set! v i x)
  13226. (subvector-fill! v (+ i 1) j x))))
  13227. (define (kill-stack! j)
  13228. (do ((i 0 (+ i 1)))
  13229. ((= i *nregs*))
  13230. (let ((x (vector-ref registers i)))
  13231. (if (and x (= x j))
  13232. (vector-set! registers i #f)))))
  13233. ; Dispatch procedure for the forwards traversal.
  13234. (define (forwards instructions filtered)
  13235. (if (null? instructions)
  13236. (begin (vector-fill! registers #f)
  13237. (vector-set! registers 0 #t)
  13238. (compute-transitive-closure!)
  13239. (backwards0 filtered '()))
  13240. (let* ((instruction (car instructions))
  13241. (instructions (cdr instructions))
  13242. (op (instruction.op instruction))
  13243. (flags (bytevector-ref forward-table op)))
  13244. (cond ((eqv? flags forward:normal)
  13245. (forwards instructions (cons instruction filtered)))
  13246. ((eqv? flags forward:nop)
  13247. (forwards instructions filtered))
  13248. ((eqv? flags forward:nop-if-arg1-is-negative)
  13249. (if (negative? (instruction.arg1 instruction))
  13250. (forwards instructions filtered)
  13251. (begin (vector-fill! registers #f)
  13252. (forwards instructions
  13253. (cons instruction filtered)))))
  13254. ((eqv? flags forward:kills-all-registers)
  13255. (vector-fill! registers #f)
  13256. (forwards instructions
  13257. (cons instruction filtered)))
  13258. ((eqv? flags forward:ends-block)
  13259. (vector-fill! registers #f)
  13260. (if (eqv? op $.label)
  13261. (forwards-label instruction
  13262. instructions
  13263. filtered)
  13264. (forwards instructions
  13265. (cons instruction filtered))))
  13266. ((eqv? flags forward:interesting)
  13267. (cond ((eqv? op $setreg)
  13268. (vector-set! registers
  13269. (instruction.arg1 instruction)
  13270. #f)
  13271. (forwards instructions
  13272. (cons instruction filtered)))
  13273. ((eqv? op $const/setreg)
  13274. (vector-set! registers
  13275. (instruction.arg2 instruction)
  13276. #f)
  13277. (forwards instructions
  13278. (cons instruction filtered)))
  13279. ((eqv? op $movereg)
  13280. (vector-set! registers
  13281. (instruction.arg2 instruction)
  13282. #f)
  13283. (forwards instructions
  13284. (cons instruction filtered)))
  13285. ((eqv? op $setstk)
  13286. (kill-stack! (instruction.arg1 instruction))
  13287. (forwards instructions
  13288. (cons instruction filtered)))
  13289. ((eqv? op $load)
  13290. (let ((i (instruction.arg1 instruction))
  13291. (j (instruction.arg2 instruction)))
  13292. (if (eqv? (vector-ref registers i) j)
  13293. ; Suppress redundant load.
  13294. ; Should never happen with Twobit.
  13295. (suppress-forwards instruction
  13296. instructions
  13297. filtered)
  13298. (begin (vector-set! registers i j)
  13299. (forwards instructions
  13300. (cons instruction
  13301. filtered))))))
  13302. ((eqv? op $store)
  13303. (let ((i (instruction.arg1 instruction))
  13304. (j (instruction.arg2 instruction)))
  13305. (if (eqv? (vector-ref registers i) j)
  13306. ; Suppress redundant store.
  13307. ; Should never happen with Twobit.
  13308. (suppress-forwards instruction
  13309. instructions
  13310. filtered)
  13311. (begin (kill-stack! j)
  13312. (forwards instructions
  13313. (cons instruction
  13314. filtered))))))
  13315. (else
  13316. (local-optimization-error op))))
  13317. (else
  13318. (local-optimization-error op))))))
  13319. ; Enters labels into a table for branch tensioning.
  13320. (define (forwards-label instruction1 instructions filtered)
  13321. (let ((label1 (instruction.arg1 instruction1)))
  13322. (if (null? instructions)
  13323. ; This is ok provided the label is unreachable.
  13324. (forwards instructions (cdr filtered))
  13325. (let loop ((instructions instructions)
  13326. (filtered (cons instruction1 filtered)))
  13327. (let* ((instruction (car instructions))
  13328. (op (instruction.op instruction))
  13329. (flags (bytevector-ref forward-table op)))
  13330. (cond ((eqv? flags forward:nop)
  13331. (loop (cdr instructions) filtered))
  13332. ((and (eqv? flags forward:nop-if-arg1-is-negative)
  13333. (negative? (instruction.arg1 instruction)))
  13334. (loop (cdr instructions) filtered))
  13335. ((eqv? op $.label)
  13336. (let ((label2 (instruction.arg1 instruction)))
  13337. (hashtable-put! label-table label1 label2)
  13338. (forwards-label instruction
  13339. (cdr instructions)
  13340. (cdr filtered))))
  13341. ((eqv? op $skip)
  13342. (let ((label2 (instruction.arg1 instruction)))
  13343. (hashtable-put! label-table label1 label2)
  13344. ; We can't get rid of the skip instruction
  13345. ; because control might fall into this block,
  13346. ; but we can get rid of the label.
  13347. (forwards instructions (cdr filtered))))
  13348. (else
  13349. (forwards instructions filtered))))))))
  13350. ; Dispatch procedure for the backwards traversal.
  13351. (define (backwards instructions filtered)
  13352. (if (null? instructions)
  13353. filtered
  13354. (let* ((instruction (car instructions))
  13355. (instructions (cdr instructions))
  13356. (op (instruction.op instruction))
  13357. (flags (bytevector-ref backward-table op)))
  13358. (cond ((eqv? flags backward:normal)
  13359. (backwards instructions (cons instruction filtered)))
  13360. ((eqv? flags backward:ends-block)
  13361. (backwards0 (cons instruction instructions)
  13362. filtered))
  13363. ((eqv? flags backward:begins-block)
  13364. (backwards0 instructions
  13365. (cons instruction filtered)))
  13366. ((eqv? flags backward:uses-many)
  13367. (cond ((or (eqv? op $lambda)
  13368. (eqv? op $lexes))
  13369. (let ((live
  13370. (if (eqv? op $lexes)
  13371. (instruction.arg1 instruction)
  13372. (instruction.arg2 instruction))))
  13373. (subvector-fill! registers
  13374. 0
  13375. (min *nregs* (+ 1 live))
  13376. #t)
  13377. (backwards instructions
  13378. (cons instruction filtered))))
  13379. ((eqv? op $args>=)
  13380. (vector-fill! registers #t)
  13381. (backwards instructions
  13382. (cons instruction filtered)))
  13383. (else
  13384. (local-optimization-error op))))
  13385. ((and (eqv? (logand flags backward:kills-arg1)
  13386. backward:kills-arg1)
  13387. (not (vector-ref registers
  13388. (instruction.arg1 instruction))))
  13389. ; Suppress initialization of dead register.
  13390. (suppress-backwards instruction
  13391. instructions
  13392. filtered))
  13393. ((and (eqv? (logand flags backward:kills-arg2)
  13394. backward:kills-arg2)
  13395. (not (vector-ref registers
  13396. (instruction.arg2 instruction))))
  13397. ; Suppress initialization of dead register.
  13398. (suppress-backwards instruction
  13399. instructions
  13400. filtered))
  13401. ((and (eqv? op $movereg)
  13402. (= (instruction.arg1 instruction)
  13403. (instruction.arg2 instruction)))
  13404. (backwards instructions filtered))
  13405. (else
  13406. (let ((filtered (cons instruction filtered)))
  13407. (if (eqv? (logand flags backward:kills-arg1)
  13408. backward:kills-arg1)
  13409. (vector-set! registers
  13410. (instruction.arg1 instruction)
  13411. #f))
  13412. (if (eqv? (logand flags backward:kills-arg2)
  13413. backward:kills-arg2)
  13414. (vector-set! registers
  13415. (instruction.arg2 instruction)
  13416. #f))
  13417. (if (eqv? (logand flags backward:uses-arg1)
  13418. backward:uses-arg1)
  13419. (vector-set! registers
  13420. (instruction.arg1 instruction)
  13421. #t))
  13422. (if (eqv? (logand flags backward:uses-arg2)
  13423. backward:uses-arg2)
  13424. (vector-set! registers
  13425. (instruction.arg2 instruction)
  13426. #t))
  13427. (if (eqv? (logand flags backward:uses-arg3)
  13428. backward:uses-arg3)
  13429. (vector-set! registers
  13430. (instruction.arg3 instruction)
  13431. #t))
  13432. (backwards instructions filtered)))))))
  13433. ; Given a list of instructions in reverse order, whose first
  13434. ; element is the last instruction of a basic block,
  13435. ; and a filtered list of instructions in forward order,
  13436. ; returns a filtered list of instructions in the correct order.
  13437. (define (backwards0 instructions filtered)
  13438. (if (null? instructions)
  13439. filtered
  13440. (let* ((instruction (car instructions))
  13441. (mnemonic (instruction.op instruction)))
  13442. (cond ((or (eqv? mnemonic $.label)
  13443. (eqv? mnemonic $.proc)
  13444. (eqv? mnemonic $.cont)
  13445. (eqv? mnemonic $.align))
  13446. (backwards0 (cdr instructions)
  13447. (cons instruction filtered)))
  13448. ; all registers are dead at a $return
  13449. ((eqv? mnemonic $return)
  13450. (vector-fill! registers #f)
  13451. (vector-set! registers 0 #t)
  13452. (backwards (cdr instructions)
  13453. (cons instruction filtered)))
  13454. ; all but the argument registers are dead at an $invoke
  13455. ((eqv? mnemonic $invoke)
  13456. (let ((n+1 (min *nregs*
  13457. (+ (instruction.arg1 instruction) 1))))
  13458. (subvector-fill! registers 0 n+1 #t)
  13459. (subvector-fill! registers n+1 *nregs* #f)
  13460. (backwards (cdr instructions)
  13461. (cons instruction filtered))))
  13462. ; the compiler says which registers are live at the
  13463. ; target of $skip, $branch, $branchf, or $jump
  13464. ((or (eqv? mnemonic $skip)
  13465. (eqv? mnemonic $branch))
  13466. (let* ((live (instruction.arg2 instruction))
  13467. (n+1 (min *nregs* (+ live 1))))
  13468. (subvector-fill! registers 0 n+1 #t)
  13469. (subvector-fill! registers n+1 *nregs* #f)
  13470. (let ((instruction
  13471. ; FIXME
  13472. (list mnemonic
  13473. (lookup-label
  13474. (instruction.arg1 instruction))
  13475. live)))
  13476. (backwards (cdr instructions)
  13477. (cons instruction filtered)))))
  13478. ((eqv? mnemonic $jump)
  13479. (let ((n+1 (min *nregs*
  13480. (+ (instruction.arg3 instruction) 1))))
  13481. (subvector-fill! registers 0 n+1 #t)
  13482. (subvector-fill! registers n+1 *nregs* #f)
  13483. (backwards (cdr instructions)
  13484. (cons instruction filtered))))
  13485. ; the live registers at the target of a $branchf must be
  13486. ; combined with the live registers at the $branchf
  13487. ((eqv? mnemonic $branchf)
  13488. (let* ((live (instruction.arg2 instruction))
  13489. (n+1 (min *nregs* (+ live 1))))
  13490. (subvector-fill! registers 0 n+1 #t)
  13491. (let ((instruction
  13492. ; FIXME
  13493. (list mnemonic
  13494. (lookup-label
  13495. (instruction.arg1 instruction))
  13496. live)))
  13497. (backwards (cdr instructions)
  13498. (cons instruction filtered)))))
  13499. (else (backwards instructions filtered))))))
  13500. (define (suppress-forwards instruction instructions filtered)
  13501. (if (issue-warnings)
  13502. '(begin (display suppression-message)
  13503. (newline)))
  13504. (forwards instructions filtered))
  13505. (define (suppress-backwards instruction instructions filtered)
  13506. (if (issue-warnings)
  13507. '(begin (display suppression-message)
  13508. (newline)))
  13509. (backwards instructions filtered))
  13510. (define (local-optimization-error op)
  13511. (error "Compiler bug: local optimization" op))
  13512. (vector-fill! registers #f)
  13513. (forwards instructions '())))))
  13514. ; Copyright 1998 Lars T Hansen.
  13515. ;
  13516. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  13517. ;
  13518. ; 28 April 1999
  13519. ;
  13520. ; compile313 -- compilation parameters and driver procedures.
  13521. ; File types -- these may differ between operating systems.
  13522. (define *scheme-file-types* '(".sch" ".scm"))
  13523. (define *lap-file-type* ".lap")
  13524. (define *mal-file-type* ".mal")
  13525. (define *lop-file-type* ".lop")
  13526. (define *fasl-file-type* ".fasl")
  13527. ; Compile and assemble a scheme source file and produce a fastload file.
  13528. (define (compile-file infilename . rest)
  13529. (define (doit)
  13530. (let ((outfilename
  13531. (if (not (null? rest))
  13532. (car rest)
  13533. (rewrite-file-type infilename
  13534. *scheme-file-types*
  13535. *fasl-file-type*)))
  13536. (user
  13537. (assembly-user-data)))
  13538. (if (and (not (integrate-usual-procedures))
  13539. (issue-warnings))
  13540. (begin
  13541. (display "WARNING from compiler: ")
  13542. (display "integrate-usual-procedures is turned off")
  13543. (newline)
  13544. (display "Performance is likely to be poor.")
  13545. (newline)))
  13546. (if (benchmark-block-mode)
  13547. (process-file-block infilename
  13548. outfilename
  13549. dump-fasl-segment-to-port
  13550. (lambda (forms)
  13551. (assemble (compile-block forms) user)))
  13552. (process-file infilename
  13553. outfilename
  13554. dump-fasl-segment-to-port
  13555. (lambda (expr)
  13556. (assemble (compile expr) user))))
  13557. (unspecified)))
  13558. (if (eq? (nbuild-parameter 'target-machine) 'standard-c)
  13559. (error "Compile-file not supported on this target architecture.")
  13560. (doit)))
  13561. ; Assemble a MAL or LOP file and produce a FASL file.
  13562. (define (assemble-file infilename . rest)
  13563. (define (doit)
  13564. (let ((outfilename
  13565. (if (not (null? rest))
  13566. (car rest)
  13567. (rewrite-file-type infilename
  13568. (list *lap-file-type* *mal-file-type*)
  13569. *fasl-file-type*)))
  13570. (malfile?
  13571. (file-type=? infilename *mal-file-type*))
  13572. (user
  13573. (assembly-user-data)))
  13574. (process-file infilename
  13575. outfilename
  13576. dump-fasl-segment-to-port
  13577. (lambda (x) (assemble (if malfile? (eval x) x) user)))
  13578. (unspecified)))
  13579. (if (eq? (nbuild-parameter 'target-machine) 'standard-c)
  13580. (error "Assemble-file not supported on this target architecture.")
  13581. (doit)))
  13582. ; Compile and assemble a single expression; return the LOP segment.
  13583. (define compile-expression
  13584. (let ()
  13585. (define (compile-expression expr env)
  13586. (let ((syntax-env
  13587. (case (environment-tag env)
  13588. ((0 1) (make-standard-syntactic-environment))
  13589. ((2) global-syntactic-environment)
  13590. (else
  13591. (error "Invalid environment for compile-expression: " env)
  13592. #t))))
  13593. (let ((current-env global-syntactic-environment))
  13594. (dynamic-wind
  13595. (lambda ()
  13596. (set! global-syntactic-environment syntax-env))
  13597. (lambda ()
  13598. (assemble (compile expr)))
  13599. (lambda ()
  13600. (set! global-syntactic-environment current-env))))))
  13601. compile-expression))
  13602. (define macro-expand-expression
  13603. (let ()
  13604. (define (macro-expand-expression expr env)
  13605. (let ((syntax-env
  13606. (case (environment-tag env)
  13607. ((0 1) (make-standard-syntactic-environment))
  13608. ((2) global-syntactic-environment)
  13609. (else
  13610. (error "Invalid environment for compile-expression: " env)
  13611. #t))))
  13612. (let ((current-env global-syntactic-environment))
  13613. (dynamic-wind
  13614. (lambda ()
  13615. (set! global-syntactic-environment syntax-env))
  13616. (lambda ()
  13617. (make-readable
  13618. (macro-expand expr)))
  13619. (lambda ()
  13620. (set! global-syntactic-environment current-env))))))
  13621. macro-expand-expression))
  13622. ; Compile a scheme source file to a LAP file.
  13623. (define (compile313 infilename . rest)
  13624. (let ((outfilename
  13625. (if (not (null? rest))
  13626. (car rest)
  13627. (rewrite-file-type infilename
  13628. *scheme-file-types*
  13629. *lap-file-type*)))
  13630. (write-lap
  13631. (lambda (item port)
  13632. (write item port)
  13633. (newline port)
  13634. (newline port))))
  13635. (if (benchmark-block-mode)
  13636. (process-file-block infilename outfilename write-lap compile-block)
  13637. (process-file infilename outfilename write-lap compile))
  13638. (unspecified)))
  13639. ; Assemble a LAP or MAL file to a LOP file.
  13640. (define (assemble313 file . rest)
  13641. (let ((outputfile
  13642. (if (not (null? rest))
  13643. (car rest)
  13644. (rewrite-file-type file
  13645. (list *lap-file-type* *mal-file-type*)
  13646. *lop-file-type*)))
  13647. (malfile?
  13648. (file-type=? file *mal-file-type*))
  13649. (user
  13650. (assembly-user-data)))
  13651. (process-file file
  13652. outputfile
  13653. write-lop
  13654. (lambda (x) (assemble (if malfile? (eval x) x) user)))
  13655. (unspecified)))
  13656. ; Compile and assemble a Scheme source file to a LOP file.
  13657. (define (compile-and-assemble313 input-file . rest)
  13658. (let ((output-file
  13659. (if (not (null? rest))
  13660. (car rest)
  13661. (rewrite-file-type input-file
  13662. *scheme-file-types*
  13663. *lop-file-type*)))
  13664. (user
  13665. (assembly-user-data)))
  13666. (if (benchmark-block-mode)
  13667. (process-file-block input-file
  13668. output-file
  13669. write-lop
  13670. (lambda (x) (assemble (compile-block x) user)))
  13671. (process-file input-file
  13672. output-file
  13673. write-lop
  13674. (lambda (x) (assemble (compile x) user))))
  13675. (unspecified)))
  13676. ; Convert a LOP file to a FASL file.
  13677. (define (make-fasl infilename . rest)
  13678. (define (doit)
  13679. (let ((outfilename
  13680. (if (not (null? rest))
  13681. (car rest)
  13682. (rewrite-file-type infilename
  13683. *lop-file-type*
  13684. *fasl-file-type*))))
  13685. (process-file infilename
  13686. outfilename
  13687. dump-fasl-segment-to-port
  13688. (lambda (x) x))
  13689. (unspecified)))
  13690. (if (eq? (nbuild-parameter 'target-machine) 'standard-c)
  13691. (error "Make-fasl not supported on this target architecture.")
  13692. (doit)))
  13693. ; Disassemble a procedure's code vector.
  13694. (define (disassemble item . rest)
  13695. (let ((output-port (if (null? rest)
  13696. (current-output-port)
  13697. (car rest))))
  13698. (disassemble-item item #f output-port)
  13699. (unspecified)))
  13700. ; The item can be either a procedure or a pair (assumed to be a segment).
  13701. (define (disassemble-item item segment-no port)
  13702. (define (print . rest)
  13703. (for-each (lambda (x) (display x port)) rest)
  13704. (newline port))
  13705. (define (print-constvector cv)
  13706. (do ((i 0 (+ i 1)))
  13707. ((= i (vector-length cv)))
  13708. (print "------------------------------------------")
  13709. (print "Constant vector element # " i)
  13710. (case (car (vector-ref cv i))
  13711. ((codevector)
  13712. (print "Code vector")
  13713. (print-instructions (disassemble-codevector
  13714. (cadr (vector-ref cv i)))
  13715. port))
  13716. ((constantvector)
  13717. (print "Constant vector")
  13718. (print-constvector (cadr (vector-ref cv i))))
  13719. ((global)
  13720. (print "Global: " (cadr (vector-ref cv i))))
  13721. ((data)
  13722. (print "Data: " (cadr (vector-ref cv i)))))))
  13723. (define (print-segment segment)
  13724. (print "Segment # " segment-no)
  13725. (print-instructions (disassemble-codevector (car segment)) port)
  13726. (print-constvector (cdr segment))
  13727. (print "========================================"))
  13728. (cond ((procedure? item)
  13729. (print-instructions (disassemble-codevector (procedure-ref item 0))
  13730. port))
  13731. ((and (pair? item)
  13732. (bytevector? (car item))
  13733. (vector? (cdr item)))
  13734. (print-segment item))
  13735. (else
  13736. (error "disassemble-item: " item " is not disassemblable."))))
  13737. ; Disassemble a ".lop" or ".fasl" file; dump output to screen or
  13738. ; other (optional) file.
  13739. (define (disassemble-file file . rest)
  13740. (define (doit input-port output-port)
  13741. (display "; From " output-port)
  13742. (display file output-port)
  13743. (newline output-port)
  13744. (do ((segment-no 0 (+ segment-no 1))
  13745. (segment (read input-port) (read input-port)))
  13746. ((eof-object? segment))
  13747. (disassemble-item segment segment-no output-port)))
  13748. ; disassemble313
  13749. (call-with-input-file
  13750. file
  13751. (lambda (input-port)
  13752. (if (null? rest)
  13753. (doit input-port (current-output-port))
  13754. (begin
  13755. (delete-file (car rest))
  13756. (call-with-output-file
  13757. (car rest)
  13758. (lambda (output-port) (doit input-port output-port)))))))
  13759. (unspecified))
  13760. ; Display and manipulate the compiler switches.
  13761. (define (compiler-switches . rest)
  13762. (define (slow-code)
  13763. (set-compiler-flags! 'no-optimization)
  13764. (set-assembler-flags! 'no-optimization))
  13765. (define (standard-code)
  13766. (set-compiler-flags! 'standard)
  13767. (set-assembler-flags! 'standard))
  13768. (define (fast-safe-code)
  13769. (set-compiler-flags! 'fast-safe)
  13770. (set-assembler-flags! 'fast-safe))
  13771. (define (fast-unsafe-code)
  13772. (set-compiler-flags! 'fast-unsafe)
  13773. (set-assembler-flags! 'fast-unsafe))
  13774. (cond ((null? rest)
  13775. (display "Debugging:")
  13776. (newline)
  13777. (display-twobit-flags 'debugging)
  13778. (display-assembler-flags 'debugging)
  13779. (newline)
  13780. (display "Safety:")
  13781. (newline)
  13782. (display-twobit-flags 'safety)
  13783. (display-assembler-flags 'safety)
  13784. (newline)
  13785. (display "Speed:")
  13786. (newline)
  13787. (display-twobit-flags 'optimization)
  13788. (display-assembler-flags 'optimization)
  13789. (if #f #f))
  13790. ((null? (cdr rest))
  13791. (case (car rest)
  13792. ((0 slow) (slow-code))
  13793. ((1 standard) (standard-code))
  13794. ((2 fast-safe) (fast-safe-code))
  13795. ((3 fast-unsafe) (fast-unsafe-code))
  13796. ((default
  13797. factory-settings) (fast-safe-code)
  13798. (include-source-code #t)
  13799. (benchmark-mode #f)
  13800. (benchmark-block-mode #f)
  13801. (common-subexpression-elimination #f)
  13802. (representation-inference #f))
  13803. (else
  13804. (error "Unrecognized flag " (car rest) " to compiler-switches.")))
  13805. (unspecified))
  13806. (else
  13807. (error "Too many arguments to compiler-switches."))))
  13808. ; Read and process one file, producing another.
  13809. ; Preserves the global syntactic environment.
  13810. (define (process-file infilename outfilename writer processer)
  13811. (define (doit)
  13812. (delete-file outfilename)
  13813. (call-with-output-file
  13814. outfilename
  13815. (lambda (outport)
  13816. (call-with-input-file
  13817. infilename
  13818. (lambda (inport)
  13819. (let loop ((x (read inport)))
  13820. (if (eof-object? x)
  13821. #t
  13822. (begin (writer (processer x) outport)
  13823. (loop (read inport))))))))))
  13824. (let ((current-syntactic-environment
  13825. (syntactic-copy global-syntactic-environment)))
  13826. (dynamic-wind
  13827. (lambda () #t)
  13828. (lambda () (doit))
  13829. (lambda ()
  13830. (set! global-syntactic-environment
  13831. current-syntactic-environment)))))
  13832. ; Same as above, but passes a list of the entire file's contents
  13833. ; to the processer.
  13834. ; FIXME: Both versions of PROCESS-FILE always delete the output file.
  13835. ; Shouldn't it be left alone if the input file can't be opened?
  13836. (define (process-file-block infilename outfilename writer processer)
  13837. (define (doit)
  13838. (delete-file outfilename)
  13839. (call-with-output-file
  13840. outfilename
  13841. (lambda (outport)
  13842. (call-with-input-file
  13843. infilename
  13844. (lambda (inport)
  13845. (do ((x (read inport) (read inport))
  13846. (forms '() (cons x forms)))
  13847. ((eof-object? x)
  13848. (writer (processer (reverse forms)) outport))))))))
  13849. (let ((current-syntactic-environment
  13850. (syntactic-copy global-syntactic-environment)))
  13851. (dynamic-wind
  13852. (lambda () #t)
  13853. (lambda () (doit))
  13854. (lambda ()
  13855. (set! global-syntactic-environment
  13856. current-syntactic-environment)))))
  13857. ; Given a file name with some type, produce another with some other type.
  13858. (define (rewrite-file-type filename matches new)
  13859. (if (not (pair? matches))
  13860. (rewrite-file-type filename (list matches) new)
  13861. (let ((j (string-length filename)))
  13862. (let loop ((m matches))
  13863. (cond ((null? m)
  13864. (string-append filename new))
  13865. (else
  13866. (let* ((n (car m))
  13867. (l (string-length n)))
  13868. (if (file-type=? filename n)
  13869. (string-append (substring filename 0 (- j l)) new)
  13870. (loop (cdr m))))))))))
  13871. (define (file-type=? file-name type-name)
  13872. (let ((fl (string-length file-name))
  13873. (tl (string-length type-name)))
  13874. (and (>= fl tl)
  13875. (string-ci=? type-name
  13876. (substring file-name (- fl tl) fl)))))
  13877. ; eof
  13878. ; Copyright 1998 William Clinger.
  13879. ;
  13880. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  13881. ;
  13882. ; Procedures that make .LAP structures human-readable
  13883. (define (readify-lap code)
  13884. (map (lambda (x)
  13885. (let ((iname (cdr (assv (car x) *mnemonic-names*))))
  13886. (if (not (= (car x) $lambda))
  13887. (cons iname (cdr x))
  13888. (list iname (readify-lap (cadr x)) (caddr x)))))
  13889. code))
  13890. (define (readify-file f . o)
  13891. (define (doit)
  13892. (let ((i (open-input-file f)))
  13893. (let loop ((x (read i)))
  13894. (if (not (eof-object? x))
  13895. (begin (pretty-print (readify-lap x))
  13896. (loop (read i)))))))
  13897. (if (null? o)
  13898. (doit)
  13899. (begin (delete-file (car o))
  13900. (with-output-to-file (car o) doit))))
  13901. ; eof
  13902. ; Copyright 1991 Lightship Software, Incorporated.
  13903. ;
  13904. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  13905. ;
  13906. ; Target-independent part of the assembler.
  13907. ;
  13908. ; This is a simple, table-driven, one-pass assembler.
  13909. ; Part of it assumes a big-endian target machine.
  13910. ;
  13911. ; The input to this pass is a list of symbolic MacScheme machine
  13912. ; instructions and pseudo-instructions. Each symbolic MacScheme
  13913. ; machine instruction or pseudo-instruction is a list whose car
  13914. ; is a small non-negative fixnum that acts as the mnemonic for the
  13915. ; instruction. The rest of the list is interpreted as indicated
  13916. ; by the mnemonic.
  13917. ;
  13918. ; The output is a pair consisting of machine code (a bytevector or
  13919. ; string) and a constant vector.
  13920. ;
  13921. ; This assembler is table-driven, and may be customized to emit
  13922. ; machine code for different target machines. The table consists
  13923. ; of a vector of procedures indexed by mnemonics. Each procedure
  13924. ; in the table should take two arguments: an assembly structure
  13925. ; and a source instruction. The procedure should just assemble
  13926. ; the instruction using the operations defined below.
  13927. ;
  13928. ; The table and target can be changed by redefining the following
  13929. ; five procedures.
  13930. (define (assembly-table) (error "No assembly table defined."))
  13931. (define (assembly-start as) #t)
  13932. (define (assembly-end as segment) segment)
  13933. (define (assembly-user-data) #f)
  13934. ; The main entry point.
  13935. (define (assemble source . rest)
  13936. (let* ((user (if (null? rest) (assembly-user-data) (car rest)))
  13937. (as (make-assembly-structure source (assembly-table) user)))
  13938. (assembly-start as)
  13939. (assemble1 as
  13940. (lambda (as)
  13941. (let ((segment (assemble-pasteup as)))
  13942. (assemble-finalize! as)
  13943. (assembly-end as segment)))
  13944. #f)))
  13945. ; The following procedures are to be called by table routines.
  13946. ;
  13947. ; The assembly source for nested lambda expressions should be
  13948. ; assembled by calling this procedure. This allows an inner
  13949. ; lambda to refer to labels defined by outer lambdas.
  13950. ;
  13951. ; We delay the assembly of the nested lambda until after the outer lambda
  13952. ; has been finalized so that all labels in the outer lambda are known
  13953. ; to the inner lambda.
  13954. ;
  13955. ; The continuation procedure k is called to backpatch the constant
  13956. ; vector of the outer lambda after the inner lambda has been
  13957. ; finalized. This is necessary because of the delayed evaluation: the
  13958. ; outer lambda holds code and constants for the inner lambda in its
  13959. ; constant vector.
  13960. (define (assemble-nested-lambda as source doc k . rest)
  13961. (let* ((user (if (null? rest) #f (car rest)))
  13962. (nested-as (make-assembly-structure source (as-table as) user)))
  13963. (as-parent! nested-as as)
  13964. (as-nested! as (cons (lambda ()
  13965. (assemble1 nested-as
  13966. (lambda (nested-as)
  13967. (let ((segment
  13968. (assemble-pasteup nested-as)))
  13969. (assemble-finalize! nested-as)
  13970. (k nested-as segment)))
  13971. doc))
  13972. (as-nested as)))))
  13973. (define operand0 car) ; the mnemonic
  13974. (define operand1 cadr)
  13975. (define operand2 caddr)
  13976. (define operand3 cadddr)
  13977. (define (operand4 i) (car (cddddr i)))
  13978. ; Emits the bits contained in the bytevector bv.
  13979. (define (emit! as bv)
  13980. (as-code! as (cons bv (as-code as)))
  13981. (as-lc! as (+ (as-lc as) (bytevector-length bv))))
  13982. ; Emits the characters contained in the string s as code (for C generation).
  13983. (define (emit-string! as s)
  13984. (as-code! as (cons s (as-code as)))
  13985. (as-lc! as (+ (as-lc as) (string-length s))))
  13986. ; Given any Scheme object that may legally be quoted, returns an
  13987. ; index into the constant vector for that constant.
  13988. (define (emit-constant as x)
  13989. (do ((i 0 (+ i 1))
  13990. (y (as-constants as) (cdr y)))
  13991. ((or (null? y) (equal? x (car y)))
  13992. (if (null? y)
  13993. (as-constants! as (append! (as-constants as) (list x))))
  13994. i)))
  13995. (define (emit-datum as x)
  13996. (emit-constant as (list 'data x)))
  13997. (define (emit-global as x)
  13998. (emit-constant as (list 'global x)))
  13999. (define (emit-codevector as x)
  14000. (emit-constants as (list 'codevector x)))
  14001. (define (emit-constantvector as x)
  14002. (emit-constants as (list 'constantvector x)))
  14003. ; Set-constant changes the datum stored, without affecting the tag.
  14004. ; It can operate on the list form because the pair stored in the list
  14005. ; is shared between the list and any vector created from the list.
  14006. (define (set-constant! as n datum)
  14007. (let ((pair (list-ref (as-constants as) n)))
  14008. (set-car! (cdr pair) datum)))
  14009. ; Guarantees that the constants will not share structure
  14010. ; with any others, and will occupy consecutive positions
  14011. ; in the constant vector. Returns the index of the first
  14012. ; constant.
  14013. (define (emit-constants as x . rest)
  14014. (let* ((constants (as-constants as))
  14015. (i (length constants)))
  14016. (as-constants! as (append! constants (cons x rest)))
  14017. i))
  14018. ; Defines the given label using the current location counter.
  14019. (define (emit-label! as L)
  14020. (set-cdr! L (as-lc as)))
  14021. ; Adds the integer n to the size code bytes beginning at the
  14022. ; given byte offset from the current value of the location counter.
  14023. (define (emit-fixup! as offset size n)
  14024. (as-fixups! as (cons (list (+ offset (as-lc as)) size n)
  14025. (as-fixups as))))
  14026. ; Adds the value of the label L to the size code bytes beginning
  14027. ; at the given byte offset from the current location counter.
  14028. (define (emit-fixup-label! as offset size L)
  14029. (as-fixups! as (cons (list (+ offset (as-lc as)) size (list L))
  14030. (as-fixups as))))
  14031. ; Allows the procedure proc of two arguments (code vector and current
  14032. ; location counter) to modify the code vector at will, at fixup time.
  14033. (define (emit-fixup-proc! as proc)
  14034. (as-fixups! as (cons (list (as-lc as) 0 proc)
  14035. (as-fixups as))))
  14036. ; Labels.
  14037. ; The current value of the location counter.
  14038. (define (here as) (as-lc as))
  14039. ; Given a MAL label (a number), create an assembler label.
  14040. (define (make-asm-label as label)
  14041. (let ((probe (find-label as label)))
  14042. (if probe
  14043. probe
  14044. (let ((l (cons label #f)))
  14045. (as-labels! as (cons l (as-labels as)))
  14046. l))))
  14047. ; This can use hashed lookup.
  14048. (define (find-label as L)
  14049. (define (lookup-label-loop x labels parent)
  14050. (let ((entry (assq x labels)))
  14051. (cond (entry)
  14052. ((not parent) #f)
  14053. (else
  14054. (lookup-label-loop x (as-labels parent) (as-parent parent))))))
  14055. (lookup-label-loop L (as-labels as) (as-parent as)))
  14056. ; Create a new assembler label, distinguishable from a MAL label.
  14057. (define new-label
  14058. (let ((n 0))
  14059. (lambda ()
  14060. (set! n (- n 1))
  14061. (cons n #f))))
  14062. ; Given a value name (a number), return the label value or #f.
  14063. (define (label-value as L) (cdr L))
  14064. ; For peephole optimization.
  14065. (define (next-instruction as)
  14066. (let ((source (as-source as)))
  14067. (if (null? source)
  14068. '(-1)
  14069. (car source))))
  14070. (define (consume-next-instruction! as)
  14071. (as-source! as (cdr (as-source as))))
  14072. (define (push-instruction as instruction)
  14073. (as-source! as (cons instruction (as-source as))))
  14074. ; For use by the machine assembler: assoc lists connected to as structure.
  14075. (define (assembler-value as key)
  14076. (let ((probe (assq key (as-values as))))
  14077. (if probe
  14078. (cdr probe)
  14079. #f)))
  14080. (define (assembler-value! as key value)
  14081. (let ((probe (assq key (as-values as))))
  14082. (if probe
  14083. (set-cdr! probe value)
  14084. (as-values! as (cons (cons key value) (as-values as))))))
  14085. ; For documentation.
  14086. ;
  14087. ; The value must be a documentation structure (a vector).
  14088. (define (add-documentation as doc)
  14089. (let* ((existing-constants (cadr (car (as-constants as))))
  14090. (new-constants
  14091. (twobit-sort (lambda (a b)
  14092. (< (car a) (car b)))
  14093. (cond ((not existing-constants)
  14094. (list (cons (here as) doc)))
  14095. ((pair? existing-constants)
  14096. (cons (cons (here as) doc)
  14097. existing-constants))
  14098. (else
  14099. (list (cons (here as) doc)
  14100. (cons 0 existing-constants)))))))
  14101. (set-car! (cdar (as-constants as)) new-constants)))
  14102. ; This is called when a value is too large to be handled by the assembler.
  14103. ; Info is a string, expr an assembler expression, and val the resulting
  14104. ; value. The default behavior is to signal an error.
  14105. (define (asm-value-too-large as info expr val)
  14106. (if (as-retry as)
  14107. ((as-retry as))
  14108. (asm-error info ": Value too large: " expr " = " val)))
  14109. ; The implementations of asm-error and disasm-error depend on the host
  14110. ; system. Sigh.
  14111. (define (asm-error msg . rest)
  14112. (cond ((eq? host-system 'chez)
  14113. (error 'assembler "~a" (list msg rest)))
  14114. (else
  14115. (apply error msg rest))))
  14116. (define (disasm-error msg . rest)
  14117. (cond ((eq? host-system 'chez)
  14118. (error 'disassembler "~a" (list msg rest)))
  14119. (else
  14120. (apply error msg rest))))
  14121. ; The remaining procedures in this file are local to the assembler.
  14122. ; An assembly structure is a vector consisting of
  14123. ;
  14124. ; table (a table of assembly routines)
  14125. ; source (a list of symbolic instructions)
  14126. ; lc (location counter; an integer)
  14127. ; code (a list of bytevectors)
  14128. ; constants (a list)
  14129. ; labels (an alist of labels and values)
  14130. ; fixups (an alist of locations, sizes, and labels or fixnums)
  14131. ; nested (a list of assembly procedures for nested lambdas)
  14132. ; values (an assoc list)
  14133. ; parent (an assembly structure or #f)
  14134. ; retry (a thunk or #f)
  14135. ; user-data (anything)
  14136. ;
  14137. ; In fixups, labels are of the form (<L>) to distinguish them from fixnums.
  14138. (define (label? x) (and (pair? x) (fixnum? (car x))))
  14139. (define label.ident car)
  14140. (define (make-assembly-structure source table user-data)
  14141. (vector table
  14142. source
  14143. 0
  14144. '()
  14145. '()
  14146. '()
  14147. '()
  14148. '()
  14149. '()
  14150. #f
  14151. #f
  14152. user-data))
  14153. (define (as-reset! as source)
  14154. (as-source! as source)
  14155. (as-lc! as 0)
  14156. (as-code! as '())
  14157. (as-constants! as '())
  14158. (as-labels! as '())
  14159. (as-fixups! as '())
  14160. (as-nested! as '())
  14161. (as-values! as '())
  14162. (as-retry! as #f))
  14163. (define (as-table as) (vector-ref as 0))
  14164. (define (as-source as) (vector-ref as 1))
  14165. (define (as-lc as) (vector-ref as 2))
  14166. (define (as-code as) (vector-ref as 3))
  14167. (define (as-constants as) (vector-ref as 4))
  14168. (define (as-labels as) (vector-ref as 5))
  14169. (define (as-fixups as) (vector-ref as 6))
  14170. (define (as-nested as) (vector-ref as 7))
  14171. (define (as-values as) (vector-ref as 8))
  14172. (define (as-parent as) (vector-ref as 9))
  14173. (define (as-retry as) (vector-ref as 10))
  14174. (define (as-user as) (vector-ref as 11))
  14175. (define (as-source! as x) (vector-set! as 1 x))
  14176. (define (as-lc! as x) (vector-set! as 2 x))
  14177. (define (as-code! as x) (vector-set! as 3 x))
  14178. (define (as-constants! as x) (vector-set! as 4 x))
  14179. (define (as-labels! as x) (vector-set! as 5 x))
  14180. (define (as-fixups! as x) (vector-set! as 6 x))
  14181. (define (as-nested! as x) (vector-set! as 7 x))
  14182. (define (as-values! as x) (vector-set! as 8 x))
  14183. (define (as-parent! as x) (vector-set! as 9 x))
  14184. (define (as-retry! as x) (vector-set! as 10 x))
  14185. (define (as-user! as x) (vector-set! as 11 x))
  14186. ; The guts of the assembler.
  14187. (define (assemble1 as finalize doc)
  14188. (let ((assembly-table (as-table as))
  14189. (peep? (peephole-optimization))
  14190. (step? (single-stepping))
  14191. (step-instr (list $.singlestep))
  14192. (end-instr (list $.end)))
  14193. (define (loop)
  14194. (let ((source (as-source as)))
  14195. (if (null? source)
  14196. (begin ((vector-ref assembly-table $.end) end-instr as)
  14197. (finalize as))
  14198. (begin (if step?
  14199. ((vector-ref assembly-table $.singlestep)
  14200. step-instr
  14201. as))
  14202. (if peep?
  14203. (let peeploop ((src1 source))
  14204. (peep as)
  14205. (let ((src2 (as-source as)))
  14206. (if (not (eq? src1 src2))
  14207. (peeploop src2)))))
  14208. (let ((source (as-source as)))
  14209. (as-source! as (cdr source))
  14210. ((vector-ref assembly-table (caar source))
  14211. (car source)
  14212. as)
  14213. (loop))))))
  14214. (define (doit)
  14215. (emit-datum as doc)
  14216. (loop))
  14217. (let* ((source (as-source as))
  14218. (r (call-with-current-continuation
  14219. (lambda (k)
  14220. (as-retry! as (lambda () (k 'retry)))
  14221. (doit)))))
  14222. (if (eq? r 'retry)
  14223. (let ((old (short-effective-addresses)))
  14224. (as-reset! as source)
  14225. (dynamic-wind
  14226. (lambda ()
  14227. (short-effective-addresses #f))
  14228. doit
  14229. (lambda ()
  14230. (short-effective-addresses old))))
  14231. r))))
  14232. (define (assemble-pasteup as)
  14233. (define (pasteup-code)
  14234. (let ((code (make-bytevector (as-lc as)))
  14235. (constants (list->vector (as-constants as))))
  14236. ; The bytevectors: byte 0 is most significant.
  14237. (define (paste-code! bvs i)
  14238. (if (not (null? bvs))
  14239. (let* ((bv (car bvs))
  14240. (n (bytevector-length bv)))
  14241. (do ((i i (- i 1))
  14242. (j (- n 1) (- j 1))) ; (j 0 (+ j 1))
  14243. ((< j 0) ; (= j n)
  14244. (paste-code! (cdr bvs) i))
  14245. (bytevector-set! code i (bytevector-ref bv j))))))
  14246. (paste-code! (as-code as) (- (as-lc as) 1))
  14247. (as-code! as (list code))
  14248. (cons code constants)))
  14249. (define (pasteup-strings)
  14250. (let ((code (make-string (as-lc as)))
  14251. (constants (list->vector (as-constants as))))
  14252. (define (paste-code! strs i)
  14253. (if (not (null? strs))
  14254. (let* ((s (car strs))
  14255. (n (string-length s)))
  14256. (do ((i i (- i 1))
  14257. (j (- n 1) (- j 1))) ; (j 0 (+ j 1))
  14258. ((< j 0) ; (= j n)
  14259. (paste-code! (cdr strs) i))
  14260. (string-set! code i (string-ref s j))))))
  14261. (paste-code! (as-code as) (- (as-lc as) 1))
  14262. (as-code! as (list code))
  14263. (cons code constants)))
  14264. (if (bytevector? (car (as-code as)))
  14265. (pasteup-code)
  14266. (pasteup-strings)))
  14267. (define (assemble-finalize! as)
  14268. (let ((code (car (as-code as))))
  14269. (define (apply-fixups! fixups)
  14270. (if (not (null? fixups))
  14271. (let* ((fixup (car fixups))
  14272. (i (car fixup))
  14273. (size (cadr fixup))
  14274. (adjustment (caddr fixup)) ; may be procedure
  14275. (n (if (label? adjustment)
  14276. (lookup-label adjustment)
  14277. adjustment)))
  14278. (case size
  14279. ((0) (fixup-proc code i n))
  14280. ((1) (fixup1 code i n))
  14281. ((2) (fixup2 code i n))
  14282. ((3) (fixup3 code i n))
  14283. ((4) (fixup4 code i n))
  14284. (else ???))
  14285. (apply-fixups! (cdr fixups)))))
  14286. (define (lookup-label L)
  14287. (or (label-value as (label.ident L))
  14288. (asm-error "Assembler error -- undefined label " L)))
  14289. (apply-fixups! (reverse! (as-fixups as)))
  14290. (for-each (lambda (nested-as-proc)
  14291. (nested-as-proc))
  14292. (as-nested as))))
  14293. ; These fixup routines assume a big-endian target machine.
  14294. (define (fixup1 code i n)
  14295. (bytevector-set! code i (+ n (bytevector-ref code i))))
  14296. (define (fixup2 code i n)
  14297. (let* ((x (+ (* 256 (bytevector-ref code i))
  14298. (bytevector-ref code (+ i 1))))
  14299. (y (+ x n))
  14300. (y0 (modulo y 256))
  14301. (y1 (modulo (quotient (- y y0) 256) 256)))
  14302. (bytevector-set! code i y1)
  14303. (bytevector-set! code (+ i 1) y0)))
  14304. (define (fixup3 code i n)
  14305. (let* ((x (+ (* 65536 (bytevector-ref code i))
  14306. (* 256 (bytevector-ref code (+ i 1)))
  14307. (bytevector-ref code (+ i 2))))
  14308. (y (+ x n))
  14309. (y0 (modulo y 256))
  14310. (y1 (modulo (quotient (- y y0) 256) 256))
  14311. (y2 (modulo (quotient (- y (* 256 y1) y0) 256) 256)))
  14312. (bytevector-set! code i y2)
  14313. (bytevector-set! code (+ i 1) y1)
  14314. (bytevector-set! code (+ i 2) y0)))
  14315. (define (fixup4 code i n)
  14316. (let* ((x (+ (* 16777216 (bytevector-ref code i))
  14317. (* 65536 (bytevector-ref code (+ i 1)))
  14318. (* 256 (bytevector-ref code (+ i 2)))
  14319. (bytevector-ref code (+ i 3))))
  14320. (y (+ x n))
  14321. (y0 (modulo y 256))
  14322. (y1 (modulo (quotient (- y y0) 256) 256))
  14323. (y2 (modulo (quotient (- y (* 256 y1) y0) 256) 256))
  14324. (y3 (modulo (quotient (- y (* 65536 y2)
  14325. (* 256 y1)
  14326. y0)
  14327. 256)
  14328. 256)))
  14329. (bytevector-set! code i y3)
  14330. (bytevector-set! code (+ i 1) y2)
  14331. (bytevector-set! code (+ i 2) y1)
  14332. (bytevector-set! code (+ i 3) y0)))
  14333. (define (fixup-proc code i p)
  14334. (p code i))
  14335. ; For testing.
  14336. (define (view-segment segment)
  14337. (define (display-bytevector bv)
  14338. (let ((n (bytevector-length bv)))
  14339. (do ((i 0 (+ i 1)))
  14340. ((= i n))
  14341. (if (zero? (remainder i 4))
  14342. (write-char #\space))
  14343. (if (zero? (remainder i 8))
  14344. (write-char #\space))
  14345. (if (zero? (remainder i 32))
  14346. (newline))
  14347. (let ((byte (bytevector-ref bv i)))
  14348. (write-char
  14349. (string-ref (number->string (quotient byte 16) 16) 0))
  14350. (write-char
  14351. (string-ref (number->string (remainder byte 16) 16) 0))))))
  14352. (if (and (pair? segment)
  14353. (bytevector? (car segment))
  14354. (vector? (cdr segment)))
  14355. (begin (display-bytevector (car segment))
  14356. (newline)
  14357. (write (cdr segment))
  14358. (newline)
  14359. (do ((constants (vector->list (cdr segment))
  14360. (cdr constants)))
  14361. ((or (null? constants)
  14362. (null? (cdr constants))))
  14363. (if (and (bytevector? (car constants))
  14364. (vector? (cadr constants)))
  14365. (view-segment (cons (car constants)
  14366. (cadr constants))))))))
  14367. ; emit is a procedure that takes an as and emits instructions into it.
  14368. (define (test-asm emit)
  14369. (let ((as (make-assembly-structure #f #f #f)))
  14370. (emit as)
  14371. (let ((segment (assemble-pasteup as)))
  14372. (assemble-finalize! as)
  14373. (disassemble segment))))
  14374. (define (compile&assemble x)
  14375. (view-segment (assemble (compile x))))
  14376. ; eof
  14377. ; Copyright 1998 Lars T Hansen.
  14378. ;
  14379. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  14380. ;
  14381. ; Common assembler -- miscellaneous utility procedures.
  14382. ; Given any Scheme object, return its printable representation as a string.
  14383. ; This code is largely portable (see comments).
  14384. (define (format-object x)
  14385. (define (format-list x)
  14386. (define (loop x)
  14387. (cond ((null? x)
  14388. '(")"))
  14389. ((null? (cdr x))
  14390. (list (format-object (car x)) ")"))
  14391. (else
  14392. (cons (format-object (car x))
  14393. (cons " "
  14394. (loop (cdr x)))))))
  14395. (apply string-append (cons "(" (loop x))))
  14396. (define (format-improper-list x)
  14397. (define (loop x)
  14398. (if (pair? (cdr x))
  14399. (cons (format-object (car x))
  14400. (cons " "
  14401. (loop (cdr x))))
  14402. (list (format-object (car x))
  14403. " . "
  14404. (format-object (cdr x))
  14405. ")")))
  14406. (apply string-append (cons "(" (loop x))))
  14407. (cond ((null? x) "()")
  14408. ((not x) "#f")
  14409. ((eq? x #t) "#t")
  14410. ((symbol? x) (symbol->string x))
  14411. ((number? x) (number->string x))
  14412. ((char? x) (string x))
  14413. ((string? x) x)
  14414. ((procedure? x) "#<procedure>")
  14415. ((bytevector? x) "#<bytevector>") ; Larceny
  14416. ((eof-object? x) "#<eof>")
  14417. ((port? x) "#<port>")
  14418. ((eq? x (unspecified)) "#!unspecified") ; Larceny
  14419. ((eq? x (undefined)) "#!undefined") ; Larceny
  14420. ((vector? x)
  14421. (string-append "#" (format-list (vector->list x))))
  14422. ((list? x)
  14423. (format-list x))
  14424. ((pair? x)
  14425. (format-improper-list x))
  14426. (else "#<weird>")))
  14427. ; eof
  14428. ; Copyright 1998 Lars T Hansen.
  14429. ;
  14430. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  14431. ;
  14432. ; Larceny assembler -- 32-bit big-endian utility procedures.
  14433. ;
  14434. ; 32-bit numbers are represented as 4-byte bytevectors where byte 3
  14435. ; is the least significant and byte 0 is the most significant.
  14436. ;
  14437. ; Logically, the 'big' end is on the left and the 'little' end
  14438. ; is on the right, so a left shift shifts towards the 'big' end.
  14439. ;
  14440. ; Performance: poor, for good reasons. See asmutil32.sch.
  14441. ; Identifies the code loaded.
  14442. (define asm:endianness 'big)
  14443. ; Given four bytes, create a length-4 bytevector.
  14444. ; N1 is the most significant byte, n4 the least significant.
  14445. (define (asm:bv n1 n2 n3 n4)
  14446. (let ((bv (make-bytevector 4)))
  14447. (bytevector-set! bv 0 n1)
  14448. (bytevector-set! bv 1 n2)
  14449. (bytevector-set! bv 2 n3)
  14450. (bytevector-set! bv 3 n4)
  14451. bv))
  14452. ; Given a length-4 bytevector, convert it to an integer.
  14453. (define (asm:bv->int bv)
  14454. (let ((i (+ (* (+ (* (+ (* (bytevector-ref bv 0) 256)
  14455. (bytevector-ref bv 1))
  14456. 256)
  14457. (bytevector-ref bv 2))
  14458. 256)
  14459. (bytevector-ref bv 3))))
  14460. (if (> (bytevector-ref bv 0) 127)
  14461. (- i)
  14462. i)))
  14463. ; Shift the bits of m left by n bits, shifting in zeroes at the right end.
  14464. ; Returns a length-4 bytevector.
  14465. ;
  14466. ; M may be an exact integer or a length-4 bytevector.
  14467. ; N must be an exact nonnegative integer; it's interpreted modulo 33.
  14468. (define (asm:lsh m n)
  14469. (if (not (bytevector? m))
  14470. (asm:lsh (asm:int->bv m) n)
  14471. (let ((m (bytevector-copy m))
  14472. (n (remainder n 33)))
  14473. (if (>= n 8)
  14474. (let ((k (quotient n 8)))
  14475. (do ((i 0 (+ i 1)))
  14476. ((= (+ i k) 4)
  14477. (do ((i i (+ i 1)))
  14478. ((= i 4))
  14479. (bytevector-set! m i 0)))
  14480. (bytevector-set! m i (bytevector-ref m (+ i k))))))
  14481. (let* ((d0 (bytevector-ref m 0))
  14482. (d1 (bytevector-ref m 1))
  14483. (d2 (bytevector-ref m 2))
  14484. (d3 (bytevector-ref m 3))
  14485. (n (remainder n 8))
  14486. (n- (- 8 n)))
  14487. (asm:bv (logand (logior (lsh d0 n) (rshl d1 n-)) 255)
  14488. (logand (logior (lsh d1 n) (rshl d2 n-)) 255)
  14489. (logand (logior (lsh d2 n) (rshl d3 n-)) 255)
  14490. (logand (lsh d3 n) 255))))))
  14491. ; Shift the bits of m right by n bits, shifting in zeroes at the high end.
  14492. ; Returns a length-4 bytevector.
  14493. ;
  14494. ; M may be an exact integer or a length-4 bytevector.
  14495. ; N must be an exact nonnegative integer; it's interpreted modulo 33.
  14496. (define (asm:rshl m n)
  14497. (if (not (bytevector? m))
  14498. (asm:rshl (asm:int->bv m) n)
  14499. (let ((m (bytevector-copy m))
  14500. (n (remainder n 33)))
  14501. (if (>= n 8)
  14502. (let ((k (quotient n 8)))
  14503. (do ((i 3 (- i 1)))
  14504. ((< (- i k) 0)
  14505. (do ((i i (- i 1)))
  14506. ((< i 0))
  14507. (bytevector-set! m i 0)))
  14508. (bytevector-set! m i (bytevector-ref m (- i k))))))
  14509. (let* ((d0 (bytevector-ref m 0))
  14510. (d1 (bytevector-ref m 1))
  14511. (d2 (bytevector-ref m 2))
  14512. (d3 (bytevector-ref m 3))
  14513. (n (remainder n 8))
  14514. (n- (- 8 n)))
  14515. (asm:bv (rshl d0 n)
  14516. (logand (logior (rshl d1 n) (lsh d0 n-)) 255)
  14517. (logand (logior (rshl d2 n) (lsh d1 n-)) 255)
  14518. (logand (logior (rshl d3 n) (lsh d2 n-)) 255))))))
  14519. ; Shift the bits of m right by n bits, shifting in the sign bit at the
  14520. ; high end. Returns a length-4 bytevector.
  14521. ;
  14522. ; M may be an exact integer or a length-4 bytevector.
  14523. ; N must be an exact nonnegative integer; it's interpreted modulo 33.
  14524. (define asm:rsha
  14525. (let ((ones (asm:bv #xff #xff #xff #xff)))
  14526. (lambda (m n)
  14527. (let* ((m (if (bytevector? m) m (asm:int->bv m)))
  14528. (n (remainder n 33))
  14529. (h (rshl (bytevector-ref m 0) 7))
  14530. (k (asm:rshl m n)))
  14531. ; (format #t "~a ~a ~a~%" h (bytevector-ref m 0) n)
  14532. ; (prnx (asm:lsh ones (- 32 n))) (newline)
  14533. (if (zero? h)
  14534. k
  14535. (asm:logior k (asm:lsh ones (- 32 n))))))))
  14536. ; eof
  14537. ; Copyright 1998 Lars T Hansen.
  14538. ;
  14539. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  14540. ;
  14541. ; Larceny assembler -- 32-bit endianness-independent utility procedures.
  14542. ;
  14543. ; 32-bit numbers are represented as 4-byte bytevectors where the
  14544. ; exact layout depends on whether the little-endian or big-endian
  14545. ; module has been loaded. One of them must be loaded prior to loading
  14546. ; this module.
  14547. ;
  14548. ; Logically, the 'big' end is on the left and the 'little' end
  14549. ; is on the right, so a left shift shifts towards the big end.
  14550. ;
  14551. ; Generally, performance is not a major issue in this module. The
  14552. ; assemblers should use more specialized code for truly good performance.
  14553. ; These procedures are mainly suitable for one-time construction of
  14554. ; instruction templates, and during development.
  14555. ;
  14556. ; Endian-ness specific operations are in asmutil32be.sch and asmutil32le.sch:
  14557. ;
  14558. ; (asm:bv n0 n1 n2 n3) ; Construct bytevector
  14559. ; (asm:bv->int bv) ; Convert bytevector to integer
  14560. ; (asm:lsh m k) ; Shift left logical k bits
  14561. ; (asm:rshl m k) ; Shift right logical k bits
  14562. ; (asm:rsha m k) ; Shirt right arithmetic k bits
  14563. ; Convert an integer to a length-4 bytevector using two's complement
  14564. ; representation for negative numbers.
  14565. ; Returns length-4 bytevector.
  14566. ;
  14567. ; The procedure handles numbers in the range -2^31..2^32-1 [sic].
  14568. ; It is an error for the number to be outside this range.
  14569. ;
  14570. ; FIXME: quotient/remainder may be slow; we could have special fixnum
  14571. ; case that uses shifts (that could be in-lined as macro). It could
  14572. ; work for negative numbers too.
  14573. ; FIXME: should probably check that the number is within range.
  14574. (define asm:int->bv
  14575. (let ((two^32 (expt 2 32)))
  14576. (lambda (m)
  14577. (let* ((m (if (< m 0) (+ two^32 m) m))
  14578. (b0 (remainder m 256))
  14579. (m (quotient m 256))
  14580. (b1 (remainder m 256))
  14581. (m (quotient m 256))
  14582. (b2 (remainder m 256))
  14583. (m (quotient m 256))
  14584. (b3 (remainder m 256)))
  14585. (asm:bv b3 b2 b1 b0)))))
  14586. ; `Or' the bits of multiple operands together.
  14587. ; Each operand may be an exact integer or a length-4 bytevector.
  14588. ; Returns a length-4 bytevector.
  14589. (define (asm:logior . ops)
  14590. (let ((r (asm:bv 0 0 0 0)))
  14591. (do ((ops ops (cdr ops)))
  14592. ((null? ops) r)
  14593. (let* ((op (car ops))
  14594. (op (if (bytevector? op) op (asm:int->bv op))))
  14595. (bytevector-set! r 0 (logior (bytevector-ref r 0)
  14596. (bytevector-ref op 0)))
  14597. (bytevector-set! r 1 (logior (bytevector-ref r 1)
  14598. (bytevector-ref op 1)))
  14599. (bytevector-set! r 2 (logior (bytevector-ref r 2)
  14600. (bytevector-ref op 2)))
  14601. (bytevector-set! r 3 (logior (bytevector-ref r 3)
  14602. (bytevector-ref op 3)))))))
  14603. ; `And' the bits of two operands together.
  14604. ; Either may be an exact integer or length-4 bytevector.
  14605. ; Returns length-4 bytevector.
  14606. (define (asm:logand op1 op2)
  14607. (let ((op1 (if (bytevector? op1) op1 (asm:int->bv op1)))
  14608. (op2 (if (bytevector? op2) op2 (asm:int->bv op2)))
  14609. (bv (make-bytevector 4)))
  14610. (bytevector-set! bv 0 (logand (bytevector-ref op1 0)
  14611. (bytevector-ref op2 0)))
  14612. (bytevector-set! bv 1 (logand (bytevector-ref op1 1)
  14613. (bytevector-ref op2 1)))
  14614. (bytevector-set! bv 2 (logand (bytevector-ref op1 2)
  14615. (bytevector-ref op2 2)))
  14616. (bytevector-set! bv 3 (logand (bytevector-ref op1 3)
  14617. (bytevector-ref op2 3)))
  14618. bv))
  14619. ; Extract the n low-order bits of m.
  14620. ; m may be an exact integer or a length-4 bytevector.
  14621. ; n must be an exact nonnegative integer, interpreted modulo 32.
  14622. ; Returns length-4 bytevector.
  14623. ;
  14624. ; Does not depend on endian-ness.
  14625. (define asm:lobits
  14626. (let ((v (make-vector 33)))
  14627. (do ((i 0 (+ i 1)))
  14628. ((= i 33))
  14629. (vector-set! v i (asm:int->bv (- (expt 2 i) 1))))
  14630. (lambda (m n)
  14631. (asm:logand m (vector-ref v (remainder n 33))))))
  14632. ; Extract the n high-order bits of m.
  14633. ; m may be an exact integer or a length-4 bytevector.
  14634. ; n must be an exact nonnegative integer, interpreted modulo 33.
  14635. ; Returns length-4 bytevector with the high-order bits of m at low end.
  14636. ;
  14637. ; Does not depend on endian-ness.
  14638. (define (asm:hibits m n)
  14639. (asm:rshl m (- 32 (remainder n 33))))
  14640. ; Test that the given number (not! bytevector) m fits in an n-bit
  14641. ; signed slot.
  14642. ;
  14643. ; Does not depend on endian-ness.
  14644. (define asm:fits?
  14645. (let ((v (make-vector 33)))
  14646. (do ((i 0 (+ i 1)))
  14647. ((= i 33))
  14648. (vector-set! v i (expt 2 i)))
  14649. (lambda (m n)
  14650. (<= (- (vector-ref v (- n 1))) m (- (vector-ref v (- n 1)) 1)))))
  14651. ; Test that the given number (not! bytevector) m fits in an n-bit
  14652. ; unsigned slot.
  14653. ;
  14654. ; Does not depend on endian-ness.
  14655. (define asm:fits-unsigned?
  14656. (let ((v (make-vector 33)))
  14657. (do ((i 0 (+ i 1)))
  14658. ((= i 33))
  14659. (vector-set! v i (expt 2 i)))
  14660. (lambda (m n)
  14661. (<= 0 m (- (vector-ref v n) 1)))))
  14662. ; Add two operands (numbers or bytevectors).
  14663. ;
  14664. ; Does not depend on endian-ness.
  14665. (define (asm:add a b)
  14666. (asm:int->bv (+ (if (bytevector? a) (asm:bv->int a) a)
  14667. (if (bytevector? b) (asm:bv->int b) b))))
  14668. ; Given an unsigned 32-bit number, return it as a signed number
  14669. ; as appropriate.
  14670. ;
  14671. ; Does not depend on endian-ness.
  14672. (define (asm:signed n)
  14673. (if (< n 2147483647)
  14674. n
  14675. (- n 4294967296)))
  14676. (define (asm:print-bv bv)
  14677. (define hex "0123456789abcdef")
  14678. (define (pdig k)
  14679. (display (string-ref hex (quotient k 16)))
  14680. (display (string-ref hex (remainder k 16)))
  14681. (display " "))
  14682. (if (eq? asm:endianness 'little)
  14683. (do ((i 3 (- i 1)))
  14684. ((< i 0))
  14685. (pdig (bytevector-ref bv i)))
  14686. (do ((i 0 (+ i 1)))
  14687. ((= i 4))
  14688. (pdig (bytevector-ref bv i)))))
  14689. ; eof
  14690. ; Copyright 1998 Lars T Hansen.
  14691. ;
  14692. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  14693. ;
  14694. ; Procedure that writes fastload segment.
  14695. ;
  14696. ; The procedure 'dump-fasl-segment-to-port' takes a segment and an output
  14697. ; port as arguments and dumps the segment in fastload format on that port.
  14698. ; The port must be a binary (untranslated) port.
  14699. ;
  14700. ; A fastload segment looks like a Scheme expression, and in fact,
  14701. ; fastload files can mix compiled and uncompiled expressions. A compiled
  14702. ; expression (as created by dump-fasl-segment-to-port) is a list with
  14703. ; a literal procedure in the operator position and no arguments.
  14704. ;
  14705. ; A literal procedure is a three-element list prefixed by #^P. The three
  14706. ; elements are code (a bytevector), constants (a regular vector), and
  14707. ; R0/static link slot (always #f).
  14708. ;
  14709. ; A bytevector is a string prefixed by #^B. The string may contain
  14710. ; control characters; \ and " must be quoted as usual.
  14711. ;
  14712. ; A global variable reference in the constant vector is a symbol prefixed
  14713. ; by #^G. On reading, the reference is replaced by (a pointer to) the
  14714. ; actual cell.
  14715. ;
  14716. ; This code is highly bummed. The procedure write-bytevector-like has the
  14717. ; same meaning as display, but in Larceny, the former is currently much
  14718. ; faster than the latter.
  14719. (define (dump-fasl-segment-to-port segment outp . rest)
  14720. (let* ((omit-code? (not (null? rest)))
  14721. (controllify
  14722. (lambda (char)
  14723. (integer->char (- (char->integer char) (char->integer #\@)))))
  14724. (CTRLP (controllify #\P))
  14725. (CTRLB (controllify #\B))
  14726. (CTRLG (controllify #\G))
  14727. (DOUBLEQUOTE (char->integer #\"))
  14728. (BACKSLASH (char->integer #\\))
  14729. (len 1024))
  14730. (define buffer (make-string len #\&))
  14731. (define ptr 0)
  14732. (define (flush)
  14733. (if (< ptr len)
  14734. (write-bytevector-like (substring buffer 0 ptr) outp)
  14735. (write-bytevector-like buffer outp))
  14736. (set! ptr 0))
  14737. (define (putc c)
  14738. (if (= ptr len) (flush))
  14739. (string-set! buffer ptr c)
  14740. (set! ptr (+ ptr 1)))
  14741. (define (putb b)
  14742. (if (= ptr len) (flush))
  14743. (string-set! buffer ptr (integer->char b))
  14744. (set! ptr (+ ptr 1)))
  14745. (define (puts s)
  14746. (let ((ls (string-length s)))
  14747. (if (>= (+ ptr ls) len)
  14748. (begin (flush)
  14749. (write-bytevector-like s outp))
  14750. (do ((i (- ls 1) (- i 1))
  14751. (p (+ ptr ls -1) (- p 1)))
  14752. ((< i 0)
  14753. (set! ptr (+ ptr ls)))
  14754. (string-set! buffer p (string-ref s i))))))
  14755. (define (putd d)
  14756. (flush)
  14757. (write-fasl-datum d outp))
  14758. (define (dump-codevec bv)
  14759. (if omit-code?
  14760. (puts "#f")
  14761. (begin
  14762. (putc #\#)
  14763. (putc CTRLB)
  14764. (putc #\")
  14765. (let ((limit (bytevector-length bv)))
  14766. (do ((i 0 (+ i 1)))
  14767. ((= i limit) (putc #\")
  14768. (putc #\newline))
  14769. (let ((c (bytevector-ref bv i)))
  14770. (cond ((= c DOUBLEQUOTE) (putc #\\))
  14771. ((= c BACKSLASH) (putc #\\)))
  14772. (putb c)))))))
  14773. (define (dump-constvec cv)
  14774. (puts "#(")
  14775. (for-each (lambda (const)
  14776. (putc #\space)
  14777. (case (car const)
  14778. ((data)
  14779. (putd (cadr const)))
  14780. ((constantvector)
  14781. (dump-constvec (cadr const)))
  14782. ((codevector)
  14783. (dump-codevec (cadr const)))
  14784. ((global)
  14785. (putc #\#)
  14786. (putc CTRLG)
  14787. (putd (cadr const)))
  14788. ((bits)
  14789. (error "BITS attribute is not supported in fasl files."))
  14790. (else
  14791. (error "Faulty .lop file."))))
  14792. (vector->list cv))
  14793. (puts ")")
  14794. (putc #\newline))
  14795. (define (dump-fasl-segment segment)
  14796. (if (not omit-code?) (putc #\())
  14797. (putc #\#)
  14798. (putc CTRLP)
  14799. (putc #\()
  14800. (dump-codevec (car segment))
  14801. (putc #\space)
  14802. (dump-constvec (cdr segment))
  14803. (puts " #f)")
  14804. (if (not omit-code?) (putc #\)))
  14805. (putc #\newline))
  14806. (dump-fasl-segment segment)
  14807. (flush)))
  14808. ; eof
  14809. ; Copyright 1998 Lars T Hansen.
  14810. ;
  14811. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  14812. ;
  14813. ; Bootstrap heap dumper.
  14814. ;
  14815. ; Usage: (build-heap-image outputfile inputfile-list)
  14816. ;
  14817. ; Each input file is a sequence of segments, the structure of which
  14818. ; depends on the target architecture, but at least segment.code and
  14819. ; segment.constants exist as accessors.
  14820. ;
  14821. ; The code is a bytevector. The constant vector contains tagged
  14822. ; entries (represented using length-2 lists), where the tags are
  14823. ; `data', `codevector', `constantvector', `global', or `bits'.
  14824. ;
  14825. ; `build-heap-image' reads its file arguments into the heap, creates
  14826. ; thunks from the segments, and creates a list of the thunks. It also
  14827. ; creates a list of all symbols present in the loaded files. Finally,
  14828. ; it generates an initialization procedure (the LAP of which is hardcoded
  14829. ; into this file; see below). A pointer to this procedure is installed
  14830. ; in the SCHEME_ENTRY root pointer; hence, this procedure (a thunk, as
  14831. ; it were) is called when the heap image is loaded.
  14832. ;
  14833. ; The initialization procedure calls each procedure in the thunk list in
  14834. ; order. It then invokes the procedure `go', which takes one argument:
  14835. ; the list of symbols. Typically, `go' will initialize the symbol table
  14836. ; and other system tables and then call `main', but this is by no means
  14837. ; required.
  14838. ;
  14839. ; The Scheme assembler must be co-resident, since it is used by
  14840. ; `build-heap-image' procedure to assemble the final startup code. This
  14841. ; could be avoided by pre-assembling the code and patching it here, but
  14842. ; the way it is now, this procedure is entirely portable -- no target
  14843. ; dependencies.
  14844. ;
  14845. ; The code is structured to allow most procedures to be overridden for
  14846. ; target architectures with more complex needs (notably the C backend).
  14847. (define generate-global-symbols
  14848. (make-twobit-flag 'generate-global-symbols))
  14849. (generate-global-symbols #t)
  14850. (define heap.version-number 9) ; Heap version number
  14851. (define heap.root-names ; Roots in heap version 9
  14852. '(result argreg2 argreg3
  14853. reg0 reg1 reg2 reg3 reg3 reg5 reg6 reg7 reg8 reg9 reg10 reg11 reg12
  14854. reg13 reg14 reg15 reg16 reg17 reg18 reg19 reg20 reg21 reg22 reg23
  14855. reg24 reg25 reg26 reg27 reg28 reg29 reg30 reg31
  14856. cont startup callouts schcall-arg4 alloci-tmp))
  14857. (define (build-heap-image output-file input-files)
  14858. (define tmp-file "HEAPDATA.dat")
  14859. (define (process-input-files heap)
  14860. (let loop ((files input-files) (inits '()))
  14861. (cond ((null? files)
  14862. (heap.thunks! heap (apply append inits)))
  14863. (else
  14864. (let ((filename (car files)))
  14865. (display "Loading ")
  14866. (display filename)
  14867. (newline)
  14868. (loop (cdr files)
  14869. (append inits (list (dump-file! heap filename)))))))))
  14870. (delete-file tmp-file)
  14871. (let ((heap (make-heap #f (open-output-file tmp-file))))
  14872. (before-all-files heap output-file input-files)
  14873. (process-input-files heap)
  14874. (heap.set-root! heap
  14875. 'startup
  14876. (dump-startup-procedure! heap))
  14877. (heap.set-root! heap
  14878. 'callouts
  14879. (dump-global! heap 'millicode-support))
  14880. (write-header heap output-file)
  14881. (after-all-files heap output-file input-files)
  14882. (close-output-port (heap.output-port heap))
  14883. (append-file-shell-command tmp-file output-file)
  14884. (load-map heap)
  14885. (unspecified)))
  14886. (define (before-all-files heap output-file-name input-file-names) #t)
  14887. (define (after-all-files heap output-file-name input-file-names) #t)
  14888. ; Public
  14889. ;
  14890. ; A 'heap' is a data structure with the following public fields; none
  14891. ; of them are constant unless so annotated:
  14892. ;
  14893. ; version a fixnum (constant) - heap type version number
  14894. ; roots an assoc list that maps root names to values
  14895. ; top an exact nonnegative integer: the address of the
  14896. ; next byte to be emitted
  14897. ; symbol-table a symbol table abstract data type
  14898. ; extra any value - a client-extension field
  14899. ; output-port an output port (for the data stream)
  14900. ; thunks a list of codevector addresses
  14901. ;
  14902. ; Bytes are emitted with the heap.byte! and heap.word! procedures,
  14903. ; which emit a byte and a 4-byte word respectively. These update
  14904. ; the top field.
  14905. (define (make-heap extra output-port)
  14906. (vector heap.version-number ; version
  14907. '() ; roots
  14908. 0 ; top
  14909. (make-heap-symbol-table) ; symtab
  14910. extra ; extra
  14911. output-port ; output port
  14912. '() ; thunks
  14913. ))
  14914. (define (heap.version h) (vector-ref h 0))
  14915. (define (heap.roots h) (vector-ref h 1))
  14916. (define (heap.top h) (vector-ref h 2))
  14917. (define (heap.symbol-table h) (vector-ref h 3))
  14918. (define (heap.extra h) (vector-ref h 4))
  14919. (define (heap.output-port h) (vector-ref h 5))
  14920. (define (heap.thunks h) (vector-ref h 6))
  14921. (define (heap.roots! h x) (vector-set! h 1 x))
  14922. (define (heap.top! h x) (vector-set! h 2 x))
  14923. (define (heap.thunks! h x) (vector-set! h 6 x))
  14924. ; Symbol table.
  14925. ;
  14926. ; The symbol table maps names to symbol structures, and a symbol
  14927. ; structure contains information about that symbol.
  14928. ;
  14929. ; The structure has four fields:
  14930. ; name a symbol - the print name
  14931. ; symloc a fixnum or null - if fixnum, the location in the
  14932. ; heap of the symbol structure.
  14933. ; valloc a fixnum or null - if fixnum, the location in the
  14934. ; heap of the global variable cell that has this
  14935. ; symbol for its name.
  14936. ; valno a fixnum or null - if fixnum, the serial number of
  14937. ; the global variable cell (largely obsolete).
  14938. ;
  14939. ; Note therefore that the symbol table maintains information about
  14940. ; whether the symbol is used as a symbol (in a datum), as a global
  14941. ; variable, or both.
  14942. (define (make-heap-symbol-table)
  14943. (vector '() 0))
  14944. (define (symtab.symbols st) (vector-ref st 0))
  14945. (define (symtab.cell-no st) (vector-ref st 1))
  14946. (define (symtab.symbols! st x) (vector-set! st 0 x))
  14947. (define (symtab.cell-no! st x) (vector-set! st 1 x))
  14948. (define (make-symcell name)
  14949. (vector name '() '() '()))
  14950. (define (symcell.name sc) (vector-ref sc 0)) ; name
  14951. (define (symcell.symloc sc) (vector-ref sc 1)) ; symbol location (if any)
  14952. (define (symcell.valloc sc) (vector-ref sc 2)) ; value cell location (ditto)
  14953. (define (symcell.valno sc) (vector-ref sc 3)) ; value cell number (ditto)
  14954. (define (symcell.symloc! sc x) (vector-set! sc 1 x))
  14955. (define (symcell.valloc! sc x) (vector-set! sc 2 x))
  14956. (define (symcell.valno! sc x) (vector-set! sc 3 x))
  14957. ; Find a symcell in the table, or make a new one if there's none.
  14958. (define (symbol-cell h name)
  14959. (let ((symtab (heap.symbol-table h)))
  14960. (let loop ((symbols (symtab.symbols symtab)))
  14961. (cond ((null? symbols)
  14962. (let ((new-sym (make-symcell name)))
  14963. (symtab.symbols! symtab (cons new-sym
  14964. (symtab.symbols symtab)))
  14965. new-sym))
  14966. ((eq? name (symcell.name (car symbols)))
  14967. (car symbols))
  14968. (else
  14969. (loop (cdr symbols)))))))
  14970. ; Fundamental data emitters
  14971. (define twofiftysix^3 (* 256 256 256))
  14972. (define twofiftysix^2 (* 256 256))
  14973. (define twofiftysix 256)
  14974. (define (heap.word-be! h w)
  14975. (heap.byte! h (quotient w twofiftysix^3))
  14976. (heap.byte! h (quotient (remainder w twofiftysix^3) twofiftysix^2))
  14977. (heap.byte! h (quotient (remainder w twofiftysix^2) twofiftysix))
  14978. (heap.byte! h (remainder w twofiftysix)))
  14979. (define (heap.word-el! h w)
  14980. (heap.byte! h (remainder w twofiftysix))
  14981. (heap.byte! h (quotient (remainder w twofiftysix^2) twofiftysix))
  14982. (heap.byte! h (quotient (remainder w twofiftysix^3) twofiftysix^2))
  14983. (heap.byte! h (quotient w twofiftysix^3)))
  14984. (define heap.word! heap.word-be!)
  14985. (define (dumpheap.set-endianness! which)
  14986. (case which
  14987. ((big) (set! heap.word! heap.word-be!))
  14988. ((little) (set! heap.word! heap.word-el!))
  14989. (else ???)))
  14990. (define (heap.byte! h b)
  14991. (write-char (integer->char b) (heap.output-port h))
  14992. (heap.top! h (+ 1 (heap.top h))))
  14993. ; Useful abstractions and constants.
  14994. (define (heap.header-word! h immediate length)
  14995. (heap.word! h (+ (* length 256) immediate)))
  14996. (define (heap.adjust! h)
  14997. (let ((p (heap.top h)))
  14998. (let loop ((i (- (* 8 (quotient (+ p 7) 8)) p)))
  14999. (if (zero? i)
  15000. '()
  15001. (begin (heap.byte! h 0)
  15002. (loop (- i 1)))))))
  15003. (define heap.largest-fixnum (- (expt 2 29) 1))
  15004. (define heap.smallest-fixnum (- (expt 2 29)))
  15005. (define (heap.set-root! h name value)
  15006. (heap.roots! h (cons (cons name value) (heap.roots h))))
  15007. ;;; The segment.* procedures may be overridden by custom code.
  15008. (define segment.code car)
  15009. (define segment.constants cdr)
  15010. ;;; The dump-*! procedures may be overridden by custom code.
  15011. ; Load a LOP file into the heap, create a thunk in the heap to hold the
  15012. ; code and constant vector, and return the list of thunk addresses in
  15013. ; the order dumped.
  15014. (define (dump-file! h filename)
  15015. (before-dump-file h filename)
  15016. (call-with-input-file filename
  15017. (lambda (in)
  15018. (do ((segment (read in) (read in))
  15019. (thunks '() (cons (dump-segment! h segment) thunks)))
  15020. ((eof-object? segment)
  15021. (after-dump-file h filename)
  15022. (reverse thunks))))))
  15023. (define (before-dump-file h filename) #t)
  15024. (define (after-dump-file h filename) #t)
  15025. ; Dump a segment and return the heap address of the resulting thunk.
  15026. (define (dump-segment! h segment)
  15027. (let* ((the-code (dump-codevector! h (segment.code segment)))
  15028. (the-consts (dump-constantvector! h (segment.constants segment))))
  15029. (dump-thunk! h the-code the-consts)))
  15030. (define (dump-tagged-item! h item)
  15031. (case (car item)
  15032. ((codevector)
  15033. (dump-codevector! h (cadr item)))
  15034. ((constantvector)
  15035. (dump-constantvector! h (cadr item)))
  15036. ((data)
  15037. (dump-datum! h (cadr item)))
  15038. ((global)
  15039. (dump-global! h (cadr item)))
  15040. ((bits)
  15041. (cadr item))
  15042. (else
  15043. (error 'dump-tagged-item! "Unknown item ~a" item))))
  15044. (define (dump-datum! h datum)
  15045. (define (fixnum? x)
  15046. (and (integer? x)
  15047. (exact? x)
  15048. (<= heap.smallest-fixnum x heap.largest-fixnum)))
  15049. (define (bignum? x)
  15050. (and (integer? x)
  15051. (exact? x)
  15052. (or (> x heap.largest-fixnum)
  15053. (< x heap.smallest-fixnum))))
  15054. (define (ratnum? x)
  15055. (and (rational? x) (exact? x) (not (integer? x))))
  15056. (define (flonum? x)
  15057. (and (real? x) (inexact? x)))
  15058. (define (compnum? x)
  15059. (and (complex? x) (inexact? x) (not (real? x))))
  15060. (define (rectnum? x)
  15061. (and (complex? x) (exact? x) (not (real? x))))
  15062. (cond ((fixnum? datum)
  15063. (dump-fixnum! h datum))
  15064. ((bignum? datum)
  15065. (dump-bignum! h datum))
  15066. ((ratnum? datum)
  15067. (dump-ratnum! h datum))
  15068. ((flonum? datum)
  15069. (dump-flonum! h datum))
  15070. ((compnum? datum)
  15071. (dump-compnum! h datum))
  15072. ((rectnum? datum)
  15073. (dump-rectnum! h datum))
  15074. ((char? datum)
  15075. (dump-char! h datum))
  15076. ((null? datum)
  15077. $imm.null)
  15078. ((eq? datum #t)
  15079. $imm.true)
  15080. ((eq? datum #f)
  15081. $imm.false)
  15082. ((equal? datum (unspecified))
  15083. $imm.unspecified)
  15084. ((equal? datum (undefined))
  15085. $imm.undefined)
  15086. ((vector? datum)
  15087. (dump-vector! h datum $tag.vector-typetag))
  15088. ((bytevector? datum)
  15089. (dump-bytevector! h datum $tag.bytevector-typetag))
  15090. ((pair? datum)
  15091. (dump-pair! h datum))
  15092. ((string? datum)
  15093. (dump-string! h datum))
  15094. ((symbol? datum)
  15095. (dump-symbol! h datum))
  15096. (else
  15097. (error 'dump-datum! "Unsupported type of datum ~a" datum))))
  15098. ; Returns the two's complement representation as a positive number.
  15099. (define (dump-fixnum! h f)
  15100. (if (negative? f)
  15101. (- #x100000000 (* (abs f) 4))
  15102. (* 4 f)))
  15103. (define (dump-char! h c)
  15104. (+ (* (char->integer c) twofiftysix^2) $imm.character))
  15105. (define (dump-bignum! h b)
  15106. (dump-bytevector! h (bignum->bytevector b) $tag.bignum-typetag))
  15107. (define (dump-ratnum! h r)
  15108. (dump-vector! h
  15109. (vector (numerator r) (denominator r))
  15110. $tag.ratnum-typetag))
  15111. (define (dump-flonum! h f)
  15112. (dump-bytevector! h (flonum->bytevector f) $tag.flonum-typetag))
  15113. (define (dump-compnum! h c)
  15114. (dump-bytevector! h (compnum->bytevector c) $tag.compnum-typetag))
  15115. (define (dump-rectnum! h r)
  15116. (dump-vector! h
  15117. (vector (real-part r) (imag-part r))
  15118. $tag.rectnum-typetag))
  15119. (define (dump-string! h s)
  15120. (dump-bytevector! h (string->bytevector s) $tag.string-typetag))
  15121. (define (dump-pair! h p)
  15122. (let ((the-car (dump-datum! h (car p)))
  15123. (the-cdr (dump-datum! h (cdr p))))
  15124. (let ((base (heap.top h)))
  15125. (heap.word! h the-car)
  15126. (heap.word! h the-cdr)
  15127. (+ base $tag.pair-tag))))
  15128. (define (dump-bytevector! h bv variation)
  15129. (let ((base (heap.top h))
  15130. (l (bytevector-length bv)))
  15131. (heap.header-word! h (+ $imm.bytevector-header variation) l)
  15132. (let loop ((i 0))
  15133. (if (< i l)
  15134. (begin (heap.byte! h (bytevector-ref bv i))
  15135. (loop (+ i 1)))
  15136. (begin (heap.adjust! h)
  15137. (+ base $tag.bytevector-tag))))))
  15138. (define (dump-vector! h v variation)
  15139. (dump-vector-like! h v dump-datum! variation))
  15140. (define (dump-vector-like! h cv recur! variation)
  15141. (let* ((l (vector-length cv))
  15142. (v (make-vector l '())))
  15143. (let loop ((i 0))
  15144. (if (< i l)
  15145. (begin (vector-set! v i (recur! h (vector-ref cv i)))
  15146. (loop (+ i 1)))
  15147. (let ((base (heap.top h)))
  15148. (heap.header-word! h (+ $imm.vector-header variation) (* l 4))
  15149. (let loop ((i 0))
  15150. (if (< i l)
  15151. (begin (heap.word! h (vector-ref v i))
  15152. (loop (+ i 1)))
  15153. (begin (heap.adjust! h)
  15154. (+ base $tag.vector-tag)))))))))
  15155. (define (dump-codevector! h cv)
  15156. (dump-bytevector! h cv $tag.bytevector-typetag))
  15157. (define (dump-constantvector! h cv)
  15158. (dump-vector-like! h cv dump-tagged-item! $tag.vector-typetag))
  15159. (define (dump-symbol! h s)
  15160. (let ((x (symbol-cell h s)))
  15161. (if (null? (symcell.symloc x))
  15162. (symcell.symloc! x (create-symbol! h s)))
  15163. (symcell.symloc x)))
  15164. (define (dump-global! h g)
  15165. (let ((x (symbol-cell h g)))
  15166. (if (null? (symcell.valloc x))
  15167. (let ((cell (create-cell! h g)))
  15168. (symcell.valloc! x (car cell))
  15169. (symcell.valno! x (cdr cell))))
  15170. (symcell.valloc x)))
  15171. (define (dump-thunk! h code constants)
  15172. (let ((base (heap.top h)))
  15173. (heap.header-word! h $imm.procedure-header 8)
  15174. (heap.word! h code)
  15175. (heap.word! h constants)
  15176. (heap.adjust! h)
  15177. (+ base $tag.procedure-tag)))
  15178. ; The car's are all heap pointers, so they should not be messed with.
  15179. ; The cdr must be dumped, and then the pair.
  15180. (define (dump-list-spine! h l)
  15181. (if (null? l)
  15182. $imm.null
  15183. (let ((the-car (car l))
  15184. (the-cdr (dump-list-spine! h (cdr l))))
  15185. (let ((base (heap.top h)))
  15186. (heap.word! h the-car)
  15187. (heap.word! h the-cdr)
  15188. (+ base $tag.pair-tag)))))
  15189. (define (dump-startup-procedure! h)
  15190. (let ((thunks (dump-list-spine! h (heap.thunks h)))
  15191. (symbols (dump-list-spine! h (symbol-locations h))))
  15192. (dump-segment! h (construct-startup-procedure symbols thunks))))
  15193. ; The initialization procedure. The lists are magically patched into
  15194. ; the constant vector after the procedure has been assembled but before
  15195. ; it is dumped into the heap. See below.
  15196. ;
  15197. ; (define (init-proc argv)
  15198. ; (let loop ((l <list-of-thunks>))
  15199. ; (if (null? l)
  15200. ; (go <list-of-symbols> argv)
  15201. ; (begin ((car l))
  15202. ; (loop (cdr l))))))
  15203. (define init-proc
  15204. `((,$.proc)
  15205. (,$args= 1)
  15206. (,$reg 1) ; argv into
  15207. (,$setreg 2) ; register 2
  15208. (,$const (thunks)) ; dummy list of thunks.
  15209. (,$setreg 1)
  15210. (,$.label 0)
  15211. (,$reg 1)
  15212. (,$op1 null?) ; (null? l)
  15213. (,$branchf 2)
  15214. (,$const (symbols)) ; dummy list of symbols
  15215. (,$setreg 1)
  15216. (,$global go)
  15217. ;(,$op1 break)
  15218. (,$invoke 2) ; (go <list of symbols> argv)
  15219. (,$.label 2)
  15220. (,$save 2)
  15221. (,$store 0 0)
  15222. (,$store 1 1)
  15223. (,$store 2 2)
  15224. (,$setrtn 3)
  15225. (,$reg 1)
  15226. (,$op1 car)
  15227. (,$invoke 0) ; ((car l))
  15228. (,$.label 3)
  15229. (,$.cont)
  15230. (,$restore 2)
  15231. (,$pop 2)
  15232. (,$reg 1)
  15233. (,$op1 cdr)
  15234. (,$setreg 1)
  15235. (,$branch 0))) ; (loop (cdr l))
  15236. ;;; Non-overridable code beyond this point
  15237. ; Stuff a new symbol into the heap, return its location.
  15238. (define (create-symbol! h s)
  15239. (dump-vector-like!
  15240. h
  15241. (vector `(bits ,(dump-string! h (symbol->string s)))
  15242. '(data 0)
  15243. '(data ()))
  15244. dump-tagged-item!
  15245. $tag.symbol-typetag))
  15246. ; Stuff a value cell into the heap, return a pair of its location
  15247. ; and its cell number.
  15248. (define (create-cell! h s)
  15249. (let* ((symtab (heap.symbol-table h))
  15250. (n (symtab.cell-no symtab))
  15251. (p (dump-pair! h (cons (undefined)
  15252. (if (generate-global-symbols)
  15253. s
  15254. n)))))
  15255. (symtab.cell-no! symtab (+ n 1))
  15256. (cons p n)))
  15257. (define (construct-startup-procedure symbol-list-addr init-list-addr)
  15258. ; Given some value which might appear in the constant vector,
  15259. ; replace the entries matching that value with a new value.
  15260. (define (patch-constant-vector! v old new)
  15261. (let loop ((i (- (vector-length v) 1)))
  15262. (if (>= i 0)
  15263. (begin (if (equal? (vector-ref v i) old)
  15264. (vector-set! v i new))
  15265. (loop (- i 1))))))
  15266. ; Assemble the startup thunk, patch it, and return it.
  15267. (display "Assembling final procedure") (newline)
  15268. (let ((e (single-stepping)))
  15269. (single-stepping #f)
  15270. (let ((segment (assemble init-proc)))
  15271. (single-stepping e)
  15272. (patch-constant-vector! (segment.constants segment)
  15273. '(data (thunks))
  15274. `(bits ,init-list-addr))
  15275. (patch-constant-vector! (segment.constants segment)
  15276. '(data (symbols))
  15277. `(bits ,symbol-list-addr))
  15278. segment)))
  15279. ; Return a list of symbol locations for symbols in the heap, in order.
  15280. (define (symbol-locations h)
  15281. (let loop ((symbols (symtab.symbols (heap.symbol-table h))) (res '()))
  15282. (cond ((null? symbols)
  15283. (reverse res))
  15284. ((not (null? (symcell.symloc (car symbols))))
  15285. (loop (cdr symbols)
  15286. (cons (symcell.symloc (car symbols)) res)))
  15287. (else
  15288. (loop (cdr symbols) res)))))
  15289. ; Return list of variable name to cell number mappings for global vars.
  15290. (define (load-map h)
  15291. (let loop ((symbols (symtab.symbols (heap.symbol-table h))) (res '()))
  15292. (cond ((null? symbols)
  15293. (reverse res))
  15294. ((not (null? (symcell.valloc (car symbols))))
  15295. (loop (cdr symbols)
  15296. (cons (cons (symcell.name (car symbols))
  15297. (symcell.valno (car symbols)))
  15298. res)))
  15299. (else
  15300. (loop (cdr symbols) res)))))
  15301. (define (write-header h output-file)
  15302. (delete-file output-file)
  15303. (call-with-output-file output-file
  15304. (lambda (out)
  15305. (define (write-word w)
  15306. (display (integer->char (quotient w twofiftysix^3)) out)
  15307. (display (integer->char (quotient (remainder w twofiftysix^3)
  15308. twofiftysix^2))
  15309. out)
  15310. (display (integer->char (quotient (remainder w twofiftysix^2)
  15311. twofiftysix))
  15312. out)
  15313. (display (integer->char (remainder w twofiftysix)) out))
  15314. (define (write-roots)
  15315. (let ((assigned-roots (heap.roots h)))
  15316. (for-each (lambda (root-name)
  15317. (let ((probe (assq root-name assigned-roots)))
  15318. (if probe
  15319. (write-word (cdr probe))
  15320. (write-word $imm.false))))
  15321. heap.root-names)))
  15322. (write-word heap.version-number)
  15323. (write-roots)
  15324. (write-word (quotient (heap.top h) 4)))))
  15325. ; This is a gross hack that happens to work very well.
  15326. (define (append-file-shell-command file-to-append file-to-append-to)
  15327. (define (message)
  15328. (display "You must execute the command") (newline)
  15329. (display " cat ") (display file-to-append)
  15330. (display " >> ") (display file-to-append-to) (newline)
  15331. (display "to create the final heap image.") (newline))
  15332. (case host-system
  15333. ((chez larceny)
  15334. (display "Creating final image in \"")
  15335. (display file-to-append-to) (display "\"...") (newline)
  15336. (if (zero? (system (string-append "cat " file-to-append " >> "
  15337. file-to-append-to)))
  15338. (delete-file file-to-append)
  15339. (begin (display "Failed to create image!")
  15340. (newline))))
  15341. (else
  15342. (message))))
  15343. ; eof
  15344. ; Copyright 1991 Lightship Software, Incorporated.
  15345. ;
  15346. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  15347. ;
  15348. ; 11 June 1999 / wdc
  15349. ;
  15350. ; Asm/Sparc/pass5p2.sch -- Sparc machine assembler, top level
  15351. ; Overrides the procedure of the same name in Asm/Common/pass5p1.sch.
  15352. (define (assembly-table) $sparc-assembly-table$)
  15353. ; Controls listing of instructions during assembly.
  15354. (define listify? #f)
  15355. ; Table of assembler procedures.
  15356. (define $sparc-assembly-table$
  15357. (make-vector
  15358. *number-of-mnemonics*
  15359. (lambda (instruction as)
  15360. (asm-error "Unrecognized mnemonic " instruction))))
  15361. (define (define-instruction i proc)
  15362. (vector-set! $sparc-assembly-table$ i proc)
  15363. #t)
  15364. (define (list-instruction name instruction)
  15365. (if listify?
  15366. (begin (display list-indentation)
  15367. (display " ")
  15368. (display name)
  15369. (display (make-string (max (- 12 (string-length name)) 1)
  15370. #\space))
  15371. (if (not (null? (cdr instruction)))
  15372. (begin (write (cadr instruction))
  15373. (do ((operands (cddr instruction)
  15374. (cdr operands)))
  15375. ((null? operands))
  15376. (write-char #\,)
  15377. (write (car operands)))))
  15378. (newline)
  15379. (flush-output-port))))
  15380. (define (list-label instruction)
  15381. (if listify?
  15382. (begin (display list-indentation)
  15383. (write-char #\L)
  15384. (write (cadr instruction))
  15385. (newline))))
  15386. (define (list-lambda-start instruction)
  15387. (list-instruction "lambda" (list $lambda '* (operand2 instruction)))
  15388. (set! list-indentation (string-append list-indentation "| ")))
  15389. (define (list-lambda-end)
  15390. (set! list-indentation
  15391. (substring list-indentation
  15392. 0
  15393. (- (string-length list-indentation) 4))))
  15394. (define list-indentation "")
  15395. ; Utilities
  15396. ; Pseudo-instructions.
  15397. (define-instruction $.label
  15398. (lambda (instruction as)
  15399. (list-label instruction)
  15400. (sparc.label as (make-asm-label as (operand1 instruction)))))
  15401. (define-instruction $.proc
  15402. (lambda (instruction as)
  15403. (list-instruction ".proc" instruction)
  15404. #t))
  15405. (define-instruction $.proc-doc
  15406. (lambda (instruction as)
  15407. (list-instruction ".proc-doc" instruction)
  15408. (add-documentation as (operand1 instruction))
  15409. #t))
  15410. (define-instruction $.cont
  15411. (lambda (instruction as)
  15412. (list-instruction ".cont" instruction)
  15413. #t))
  15414. (define-instruction $.align
  15415. (lambda (instruction as)
  15416. (list-instruction ".align" instruction)
  15417. #t))
  15418. (define-instruction $.end
  15419. (lambda (instruction as)
  15420. #t))
  15421. (define-instruction $.singlestep
  15422. (lambda (instruction as)
  15423. (let ((instr (car (as-source as))))
  15424. (define (special?)
  15425. (let ((op (operand0 instr)))
  15426. (or (= op $.label)
  15427. (= op $.proc)
  15428. (= op $.cont)
  15429. (= op $.align)
  15430. (and (= op $load) (= 0 (operand1 instr))))))
  15431. (define (readify-instr)
  15432. (if (= (operand0 instr) $lambda)
  15433. (list 'lambda '(...) (caddr instr) (cadddr instr))
  15434. (car (readify-lap (list instr)))))
  15435. (if (not (special?))
  15436. (let ((repr (format-object (readify-instr)))
  15437. (funky? (= (operand0 instr) $restore)))
  15438. (let ((o (emit-datum as repr)))
  15439. (emit-singlestep-instr! as funky? 0 o)))))))
  15440. ; Instructions.
  15441. (define-instruction $op1
  15442. (lambda (instruction as)
  15443. (list-instruction "op1" instruction)
  15444. (emit-primop.1arg! as (operand1 instruction))))
  15445. (define-instruction $op2
  15446. (lambda (instruction as)
  15447. (list-instruction "op2" instruction)
  15448. (emit-primop.2arg! as
  15449. (operand1 instruction)
  15450. (regname (operand2 instruction)))))
  15451. (define-instruction $op3
  15452. (lambda (instruction as)
  15453. (list-instruction "op3" instruction)
  15454. (emit-primop.3arg! as
  15455. (operand1 instruction)
  15456. (regname (operand2 instruction))
  15457. (regname (operand3 instruction)))))
  15458. (define-instruction $op2imm
  15459. (lambda (instruction as)
  15460. (list-instruction "op2imm" instruction)
  15461. (let ((op (case (operand1 instruction)
  15462. ((+) 'internal:+/imm)
  15463. ((-) 'internal:-/imm)
  15464. ((fx+) 'internal:fx+/imm)
  15465. ((fx-) 'internal:fx-/imm)
  15466. ((fx=) 'internal:fx=/imm)
  15467. ((fx<) 'internal:fx</imm)
  15468. ((fx<=) 'internal:fx<=/imm)
  15469. ((fx>) 'internal:fx>/imm)
  15470. ((fx>=) 'internal:fx>=/imm)
  15471. ((=:fix:fix) 'internal:=:fix:fix/imm)
  15472. ((<:fix:fix) 'internal:<:fix:fix/imm)
  15473. ((<=:fix:fix) 'internal:<=:fix:fix/imm)
  15474. ((>:fix:fix) 'internal:>:fix:fix/imm)
  15475. ((>=:fix:fix) 'internal:>=:fix:fix/imm)
  15476. (else #f))))
  15477. (if op
  15478. (emit-primop.4arg! as op $r.result (operand2 instruction) $r.result)
  15479. (begin
  15480. (emit-constant->register as (operand2 instruction) $r.argreg2)
  15481. (emit-primop.2arg! as
  15482. (operand1 instruction)
  15483. $r.argreg2))))))
  15484. (define-instruction $const
  15485. (lambda (instruction as)
  15486. (list-instruction "const" instruction)
  15487. (emit-constant->register as (operand1 instruction) $r.result)))
  15488. (define-instruction $global
  15489. (lambda (instruction as)
  15490. (list-instruction "global" instruction)
  15491. (emit-global->register! as
  15492. (emit-global as (operand1 instruction))
  15493. $r.result)))
  15494. (define-instruction $setglbl
  15495. (lambda (instruction as)
  15496. (list-instruction "setglbl" instruction)
  15497. (emit-register->global! as
  15498. $r.result
  15499. (emit-global as (operand1 instruction)))))
  15500. ; FIXME: A problem is that the listing is messed up because of the delayed
  15501. ; assembly; somehow we should fix this by putting an identifying label
  15502. ; in the listing and emitting this label later, with the code.
  15503. (define-instruction $lambda
  15504. (lambda (instruction as)
  15505. (let ((code-offset #f)
  15506. (const-offset #f))
  15507. (list-lambda-start instruction)
  15508. (assemble-nested-lambda as
  15509. (operand1 instruction)
  15510. (operand3 instruction) ; documentation
  15511. (lambda (nested-as segment)
  15512. (set-constant! as code-offset (car segment))
  15513. (set-constant! as const-offset (cdr segment))))
  15514. (list-lambda-end)
  15515. (set! code-offset (emit-codevector as 0))
  15516. (set! const-offset (emit-constantvector as 0))
  15517. (emit-lambda! as
  15518. code-offset
  15519. const-offset
  15520. (operand2 instruction)))))
  15521. (define-instruction $lexes
  15522. (lambda (instruction as)
  15523. (list-instruction "lexes" instruction)
  15524. (emit-lexes! as (operand1 instruction))))
  15525. (define-instruction $args=
  15526. (lambda (instruction as)
  15527. (list-instruction "args=" instruction)
  15528. (emit-args=! as (operand1 instruction))))
  15529. (define-instruction $args>=
  15530. (lambda (instruction as)
  15531. (list-instruction "args>=" instruction)
  15532. (emit-args>=! as (operand1 instruction))))
  15533. (define-instruction $invoke
  15534. (lambda (instruction as)
  15535. (list-instruction "invoke" instruction)
  15536. (emit-invoke as (operand1 instruction) #f $m.invoke-ex)))
  15537. (define-instruction $restore
  15538. (lambda (instruction as)
  15539. (if (not (negative? (operand1 instruction)))
  15540. (begin
  15541. (list-instruction "restore" instruction)
  15542. (emit-restore! as (operand1 instruction))))))
  15543. (define-instruction $pop
  15544. (lambda (instruction as)
  15545. (if (not (negative? (operand1 instruction)))
  15546. (begin
  15547. (list-instruction "pop" instruction)
  15548. (let ((next (next-instruction as)))
  15549. (if (and (peephole-optimization)
  15550. (eqv? $return (operand0 next)))
  15551. (begin (list-instruction "return" next)
  15552. (consume-next-instruction! as)
  15553. (emit-pop! as (operand1 instruction) #t))
  15554. (emit-pop! as (operand1 instruction) #f)))))))
  15555. (define-instruction $stack
  15556. (lambda (instruction as)
  15557. (list-instruction "stack" instruction)
  15558. (emit-load! as (operand1 instruction) $r.result)))
  15559. (define-instruction $setstk
  15560. (lambda (instruction as)
  15561. (list-instruction "setstk" instruction)
  15562. (emit-store! as $r.result (operand1 instruction))))
  15563. (define-instruction $load
  15564. (lambda (instruction as)
  15565. (list-instruction "load" instruction)
  15566. (emit-load! as (operand2 instruction) (regname (operand1 instruction)))))
  15567. (define-instruction $store
  15568. (lambda (instruction as)
  15569. (list-instruction "store" instruction)
  15570. (emit-store! as (regname (operand1 instruction)) (operand2 instruction))))
  15571. (define-instruction $lexical
  15572. (lambda (instruction as)
  15573. (list-instruction "lexical" instruction)
  15574. (emit-lexical! as (operand1 instruction) (operand2 instruction))))
  15575. (define-instruction $setlex
  15576. (lambda (instruction as)
  15577. (list-instruction "setlex" instruction)
  15578. (emit-setlex! as (operand1 instruction) (operand2 instruction))))
  15579. (define-instruction $reg
  15580. (lambda (instruction as)
  15581. (list-instruction "reg" instruction)
  15582. (emit-register->register! as (regname (operand1 instruction)) $r.result)))
  15583. (define-instruction $setreg
  15584. (lambda (instruction as)
  15585. (list-instruction "setreg" instruction)
  15586. (emit-register->register! as $r.result (regname (operand1 instruction)))))
  15587. (define-instruction $movereg
  15588. (lambda (instruction as)
  15589. (list-instruction "movereg" instruction)
  15590. (emit-register->register! as
  15591. (regname (operand1 instruction))
  15592. (regname (operand2 instruction)))))
  15593. (define-instruction $return
  15594. (lambda (instruction as)
  15595. (list-instruction "return" instruction)
  15596. (emit-return! as)))
  15597. (define-instruction $reg/return
  15598. (lambda (instruction as)
  15599. (list-instruction "reg/return" instruction)
  15600. (emit-return-reg! as (regname (operand1 instruction)))))
  15601. (define-instruction $const/return
  15602. (lambda (instruction as)
  15603. (list-instruction "const/return" instruction)
  15604. (emit-return-const! as (operand1 instruction))))
  15605. (define-instruction $nop
  15606. (lambda (instruction as)
  15607. (list-instruction "nop" instruction)))
  15608. (define-instruction $save
  15609. (lambda (instruction as)
  15610. (if (not (negative? (operand1 instruction)))
  15611. (begin
  15612. (list-instruction "save" instruction)
  15613. (let* ((n (operand1 instruction))
  15614. (v (make-vector (+ n 1) #t)))
  15615. (emit-save0! as n)
  15616. (if (peephole-optimization)
  15617. (let loop ((instruction (next-instruction as)))
  15618. (if (eqv? $store (operand0 instruction))
  15619. (begin (list-instruction "store" instruction)
  15620. (emit-store! as
  15621. (regname (operand1 instruction))
  15622. (operand2 instruction))
  15623. (consume-next-instruction! as)
  15624. (vector-set! v (operand2 instruction) #f)
  15625. (loop (next-instruction as))))))
  15626. (emit-save1! as v))))))
  15627. (define-instruction $setrtn
  15628. (lambda (instruction as)
  15629. (list-instruction "setrtn" instruction)
  15630. (emit-setrtn! as (make-asm-label as (operand1 instruction)))))
  15631. (define-instruction $apply
  15632. (lambda (instruction as)
  15633. (list-instruction "apply" instruction)
  15634. (emit-apply! as
  15635. (regname (operand1 instruction))
  15636. (regname (operand2 instruction)))))
  15637. (define-instruction $jump
  15638. (lambda (instruction as)
  15639. (list-instruction "jump" instruction)
  15640. (emit-jump! as
  15641. (operand1 instruction)
  15642. (make-asm-label as (operand2 instruction)))))
  15643. (define-instruction $skip
  15644. (lambda (instruction as)
  15645. (list-instruction "skip" instruction)
  15646. (emit-branch! as #f (make-asm-label as (operand1 instruction)))))
  15647. (define-instruction $branch
  15648. (lambda (instruction as)
  15649. (list-instruction "branch" instruction)
  15650. (emit-branch! as #t (make-asm-label as (operand1 instruction)))))
  15651. (define-instruction $branchf
  15652. (lambda (instruction as)
  15653. (list-instruction "branchf" instruction)
  15654. (emit-branchf! as (make-asm-label as (operand1 instruction)))))
  15655. (define-instruction $check
  15656. (lambda (instruction as)
  15657. (list-instruction "check" instruction)
  15658. (if (not (unsafe-code))
  15659. (emit-check! as $r.result
  15660. (make-asm-label as (operand4 instruction))
  15661. (list (regname (operand1 instruction))
  15662. (regname (operand2 instruction))
  15663. (regname (operand3 instruction)))))))
  15664. (define-instruction $trap
  15665. (lambda (instruction as)
  15666. (list-instruction "trap" instruction)
  15667. (emit-trap! as
  15668. (regname (operand1 instruction))
  15669. (regname (operand2 instruction))
  15670. (regname (operand3 instruction))
  15671. (operand4 instruction))))
  15672. (define-instruction $const/setreg
  15673. (lambda (instruction as)
  15674. (list-instruction "const/setreg" instruction)
  15675. (let ((x (operand1 instruction))
  15676. (r (operand2 instruction)))
  15677. (if (hwreg? r)
  15678. (emit-constant->register as x (regname r))
  15679. (begin (emit-constant->register as x $r.tmp0)
  15680. (emit-register->register! as $r.tmp0 (regname r)))))))
  15681. ; Operations introduced by the peephole optimizer.
  15682. (define (peep-regname r)
  15683. (if (eq? r 'RESULT) $r.result (regname r)))
  15684. (define-instruction $reg/op1/branchf
  15685. (lambda (instruction as)
  15686. (list-instruction "reg/op1/branchf" instruction)
  15687. (emit-primop.3arg! as
  15688. (operand1 instruction)
  15689. (peep-regname (operand2 instruction))
  15690. (make-asm-label as (operand3 instruction)))))
  15691. (define-instruction $reg/op2/branchf
  15692. (lambda (instruction as)
  15693. (list-instruction "reg/op2/branchf" instruction)
  15694. (emit-primop.4arg! as
  15695. (operand1 instruction)
  15696. (peep-regname (operand2 instruction))
  15697. (peep-regname (operand3 instruction))
  15698. (make-asm-label as (operand4 instruction)))))
  15699. (define-instruction $reg/op2imm/branchf
  15700. (lambda (instruction as)
  15701. (list-instruction "reg/op2imm/branchf" instruction)
  15702. (emit-primop.4arg! as
  15703. (operand1 instruction)
  15704. (peep-regname (operand2 instruction))
  15705. (operand3 instruction)
  15706. (make-asm-label as (operand4 instruction)))))
  15707. ; These three are like the corresponding branchf sequences except that
  15708. ; there is a strong prediction that the branch will not be taken.
  15709. (define-instruction $reg/op1/check
  15710. (lambda (instruction as)
  15711. (list-instruction "reg/op1/check" instruction)
  15712. (emit-primop.4arg! as
  15713. (operand1 instruction)
  15714. (peep-regname (operand2 instruction))
  15715. (make-asm-label as (operand3 instruction))
  15716. (map peep-regname (operand4 instruction)))))
  15717. (define-instruction $reg/op2/check
  15718. (lambda (instruction as)
  15719. (list-instruction "reg/op2/check" instruction)
  15720. (emit-primop.5arg! as
  15721. (operand1 instruction)
  15722. (peep-regname (operand2 instruction))
  15723. (peep-regname (operand3 instruction))
  15724. (make-asm-label as (operand4 instruction))
  15725. (map peep-regname (operand5 instruction)))))
  15726. (define-instruction $reg/op2imm/check
  15727. (lambda (instruction as)
  15728. (list-instruction "reg/op2imm/check" instruction)
  15729. (emit-primop.5arg! as
  15730. (operand1 instruction)
  15731. (peep-regname (operand2 instruction))
  15732. (operand3 instruction)
  15733. (make-asm-label as (operand4 instruction))
  15734. (map peep-regname (operand5 instruction)))))
  15735. ;
  15736. (define-instruction $reg/op1/setreg
  15737. (lambda (instruction as)
  15738. (list-instruction "reg/op1/setreg" instruction)
  15739. (emit-primop.3arg! as
  15740. (operand1 instruction)
  15741. (peep-regname (operand2 instruction))
  15742. (peep-regname (operand3 instruction)))))
  15743. (define-instruction $reg/op2/setreg
  15744. (lambda (instruction as)
  15745. (list-instruction "reg/op2/setreg" instruction)
  15746. (emit-primop.4arg! as
  15747. (operand1 instruction)
  15748. (peep-regname (operand2 instruction))
  15749. (peep-regname (operand3 instruction))
  15750. (peep-regname (operand4 instruction)))))
  15751. (define-instruction $reg/op2imm/setreg
  15752. (lambda (instruction as)
  15753. (list-instruction "reg/op2imm/setreg" instruction)
  15754. (emit-primop.4arg! as
  15755. (operand1 instruction)
  15756. (peep-regname (operand2 instruction))
  15757. (operand3 instruction)
  15758. (peep-regname (operand4 instruction)))))
  15759. (define-instruction $reg/op3
  15760. (lambda (instruction as)
  15761. (list-instruction "reg/op3" instruction)
  15762. (emit-primop.4arg! as
  15763. (operand1 instruction)
  15764. (peep-regname (operand2 instruction))
  15765. (peep-regname (operand3 instruction))
  15766. (peep-regname (operand4 instruction)))))
  15767. (define-instruction $reg/branchf
  15768. (lambda (instruction as)
  15769. (list-instruction "reg/branchf" instruction)
  15770. (emit-branchfreg! as
  15771. (regname (operand1 instruction))
  15772. (make-asm-label as (operand2 instruction)))))
  15773. (define-instruction $setrtn/branch
  15774. (lambda (instruction as)
  15775. (list-instruction "setrtn/branch" instruction)
  15776. (emit-branch-with-setrtn! as (make-asm-label as (operand1 instruction)))))
  15777. (define-instruction $setrtn/invoke
  15778. (lambda (instruction as)
  15779. (list-instruction "setrtn/invoke" instruction)
  15780. (emit-invoke as (operand1 instruction) #t $m.invoke-ex)))
  15781. (define-instruction $global/setreg
  15782. (lambda (instruction as)
  15783. (list-instruction "global/setreg" instruction)
  15784. (emit-global->register! as
  15785. (emit-global as (operand1 instruction))
  15786. (regname (operand2 instruction)))))
  15787. (define-instruction $global/invoke
  15788. (lambda (instruction as)
  15789. (list-instruction "global/invoke" instruction)
  15790. (emit-load-global as
  15791. (emit-global as (operand1 instruction))
  15792. $r.result
  15793. #f)
  15794. (emit-invoke as (operand2 instruction) #f $m.global-invoke-ex)))
  15795. (define-instruction $reg/setglbl
  15796. (lambda (instruction as)
  15797. (list-instruction "reg/setglbl" instruction)
  15798. (emit-register->global! as
  15799. (regname (operand1 instruction))
  15800. (emit-global as (operand2 instruction)))))
  15801. ; eof
  15802. ; Copyright 1998 Lars T Hansen.
  15803. ;
  15804. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  15805. ;
  15806. ; 9 May 1999.
  15807. ;
  15808. ; Asm/Sparc/peepopt.sch -- MAL peephole optimizer, for the SPARC assembler.
  15809. ;
  15810. ; The procedure `peep' is called on the as structure before every
  15811. ; instruction is assembled. It may replace the prefix of the instruction
  15812. ; stream by some other instruction sequence.
  15813. ;
  15814. ; Invariant: if the peephole optimizer doesn't change anything, then
  15815. ;
  15816. ; (let ((x (as-source as)))
  15817. ; (peep as)
  15818. ; (eq? x (as-source as))) => #t
  15819. ;
  15820. ; Note this still isn't right -- it should be integrated with pass5p2 --
  15821. ; but it's a step in the right direction.
  15822. (define *peephole-table* (make-vector *number-of-mnemonics* #f))
  15823. (define (define-peephole n p)
  15824. (vector-set! *peephole-table* n p)
  15825. (unspecified))
  15826. (define (peep as)
  15827. (let ((t0 (as-source as)))
  15828. (if (not (null? t0))
  15829. (let ((i1 (car t0)))
  15830. (let ((p (vector-ref *peephole-table* (car i1))))
  15831. (if p
  15832. (let* ((t1 (if (null? t0) t0 (cdr t0)))
  15833. (i2 (if (null? t1) '(-1 0 0 0) (car t1)))
  15834. (t2 (if (null? t1) t1 (cdr t1)))
  15835. (i3 (if (null? t2) '(-1 0 0 0) (car t2)))
  15836. (t3 (if (null? t2) t2 (cdr t2))))
  15837. (p as i1 i2 i3 t1 t2 t3))))))))
  15838. (define-peephole $reg
  15839. (lambda (as i1 i2 i3 t1 t2 t3)
  15840. (cond ((= (car i2) $return)
  15841. (reg-return as i1 i2 t2))
  15842. ((= (car i2) $setglbl)
  15843. (reg-setglbl as i1 i2 t2))
  15844. ((= (car i2) $op1)
  15845. (cond ((= (car i3) $setreg)
  15846. (reg-op1-setreg as i1 i2 i3 t2 t3))
  15847. ((= (car i3) $branchf)
  15848. (reg-op1-branchf as i1 i2 i3 t3))
  15849. ((= (car i3) $check)
  15850. (reg-op1-check as i1 i2 i3 t3))
  15851. (else
  15852. (reg-op1 as i1 i2 t2))))
  15853. ((= (car i2) $op2)
  15854. (cond ((= (car i3) $setreg)
  15855. (reg-op2-setreg as i1 i2 i3 t2 t3))
  15856. ((= (car i3) $branchf)
  15857. (reg-op2-branchf as i1 i2 i3 t3))
  15858. ((= (car i3) $check)
  15859. (reg-op2-check as i1 i2 i3 t3))
  15860. (else
  15861. (reg-op2 as i1 i2 t2))))
  15862. ((= (car i2) $op2imm)
  15863. (cond ((= (car i3) $setreg)
  15864. (reg-op2imm-setreg as i1 i2 i3 t2 t3))
  15865. ((= (car i3) $branchf)
  15866. (reg-op2imm-branchf as i1 i2 i3 t3))
  15867. ((= (car i3) $check)
  15868. (reg-op2imm-check as i1 i2 i3 t3))
  15869. (else
  15870. (reg-op2imm as i1 i2 t2))))
  15871. ((= (car i2) $op3)
  15872. (reg-op3 as i1 i2 t2))
  15873. ((= (car i2) $setreg)
  15874. (reg-setreg as i1 i2 t2))
  15875. ((= (car i2) $branchf)
  15876. (reg-branchf as i1 i2 t2)))))
  15877. (define-peephole $op1
  15878. (lambda (as i1 i2 i3 t1 t2 t3)
  15879. (cond ((= (car i2) $branchf)
  15880. (op1-branchf as i1 i2 t2))
  15881. ((= (car i2) $setreg)
  15882. (op1-setreg as i1 i2 t2))
  15883. ((= (car i2) $check)
  15884. (op1-check as i1 i2 t2)))))
  15885. (define-peephole $op2
  15886. (lambda (as i1 i2 i3 t1 t2 t3)
  15887. (cond ((= (car i2) $branchf)
  15888. (op2-branchf as i1 i2 t2))
  15889. ((= (car i2) $setreg)
  15890. (op2-setreg as i1 i2 t2))
  15891. ((= (car i2) $check)
  15892. (op2-check as i1 i2 t2)))))
  15893. (define-peephole $op2imm
  15894. (lambda (as i1 i2 i3 t1 t2 t3)
  15895. (cond ((= (car i2) $branchf)
  15896. (op2imm-branchf as i1 i2 t2))
  15897. ((= (car i2) $setreg)
  15898. (op2imm-setreg as i1 i2 t2))
  15899. ((= (car i2) $check)
  15900. (op2imm-check as i1 i2 t2)))))
  15901. (define-peephole $const
  15902. (lambda (as i1 i2 i3 t1 t2 t3)
  15903. (cond ((= (car i2) $setreg)
  15904. (const-setreg as i1 i2 t2))
  15905. ((= (car i2) $op2)
  15906. (const-op2 as i1 i2 t2))
  15907. ((= (car i2) $return)
  15908. (const-return as i1 i2 t2)))))
  15909. (define-peephole $setrtn
  15910. (lambda (as i1 i2 i3 t1 t2 t3)
  15911. (cond ((= (car i2) $branch)
  15912. (cond ((= (car i3) $.align)
  15913. (if (not (null? t3))
  15914. (let ((i4 (car t3))
  15915. (t4 (cdr t3)))
  15916. (cond ((= (car i4) $.label)
  15917. (setrtn-branch as i1 i2 i3 i4 t4))))))))
  15918. ((= (car i2) $invoke)
  15919. (cond ((= (car i3) $.align)
  15920. (if (not (null? t3))
  15921. (let ((i4 (car t3))
  15922. (t4 (cdr t3)))
  15923. (cond ((= (car i4) $.label)
  15924. (setrtn-invoke as i1 i2 i3 i4 t4)))))))))))
  15925. (define-peephole $branch
  15926. (lambda (as i1 i2 i3 t1 t2 t3)
  15927. (cond ((= (car i2) $.align)
  15928. (cond ((= (car i3) $.label)
  15929. (branch-and-label as i1 i2 i3 t3)))))))
  15930. (define-peephole $global
  15931. (lambda (as i1 i2 i3 t1 t2 t3)
  15932. (cond ((= (car i2) $setreg)
  15933. (global-setreg as i1 i2 t2))
  15934. ((= (car i2) $invoke)
  15935. (global-invoke as i1 i2 t2))
  15936. ((= (car i2) $setrtn)
  15937. (cond ((= (car i3) $invoke)
  15938. (global-setrtn-invoke as i1 i2 i3 t3)))))))
  15939. (define-peephole $reg/op1/check
  15940. (lambda (as i1 i2 i3 t1 t2 t3)
  15941. (cond ((= (car i2) $reg)
  15942. (cond ((= (car i3) $op1)
  15943. (if (not (null? t3))
  15944. (let ((i4 (car t3))
  15945. (t4 (cdr t3)))
  15946. (cond ((= (car i4) $setreg)
  15947. (reg/op1/check-reg-op1-setreg
  15948. as i1 i2 i3 i4 t4)))))))))))
  15949. (define-peephole $reg/op2/check
  15950. (lambda (as i1 i2 i3 t1 t2 t3)
  15951. (cond ((= (car i2) $reg)
  15952. (cond ((= (car i3) $op2imm)
  15953. (if (not (null? t3))
  15954. (let ((i4 (car t3))
  15955. (t4 (cdr t3)))
  15956. (cond ((= (car i4) $check)
  15957. (reg/op2/check-reg-op2imm-check
  15958. as i1 i2 i3 i4 t4)))))))))))
  15959. ; Worker procedures.
  15960. (define (reg-return as i:reg i:return tail)
  15961. (let ((rs (operand1 i:reg)))
  15962. (if (hwreg? rs)
  15963. (as-source! as (cons (list $reg/return rs) tail)))))
  15964. (define (reg-op1-setreg as i:reg i:op1 i:setreg tail-1 tail)
  15965. (let ((rs (operand1 i:reg))
  15966. (rd (operand1 i:setreg))
  15967. (op (operand1 i:op1)))
  15968. (if (hwreg? rs)
  15969. (if (hwreg? rd)
  15970. (peep-reg/op1/setreg as op rs rd tail)
  15971. (peep-reg/op1/setreg as op rs 'RESULT tail-1)))))
  15972. (define (reg-op1 as i:reg i:op1 tail)
  15973. (let ((rs (operand1 i:reg))
  15974. (op (operand1 i:op1)))
  15975. (if (hwreg? rs)
  15976. (peep-reg/op1/setreg as op rs 'RESULT tail))))
  15977. (define (op1-setreg as i:op1 i:setreg tail)
  15978. (let ((op (operand1 i:op1))
  15979. (rd (operand1 i:setreg)))
  15980. (if (hwreg? rd)
  15981. (peep-reg/op1/setreg as op 'RESULT rd tail))))
  15982. (define (peep-reg/op1/setreg as op rs rd tail)
  15983. (let ((op (case op
  15984. ((car) 'internal:car)
  15985. ((cdr) 'internal:cdr)
  15986. ((car:pair) 'internal:car:pair)
  15987. ((cdr:pair) 'internal:cdr:pair)
  15988. ((cell-ref) 'internal:cell-ref)
  15989. ((vector-length) 'internal:vector-length)
  15990. ((vector-length:vec) 'internal:vector-length:vec)
  15991. ((string-length) 'internal:string-length)
  15992. ((--) 'internal:--)
  15993. ((fx--) 'internal:fx--)
  15994. ((fxpositive?) 'internal:fxpositive?)
  15995. ((fxnegative?) 'internal:fxnegative?)
  15996. ((fxzero?) 'internal:fxzero?)
  15997. (else #f))))
  15998. (if op
  15999. (as-source! as (cons (list $reg/op1/setreg op rs rd) tail)))))
  16000. (define (reg-op2-setreg as i:reg i:op2 i:setreg tail-1 tail)
  16001. (let ((rs1 (operand1 i:reg))
  16002. (rs2 (operand2 i:op2))
  16003. (op (operand1 i:op2))
  16004. (rd (operand1 i:setreg)))
  16005. (if (hwreg? rs1)
  16006. (if (hwreg? rd)
  16007. (peep-reg/op2/setreg as op rs1 rs2 rd tail)
  16008. (peep-reg/op2/setreg as op rs1 rs2 'RESULT tail-1)))))
  16009. (define (reg-op2 as i:reg i:op2 tail)
  16010. (let ((rs1 (operand1 i:reg))
  16011. (rs2 (operand2 i:op2))
  16012. (op (operand1 i:op2)))
  16013. (if (hwreg? rs1)
  16014. (peep-reg/op2/setreg as op rs1 rs2 'RESULT tail))))
  16015. (define (op2-setreg as i:op2 i:setreg tail)
  16016. (let ((op (operand1 i:op2))
  16017. (rs2 (operand2 i:op2))
  16018. (rd (operand1 i:setreg)))
  16019. (if (hwreg? rd)
  16020. (peep-reg/op2/setreg as op 'RESULT rs2 rd tail))))
  16021. (define (peep-reg/op2/setreg as op rs1 rs2 rd tail)
  16022. (let ((op (case op
  16023. ((+) 'internal:+)
  16024. ((-) 'internal:-)
  16025. ((fx+) 'internal:fx+)
  16026. ((fx-) 'internal:fx-)
  16027. ((fx=) 'internal:fx=)
  16028. ((fx>) 'internal:fx>)
  16029. ((fx>=) 'internal:fx>=)
  16030. ((fx<) 'internal:fx<)
  16031. ((fx<=) 'internal:fx<=)
  16032. ((eq?) 'internal:eq?)
  16033. ((cons) 'internal:cons)
  16034. ((vector-ref) 'internal:vector-ref)
  16035. ((vector-ref:trusted) 'internal:vector-ref:trusted)
  16036. ((string-ref) 'internal:string-ref)
  16037. ((set-car!) 'internal:set-car!)
  16038. ((set-cdr!) 'internal:set-cdr!)
  16039. ((cell-set!) 'internal:cell-set!)
  16040. (else #f))))
  16041. (if op
  16042. (as-source! as (cons (list $reg/op2/setreg op rs1 rs2 rd) tail)))))
  16043. (define (reg-op2imm-setreg as i:reg i:op2imm i:setreg tail-1 tail)
  16044. (let ((rs (operand1 i:reg))
  16045. (imm (operand2 i:op2imm))
  16046. (op (operand1 i:op2imm))
  16047. (rd (operand1 i:setreg)))
  16048. (if (hwreg? rs)
  16049. (if (hwreg? rd)
  16050. (peep-reg/op2imm/setreg as op rs imm rd tail)
  16051. (peep-reg/op2imm/setreg as op rs imm 'RESULT tail-1)))))
  16052. (define (reg-op2imm as i:reg i:op2imm tail)
  16053. (let ((rs (operand1 i:reg))
  16054. (imm (operand2 i:op2imm))
  16055. (op (operand1 i:op2imm)))
  16056. (if (hwreg? rs)
  16057. (peep-reg/op2imm/setreg as op rs imm 'RESULT tail))))
  16058. (define (op2imm-setreg as i:op2imm i:setreg tail)
  16059. (let ((op (operand1 i:op2imm))
  16060. (imm (operand2 i:op2imm))
  16061. (rd (operand1 i:setreg)))
  16062. (if (hwreg? rd)
  16063. (peep-reg/op2imm/setreg as op 'RESULT imm rd tail))))
  16064. (define (peep-reg/op2imm/setreg as op rs imm rd tail)
  16065. (let ((op (case op
  16066. ((+) 'internal:+/imm)
  16067. ((-) 'internal:-/imm)
  16068. ((fx+) 'internal:fx+/imm)
  16069. ((fx-) 'internal:fx-/imm)
  16070. ((fx=) 'internal:fx=/imm)
  16071. ((fx<) 'internal:fx</imm)
  16072. ((fx<=) 'internal:fx<=/imm)
  16073. ((fx>) 'internal:fx>/imm)
  16074. ((fx>=) 'internal:fx>=/imm)
  16075. ((eq?) 'internal:eq?/imm)
  16076. ((vector-ref) 'internal:vector-ref/imm)
  16077. ((string-ref) 'internal:string-ref/imm)
  16078. (else #f))))
  16079. (if op
  16080. (as-source! as (cons (list $reg/op2imm/setreg op rs imm rd) tail)))))
  16081. (define (reg-op1-branchf as i:reg i:op1 i:branchf tail)
  16082. (let ((rs (operand1 i:reg))
  16083. (op (operand1 i:op1))
  16084. (L (operand1 i:branchf)))
  16085. (if (hwreg? rs)
  16086. (peep-reg/op1/branchf as op rs L tail))))
  16087. (define (op1-branchf as i:op1 i:branchf tail)
  16088. (let ((op (operand1 i:op1))
  16089. (L (operand1 i:branchf)))
  16090. (peep-reg/op1/branchf as op 'RESULT L tail)))
  16091. (define (peep-reg/op1/branchf as op rs L tail)
  16092. (let ((op (case op
  16093. ((null?) 'internal:branchf-null?)
  16094. ((pair?) 'internal:branchf-pair?)
  16095. ((zero?) 'internal:branchf-zero?)
  16096. ((eof-object?) 'internal:branchf-eof-object?)
  16097. ((fixnum?) 'internal:branchf-fixnum?)
  16098. ((char?) 'internal:branchf-char?)
  16099. ((fxzero?) 'internal:branchf-fxzero?)
  16100. ((fxnegative?) 'internal:branchf-fxnegative?)
  16101. ((fxpositive?) 'internal:branchf-fxpositive?)
  16102. (else #f))))
  16103. (if op
  16104. (as-source! as (cons (list $reg/op1/branchf op rs L) tail)))))
  16105. (define (reg-op2-branchf as i:reg i:op2 i:branchf tail)
  16106. (let ((rs1 (operand1 i:reg))
  16107. (rs2 (operand2 i:op2))
  16108. (op (operand1 i:op2))
  16109. (L (operand1 i:branchf)))
  16110. (if (hwreg? rs1)
  16111. (peep-reg/op2/branchf as op rs1 rs2 L tail))))
  16112. (define (op2-branchf as i:op2 i:branchf tail)
  16113. (let ((op (operand1 i:op2))
  16114. (rs2 (operand2 i:op2))
  16115. (L (operand1 i:branchf)))
  16116. (peep-reg/op2/branchf as op 'RESULT rs2 L tail)))
  16117. (define (peep-reg/op2/branchf as op rs1 rs2 L tail)
  16118. (let ((op (case op
  16119. ((<) 'internal:branchf-<)
  16120. ((>) 'internal:branchf->)
  16121. ((>=) 'internal:branchf->=)
  16122. ((<=) 'internal:branchf-<=)
  16123. ((=) 'internal:branchf-=)
  16124. ((eq?) 'internal:branchf-eq?)
  16125. ((char=?) 'internal:branchf-char=?)
  16126. ((char>=?) 'internal:branchf-char>=?)
  16127. ((char>?) 'internal:branchf-char>?)
  16128. ((char<=?) 'internal:branchf-char<=?)
  16129. ((char<?) 'internal:branchf-char<?)
  16130. ((fx=) 'internal:branchf-fx=)
  16131. ((fx>) 'internal:branchf-fx>)
  16132. ((fx>=) 'internal:branchf-fx>=)
  16133. ((fx<) 'internal:branchf-fx<)
  16134. ((fx<=) 'internal:branchf-fx<=)
  16135. (else #f))))
  16136. (if op
  16137. (as-source! as
  16138. (cons (list $reg/op2/branchf op rs1 rs2 L)
  16139. tail)))))
  16140. (define (reg-op2imm-branchf as i:reg i:op2imm i:branchf tail)
  16141. (let ((rs (operand1 i:reg))
  16142. (imm (operand2 i:op2imm))
  16143. (op (operand1 i:op2imm))
  16144. (L (operand1 i:branchf)))
  16145. (if (hwreg? rs)
  16146. (peep-reg/op2imm/branchf as op rs imm L tail))))
  16147. (define (op2imm-branchf as i:op2imm i:branchf tail)
  16148. (let ((op (operand1 i:op2imm))
  16149. (imm (operand2 i:op2imm))
  16150. (L (operand1 i:branchf)))
  16151. (peep-reg/op2imm/branchf as op 'RESULT imm L tail)))
  16152. (define (peep-reg/op2imm/branchf as op rs imm L tail)
  16153. (let ((op (case op
  16154. ((<) 'internal:branchf-</imm)
  16155. ((>) 'internal:branchf->/imm)
  16156. ((>=) 'internal:branchf->=/imm)
  16157. ((<=) 'internal:branchf-<=/imm)
  16158. ((=) 'internal:branchf-=/imm)
  16159. ((eq?) 'internal:branchf-eq?/imm)
  16160. ((char=?) 'internal:branchf-char=?/imm)
  16161. ((char>=?) 'internal:branchf-char>=?/imm)
  16162. ((char>?) 'internal:branchf-char>?/imm)
  16163. ((char<=?) 'internal:branchf-char<=?/imm)
  16164. ((char<?) 'internal:branchf-char<?/imm)
  16165. ((fx=) 'internal:branchf-fx=/imm)
  16166. ((fx>) 'internal:branchf-fx>/imm)
  16167. ((fx>=) 'internal:branchf-fx>=/imm)
  16168. ((fx<) 'internal:branchf-fx</imm)
  16169. ((fx<=) 'internal:branchf-fx<=/imm)
  16170. (else #f))))
  16171. (if op
  16172. (as-source! as
  16173. (cons (list $reg/op2imm/branchf op rs imm L)
  16174. tail)))))
  16175. ; Check optimization.
  16176. (define (reg-op1-check as i:reg i:op1 i:check tail)
  16177. (let ((rs (operand1 i:reg))
  16178. (op (operand1 i:op1)))
  16179. (if (hwreg? rs)
  16180. (peep-reg/op1/check as
  16181. op
  16182. rs
  16183. (operand4 i:check)
  16184. (list (operand1 i:check)
  16185. (operand2 i:check)
  16186. (operand3 i:check))
  16187. tail))))
  16188. (define (op1-check as i:op1 i:check tail)
  16189. (let ((op (operand1 i:op1)))
  16190. (peep-reg/op1/check as
  16191. op
  16192. 'RESULT
  16193. (operand4 i:check)
  16194. (list (operand1 i:check)
  16195. (operand2 i:check)
  16196. (operand3 i:check))
  16197. tail)))
  16198. (define (peep-reg/op1/check as op rs L1 liveregs tail)
  16199. (let ((op (case op
  16200. ((fixnum?) 'internal:check-fixnum?)
  16201. ((pair?) 'internal:check-pair?)
  16202. ((vector?) 'internal:check-vector?)
  16203. (else #f))))
  16204. (if op
  16205. (as-source! as
  16206. (cons (list $reg/op1/check op rs L1 liveregs)
  16207. tail)))))
  16208. (define (reg-op2-check as i:reg i:op2 i:check tail)
  16209. (let ((rs1 (operand1 i:reg))
  16210. (rs2 (operand2 i:op2))
  16211. (op (operand1 i:op2)))
  16212. (if (hwreg? rs1)
  16213. (peep-reg/op2/check as
  16214. op
  16215. rs1
  16216. rs2
  16217. (operand4 i:check)
  16218. (list (operand1 i:check)
  16219. (operand2 i:check)
  16220. (operand3 i:check))
  16221. tail))))
  16222. (define (op2-check as i:op2 i:check tail)
  16223. (let ((rs2 (operand2 i:op2))
  16224. (op (operand1 i:op2)))
  16225. (peep-reg/op2/check as
  16226. op
  16227. 'RESULT
  16228. rs2
  16229. (operand4 i:check)
  16230. (list (operand1 i:check)
  16231. (operand2 i:check)
  16232. (operand3 i:check))
  16233. tail)))
  16234. (define (peep-reg/op2/check as op rs1 rs2 L1 liveregs tail)
  16235. (let ((op (case op
  16236. ((<:fix:fix) 'internal:check-<:fix:fix)
  16237. ((<=:fix:fix) 'internal:check-<=:fix:fix)
  16238. ((>=:fix:fix) 'internal:check->=:fix:fix)
  16239. (else #f))))
  16240. (if op
  16241. (as-source! as
  16242. (cons (list $reg/op2/check op rs1 rs2 L1 liveregs)
  16243. tail)))))
  16244. (define (reg-op2imm-check as i:reg i:op2imm i:check tail)
  16245. (let ((rs1 (operand1 i:reg))
  16246. (op (operand1 i:op2imm))
  16247. (imm (operand2 i:op2imm)))
  16248. (if (hwreg? rs1)
  16249. (peep-reg/op2imm/check as
  16250. op
  16251. rs1
  16252. imm
  16253. (operand4 i:check)
  16254. (list (operand1 i:check)
  16255. (operand2 i:check)
  16256. (operand3 i:check))
  16257. tail))))
  16258. (define (op2imm-check as i:op2imm i:check tail)
  16259. (let ((op (operand1 i:op2imm))
  16260. (imm (operand2 i:op2imm)))
  16261. (peep-reg/op2imm/check as
  16262. op
  16263. 'RESULT
  16264. imm
  16265. (operand4 i:check)
  16266. (list (operand1 i:check)
  16267. (operand2 i:check)
  16268. (operand3 i:check))
  16269. tail)))
  16270. (define (peep-reg/op2imm/check as op rs1 imm L1 liveregs tail)
  16271. (let ((op (case op
  16272. ((<:fix:fix) 'internal:check-<:fix:fix/imm)
  16273. ((<=:fix:fix) 'internal:check-<=:fix:fix/imm)
  16274. ((>=:fix:fix) 'internal:check->=:fix:fix/imm)
  16275. (else #f))))
  16276. (if op
  16277. (as-source! as
  16278. (cons (list $reg/op2imm/check op rs1 imm L1 liveregs)
  16279. tail)))))
  16280. (define (reg/op1/check-reg-op1-setreg as i:ro1check i:reg i:op1 i:setreg tail)
  16281. (let ((o1 (operand1 i:ro1check))
  16282. (r1 (operand2 i:ro1check))
  16283. (r2 (operand1 i:reg))
  16284. (o2 (operand1 i:op1))
  16285. (r3 (operand1 i:setreg)))
  16286. (if (and (eq? o1 'internal:check-vector?)
  16287. (eq? r1 r2)
  16288. (eq? o2 'vector-length:vec)
  16289. (hwreg? r1)
  16290. (hwreg? r3))
  16291. (as-source! as
  16292. (cons (list $reg/op2/check
  16293. 'internal:check-vector?/vector-length:vec
  16294. r1
  16295. r3
  16296. (operand3 i:ro1check)
  16297. (operand4 i:ro1check))
  16298. tail)))))
  16299. ; Range checks of the form 0 <= i < n can be performed by a single check.
  16300. ; This peephole optimization recognizes
  16301. ; reg rs1
  16302. ; op2 <:fix:fix,rs2
  16303. ; check r1,r2,r3,L
  16304. ; reg rs1 ; must match earlier reg
  16305. ; op2imm >=:fix:fix,0
  16306. ; check r1,r2,r3,L ; label must match earlier check
  16307. (define (reg/op2/check-reg-op2imm-check
  16308. as i:ro2check i:reg i:op2imm i:check tail)
  16309. (let ((o1 (operand1 i:ro2check))
  16310. (rs1 (operand2 i:ro2check))
  16311. (rs2 (operand3 i:ro2check))
  16312. (L1 (operand4 i:ro2check))
  16313. (live (operand5 i:ro2check))
  16314. (rs3 (operand1 i:reg))
  16315. (o2 (operand1 i:op2imm))
  16316. (x (operand2 i:op2imm))
  16317. (L2 (operand4 i:check)))
  16318. (if (and (eq? o1 'internal:check-<:fix:fix)
  16319. (eq? o2 '>=:fix:fix)
  16320. (eq? rs1 rs3)
  16321. (eq? x 0)
  16322. (eq? L1 L2))
  16323. (as-source! as
  16324. (cons (list $reg/op2/check 'internal:check-range
  16325. rs1 rs2 L1 live)
  16326. tail)))))
  16327. ; End of check optimization.
  16328. (define (reg-op3 as i:reg i:op3 tail)
  16329. (let ((rs1 (operand1 i:reg))
  16330. (rs2 (operand2 i:op3))
  16331. (rs3 (operand3 i:op3))
  16332. (op (operand1 i:op3)))
  16333. (if (hwreg? rs1)
  16334. (let ((op (case op
  16335. ((vector-set!) 'internal:vector-set!)
  16336. ((string-set!) 'internal:string-set!)
  16337. (else #f))))
  16338. (if op
  16339. (as-source! as (cons (list $reg/op3 op rs1 rs2 rs3) tail)))))))
  16340. ; Reg-setreg is not restricted to hardware registers, as $movereg is
  16341. ; a standard instruction.
  16342. (define (reg-setreg as i:reg i:setreg tail)
  16343. (let ((rs (operand1 i:reg))
  16344. (rd (operand1 i:setreg)))
  16345. (if (= rs rd)
  16346. (as-source! as tail)
  16347. (as-source! as (cons (list $movereg rs rd) tail)))))
  16348. (define (reg-branchf as i:reg i:branchf tail)
  16349. (let ((rs (operand1 i:reg))
  16350. (L (operand1 i:branchf)))
  16351. (if (hwreg? rs)
  16352. (as-source! as (cons (list $reg/branchf rs L) tail)))))
  16353. (define (const-setreg as i:const i:setreg tail)
  16354. (let ((c (operand1 i:const))
  16355. (rd (operand1 i:setreg)))
  16356. (if (hwreg? rd)
  16357. (as-source! as (cons (list $const/setreg c rd) tail)))))
  16358. ; Make-vector on vectors of known short length.
  16359. (define (const-op2 as i:const i:op2 tail)
  16360. (let ((vn '#(make-vector:0 make-vector:1 make-vector:2 make-vector:3
  16361. make-vector:4 make-vector:5 make-vector:6 make-vector:7
  16362. make-vector:8 make-vector:9))
  16363. (c (operand1 i:const))
  16364. (op (operand1 i:op2))
  16365. (r (operand2 i:op2)))
  16366. (if (and (eq? op 'make-vector)
  16367. (fixnum? c)
  16368. (<= 0 c 9))
  16369. (as-source! as (cons (list $op2 (vector-ref vn c) r) tail)))))
  16370. ; Constants that can be synthesized in a single instruction can be
  16371. ; moved into RESULT in the delay slot of the return instruction.
  16372. (define (const-return as i:const i:return tail)
  16373. (let ((c (operand1 i:const)))
  16374. (if (or (and (number? c) (immediate-int? c))
  16375. (null? c)
  16376. (boolean? c))
  16377. (as-source! as (cons (list $const/return c) tail)))))
  16378. ; This allows the use of hardware 'call' instructions.
  16379. ; (setrtn Lx)
  16380. ; (branch Ly k)
  16381. ; (.align k) Ignored on SPARC
  16382. ; (.label Lx)
  16383. ; => (setrtn/branch Ly k)
  16384. ; (.label Lx)
  16385. (define (setrtn-branch as i:setrtn i:branch i:align i:label tail)
  16386. (let ((return-label (operand1 i:setrtn))
  16387. (branch-ops (cdr i:branch))
  16388. (label (operand1 i:label)))
  16389. (if (= return-label label)
  16390. (as-source! as (cons (cons $setrtn/branch branch-ops)
  16391. (cons i:label
  16392. tail))))))
  16393. ; Ditto for 'invoke'.
  16394. ;
  16395. ; Disabled because it does _not_ pay off on the SPARC currently --
  16396. ; probably, the dependency created between 'jmpl' and 'st' is not
  16397. ; handled well on the test machine (an Ultrasparc). Might work
  16398. ; better if the return address were to be kept in a register always.
  16399. (define (setrtn-invoke as i:setrtn i:invoke i:align i:label tail)
  16400. (let ((return-label (operand1 i:setrtn))
  16401. (invoke-ops (operand1 i:invoke))
  16402. (label (operand1 i:label)))
  16403. (if (and #f ; DISABLED
  16404. (= return-label label))
  16405. (as-source! as (cons (cons $setrtn/invoke invoke-ops)
  16406. (cons i:label
  16407. tail))))))
  16408. ; Gets rid of spurious branch-to-next-instruction
  16409. ; (branch Lx k)
  16410. ; (.align y)
  16411. ; (.label Lx)
  16412. ; => (.align y)
  16413. ; (.label Lx)
  16414. (define (branch-and-label as i:branch i:align i:label tail)
  16415. (let ((branch-label (operand1 i:branch))
  16416. (label (operand1 i:label)))
  16417. (if (= branch-label label)
  16418. (as-source! as (cons i:align (cons i:label tail))))))
  16419. (define (global-setreg as i:global i:setreg tail)
  16420. (let ((global (operand1 i:global))
  16421. (rd (operand1 i:setreg)))
  16422. (if (hwreg? rd)
  16423. (as-source! as (cons (list $global/setreg global rd) tail)))))
  16424. ; Obscure guard: unsafe-code = #t implies that global/invoke will not
  16425. ; check the value of the global variable, yet unsafe-code and
  16426. ; catch-undefined-globals are supposed to be independent.
  16427. (define (global-invoke as i:global i:invoke tail)
  16428. (let ((global (operand1 i:global))
  16429. (argc (operand1 i:invoke)))
  16430. (if (not (and (unsafe-code) (catch-undefined-globals)))
  16431. (as-source! as (cons (list $global/invoke global argc) tail)))))
  16432. ; Obscure guard: see comment for previous procedure.
  16433. ; FIXME! This implementation is temporary until setrtn-invoke is enabled.
  16434. (define (global-setrtn-invoke as i:global i:setrtn i:invoke tail)
  16435. (let ((global (operand1 i:global))
  16436. (argc (operand1 i:invoke)))
  16437. (if (not (and (unsafe-code) (catch-undefined-globals)))
  16438. (as-source! as (cons i:setrtn
  16439. (cons (list $global/invoke global argc)
  16440. tail))))))
  16441. (define (reg-setglbl as i:reg i:setglbl tail)
  16442. (let ((rs (operand1 i:reg))
  16443. (global (operand1 i:setglbl)))
  16444. (if (hwreg? rs)
  16445. (as-source! as (cons (list $reg/setglbl rs global) tail)))))
  16446. ; Test code
  16447. (define (peeptest istream)
  16448. (let ((as (make-assembly-structure istream)))
  16449. (let loop ((l '()))
  16450. (if (null? (as-source as))
  16451. (reverse l)
  16452. (begin (peep as)
  16453. (let ((a (car (as-source as))))
  16454. (as-source! as (cdr (as-source as)))
  16455. (loop (cons a l))))))))
  16456. ; eof
  16457. ; Copyright 1998 Lars T Hansen.
  16458. ;
  16459. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  16460. ;
  16461. ; SPARC assembler machine parameters & utility procedures.
  16462. ;
  16463. ; 13 May 1999 / wdc
  16464. ; Round up to nearest 8.
  16465. (define (roundup8 n)
  16466. (* (quotient (+ n 7) 8) 8))
  16467. ; Given an integer code for a register, return its register label.
  16468. ; This register label is the register number for a h.w. register and the
  16469. ; offsets from GLOBALS[ r0 ] for a s.w. register.
  16470. (define regname
  16471. (let ((v (vector $r.reg0 $r.reg1 $r.reg2 $r.reg3 $r.reg4 $r.reg5
  16472. $r.reg6 $r.reg7 $r.reg8 $r.reg9 $r.reg10 $r.reg11
  16473. $r.reg12 $r.reg13 $r.reg14 $r.reg15 $r.reg16 $r.reg17
  16474. $r.reg18 $r.reg19 $r.reg20 $r.reg21 $r.reg22 $r.reg23
  16475. $r.reg24 $r.reg25 $r.reg26 $r.reg27 $r.reg28 $r.reg29
  16476. $r.reg30 $r.reg31)))
  16477. (lambda (r)
  16478. (vector-ref v r))))
  16479. ; Is a general-purpose register mapped to a hardware register?
  16480. ; This is fragile! FIXME.
  16481. (define (hardware-mapped? r)
  16482. (or (and (>= r $r.reg0) (<= r $r.reg7))
  16483. (= r $r.argreg2)
  16484. (= r $r.argreg3)
  16485. (= r $r.result)
  16486. (= r $r.g0)
  16487. (= r $r.tmp0)
  16488. (= r $r.tmp1)
  16489. (= r $r.tmp2)))
  16490. ; Used by peephole optimizer
  16491. (define (hwreg? x)
  16492. (<= 0 x 7))
  16493. (define (immediate-int? x)
  16494. (and (exact? x)
  16495. (integer? x)
  16496. (<= -1024 x 1023)))
  16497. ; Given an exact integer, can it be represented as a fixnum?
  16498. (define fixnum-range?
  16499. (let ((-two^29 (- (expt 2 29)))
  16500. (two^29-1 (- (expt 2 29) 1)))
  16501. (lambda (x)
  16502. (<= -two^29 x two^29-1))))
  16503. ; Does the integer x fit in the immediate field of an instruction?
  16504. (define (immediate-literal? x)
  16505. (<= -4096 x 4095))
  16506. ; Return the offset in the %GLOBALS table of the given memory-mapped
  16507. ; register. A memory-mapped register is represented by an integer which
  16508. ; is its offet, so just return the value.
  16509. (define (swreg-global-offset r) r)
  16510. ; Return a bit representation of a character constant.
  16511. (define (char->immediate c)
  16512. (+ (* (char->integer c) 65536) $imm.character))
  16513. ; Convert an integer to a fixnum.
  16514. (define (thefixnum x) (* x 4))
  16515. ; The offset of data slot 'n' within a procedure structure, not adjusting
  16516. ; for tag. The proc is a header followed by code, const, and then data.
  16517. (define (procedure-slot-offset n)
  16518. (+ 12 (* n 4)))
  16519. ; Src is a register, hwreg is a hardware register. If src is a
  16520. ; hardware register, return src. Otherwise, emit an instruction to load
  16521. ; src into hwreg and return hwreg.
  16522. (define (force-hwreg! as src hwreg)
  16523. (if (hardware-mapped? src)
  16524. src
  16525. (emit-load-reg! as src hwreg)))
  16526. ; Given an arbitrary constant opd, generate code to load it into a
  16527. ; register r.
  16528. (define (emit-constant->register as opd r)
  16529. (cond ((and (integer? opd) (exact? opd))
  16530. (if (fixnum-range? opd)
  16531. (emit-immediate->register! as (thefixnum opd) r)
  16532. (emit-const->register! as (emit-datum as opd) r)))
  16533. ((boolean? opd)
  16534. (emit-immediate->register! as
  16535. (if (eq? opd #t)
  16536. $imm.true
  16537. $imm.false)
  16538. r))
  16539. ((equal? opd (eof-object))
  16540. (emit-immediate->register! as $imm.eof r))
  16541. ((equal? opd (unspecified))
  16542. (emit-immediate->register! as $imm.unspecified r))
  16543. ((equal? opd (undefined))
  16544. (emit-immediate->register! as $imm.undefined r))
  16545. ((null? opd)
  16546. (emit-immediate->register! as $imm.null r))
  16547. ((char? opd)
  16548. (emit-immediate->register! as (char->immediate opd) r))
  16549. (else
  16550. (emit-const->register! as (emit-datum as opd) r))))
  16551. ; Stuff a bitpattern or symbolic expression into a register.
  16552. ; (CONST, for immediate constants.)
  16553. ;
  16554. ; FIXME(?): if this had access to eval-expr (currently hidden inside the
  16555. ; sparc assembler) it could attempt to evaluate symbolic expressions,
  16556. ; thereby selecting better code sequences when possible.
  16557. (define (emit-immediate->register! as i r)
  16558. (let ((dest (if (not (hardware-mapped? r)) $r.tmp0 r)))
  16559. (cond ((and (number? i) (immediate-literal? i))
  16560. (sparc.set as i dest))
  16561. ((and (number? i) (zero? (remainder (abs i) 1024)))
  16562. (sparc.sethi as `(hi ,i) dest))
  16563. (else
  16564. (sparc.sethi as `(hi ,i) dest)
  16565. (sparc.ori as dest `(lo ,i) dest)))
  16566. (if (not (hardware-mapped? r))
  16567. (emit-store-reg! as r dest))))
  16568. ; Reference the constants vector and put the constant reference in a register.
  16569. ; `offset' is an integer offset into the constants vector (a constant) for
  16570. ; the current procedure.
  16571. ; Destroys $r.tmp0 and $r.tmp1, but either can be the destination register.
  16572. ; (CONST, for structured constants, GLOBAL, SETGLBL, LAMBDA).
  16573. (define (emit-const->register! as offset r)
  16574. (let ((cvlabel (+ 4 (- (* offset 4) $tag.vector-tag))))
  16575. (cond ((hardware-mapped? r)
  16576. (sparc.ldi as $r.reg0 $p.constvector $r.tmp0)
  16577. (if (asm:fits? cvlabel 13)
  16578. (sparc.ldi as $r.tmp0 cvlabel r)
  16579. (begin (sparc.sethi as `(hi ,cvlabel) $r.tmp1)
  16580. (sparc.addr as $r.tmp0 $r.tmp1 $r.tmp0)
  16581. (sparc.ldi as $r.tmp0 `(lo ,cvlabel) r))))
  16582. (else
  16583. (emit-const->register! as offset $r.tmp0)
  16584. (emit-store-reg! as $r.tmp0 r)))))
  16585. ; Emit single instruction to load sw-mapped reg into another reg, and return
  16586. ; the destination reg.
  16587. (define (emit-load-reg! as from to)
  16588. (if (or (hardware-mapped? from) (not (hardware-mapped? to)))
  16589. (asm-error "emit-load-reg: " from to)
  16590. (begin (sparc.ldi as $r.globals (swreg-global-offset from) to)
  16591. to)))
  16592. (define (emit-store-reg! as from to)
  16593. (if (or (not (hardware-mapped? from)) (hardware-mapped? to))
  16594. (asm-error "emit-store-reg: " from to)
  16595. (begin (sparc.sti as from (swreg-global-offset to) $r.globals)
  16596. to)))
  16597. ; Generic move-reg-to-HW-reg
  16598. (define (emit-move2hwreg! as from to)
  16599. (if (hardware-mapped? from)
  16600. (sparc.move as from to)
  16601. (emit-load-reg! as from to))
  16602. to)
  16603. ; Evaluation of condition code for value or control.
  16604. ;
  16605. ; branchf.a is an annulled conditional branch that tests the condition codes
  16606. ; and branches if some condition is false.
  16607. ; rd is #f or a hardware register.
  16608. ; target is #f or a label.
  16609. ; Exactly one of rd and target must be #f.
  16610. ;
  16611. ; (Why isn't this split into two separate procedures? Because dozens of
  16612. ; this procedure's callers have the value/control duality, and it saves
  16613. ; space to put the test here instead of putting it in each caller.)
  16614. (define (emit-evaluate-cc! as branchf.a rd target)
  16615. (if target
  16616. (begin (branchf.a as target)
  16617. (sparc.slot as))
  16618. (let ((target (new-label)))
  16619. (branchf.a as target)
  16620. (sparc.set as $imm.false rd)
  16621. (sparc.set as $imm.true rd)
  16622. (sparc.label as target))))
  16623. ; Code for runtime safety checking.
  16624. (define (emit-check! as rs0 L1 liveregs)
  16625. (sparc.cmpi as rs0 $imm.false)
  16626. (emit-checkcc! as sparc.be L1 liveregs))
  16627. ; FIXME: This should call the exception handler for non-continuable exceptions.
  16628. (define (emit-trap! as rs1 rs2 rs3 exn)
  16629. (if (not (= rs3 $r.reg0))
  16630. (emit-move2hwreg! as rs3 $r.argreg3))
  16631. (if (not (= rs2 $r.reg0))
  16632. (emit-move2hwreg! as rs2 $r.argreg2))
  16633. (if (not (= rs1 $r.reg0))
  16634. (emit-move2hwreg! as rs1 $r.result))
  16635. (millicode-call/numarg-in-reg as $m.exception (thefixnum exn) $r.tmp0))
  16636. ; Given:
  16637. ; an annulled conditional branch that branches
  16638. ; if the check is ok
  16639. ; a non-annulled conditional branch that branches
  16640. ; if the check is not ok
  16641. ; #f, or a procedure that takes an assembly segment as
  16642. ; argument and emits an instruction that goes into
  16643. ; the delay slot of either branch
  16644. ; three registers whose contents should be passed to the
  16645. ; exception handler if the check is not ok
  16646. ; the exception code
  16647. ; Emits code to call the millicode exception routine with
  16648. ; the given exception code if the condition is false.
  16649. ;
  16650. ; FIXME: The nop can often be replaced by the instruction that
  16651. ; follows it.
  16652. (begin
  16653. '
  16654. (define (emit-checkcc-and-fill-slot!
  16655. as branch-ok.a branch-bad slot-filler L1)
  16656. (let* ((situation (list exn rs1 rs2 rs3))
  16657. (L1 (exception-label as situation)))
  16658. (if L1
  16659. (begin (branch-bad as L1)
  16660. (if slot-filler
  16661. (slot-filler as)
  16662. (sparc.nop as)))
  16663. (let* ((L1 (new-label))
  16664. (L2 (new-label)))
  16665. (exception-label-set! as situation L1)
  16666. (branch-ok.a as L2)
  16667. (if slot-filler
  16668. (slot-filler as)
  16669. (sparc.slot as))
  16670. (sparc.label as L1)
  16671. (cond ((= rs3 $r.reg0)
  16672. #f)
  16673. ((hardware-mapped? $r.argreg3)
  16674. (emit-move2hwreg! as rs3 $r.argreg3))
  16675. ((hardware-mapped? rs3)
  16676. (emit-store-reg! as rs3 $r.argreg3))
  16677. (else
  16678. (emit-move2hwreg! as rs3 $r.tmp0)
  16679. (emit-store-reg! as $r.tmp0 $r.argreg3)))
  16680. (if (not (= rs2 $r.reg0))
  16681. (emit-move2hwreg! as rs2 $r.argreg2))
  16682. (if (not (= rs1 $r.reg0))
  16683. (emit-move2hwreg! as rs1 $r.result))
  16684. ; FIXME: This should be a non-continuable exception.
  16685. (sparc.jmpli as $r.millicode $m.exception $r.o7)
  16686. (emit-immediate->register! as (thefixnum exn) $r.tmp0)
  16687. (sparc.label as L2)))))
  16688. #f
  16689. )
  16690. (define (emit-checkcc! as branch-bad L1 liveregs)
  16691. (branch-bad as L1)
  16692. (apply sparc.slot2 as liveregs))
  16693. ; Generation of millicode calls for non-continuable exceptions.
  16694. (begin
  16695. '
  16696. ; To create only one millicode call per code segment per non-continuable
  16697. ; exception situation, we use the "as-user" feature of assembly segments.
  16698. ; Could use a hash table here.
  16699. (define (exception-label as situation)
  16700. (let ((user-data (as-user as)))
  16701. (if user-data
  16702. (let ((exception-labels (assq 'exception-labels user-data)))
  16703. (if exception-labels
  16704. (let ((probe (assoc situation (cdr exception-labels))))
  16705. (if probe
  16706. (cdr probe)
  16707. #f))
  16708. #f))
  16709. #f)))
  16710. '
  16711. (define (exception-label-set! as situation label)
  16712. (let ((user-data (as-user as)))
  16713. (if user-data
  16714. (let ((exception-labels (assq 'exception-labels user-data)))
  16715. (if exception-labels
  16716. (let ((probe (assoc situation (cdr exception-labels))))
  16717. (if probe
  16718. (error "COMPILER BUG: Exception situation defined twice")
  16719. (set-cdr! exception-labels
  16720. (cons (cons situation label)
  16721. (cdr exception-labels)))))
  16722. (begin (as-user! as
  16723. (cons (list 'exception-labels)
  16724. user-data))
  16725. (exception-label-set! as situation label))))
  16726. (begin (as-user! as '())
  16727. (exception-label-set! as situation label)))))
  16728. #f
  16729. )
  16730. ; Millicode calling
  16731. (define (millicode-call/0arg as mproc)
  16732. (sparc.jmpli as $r.millicode mproc $r.o7)
  16733. (sparc.nop as))
  16734. (define (millicode-call/1arg as mproc r)
  16735. (sparc.jmpli as $r.millicode mproc $r.o7)
  16736. (emit-move2hwreg! as r $r.argreg2))
  16737. (define (millicode-call/1arg-in-result as mproc r)
  16738. (millicode-call/1arg-in-reg as mproc r $r.result))
  16739. (define (millicode-call/1arg-in-reg as mproc rs rd)
  16740. (sparc.jmpli as $r.millicode mproc $r.o7)
  16741. (emit-move2hwreg! as rs rd))
  16742. (define (millicode-call/numarg-in-result as mproc num)
  16743. (sparc.jmpli as $r.millicode mproc $r.o7)
  16744. (sparc.set as num $r.result))
  16745. (define (millicode-call/numarg-in-reg as mproc num reg)
  16746. (if (not (hardware-mapped? reg))
  16747. (asm-error "millicode-call/numarg-in-reg requires HW register: " reg))
  16748. (sparc.jmpli as $r.millicode mproc $r.o7)
  16749. (sparc.set as num reg))
  16750. (define (millicode-call/2arg as mproc r1 r2)
  16751. (emit-move2hwreg! as r1 $r.argreg2)
  16752. (sparc.jmpli as $r.millicode mproc $r.o7)
  16753. (emit-move2hwreg! as r2 $r.argreg3))
  16754. ; NOTE: Don't use TMP0 since TMP0 is sometimes a millicode argument
  16755. ; register (for example to m_exception).
  16756. ;
  16757. ; NOTE: Don't use sparc.set rather than sethi/ori; we need to know that
  16758. ; two instructions get generated.
  16759. ;
  16760. ; FIXME: Should calculate the value if possible to get better precision
  16761. ; and to avoid generating a fixup. See emit-return-address! in gen-msi.sch.
  16762. (define (millicode-call/ret as mproc label)
  16763. (cond ((short-effective-addresses)
  16764. (sparc.jmpli as $r.millicode mproc $r.o7)
  16765. (sparc.addi as $r.o7 `(- ,label (- ,(here as) 4) 8) $r.o7))
  16766. (else
  16767. (let ((val `(- ,label (+ ,(here as) 8) 8)))
  16768. (sparc.sethi as `(hi ,val) $r.tmp1)
  16769. (sparc.ori as $r.tmp1 `(lo ,val) $r.tmp1)
  16770. (sparc.jmpli as $r.millicode mproc $r.o7)
  16771. (sparc.addr as $r.o7 $r.tmp1 $r.o7)))))
  16772. (define (check-timer as DESTINATION RETRY)
  16773. (sparc.subicc as $r.timer 1 $r.timer)
  16774. (sparc.bne.a as DESTINATION)
  16775. (sparc.slot as)
  16776. (millicode-call/ret as $m.timer-exception RETRY))
  16777. ; When the destination and retry labels are the same, and follow the
  16778. ; timer check immediately, then this code saves two static instructions.
  16779. (define (check-timer0 as)
  16780. (sparc.subicc as $r.timer 1 $r.timer)
  16781. (sparc.bne.a as (+ (here as) 16))
  16782. (sparc.slot as)
  16783. (sparc.jmpli as $r.millicode $m.timer-exception $r.o7)
  16784. (sparc.nop as))
  16785. ; eof
  16786. ; Copyright 1998 Lars T Hansen.
  16787. ;
  16788. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  16789. ;
  16790. ; 9 May 1999 / wdc
  16791. ;
  16792. ; SPARC machine assembler.
  16793. ;
  16794. ; The procedure `sparc-instruction' takes an instruction class keyword and
  16795. ; some operands and returns an assembler procedure for the instruction
  16796. ; denoted by the class and the operands.
  16797. ;
  16798. ; All assembler procedures for SPARC mnemonics are defined in sparcasm2.sch.
  16799. ;
  16800. ; The SPARC has 32-bit, big-endian words. All instructions are 1 word.
  16801. ; This assembler currently accepts a subset of the SPARC v8 instruction set.
  16802. ;
  16803. ; Each assembler procedure takes an `as' assembly structure (see
  16804. ; Asm/Common/pass5p1.sch) and operands relevant to the instruction, and
  16805. ; side-effects the assembly structure by emitting bits for the instruction
  16806. ; and any necessary fixups. There are separate instruction mnemonics and
  16807. ; assembler procedures for instructions which in the SPARC instruction set
  16808. ; are normally considered the "same". For example, the `add' instruction is
  16809. ; split into two operations here: `sparc.addr' takes a register as operand2,
  16810. ; and `sparc.addi' takes an immediate. We could remove this restriction
  16811. ; by using objects with identity rather than numbers for registers, but it
  16812. ; does not seem to be an important problem.
  16813. ;
  16814. ; Operands that denote values (addresses, immediates, offsets) may be
  16815. ; expressed using symbolic expressions. These expressions must conform
  16816. ; to the following grammar:
  16817. ;
  16818. ; <expr> --> ( <number> . <obj> ) ; label
  16819. ; | <number> ; literal value (exact integer)
  16820. ; | (+ <expr> ... ) ; sum
  16821. ; | (- <expr> ... ) ; difference
  16822. ; | (hi <expr>) ; high 22 bits
  16823. ; | (lo <expr>) ; low 10 bits
  16824. ;
  16825. ; Each assembler procedure will check that its value operand(s) fit in
  16826. ; their instruction fields. It is a fatal error for an operand not
  16827. ; to fit, and the assembler calls `asm-error' to signal this error.
  16828. ; However, in some cases the assembler will instead call the error
  16829. ; procedure `asm-value-too-large', which allows the higher-level assembler
  16830. ; to retry the assembly with different settings (typically, by splitting
  16831. ; a jump instruction into an offset calculation and a jump).
  16832. ;
  16833. ; Note: the idiom that is seen in this file,
  16834. ; (emit-fixup-proc! as (lambda (b l) (fixup b l)))
  16835. ; when `fixup' is a local procedure, avoids allocation of the closure
  16836. ; except in the cases where the fixup is in fact needed, for gains in
  16837. ; speed and reduction in allocation. (Ask me if you want numbers.)
  16838. ;
  16839. ; If FILL-DELAY-SLOTS returns true, then this assembler supports two
  16840. ; distinct mechanisms for filling branch delay slots.
  16841. ;
  16842. ; An annulled conditional branch or an un-annulled unconditional branch
  16843. ; may be followed by the strange instruction SPARC.SLOT, which turns into
  16844. ; a nop in the delay slot that may be replaced by copying the instruction
  16845. ; at the target of the branch into the delay slot and increasing the branch
  16846. ; offset by 4.
  16847. ;
  16848. ; An un-annulled conditional branch whose target depends upon a known set
  16849. ; of general registers, and does not depend upon the condition codes, may
  16850. ; be followed by the strange instruction SPARC.SLOT2, which takes any
  16851. ; number of registers as operands. This strange instruction turns into
  16852. ; nothing at all if the following instruction has no side effects except
  16853. ; to the condition codes and/or to a destination register that is distinct
  16854. ; from the specified registers plus the stack pointer and %o7; otherwise
  16855. ; the SPARC.SLOT2 instruction becomes a nop in the delay slot. The
  16856. ; implementation of this uses a buffer that must be cleared when a label
  16857. ; is emitted or when the current offset is obtained.
  16858. (define sparc-instruction)
  16859. (let ((original-emit-label! emit-label!)
  16860. (original-here here))
  16861. (set! emit-label!
  16862. (lambda (as L)
  16863. (assembler-value! as 'slot2-info #f)
  16864. (original-emit-label! as L)))
  16865. (set! here
  16866. (lambda (as)
  16867. (assembler-value! as 'slot2-info #f)
  16868. (original-here as)))
  16869. 'emit-label!)
  16870. (let ((emit! (lambda (as bits)
  16871. (assembler-value! as 'slot2-info #f)
  16872. (emit! as bits)))
  16873. (emit-fixup-proc! (lambda (as proc)
  16874. (assembler-value! as 'slot2-info #f)
  16875. (emit-fixup-proc! as proc)))
  16876. (goes-in-delay-slot2? (lambda (as rd)
  16877. (let ((regs (assembler-value as 'slot2-info)))
  16878. (and regs
  16879. (fill-delay-slots)
  16880. (not (= rd $r.stkp))
  16881. (not (= rd $r.o7))
  16882. (not (memv rd regs)))))))
  16883. (define ibit (asm:bv 0 0 #x20 0)) ; immediate bit: 2^13
  16884. (define abit (asm:bv #x20 0 0 0)) ; annul bit: 2^29
  16885. (define zero (asm:bv 0 0 0 0)) ; all zero bits
  16886. (define two^32 (expt 2 32))
  16887. ; Constant expression evaluation. If the expression cannot be
  16888. ; evaluated, eval-expr returns #f, otherwise a number.
  16889. ; The symbol table lookup must fail by returning #f.
  16890. (define (eval-expr as e)
  16891. (define (complement x)
  16892. (modulo (+ two^32 x) two^32))
  16893. (define (hibits e)
  16894. (cond ((not e) e)
  16895. ((< e 0)
  16896. (complement (quotient (complement e) 1024)))
  16897. (else
  16898. (quotient e 1024))))
  16899. (define (lobits e)
  16900. (cond ((not e) e)
  16901. ((< e 0)
  16902. (remainder (complement e) 1024))
  16903. (else
  16904. (remainder e 1024))))
  16905. (define (evaluate e)
  16906. (cond ((integer? e) e)
  16907. ((label? e) (label-value as e))
  16908. ((eq? 'hi (car e)) (hibits (evaluate (cadr e))))
  16909. ((eq? 'lo (car e)) (lobits (evaluate (cadr e))))
  16910. ((eq? '+ (car e))
  16911. (let loop ((e (cdr e)) (s 0))
  16912. (if (null? e) s
  16913. (let ((op (evaluate (car e))))
  16914. (if (not op) op
  16915. (loop (cdr e) (+ s op)))))))
  16916. ((eq? '- (car e))
  16917. (let loop ((e (cdr e)) (d #f))
  16918. (if (null? e) d
  16919. (let ((op (evaluate (car e))))
  16920. (if (not op) op
  16921. (loop (cdr e) (if d (- d op) op)))))))
  16922. (else
  16923. (signal-error 'badexpr e))))
  16924. (evaluate e))
  16925. ; Common error handling.
  16926. (define (signal-error code . rest)
  16927. (define msg "SPARC assembler: ")
  16928. (case code
  16929. ((badexpr)
  16930. (asm-error msg "invalid expression " (car rest)))
  16931. ((toolarge)
  16932. (asm-error msg "value too large in " (car rest) ": "
  16933. (cadr rest) " = " (caddr rest)))
  16934. ((fixup)
  16935. (asm-error msg "fixup failed in " (car rest) " for " (cadr rest)))
  16936. ((unaligned)
  16937. (asm-error msg "unaligned target in " (car rest) ": " (cadr rest)))
  16938. (else
  16939. (error "Invalid error code in assembler: " code))))
  16940. ; The following procedures construct instructions by depositing field
  16941. ; values directly into bytevectors; the location parameter in the dep-*!
  16942. ; procedures is the address in the bytevector of the most significant byte.
  16943. (define (copy! bv k bits)
  16944. (bytevector-set! bv k (bytevector-ref bits 0))
  16945. (bytevector-set! bv (+ k 1) (bytevector-ref bits 1))
  16946. (bytevector-set! bv (+ k 2) (bytevector-ref bits 2))
  16947. (bytevector-set! bv (+ k 3) (bytevector-ref bits 3))
  16948. bv)
  16949. (define (copy bits)
  16950. (let ((bv (make-bytevector 4)))
  16951. (bytevector-set! bv 0 (bytevector-ref bits 0))
  16952. (bytevector-set! bv 1 (bytevector-ref bits 1))
  16953. (bytevector-set! bv 2 (bytevector-ref bits 2))
  16954. (bytevector-set! bv 3 (bytevector-ref bits 3))
  16955. bv))
  16956. (define (copy-instr bv from to)
  16957. (bytevector-set! bv to (bytevector-ref bv from))
  16958. (bytevector-set! bv (+ to 1) (bytevector-ref bv (+ from 1)))
  16959. (bytevector-set! bv (+ to 2) (bytevector-ref bv (+ from 2)))
  16960. (bytevector-set! bv (+ to 3) (bytevector-ref bv (+ from 3))))
  16961. (define (dep-rs1! bits k rs1)
  16962. (bytevector-set! bits (+ k 1)
  16963. (logior (bytevector-ref bits (+ k 1))
  16964. (rshl rs1 2)))
  16965. (bytevector-set! bits (+ k 2)
  16966. (logior (bytevector-ref bits (+ k 2))
  16967. (lsh (logand rs1 3) 6))))
  16968. (define (dep-rs2! bits k rs2)
  16969. (bytevector-set! bits (+ k 3)
  16970. (logior (bytevector-ref bits (+ k 3)) rs2)))
  16971. (define (dep-rd! bits k rd)
  16972. (bytevector-set! bits k
  16973. (logior (bytevector-ref bits k) (lsh rd 1))))
  16974. (define (dep-imm! bits k imm)
  16975. (cond ((fixnum? imm)
  16976. (bytevector-set! bits (+ k 3) (logand imm 255))
  16977. (bytevector-set! bits (+ k 2)
  16978. (logior (bytevector-ref bits (+ k 2))
  16979. (logand (rsha imm 8) 31))))
  16980. ((bytevector? imm)
  16981. (bytevector-set! bits (+ k 3) (bytevector-ref imm 0))
  16982. (bytevector-set! bits (+ k 2)
  16983. (logior (bytevector-ref bits (+ k 2))
  16984. (logand (bytevector-ref imm 1)
  16985. 31))))
  16986. (else
  16987. (dep-imm! bits k (asm:int->bv imm)))))
  16988. (define (dep-branch-offset! bits k offs)
  16989. (cond ((fixnum? offs)
  16990. (if (not (= (logand offs 3) 0))
  16991. (signal-error 'unaligned "branch" offs))
  16992. (dep-imm22! bits k (rsha offs 2)))
  16993. ((bytevector? offs)
  16994. (if (not (= (logand (bytevector-ref offs 3) 3) 0))
  16995. (signal-error 'unaligned "branch" (asm:bv->int offs)))
  16996. (dep-imm22! bits k (asm:rsha offs 2)))
  16997. (else
  16998. (dep-branch-offset! bits k (asm:int->bv offs)))))
  16999. (define (dep-imm22! bits k imm)
  17000. (cond ((fixnum? imm)
  17001. (bytevector-set! bits (+ k 3) (logand imm 255))
  17002. (bytevector-set! bits (+ k 2)
  17003. (logand (rsha imm 8) 255))
  17004. (bytevector-set! bits (+ k 1)
  17005. (logior (bytevector-ref bits (+ k 1))
  17006. (logand (rsha imm 16) 63))))
  17007. ((bytevector? imm)
  17008. (bytevector-set! bits (+ k 3) (bytevector-ref imm 3))
  17009. (bytevector-set! bits (+ k 2) (bytevector-ref imm 2))
  17010. (bytevector-set! bits (+ k 1)
  17011. (logior (bytevector-ref bits (+ k 1))
  17012. (logand (bytevector-ref imm 1)
  17013. 63))))
  17014. (else
  17015. (dep-imm22! bits k (asm:int->bv imm)))))
  17016. (define (dep-call-offset! bits k offs)
  17017. (cond ((fixnum? offs)
  17018. (if (not (= (logand offs 3) 0))
  17019. (signal-error 'unaligned "call" offs))
  17020. (bytevector-set! bits (+ k 3) (logand (rsha offs 2) 255))
  17021. (bytevector-set! bits (+ k 2) (logand (rsha offs 10) 255))
  17022. (bytevector-set! bits (+ k 1) (logand (rsha offs 18) 255))
  17023. (bytevector-set! bits k (logior (bytevector-ref bits k)
  17024. (logand (rsha offs 26) 63))))
  17025. ((bytevector? offs)
  17026. (if (not (= (logand (bytevector-ref offs 3) 3) 0))
  17027. (signal-error 'unaligned "call" (asm:bv->int offs)))
  17028. (let ((offs (asm:rsha offs 2)))
  17029. (bytevector-set! bits (+ k 3) (bytevector-ref offs 3))
  17030. (bytevector-set! bits (+ k 2) (bytevector-ref offs 2))
  17031. (bytevector-set! bits (+ k 1) (bytevector-ref offs 1))
  17032. (bytevector-set! bits k (logior (bytevector-ref bits k)
  17033. (logand (bytevector-ref offs 0)
  17034. 63)))))
  17035. (else
  17036. (dep-call-offset! bits k (asm:int->bv offs)))))
  17037. ; Add 1 to an instruction (to bump a branch offset by 4).
  17038. ; FIXME: should check for field overflow.
  17039. (define (add1 bv loc)
  17040. (let* ((r0 (+ (bytevector-ref bv (+ loc 3)) 1))
  17041. (d0 (logand r0 255))
  17042. (c0 (rshl r0 8)))
  17043. (bytevector-set! bv (+ loc 3) d0)
  17044. (let* ((r1 (+ (bytevector-ref bv (+ loc 2)) c0))
  17045. (d1 (logand r1 255))
  17046. (c1 (rshl r1 8)))
  17047. (bytevector-set! bv (+ loc 2) d1)
  17048. (let* ((r2 (+ (bytevector-ref bv (+ loc 1)) c1))
  17049. (d2 (logand r2 255)))
  17050. (bytevector-set! bv (+ loc 1) d2)))))
  17051. ; For delay slot filling -- uses the assembler value scratchpad in
  17052. ; the as structure. Delay slot filling is discussed in the comments
  17053. ; for `branch' and `class-slot', below.
  17054. (define (remember-branch-target as obj)
  17055. (assembler-value! as 'branch-target obj))
  17056. (define (recover-branch-target as)
  17057. (assembler-value as 'branch-target))
  17058. ; Mark the instruction at the current address as not being eligible
  17059. ; for being lifted into a branch delay slot.
  17060. ;
  17061. ; FIXME: should perhaps be a hash table; see BOOT-STATUS file for details.
  17062. (define (not-a-delay-slot-instruction as)
  17063. (assembler-value! as 'not-dsi
  17064. (cons (here as)
  17065. (or (assembler-value as 'not-dsi) '()))))
  17066. (define (is-a-delay-slot-instruction? as bv addr)
  17067. (and (not (memv addr (or (assembler-value as 'not-dsi) '())))
  17068. (< addr (bytevector-length bv))))
  17069. ; SETHI, etc.
  17070. (define (class-sethi bits)
  17071. (let ((bits (asm:lsh bits 22)))
  17072. (lambda (as val rd)
  17073. (define (fixup bv loc)
  17074. (dep-imm22! bv loc
  17075. (or (eval-expr as val)
  17076. (signal-error 'fixup "sethi" val))))
  17077. (define (fixup2 bv loc)
  17078. (copy! bv loc bits)
  17079. (dep-rd! bv loc rd)
  17080. (fixup bv loc))
  17081. (if (goes-in-delay-slot2? as rd)
  17082. (emit-fixup-proc! as
  17083. (lambda (b l)
  17084. (fixup2 b (- l 4))))
  17085. (let ((bits (copy bits))
  17086. (e (eval-expr as val)))
  17087. (if e
  17088. (dep-imm22! bits 0 e)
  17089. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17090. (dep-rd! bits 0 rd)
  17091. (emit! as bits))))))
  17092. ; NOP is a peculiar sethi
  17093. (define (class-nop i)
  17094. (let ((instr (class-sethi i)))
  17095. (lambda (as)
  17096. (instr as 0 $r.g0))))
  17097. ; Branches
  17098. (define (class00b i) (branch #b010 i zero)) ; Un-annulled IU branches.
  17099. (define (class00a i) (branch #b010 i abit)) ; Annulled IU branches.
  17100. (define (classf00b i) (branch #b110 i zero)) ; Un-annulled FP branches.
  17101. (define (classf00a i) (branch #b110 i abit)) ; Annulled FP branches.
  17102. ; The `type' parameter is #b010 for IU branches, #b110 for FP branches.
  17103. ; The `bits' parameter is the bits for the cond field.
  17104. ; The `annul' parameter is either `zero' or `abit' (see top of file).
  17105. ;
  17106. ; Annuled branches require special treatement for delay slot
  17107. ; filling based on the `slot' pseudo-instruction.
  17108. ;
  17109. ; Strategy: when a branch with the annul bit set is assembled, remember
  17110. ; its target in a one-element cache in the AS structure. When a slot
  17111. ; instruction is found (it has its own class) then the cached
  17112. ; value (possibly a delayed expression) is gotten, and a fixup for the
  17113. ; slot is registered. When the fixup is later evaluated, the branch
  17114. ; target instruction can be found, examined, and evaluated.
  17115. ;
  17116. ; The cached value is always valid when the slot instruction is assembled,
  17117. ; because a slot instruction is always directly preceded by an annulled
  17118. ; branch (which will always set the cache).
  17119. (define (branch type bits annul)
  17120. ; The delay slot should be filled if this is an annulled branch
  17121. ; or an unconditional branch.
  17122. (let ((fill-delay-slot? (or (not (eq? annul zero))
  17123. (eq? bits #b1000)))
  17124. (bits (asm:logior (asm:lsh bits 25) (asm:lsh type 22) annul)))
  17125. (lambda (as target0)
  17126. (let ((target `(- ,target0 ,(here as))))
  17127. (define (expr)
  17128. (let ((e (eval-expr as target)))
  17129. (cond ((not e)
  17130. e)
  17131. ((not (zero? (logand e 3)))
  17132. (signal-error 'unaligned "branch" target0))
  17133. ((asm:fits? e 24)
  17134. e)
  17135. (else
  17136. (asm-value-too-large as "branch" target e)))))
  17137. (define (fixup bv loc)
  17138. (let ((e (expr)))
  17139. (if e
  17140. (dep-branch-offset! bv loc e)
  17141. (signal-error 'fixup "branch" target0))))
  17142. (if fill-delay-slot?
  17143. (remember-branch-target as target0)
  17144. (remember-branch-target as #f)) ; Clears the cache.
  17145. (not-a-delay-slot-instruction as)
  17146. (let ((bits (copy bits))
  17147. (e (expr)))
  17148. (if e
  17149. (dep-branch-offset! bits 0 e)
  17150. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17151. (emit! as bits))))))
  17152. ; Branch delay slot pseudo-instruction.
  17153. ;
  17154. ; Get the branch target expression from the cache in the AS structure,
  17155. ; and if it is not #f, register a fixup procedure for the delay slot that
  17156. ; will copy the target instruction to the slot and add 4 to the branch
  17157. ; offset (unless that will overflow the offset or the instruction at the
  17158. ; target is not suitable for lifting).
  17159. ;
  17160. ; It's important that this fixup run _after_ any fixups for the branch
  17161. ; instruction itself!
  17162. (define (class-slot)
  17163. (let ((nop-instr (class-nop #b100)))
  17164. (lambda (as)
  17165. ; The branch target is the expression denoting the target location.
  17166. (define branch-target (recover-branch-target as))
  17167. (define (fixup bv loc)
  17168. (let ((bt (or (eval-expr as branch-target)
  17169. (asm-error "Branch fixup: can't happen: "
  17170. branch-target))))
  17171. (if (is-a-delay-slot-instruction? as bv bt)
  17172. (begin
  17173. (copy-instr bv bt loc)
  17174. (add1 bv (- loc 4))))))
  17175. (if (and branch-target (fill-delay-slots))
  17176. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17177. (nop-instr as))))
  17178. ; Branch delay slot pseudo-instruction 2.
  17179. ;
  17180. ; Emit a nop, but record the information that will allow this nop to be
  17181. ; replaced by a sufficiently harmless ALU instruction.
  17182. (define (class-slot2)
  17183. (let ((nop-instr (class-nop #b100)))
  17184. (lambda (as . regs)
  17185. (nop-instr as)
  17186. (assembler-value! as 'slot2-info regs))))
  17187. ; ALU stuff, register operand, rdy, wryr. Also: jump.
  17188. (define (class10r bits . extra)
  17189. (cond ((and (not (null? extra)) (eq? (car extra) 'rdy))
  17190. (let ((op (class10r bits)))
  17191. (lambda (as rd)
  17192. (op as 0 0 rd))))
  17193. ((and (not (null? extra)) (eq? (car extra) 'wry))
  17194. (let ((op (class10r bits)))
  17195. (lambda (as rs)
  17196. (op as rs 0 0))))
  17197. (else
  17198. (let ((bits (asm:logior (asm:lsh #b10 30) (asm:lsh bits 19)))
  17199. (jump? (and (not (null? extra)) (eq? (car extra) 'jump))))
  17200. (lambda (as rs1 rs2 rd)
  17201. (let ((bits (copy bits)))
  17202. (dep-rs1! bits 0 rs1)
  17203. (dep-rs2! bits 0 rs2)
  17204. (dep-rd! bits 0 rd)
  17205. (cond (jump?
  17206. (not-a-delay-slot-instruction as)
  17207. (emit! as bits))
  17208. ((goes-in-delay-slot2? as rd)
  17209. (emit-fixup-proc!
  17210. as
  17211. (lambda (bv loc)
  17212. (copy! bv (- loc 4) bits))))
  17213. (else
  17214. (emit! as bits)))))))))
  17215. ; ALU stuff, immediate operand, wryi. Also: jump.
  17216. (define (class10i bits . extra)
  17217. (if (and (not (null? extra)) (eq? (car extra) 'wry))
  17218. (let ((op (class10i bits)))
  17219. (lambda (as src)
  17220. (op as 0 src 0)))
  17221. (let ((bits (asm:logior (asm:lsh #b10 30) (asm:lsh bits 19) ibit))
  17222. (jump? (and (not (null? extra)) (eq? (car extra) 'jump))))
  17223. (lambda (as rs1 e rd)
  17224. (define (expr)
  17225. (let ((imm (eval-expr as e)))
  17226. (cond ((not imm)
  17227. imm)
  17228. ((asm:fits? imm 13)
  17229. imm)
  17230. (jump?
  17231. (asm-value-too-large as "`jmpli'" e imm))
  17232. (else
  17233. (asm-value-too-large as "ALU instruction" e imm)))))
  17234. (define (fixup bv loc)
  17235. (let ((e (expr)))
  17236. (if e
  17237. (dep-imm! bv loc e)
  17238. (signal-error 'fixup "ALU instruction" e))))
  17239. (let ((bits (copy bits))
  17240. (e (expr)))
  17241. (if e
  17242. (dep-imm! bits 0 e)
  17243. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17244. (dep-rs1! bits 0 rs1)
  17245. (dep-rd! bits 0 rd)
  17246. (cond (jump?
  17247. (not-a-delay-slot-instruction as)
  17248. (emit! as bits))
  17249. ((goes-in-delay-slot2? as rd)
  17250. (emit-fixup-proc!
  17251. as
  17252. (lambda (bv loc)
  17253. (copy! bv (- loc 4) bits))))
  17254. (else
  17255. (emit! as bits))))))))
  17256. ; Memory stuff, register operand.
  17257. (define (class11r bits)
  17258. (let ((bits (asm:logior (asm:lsh #b11 30) (asm:lsh bits 19))))
  17259. (lambda (as rs1 rs2 rd)
  17260. (let ((bits (copy bits)))
  17261. (dep-rs1! bits 0 rs1)
  17262. (dep-rs2! bits 0 rs2)
  17263. (dep-rd! bits 0 rd)
  17264. (emit! as bits)))))
  17265. ; Memory stuff, immediate operand.
  17266. (define (class11i bits)
  17267. (let ((bits (asm:logior (asm:lsh #b11 30) (asm:lsh bits 19) ibit)))
  17268. (lambda (as rs1 e rd)
  17269. (define (expr)
  17270. (let ((imm (eval-expr as e)))
  17271. (cond ((not imm) imm)
  17272. ((asm:fits? imm 13) imm)
  17273. (else
  17274. (signal-error 'toolarge "Memory instruction" e imm)))))
  17275. (define (fixup bv loc)
  17276. (let ((e (expr)))
  17277. (if e
  17278. (dep-imm! bv loc e)
  17279. (signal-error 'fixup "Memory instruction" e))))
  17280. (let ((bits (copy bits))
  17281. (e (expr)))
  17282. (dep-rs1! bits 0 rs1)
  17283. (dep-rd! bits 0 rd)
  17284. (if e
  17285. (dep-imm! bits 0 e)
  17286. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17287. (emit! as bits)))))
  17288. ; For store instructions. The syntax is (st a b c) meaning m[ b+c ] <- a.
  17289. ; However, on the Sparc, the destination (rd) field is the source of
  17290. ; a store, so we transform the instruction into (st c b a) and pass it
  17291. ; to the real store procedure.
  17292. (define (class11sr bits)
  17293. (let ((store-instr (class11r bits)))
  17294. (lambda (as a b c)
  17295. (store-instr as c b a))))
  17296. (define (class11si bits)
  17297. (let ((store-instr (class11i bits)))
  17298. (lambda (as a b c)
  17299. (store-instr as c b a))))
  17300. ; Call is a class all by itself.
  17301. (define (class-call)
  17302. (let ((code (asm:lsh #b01 30)))
  17303. (lambda (as target0)
  17304. (let ((target `(- ,target0 ,(here as))))
  17305. (define (fixup bv loc)
  17306. (let ((e (eval-expr as target)))
  17307. (if e
  17308. (dep-call-offset! bv loc e)
  17309. (signal-error 'fixup "call" target0))))
  17310. (let ((bits (copy code))
  17311. (e (eval-expr as target)))
  17312. (not-a-delay-slot-instruction as)
  17313. (if e
  17314. (dep-call-offset! bits 0 e)
  17315. (emit-fixup-proc! as (lambda (b l) (fixup b l))))
  17316. (emit! as bits))))))
  17317. (define (class-label)
  17318. (lambda (as label)
  17319. (emit-label! as label)))
  17320. ; FP operation, don't set CC.
  17321. (define (class-fpop1 i) (fpop #b110100 i))
  17322. ; FP operation, set CC
  17323. (define (class-fpop2 i) (fpop #b110101 i))
  17324. (define (fpop type opf)
  17325. (let ((bits (asm:logior (asm:lsh #b10 30)
  17326. (asm:lsh type 19)
  17327. (asm:lsh opf 5))))
  17328. (lambda (as rs1 rs2 rd)
  17329. (let ((bits (copy bits)))
  17330. (dep-rs1! bits 0 rs1)
  17331. (dep-rs2! bits 0 rs2)
  17332. (dep-rd! bits 0 rd)
  17333. (emit! as bits)))))
  17334. (set! sparc-instruction
  17335. (lambda (kwd . ops)
  17336. (case kwd
  17337. ((i11) (apply class11i ops))
  17338. ((r11) (apply class11r ops))
  17339. ((si11) (apply class11si ops))
  17340. ((sr11) (apply class11sr ops))
  17341. ((sethi) (apply class-sethi ops))
  17342. ((r10) (apply class10r ops))
  17343. ((i10) (apply class10i ops))
  17344. ((b00) (apply class00b ops))
  17345. ((a00) (apply class00a ops))
  17346. ((call) (apply class-call ops))
  17347. ((label) (apply class-label ops))
  17348. ((nop) (apply class-nop ops))
  17349. ((slot) (apply class-slot ops))
  17350. ((slot2) (apply class-slot2 ops))
  17351. ((fb00) (apply classf00b ops))
  17352. ((fa00) (apply classf00a ops))
  17353. ((fp) (apply class-fpop1 ops))
  17354. ((fpcc) (apply class-fpop2 ops))
  17355. (else
  17356. (asm-error "sparc-instruction: unrecognized class: " kwd)))))
  17357. 'sparc-instruction)
  17358. ; eof
  17359. ; Instruction mnemonics
  17360. (define sparc.lddi (sparc-instruction 'i11 #b000011))
  17361. (define sparc.lddr (sparc-instruction 'r11 #b000011))
  17362. (define sparc.ldi (sparc-instruction 'i11 #b000000))
  17363. (define sparc.ldr (sparc-instruction 'r11 #b000000))
  17364. (define sparc.ldhi (sparc-instruction 'i11 #b000010))
  17365. (define sparc.ldhr (sparc-instruction 'r11 #b000010))
  17366. (define sparc.ldbi (sparc-instruction 'i11 #b000001))
  17367. (define sparc.ldbr (sparc-instruction 'r11 #b000001))
  17368. (define sparc.lddfi (sparc-instruction 'i11 #b100011))
  17369. (define sparc.lddfr (sparc-instruction 'r11 #b100011))
  17370. (define sparc.stdi (sparc-instruction 'si11 #b000111))
  17371. (define sparc.stdr (sparc-instruction 'sr11 #b000111))
  17372. (define sparc.sti (sparc-instruction 'si11 #b000100))
  17373. (define sparc.str (sparc-instruction 'sr11 #b000100))
  17374. (define sparc.sthi (sparc-instruction 'si11 #b000110))
  17375. (define sparc.sthr (sparc-instruction 'sr11 #b000110))
  17376. (define sparc.stbi (sparc-instruction 'si11 #b000101))
  17377. (define sparc.stbr (sparc-instruction 'sr11 #b000101))
  17378. (define sparc.stdfi (sparc-instruction 'si11 #b100111))
  17379. (define sparc.stdfr (sparc-instruction 'sr11 #b100111))
  17380. (define sparc.sethi (sparc-instruction 'sethi #b100))
  17381. (define sparc.andr (sparc-instruction 'r10 #b000001))
  17382. (define sparc.andrcc (sparc-instruction 'r10 #b010001))
  17383. (define sparc.andi (sparc-instruction 'i10 #b000001))
  17384. (define sparc.andicc (sparc-instruction 'i10 #b010001))
  17385. (define sparc.orr (sparc-instruction 'r10 #b000010))
  17386. (define sparc.orrcc (sparc-instruction 'r10 #b010010))
  17387. (define sparc.ori (sparc-instruction 'i10 #b000010))
  17388. (define sparc.oricc (sparc-instruction 'i10 #b010010))
  17389. (define sparc.xorr (sparc-instruction 'r10 #b000011))
  17390. (define sparc.xorrcc (sparc-instruction 'r10 #b010011))
  17391. (define sparc.xori (sparc-instruction 'i10 #b000011))
  17392. (define sparc.xoricc (sparc-instruction 'i10 #b010011))
  17393. (define sparc.sllr (sparc-instruction 'r10 #b100101))
  17394. (define sparc.slli (sparc-instruction 'i10 #b100101))
  17395. (define sparc.srlr (sparc-instruction 'r10 #b100110))
  17396. (define sparc.srli (sparc-instruction 'i10 #b100110))
  17397. (define sparc.srar (sparc-instruction 'r10 #b100111))
  17398. (define sparc.srai (sparc-instruction 'i10 #b100111))
  17399. (define sparc.addr (sparc-instruction 'r10 #b000000))
  17400. (define sparc.addrcc (sparc-instruction 'r10 #b010000))
  17401. (define sparc.addi (sparc-instruction 'i10 #b000000))
  17402. (define sparc.addicc (sparc-instruction 'i10 #b010000))
  17403. (define sparc.taddrcc (sparc-instruction 'r10 #b100000))
  17404. (define sparc.taddicc (sparc-instruction 'i10 #b100000))
  17405. (define sparc.subr (sparc-instruction 'r10 #b000100))
  17406. (define sparc.subrcc (sparc-instruction 'r10 #b010100))
  17407. (define sparc.subi (sparc-instruction 'i10 #b000100))
  17408. (define sparc.subicc (sparc-instruction 'i10 #b010100))
  17409. (define sparc.tsubrcc (sparc-instruction 'r10 #b100001))
  17410. (define sparc.tsubicc (sparc-instruction 'i10 #b100001))
  17411. (define sparc.smulr (sparc-instruction 'r10 #b001011))
  17412. (define sparc.smulrcc (sparc-instruction 'r10 #b011011))
  17413. (define sparc.smuli (sparc-instruction 'i10 #b001011))
  17414. (define sparc.smulicc (sparc-instruction 'i10 #b011011))
  17415. (define sparc.sdivr (sparc-instruction 'r10 #b001111))
  17416. (define sparc.sdivrcc (sparc-instruction 'r10 #b011111))
  17417. (define sparc.sdivi (sparc-instruction 'i10 #b001111))
  17418. (define sparc.sdivicc (sparc-instruction 'i10 #b011111))
  17419. (define sparc.b (sparc-instruction 'b00 #b1000))
  17420. (define sparc.b.a (sparc-instruction 'a00 #b1000))
  17421. (define sparc.bne (sparc-instruction 'b00 #b1001))
  17422. (define sparc.bne.a (sparc-instruction 'a00 #b1001))
  17423. (define sparc.be (sparc-instruction 'b00 #b0001))
  17424. (define sparc.be.a (sparc-instruction 'a00 #b0001))
  17425. (define sparc.bg (sparc-instruction 'b00 #b1010))
  17426. (define sparc.bg.a (sparc-instruction 'a00 #b1010))
  17427. (define sparc.ble (sparc-instruction 'b00 #b0010))
  17428. (define sparc.ble.a (sparc-instruction 'a00 #b0010))
  17429. (define sparc.bge (sparc-instruction 'b00 #b1011))
  17430. (define sparc.bge.a (sparc-instruction 'a00 #b1011))
  17431. (define sparc.bl (sparc-instruction 'b00 #b0011))
  17432. (define sparc.bl.a (sparc-instruction 'a00 #b0011))
  17433. (define sparc.bgu (sparc-instruction 'b00 #b1100))
  17434. (define sparc.bgu.a (sparc-instruction 'a00 #b1100))
  17435. (define sparc.bleu (sparc-instruction 'b00 #b0100))
  17436. (define sparc.bleu.a (sparc-instruction 'a00 #b0100))
  17437. (define sparc.bcc (sparc-instruction 'b00 #b1101))
  17438. (define sparc.bcc.a (sparc-instruction 'a00 #b1101))
  17439. (define sparc.bcs (sparc-instruction 'b00 #b0101))
  17440. (define sparc.bcs.a (sparc-instruction 'a00 #b0101))
  17441. (define sparc.bpos (sparc-instruction 'b00 #b1110))
  17442. (define sparc.bpos.a (sparc-instruction 'a00 #b1110))
  17443. (define sparc.bneg (sparc-instruction 'b00 #b0110))
  17444. (define sparc.bneg.a (sparc-instruction 'a00 #b0110))
  17445. (define sparc.bvc (sparc-instruction 'b00 #b1111))
  17446. (define sparc.bvc.a (sparc-instruction 'a00 #b1111))
  17447. (define sparc.bvs (sparc-instruction 'b00 #b0111))
  17448. (define sparc.bvs.a (sparc-instruction 'a00 #b0111))
  17449. (define sparc.call (sparc-instruction 'call))
  17450. (define sparc.jmplr (sparc-instruction 'r10 #b111000 'jump))
  17451. (define sparc.jmpli (sparc-instruction 'i10 #b111000 'jump))
  17452. (define sparc.nop (sparc-instruction 'nop #b100))
  17453. (define sparc.ornr (sparc-instruction 'r10 #b000110))
  17454. (define sparc.orni (sparc-instruction 'i10 #b000110))
  17455. (define sparc.ornrcc (sparc-instruction 'r10 #b010110))
  17456. (define sparc.ornicc (sparc-instruction 'i10 #b010110))
  17457. (define sparc.andni (sparc-instruction 'i10 #b000101))
  17458. (define sparc.andnr (sparc-instruction 'r10 #b000101))
  17459. (define sparc.andnicc (sparc-instruction 'i10 #b010101))
  17460. (define sparc.andnrcc (sparc-instruction 'r10 #b010101))
  17461. (define sparc.rdy (sparc-instruction 'r10 #b101000 'rdy))
  17462. (define sparc.wryr (sparc-instruction 'r10 #b110000 'wry))
  17463. (define sparc.wryi (sparc-instruction 'i10 #b110000 'wry))
  17464. (define sparc.fb (sparc-instruction 'fb00 #b1000))
  17465. (define sparc.fb.a (sparc-instruction 'fa00 #b1000))
  17466. (define sparc.fbn (sparc-instruction 'fb00 #b0000))
  17467. (define sparc.fbn.a (sparc-instruction 'fa00 #b0000))
  17468. (define sparc.fbu (sparc-instruction 'fb00 #b0111))
  17469. (define sparc.fbu.a (sparc-instruction 'fa00 #b0111))
  17470. (define sparc.fbg (sparc-instruction 'fb00 #b0110))
  17471. (define sparc.fbg.a (sparc-instruction 'fa00 #b0110))
  17472. (define sparc.fbug (sparc-instruction 'fb00 #b0101))
  17473. (define sparc.fbug.a (sparc-instruction 'fa00 #b0101))
  17474. (define sparc.fbl (sparc-instruction 'fb00 #b0100))
  17475. (define sparc.fbl.a (sparc-instruction 'fa00 #b0100))
  17476. (define sparc.fbul (sparc-instruction 'fb00 #b0011))
  17477. (define sparc.fbul.a (sparc-instruction 'fa00 #b0011))
  17478. (define sparc.fblg (sparc-instruction 'fb00 #b0010))
  17479. (define sparc.fblg.a (sparc-instruction 'fa00 #b0010))
  17480. (define sparc.fbne (sparc-instruction 'fb00 #b0001))
  17481. (define sparc.fbne.a (sparc-instruction 'fa00 #b0001))
  17482. (define sparc.fbe (sparc-instruction 'fb00 #b1001))
  17483. (define sparc.fbe.a (sparc-instruction 'fa00 #b1001))
  17484. (define sparc.fbue (sparc-instruction 'fb00 #b1010))
  17485. (define sparc.fbue.a (sparc-instruction 'fa00 #b1010))
  17486. (define sparc.fbge (sparc-instruction 'fb00 #b1011))
  17487. (define sparc.fbge.a (sparc-instruction 'fa00 #b1011))
  17488. (define sparc.fbuge (sparc-instruction 'fb00 #b1100))
  17489. (define sparc.fbuge.a (sparc-instruction 'fa00 #b1100))
  17490. (define sparc.fble (sparc-instruction 'fb00 #b1101))
  17491. (define sparc.fble.a (sparc-instruction 'fa00 #b1101))
  17492. (define sparc.fbule (sparc-instruction 'fb00 #b1110))
  17493. (define sparc.fbule.a (sparc-instruction 'fa00 #b1110))
  17494. (define sparc.fbo (sparc-instruction 'fb00 #b1111))
  17495. (define sparc.fbo.a (sparc-instruction 'fa00 #b1111))
  17496. (define sparc.faddd (sparc-instruction 'fp #b001000010))
  17497. (define sparc.fsubd (sparc-instruction 'fp #b001000110))
  17498. (define sparc.fmuld (sparc-instruction 'fp #b001001010))
  17499. (define sparc.fdivd (sparc-instruction 'fp #b001001110))
  17500. (define sparc%fnegs (sparc-instruction 'fp #b000000101)) ; See below
  17501. (define sparc%fmovs (sparc-instruction 'fp #b000000001)) ; See below
  17502. (define sparc%fabss (sparc-instruction 'fp #b000001001)) ; See below
  17503. (define sparc%fcmpdcc (sparc-instruction 'fpcc #b001010010)) ; See below
  17504. ; Strange instructions.
  17505. (define sparc.slot (sparc-instruction 'slot))
  17506. (define sparc.slot2 (sparc-instruction 'slot2))
  17507. (define sparc.label (sparc-instruction 'label))
  17508. ; Aliases.
  17509. (define sparc.bnz sparc.bne)
  17510. (define sparc.bnz.a sparc.bne.a)
  17511. (define sparc.bz sparc.be)
  17512. (define sparc.bz.a sparc.be.a)
  17513. (define sparc.bgeu sparc.bcc)
  17514. (define sparc.bgeu.a sparc.bcc.a)
  17515. (define sparc.blu sparc.bcs)
  17516. (define sparc.blu.a sparc.bcs.a)
  17517. ; Abstractions.
  17518. (define (sparc.cmpr as r1 r2) (sparc.subrcc as r1 r2 $r.g0))
  17519. (define (sparc.cmpi as r imm) (sparc.subicc as r imm $r.g0))
  17520. (define (sparc.move as rs rd) (sparc.orr as $r.g0 rs rd))
  17521. (define (sparc.set as imm rd) (sparc.ori as $r.g0 imm rd))
  17522. (define (sparc.btsti as rs imm) (sparc.andicc as rs imm $r.g0))
  17523. (define (sparc.clr as rd) (sparc.move as $r.g0 rd))
  17524. (define (sparc.deccc as rs . rest)
  17525. (let ((k (cond ((null? rest) 1)
  17526. ((null? (cdr rest)) (car rest))
  17527. (else (asm-error "sparc.deccc: too many operands: " rest)))))
  17528. (sparc.subicc as rs k rs)))
  17529. ; Floating-point abstractions
  17530. ;
  17531. ; For fmovd, fnegd, and fabsd, we must synthesize the instruction from
  17532. ; fmovs, fnegs, and fabss -- SPARC V8 has only the latter. (SPARC V9 add
  17533. ; the former.)
  17534. (define (sparc.fmovd as rs rd)
  17535. (sparc%fmovs as rs 0 rd)
  17536. (sparc%fmovs as (+ rs 1) 0 (+ rd 1)))
  17537. (define (sparc.fnegd as rs rd)
  17538. (sparc%fnegs as rs 0 rd)
  17539. (if (not (= rs rd))
  17540. (sparc%fmovs as (+ rs 1) 0 (+ rd 1))))
  17541. (define (sparc.fabsd as rs rd)
  17542. (sparc%fabss as rs 0 rd)
  17543. (if (not (= rs rd))
  17544. (sparc%fmovs as (+ rs 1) 0 (+ rd 1))))
  17545. (define (sparc.fcmpd as rs1 rs2)
  17546. (sparc%fcmpdcc as rs1 rs2 0))
  17547. ; eof
  17548. ; Copyright 1998 Lars T Hansen.
  17549. ;
  17550. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  17551. ;
  17552. ; Asm/Sparc/gen-msi.sch -- SPARC assembler code emitters for
  17553. ; core MacScheme instructions
  17554. ;
  17555. ; 9 May 1999 / wdc
  17556. ; SETGLBL
  17557. ;
  17558. ; RS must be a hardware register.
  17559. ;
  17560. ; A global cell is a pair, where the car holds the value.
  17561. (define (emit-register->global! as rs offset)
  17562. (cond ((= rs $r.result)
  17563. (sparc.move as $r.result $r.argreg2)
  17564. (emit-const->register! as offset $r.result)
  17565. (if (write-barrier)
  17566. (sparc.jmpli as $r.millicode $m.addtrans $r.o7))
  17567. (sparc.sti as $r.argreg2 (- $tag.pair-tag) $r.result))
  17568. (else
  17569. (emit-const->register! as offset $r.result)
  17570. (sparc.sti as rs (- $tag.pair-tag) $r.result)
  17571. (if (write-barrier)
  17572. (millicode-call/1arg as $m.addtrans rs)))))
  17573. ; GLOBAL
  17574. ;
  17575. ; A global cell is a pair, where the car holds the value.
  17576. ; If (catch-undefined-globals) is true, then code will be emitted to
  17577. ; check whether the global is #!undefined when loaded. If it is,
  17578. ; an exception will be taken, with the global in question in $r.result.
  17579. (define (emit-global->register! as offset r)
  17580. (emit-load-global as offset r (catch-undefined-globals)))
  17581. ; This leaves the cell in ARGREG2. That fact is utilized by global/invoke
  17582. ; to signal an appropriate error message.
  17583. (define (emit-load-global as offset r check?)
  17584. (define (emit-undef-check! as r)
  17585. (if check?
  17586. (let ((GLOBAL-OK (new-label)))
  17587. (sparc.cmpi as r $imm.undefined)
  17588. (sparc.bne.a as GLOBAL-OK)
  17589. (sparc.slot as)
  17590. (millicode-call/0arg as $m.global-ex) ; Cell in ARGREG2.
  17591. (sparc.label as GLOBAL-OK))))
  17592. (emit-const->register! as offset $r.argreg2) ; Load cell.
  17593. (if (hardware-mapped? r)
  17594. (begin (sparc.ldi as $r.argreg2 (- $tag.pair-tag) r)
  17595. (emit-undef-check! as r))
  17596. (begin (sparc.ldi as $r.argreg2 (- $tag.pair-tag) $r.tmp0)
  17597. (emit-store-reg! as $r.tmp0 r)
  17598. (emit-undef-check! as $r.tmp0))))
  17599. ; MOVEREG
  17600. (define (emit-register->register! as from to)
  17601. (if (not (= from to))
  17602. (cond ((and (hardware-mapped? from) (hardware-mapped? to))
  17603. (sparc.move as from to))
  17604. ((hardware-mapped? from)
  17605. (emit-store-reg! as from to))
  17606. ((hardware-mapped? to)
  17607. (emit-load-reg! as from to))
  17608. (else
  17609. (emit-load-reg! as from $r.tmp0)
  17610. (emit-store-reg! as $r.tmp0 to)))))
  17611. ; ARGS=
  17612. (define (emit-args=! as n)
  17613. (if (not (unsafe-code))
  17614. (let ((L2 (new-label)))
  17615. (sparc.cmpi as $r.result (thefixnum n)) ; FIXME: limit 1023 args
  17616. (sparc.be.a as L2)
  17617. (sparc.slot as)
  17618. (millicode-call/numarg-in-reg as $m.argc-ex (thefixnum n) $r.argreg2)
  17619. (sparc.label as L2))))
  17620. ; ARGS>=
  17621. ;
  17622. ; The cases for 0 and 1 rest arguments are handled in-line; all other
  17623. ; cases, including too few, are handled in millicode (really: a C call-out).
  17624. ;
  17625. ; The fast path only applies when we don't have to mess with the last
  17626. ; register, hence the test.
  17627. (define (emit-args>=! as n)
  17628. (let ((L0 (new-label))
  17629. (L99 (new-label))
  17630. (L98 (new-label)))
  17631. (if (< n (- *lastreg* 1))
  17632. (let ((dest (regname (+ n 1))))
  17633. (sparc.cmpi as $r.result (thefixnum n)) ; n args
  17634. (if (hardware-mapped? dest)
  17635. (begin
  17636. (sparc.be.a as L99)
  17637. (sparc.set as $imm.null dest))
  17638. (begin
  17639. (sparc.set as $imm.null $r.tmp0)
  17640. (sparc.be.a as L99)
  17641. (sparc.sti as $r.tmp0 (swreg-global-offset dest) $r.globals)))
  17642. (sparc.cmpi as $r.result (thefixnum (+ n 1))) ; n+1 args
  17643. (sparc.bne.a as L98)
  17644. (sparc.nop as)
  17645. (millicode-call/numarg-in-result as $m.alloc 8)
  17646. (let ((src1 (force-hwreg! as dest $r.tmp1)))
  17647. (sparc.set as $imm.null $r.tmp0)
  17648. (sparc.sti as src1 0 $r.result)
  17649. (sparc.sti as $r.tmp0 4 $r.result)
  17650. (sparc.addi as $r.result $tag.pair-tag $r.result)
  17651. (sparc.b as L99)
  17652. (if (hardware-mapped? dest)
  17653. (sparc.move as $r.result dest)
  17654. (sparc.sti as $r.result (swreg-global-offset dest)
  17655. $r.globals)))))
  17656. ; General case
  17657. (sparc.label as L98)
  17658. (sparc.move as $r.reg0 $r.argreg3) ; FIXME in Sparc/mcode.s
  17659. (millicode-call/numarg-in-reg as $m.varargs (thefixnum n) $r.argreg2)
  17660. (sparc.label as L99)))
  17661. ; INVOKE
  17662. ; SETRTN/INVOKE
  17663. ;
  17664. ; Bummed. Can still do better when the procedure to call is in a general
  17665. ; register (avoids the redundant move to RESULT preceding INVOKE).
  17666. ;
  17667. ; Note we must set up the argument count even in unsafe mode, because we
  17668. ; may be calling code that was not compiled unsafe.
  17669. (define (emit-invoke as n setrtn? mc-exception)
  17670. (let ((START (new-label))
  17671. (TIMER-OK (new-label))
  17672. (PROC-OK (new-label)))
  17673. (cond ((not (unsafe-code))
  17674. (sparc.label as START)
  17675. (sparc.subicc as $r.timer 1 $r.timer)
  17676. (sparc.bne as TIMER-OK)
  17677. (sparc.andi as $r.result $tag.tagmask $r.tmp0)
  17678. (millicode-call/ret as $m.timer-exception START)
  17679. (sparc.label as TIMER-OK)
  17680. (sparc.cmpi as $r.tmp0 $tag.procedure-tag)
  17681. (sparc.be.a as PROC-OK)
  17682. (sparc.ldi as $r.result $p.codevector $r.tmp0)
  17683. (millicode-call/ret as mc-exception START)
  17684. (sparc.label as PROC-OK))
  17685. (else
  17686. (sparc.label as START)
  17687. (sparc.subicc as $r.timer 1 $r.timer)
  17688. (sparc.bne.a as TIMER-OK)
  17689. (sparc.ldi as $r.result $p.codevector $r.tmp0)
  17690. (millicode-call/ret as $m.timer-exception START)
  17691. (sparc.label as TIMER-OK)))
  17692. (sparc.move as $r.result $r.reg0)
  17693. ;; FIXME: limit 1023 args
  17694. (cond (setrtn?
  17695. (sparc.set as (thefixnum n) $r.result)
  17696. (sparc.jmpli as $r.tmp0 $p.codeoffset $r.o7)
  17697. (sparc.sti as $r.o7 4 $r.stkp))
  17698. (else
  17699. (sparc.jmpli as $r.tmp0 $p.codeoffset $r.g0)
  17700. (sparc.set as (thefixnum n) $r.result)))))
  17701. ; SAVE -- for new compiler
  17702. ;
  17703. ; Create stack frame. To avoid confusing the garbage collector, the
  17704. ; slots must be initialized to something definite unless they will
  17705. ; immediately be initialized by a MacScheme machine store instruction.
  17706. ; The creation is done by emit-save0!, and the initialization is done
  17707. ; by emit-save1!.
  17708. (define (emit-save0! as n)
  17709. (let* ((L1 (new-label))
  17710. (L0 (new-label))
  17711. (framesize (+ 8 (* (+ n 1) 4)))
  17712. (realsize (roundup8 (+ framesize 4))))
  17713. (sparc.label as L0)
  17714. (sparc.subi as $r.stkp realsize $r.stkp)
  17715. (sparc.cmpr as $r.stklim $r.stkp)
  17716. (sparc.ble.a as L1)
  17717. (sparc.set as framesize $r.tmp0)
  17718. (sparc.addi as $r.stkp realsize $r.stkp)
  17719. (millicode-call/ret as $m.stkoflow L0)
  17720. (sparc.label as L1)
  17721. ; initialize size and return fields of stack frame
  17722. (sparc.sti as $r.tmp0 0 $r.stkp)
  17723. (sparc.sti as $r.g0 4 $r.stkp)))
  17724. ; Given a vector v of booleans, initializes slot i of the stack frame
  17725. ; if and only if (vector-ref v i).
  17726. (define (emit-save1! as v)
  17727. (let ((n (vector-length v)))
  17728. (let loop ((i 0) (offset 12))
  17729. (cond ((= i n)
  17730. #t)
  17731. ((vector-ref v i)
  17732. (sparc.sti as $r.g0 offset $r.stkp)
  17733. (loop (+ i 1) (+ offset 4)))
  17734. (else
  17735. (loop (+ i 1) (+ offset 4)))))))
  17736. ; RESTORE
  17737. ;
  17738. ; Restore registers from stack frame
  17739. ; FIXME: Use ldd/std here; see comments for emit-save!, above.
  17740. ; We pop only actual registers.
  17741. (define (emit-restore! as n)
  17742. (let ((n (min n 31)))
  17743. (do ((i 0 (+ i 1))
  17744. (offset 12 (+ offset 4)))
  17745. ((> i n))
  17746. (let ((r (regname i)))
  17747. (if (hardware-mapped? r)
  17748. (sparc.ldi as $r.stkp offset r)
  17749. (begin (sparc.ldi as $r.stkp offset $r.tmp0)
  17750. (emit-store-reg! as $r.tmp0 r)))))))
  17751. ; POP -- for new compiler
  17752. ;
  17753. ; Pop frame.
  17754. ; If returning?, then emit the return as well and put the pop
  17755. ; in its delay slot.
  17756. (define (emit-pop! as n returning?)
  17757. (let* ((framesize (+ 8 (* (+ n 1) 4)))
  17758. (realsize (roundup8 (+ framesize 4))))
  17759. (if returning?
  17760. (begin (sparc.ldi as $r.stkp (+ realsize 4) $r.o7)
  17761. (sparc.jmpli as $r.o7 8 $r.g0)
  17762. (sparc.addi as $r.stkp realsize $r.stkp))
  17763. (sparc.addi as $r.stkp realsize $r.stkp))))
  17764. ; SETRTN
  17765. ;
  17766. ; Change the return address in the stack frame.
  17767. (define (emit-setrtn! as label)
  17768. (emit-return-address! as label)
  17769. (sparc.sti as $r.o7 4 $r.stkp))
  17770. ; APPLY
  17771. ;
  17772. ; `apply' falls into millicode.
  17773. ;
  17774. ; The timer check is performed here because it is not very easy for the
  17775. ; millicode to do this.
  17776. (define (emit-apply! as r1 r2)
  17777. (let ((L0 (new-label)))
  17778. (check-timer0 as)
  17779. (sparc.label as L0)
  17780. (emit-move2hwreg! as r1 $r.argreg2)
  17781. (emit-move2hwreg! as r2 $r.argreg3)
  17782. (millicode-call/0arg as $m.apply)))
  17783. ; LOAD
  17784. (define (emit-load! as slot dest-reg)
  17785. (if (hardware-mapped? dest-reg)
  17786. (sparc.ldi as $r.stkp (+ 12 (* slot 4)) dest-reg)
  17787. (begin (sparc.ldi as $r.stkp (+ 12 (* slot 4)) $r.tmp0)
  17788. (emit-store-reg! as $r.tmp0 dest-reg))))
  17789. ; STORE
  17790. (define (emit-store! as k n)
  17791. (if (hardware-mapped? k)
  17792. (sparc.sti as k (+ 12 (* n 4)) $r.stkp)
  17793. (begin (emit-load-reg! as k $r.tmp0)
  17794. (sparc.sti as $r.tmp0 (+ 12 (* n 4)) $r.stkp))))
  17795. ; LEXICAL
  17796. (define (emit-lexical! as m n)
  17797. (let ((base (emit-follow-chain! as m)))
  17798. (sparc.ldi as base (- (procedure-slot-offset n) $tag.procedure-tag)
  17799. $r.result)))
  17800. ; SETLEX
  17801. ; FIXME: should allow an in-line barrier
  17802. (define (emit-setlex! as m n)
  17803. (let ((base (emit-follow-chain! as m)))
  17804. (sparc.sti as $r.result (- (procedure-slot-offset n) $tag.procedure-tag)
  17805. base)
  17806. (if (write-barrier)
  17807. (begin
  17808. (sparc.move as $r.result $r.argreg2)
  17809. (millicode-call/1arg-in-result as $m.addtrans base)))))
  17810. ; Follow static links.
  17811. ;
  17812. ; By using and leaving the result in ARGREG3 rather than in RESULT,
  17813. ; we save a temporary register.
  17814. (define (emit-follow-chain! as m)
  17815. (let loop ((q m))
  17816. (cond ((not (zero? q))
  17817. (sparc.ldi as
  17818. (if (= q m) $r.reg0 $r.argreg3)
  17819. $p.linkoffset
  17820. $r.argreg3)
  17821. (loop (- q 1)))
  17822. ((zero? m)
  17823. $r.reg0)
  17824. (else
  17825. $r.argreg3))))
  17826. ; RETURN
  17827. (define (emit-return! as)
  17828. (sparc.ldi as $r.stkp 4 $r.o7)
  17829. (sparc.jmpli as $r.o7 8 $r.g0)
  17830. (sparc.nop as))
  17831. ; RETURN-REG k
  17832. (define (emit-return-reg! as r)
  17833. (sparc.ldi as $r.stkp 4 $r.o7)
  17834. (sparc.jmpli as $r.o7 8 $r.g0)
  17835. (sparc.move as r $r.result))
  17836. ; RETURN-CONST k
  17837. ;
  17838. ; The constant c must be synthesizable in a single instruction.
  17839. (define (emit-return-const! as c)
  17840. (sparc.ldi as $r.stkp 4 $r.o7)
  17841. (sparc.jmpli as $r.o7 8 $r.g0)
  17842. (emit-constant->register as c $r.result))
  17843. ; MVRTN
  17844. (define (emit-mvrtn! as)
  17845. (asm-error "multiple-value return has not been implemented (yet)."))
  17846. ; LEXES
  17847. (define (emit-lexes! as n-slots)
  17848. (emit-alloc-proc! as n-slots)
  17849. (sparc.ldi as $r.reg0 $p.codevector $r.tmp0)
  17850. (sparc.ldi as $r.reg0 $p.constvector $r.tmp1)
  17851. (sparc.sti as $r.tmp0 $p.codevector $r.result)
  17852. (sparc.sti as $r.tmp1 $p.constvector $r.result)
  17853. (emit-init-proc-slots! as n-slots))
  17854. ; LAMBDA
  17855. (define (emit-lambda! as code-offs0 const-offs0 n-slots)
  17856. (let* ((code-offs (+ 4 (- (* 4 code-offs0) $tag.vector-tag)))
  17857. (const-offs (+ 4 (- (* 4 const-offs0) $tag.vector-tag)))
  17858. (fits? (asm:fits? const-offs 13)))
  17859. (emit-alloc-proc! as n-slots)
  17860. (if fits?
  17861. (begin (sparc.ldi as $r.reg0 $p.constvector $r.tmp0)
  17862. (sparc.ldi as $r.tmp0 code-offs $r.tmp1))
  17863. (emit-const->register! as code-offs0 $r.tmp1))
  17864. (sparc.sti as $r.tmp1 $p.codevector $r.result)
  17865. (if fits?
  17866. (begin (sparc.ldi as $r.reg0 $p.constvector $r.tmp0)
  17867. (sparc.ldi as $r.tmp0 const-offs $r.tmp1))
  17868. (emit-const->register! as const-offs0 $r.tmp1))
  17869. (sparc.sti as $r.tmp1 $p.constvector $r.result)
  17870. (emit-init-proc-slots! as n-slots)))
  17871. ; Allocate procedure with room for n register slots; return tagged pointer.
  17872. (define emit-alloc-proc!
  17873. (let ((two^12 (expt 2 12)))
  17874. (lambda (as n)
  17875. (millicode-call/numarg-in-result as $m.alloc (* (+ n 4) 4))
  17876. (let ((header (+ (* (* (+ n 3) 4) 256) $imm.procedure-header)))
  17877. (emit-immediate->register! as header $r.tmp0)
  17878. (sparc.sti as $r.tmp0 0 $r.result)
  17879. (sparc.addi as $r.result $tag.procedure-tag $r.result)))))
  17880. ; Initialize data slots in procedure from current registers as specified for
  17881. ; `lamba' and `lexes'. If there are more data slots than registers, then
  17882. ; we must generate code to cdr down the list in the last register to obtain
  17883. ; the rest of the data. The list is expected to have at least the minimal
  17884. ; length.
  17885. ;
  17886. ; The tagged pointer to the procedure is in $r.result.
  17887. (define (emit-init-proc-slots! as n)
  17888. (define (save-registers lo hi offset)
  17889. (do ((lo lo (+ lo 1))
  17890. (offset offset (+ offset 4)))
  17891. ((> lo hi))
  17892. (let ((r (force-hwreg! as (regname lo) $r.tmp0)))
  17893. (sparc.sti as r offset $r.result))))
  17894. (define (save-list lo hi offset)
  17895. (emit-load-reg! as $r.reg31 $r.tmp0)
  17896. (do ((lo lo (+ lo 1))
  17897. (offset offset (+ offset 4)))
  17898. ((> lo hi))
  17899. (sparc.ldi as $r.tmp0 (- $tag.pair-tag) $r.tmp1)
  17900. (sparc.sti as $r.tmp1 offset $r.result)
  17901. (if (< lo hi)
  17902. (begin
  17903. (sparc.ldi as $r.tmp0 (+ (- $tag.pair-tag) 4) $r.tmp0)))))
  17904. (cond ((< n *lastreg*)
  17905. (save-registers 0 n $p.reg0))
  17906. (else
  17907. (save-registers 0 (- *lastreg* 1) $p.reg0)
  17908. (save-list *lastreg* n (+ $p.reg0 (* *lastreg* 4))))))
  17909. ; BRANCH
  17910. (define (emit-branch! as check-timer? label)
  17911. (if check-timer?
  17912. (check-timer as label label)
  17913. (begin (sparc.b as label)
  17914. (sparc.slot as))))
  17915. ; BRANCHF
  17916. (define (emit-branchf! as label)
  17917. (emit-branchfreg! as $r.result label))
  17918. ; BRANCHFREG -- introduced by peephole optimization.
  17919. (define (emit-branchfreg! as hwreg label)
  17920. (sparc.cmpi as hwreg $imm.false)
  17921. (sparc.be.a as label)
  17922. (sparc.slot as))
  17923. ; BRANCH-WITH-SETRTN -- introduced by peephole optimization
  17924. (define (emit-branch-with-setrtn! as label)
  17925. (check-timer0 as)
  17926. (sparc.call as label)
  17927. (sparc.sti as $r.o7 4 $r.stkp))
  17928. ; JUMP
  17929. ;
  17930. ; Given the finalization order (outer is finalized before inner is assembled)
  17931. ; the label value will always be available when a jump is assembled. The
  17932. ; only exception is when m = 0, but does this ever happen? This code handles
  17933. ; the case anyway.
  17934. (define (emit-jump! as m label)
  17935. (let* ((r (emit-follow-chain! as m))
  17936. (labelv (label-value as label))
  17937. (v (if (number? labelv)
  17938. (+ labelv $p.codeoffset)
  17939. (list '+ label $p.codeoffset))))
  17940. (sparc.ldi as r $p.codevector $r.tmp0)
  17941. (if (and (number? v) (immediate-literal? v))
  17942. (sparc.jmpli as $r.tmp0 v $r.g0)
  17943. (begin (emit-immediate->register! as v $r.tmp1)
  17944. (sparc.jmplr as $r.tmp0 $r.tmp1 $r.g0)))
  17945. (sparc.move as r $r.reg0)))
  17946. ; .SINGLESTEP
  17947. ;
  17948. ; Single step: jump to millicode; pass index of documentation string in
  17949. ; %TMP0. Some instructions execute when reg0 is not a valid pointer to
  17950. ; the current procedure (because this is just after returning); in this
  17951. ; case we restore reg0 from the stack location given by 'funkyloc'.
  17952. (define (emit-singlestep-instr! as funky? funkyloc cvlabel)
  17953. (if funky?
  17954. (sparc.ldi as $r.stkp (+ (thefixnum funkyloc) 12) $r.reg0))
  17955. (millicode-call/numarg-in-reg as $m.singlestep
  17956. (thefixnum cvlabel)
  17957. $r.argreg2))
  17958. ; Emit the effective address of a label-8 into %o7.
  17959. ;
  17960. ; There are multiple ways to do this. If the call causes an expensive
  17961. ; bubble in the pipeline it is probably much less expensive to grub
  17962. ; the code vector address out of the procedure in REG0 and calculate it
  17963. ; that way. FIXME: We need to benchmark these options.
  17964. ;
  17965. ; In general the point is moot as the common-case sequence
  17966. ; setrtn L1
  17967. ; invoke n
  17968. ; L1:
  17969. ; should be peephole-optimized into the obvious fast code.
  17970. (define (emit-return-address! as label)
  17971. (let* ((loc (here as))
  17972. (lloc (label-value as label)))
  17973. (define (emit-short val)
  17974. (sparc.call as (+ loc 8))
  17975. (sparc.addi as $r.o7 val $r.o7))
  17976. (define (emit-long val)
  17977. ; Don't use sparc.set: we need to know that two instructions get
  17978. ; generated.
  17979. (sparc.sethi as `(hi ,val) $r.tmp0)
  17980. (sparc.ori as $r.tmp0 `(lo ,val) $r.tmp0)
  17981. (sparc.call as (+ loc 16))
  17982. (sparc.addr as $r.o7 $r.tmp0 $r.o7))
  17983. (cond (lloc
  17984. (let ((target-rel-addr (- lloc loc 8)))
  17985. (if (immediate-literal? target-rel-addr)
  17986. (emit-short target-rel-addr)
  17987. (emit-long (- target-rel-addr 8)))))
  17988. ((short-effective-addresses)
  17989. (emit-short `(- ,label ,loc 8)))
  17990. (else
  17991. (emit-long `(- ,label ,loc 16))))))
  17992. ; eof
  17993. ; Copyright 1998 Lars T Hansen.
  17994. ;
  17995. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  17996. ;
  17997. ; 22 April 1999 / wdc
  17998. ;
  17999. ; SPARC code generation macros for primitives, part 1:
  18000. ; primitives defined in Compiler/sparc.imp.sch.
  18001. ; These extend Asm/Common/pass5p1.sch.
  18002. (define (operand5 instruction)
  18003. (car (cddddr (cdr instruction))))
  18004. (define (operand6 instruction)
  18005. (cadr (cddddr (cdr instruction))))
  18006. (define (operand7 instruction)
  18007. (caddr (cddddr (cdr instruction))))
  18008. ; Primop emitters.
  18009. (define (emit-primop.1arg! as op)
  18010. ((find-primop op) as))
  18011. (define (emit-primop.2arg! as op r)
  18012. ((find-primop op) as r))
  18013. (define (emit-primop.3arg! as a1 a2 a3)
  18014. ((find-primop a1) as a2 a3))
  18015. (define (emit-primop.4arg! as a1 a2 a3 a4)
  18016. ((find-primop a1) as a2 a3 a4))
  18017. (define (emit-primop.5arg! as a1 a2 a3 a4 a5)
  18018. ((find-primop a1) as a2 a3 a4 a5))
  18019. (define (emit-primop.6arg! as a1 a2 a3 a4 a5 a6)
  18020. ((find-primop a1) as a2 a3 a4 a5 a6))
  18021. (define (emit-primop.7arg! as a1 a2 a3 a4 a5 a6 a7)
  18022. ((find-primop a1) as a2 a3 a4 a5 a6 a7))
  18023. ; Hash table of primops
  18024. (define primop-vector (make-vector 256 '()))
  18025. (define (define-primop name proc)
  18026. (let ((h (logand (symbol-hash name) 255)))
  18027. (vector-set! primop-vector h (cons (cons name proc)
  18028. (vector-ref primop-vector h)))
  18029. name))
  18030. (define (find-primop name)
  18031. (let ((h (logand (symbol-hash name) 255)))
  18032. (cdr (assq name (vector-ref primop-vector h)))))
  18033. (define (for-each-primop proc)
  18034. (do ((i 0 (+ i 1)))
  18035. ((= i (vector-length primop-vector)))
  18036. (for-each (lambda (p)
  18037. (proc (cdr p)))
  18038. (vector-ref primop-vector i))))
  18039. ; Primops
  18040. (define-primop 'unspecified
  18041. (lambda (as)
  18042. (emit-immediate->register! as $imm.unspecified $r.result)))
  18043. (define-primop 'undefined
  18044. (lambda (as)
  18045. (emit-immediate->register! as $imm.undefined $r.result)))
  18046. (define-primop 'eof-object
  18047. (lambda (as)
  18048. (emit-immediate->register! as $imm.eof $r.result)))
  18049. (define-primop 'enable-interrupts
  18050. (lambda (as)
  18051. (millicode-call/0arg as $m.enable-interrupts)))
  18052. (define-primop 'disable-interrupts
  18053. (lambda (as)
  18054. (millicode-call/0arg as $m.disable-interrupts)))
  18055. (define-primop 'gc-counter
  18056. (lambda (as)
  18057. (sparc.ldi as $r.globals $g.gccnt $r.result)))
  18058. (define-primop 'zero?
  18059. (lambda (as)
  18060. (emit-cmp-primop! as sparc.be.a $m.zerop $r.g0)))
  18061. (define-primop '=
  18062. (lambda (as r)
  18063. (emit-cmp-primop! as sparc.be.a $m.numeq r)))
  18064. (define-primop '<
  18065. (lambda (as r)
  18066. (emit-cmp-primop! as sparc.bl.a $m.numlt r)))
  18067. (define-primop '<=
  18068. (lambda (as r)
  18069. (emit-cmp-primop! as sparc.ble.a $m.numle r)))
  18070. (define-primop '>
  18071. (lambda (as r)
  18072. (emit-cmp-primop! as sparc.bg.a $m.numgt r)))
  18073. (define-primop '>=
  18074. (lambda (as r)
  18075. (emit-cmp-primop! as sparc.bge.a $m.numge r)))
  18076. (define-primop 'complex?
  18077. (lambda (as)
  18078. (millicode-call/0arg as $m.complexp)))
  18079. (define-primop 'real?
  18080. (lambda (as)
  18081. (millicode-call/0arg as $m.realp)))
  18082. (define-primop 'rational?
  18083. (lambda (as)
  18084. (millicode-call/0arg as $m.rationalp)))
  18085. (define-primop 'integer?
  18086. (lambda (as)
  18087. (millicode-call/0arg as $m.integerp)))
  18088. (define-primop 'exact?
  18089. (lambda (as)
  18090. (millicode-call/0arg as $m.exactp)))
  18091. (define-primop 'inexact?
  18092. (lambda (as)
  18093. (millicode-call/0arg as $m.inexactp)))
  18094. (define-primop 'fixnum?
  18095. (lambda (as)
  18096. (sparc.btsti as $r.result 3)
  18097. (emit-set-boolean! as)))
  18098. (define-primop '+
  18099. (lambda (as r)
  18100. (emit-primop.4arg! as 'internal:+ $r.result r $r.result)))
  18101. (define-primop '-
  18102. (lambda (as r)
  18103. (emit-primop.4arg! as 'internal:- $r.result r $r.result)))
  18104. (define-primop '*
  18105. (lambda (as rs2)
  18106. (emit-multiply-code as rs2 #f)))
  18107. (define (emit-multiply-code as rs2 fixnum-arithmetic?)
  18108. (if (and (unsafe-code) fixnum-arithmetic?)
  18109. (begin
  18110. (sparc.srai as $r.result 2 $r.tmp0)
  18111. (sparc.smulr as $r.tmp0 rs2 $r.result))
  18112. (let ((rs2 (force-hwreg! as rs2 $r.argreg2))
  18113. (Lstart (new-label))
  18114. (Ltagok (new-label))
  18115. (Loflo (new-label))
  18116. (Ldone (new-label)))
  18117. (sparc.label as Lstart)
  18118. (sparc.orr as $r.result rs2 $r.tmp0)
  18119. (sparc.btsti as $r.tmp0 3)
  18120. (sparc.be.a as Ltagok)
  18121. (sparc.srai as $r.result 2 $r.tmp0)
  18122. (sparc.label as Loflo)
  18123. (if (not (= rs2 $r.argreg2)) (sparc.move as rs2 $r.argreg2))
  18124. (if (not fixnum-arithmetic?)
  18125. (begin
  18126. (millicode-call/ret as $m.multiply Ldone))
  18127. (begin
  18128. (sparc.set as (thefixnum $ex.fx*) $r.tmp0)
  18129. (millicode-call/ret as $m.exception Lstart)))
  18130. (sparc.label as Ltagok)
  18131. (sparc.smulr as $r.tmp0 rs2 $r.tmp0)
  18132. (sparc.rdy as $r.tmp1)
  18133. (sparc.srai as $r.tmp0 31 $r.tmp2)
  18134. (sparc.cmpr as $r.tmp1 $r.tmp2)
  18135. (sparc.bne.a as Loflo)
  18136. (sparc.slot as)
  18137. (sparc.move as $r.tmp0 $r.result)
  18138. (sparc.label as Ldone))))
  18139. (define-primop '/
  18140. (lambda (as r)
  18141. (millicode-call/1arg as $m.divide r)))
  18142. (define-primop 'quotient
  18143. (lambda (as r)
  18144. (millicode-call/1arg as $m.quotient r)))
  18145. (define-primop 'remainder
  18146. (lambda (as r)
  18147. (millicode-call/1arg as $m.remainder r)))
  18148. (define-primop '--
  18149. (lambda (as)
  18150. (emit-negate as $r.result $r.result)))
  18151. (define-primop 'round
  18152. (lambda (as)
  18153. (millicode-call/0arg as $m.round)))
  18154. (define-primop 'truncate
  18155. (lambda (as)
  18156. (millicode-call/0arg as $m.truncate)))
  18157. (define-primop 'lognot
  18158. (lambda (as)
  18159. (if (not (unsafe-code))
  18160. (emit-assert-fixnum! as $r.result $ex.lognot))
  18161. (sparc.ornr as $r.g0 $r.result $r.result) ; argument order matters
  18162. (sparc.xori as $r.result 3 $r.result)))
  18163. (define-primop 'logand
  18164. (lambda (as x)
  18165. (logical-op as $r.result x $r.result sparc.andr $ex.logand)))
  18166. (define-primop 'logior
  18167. (lambda (as x)
  18168. (logical-op as $r.result x $r.result sparc.orr $ex.logior)))
  18169. (define-primop 'logxor
  18170. (lambda (as x)
  18171. (logical-op as $r.result x $r.result sparc.xorr $ex.logxor)))
  18172. ; Fixnum shifts.
  18173. ;
  18174. ; Only positive shifts are meaningful.
  18175. ; FIXME: These are incompatible with MacScheme and MIT Scheme.
  18176. ; FIXME: need to return to start of sequence after fault.
  18177. (define-primop 'lsh
  18178. (lambda (as x)
  18179. (emit-shift-operation as $ex.lsh $r.result x $r.result)))
  18180. (define-primop 'rshl
  18181. (lambda (as x)
  18182. (emit-shift-operation as $ex.rshl $r.result x $r.result)))
  18183. (define-primop 'rsha
  18184. (lambda (as x)
  18185. (emit-shift-operation as $ex.rsha $r.result x $r.result)))
  18186. ; fixnums only.
  18187. ; FIXME: for symmetry with shifts there should be rotl and rotr (?)
  18188. ; or perhaps rot should only ever rotate one way.
  18189. ; FIXME: implement.
  18190. (define-primop 'rot
  18191. (lambda (as x)
  18192. (asm-error "Sparcasm: ROT primop is not implemented.")))
  18193. (define-primop 'null?
  18194. (lambda (as)
  18195. (sparc.cmpi as $r.result $imm.null)
  18196. (emit-set-boolean! as)))
  18197. (define-primop 'pair?
  18198. (lambda (as)
  18199. (emit-single-tagcheck->bool! as $tag.pair-tag)))
  18200. (define-primop 'eof-object?
  18201. (lambda (as)
  18202. (sparc.cmpi as $r.result $imm.eof)
  18203. (emit-set-boolean! as)))
  18204. ; Tests the specific representation, not 'flonum or compnum with 0i'.
  18205. (define-primop 'flonum?
  18206. (lambda (as)
  18207. (emit-double-tagcheck->bool! as $tag.bytevector-tag
  18208. (+ $imm.bytevector-header
  18209. $tag.flonum-typetag))))
  18210. (define-primop 'compnum?
  18211. (lambda (as)
  18212. (emit-double-tagcheck->bool! as $tag.bytevector-tag
  18213. (+ $imm.bytevector-header
  18214. $tag.compnum-typetag))))
  18215. (define-primop 'symbol?
  18216. (lambda (as)
  18217. (emit-double-tagcheck->bool! as $tag.vector-tag
  18218. (+ $imm.vector-header
  18219. $tag.symbol-typetag))))
  18220. (define-primop 'port?
  18221. (lambda (as)
  18222. (emit-double-tagcheck->bool! as $tag.vector-tag
  18223. (+ $imm.vector-header
  18224. $tag.port-typetag))))
  18225. (define-primop 'structure?
  18226. (lambda (as)
  18227. (emit-double-tagcheck->bool! as $tag.vector-tag
  18228. (+ $imm.vector-header
  18229. $tag.structure-typetag))))
  18230. (define-primop 'char?
  18231. (lambda (as)
  18232. (sparc.andi as $r.result #xFF $r.tmp0)
  18233. (sparc.cmpi as $r.tmp0 $imm.character)
  18234. (emit-set-boolean! as)))
  18235. (define-primop 'string?
  18236. (lambda (as)
  18237. (emit-double-tagcheck->bool! as
  18238. $tag.bytevector-tag
  18239. (+ $imm.bytevector-header
  18240. $tag.string-typetag))))
  18241. (define-primop 'bytevector?
  18242. (lambda (as)
  18243. (emit-double-tagcheck->bool! as
  18244. $tag.bytevector-tag
  18245. (+ $imm.bytevector-header
  18246. $tag.bytevector-typetag))))
  18247. (define-primop 'bytevector-like?
  18248. (lambda (as)
  18249. (emit-single-tagcheck->bool! as $tag.bytevector-tag)))
  18250. (define-primop 'vector?
  18251. (lambda (as)
  18252. (emit-double-tagcheck->bool! as
  18253. $tag.vector-tag
  18254. (+ $imm.vector-header
  18255. $tag.vector-typetag))))
  18256. (define-primop 'vector-like?
  18257. (lambda (as)
  18258. (emit-single-tagcheck->bool! as $tag.vector-tag)))
  18259. (define-primop 'procedure?
  18260. (lambda (as)
  18261. (emit-single-tagcheck->bool! as $tag.procedure-tag)))
  18262. (define-primop 'cons
  18263. (lambda (as r)
  18264. (emit-primop.4arg! as 'internal:cons $r.result r $r.result)))
  18265. (define-primop 'car
  18266. (lambda (as)
  18267. (emit-primop.3arg! as 'internal:car $r.result $r.result)))
  18268. (define-primop 'cdr
  18269. (lambda (as)
  18270. (emit-primop.3arg! as 'internal:cdr $r.result $r.result)))
  18271. (define-primop 'car:pair
  18272. (lambda (as)
  18273. (sparc.ldi as $r.result (- $tag.pair-tag) $r.result)))
  18274. (define-primop 'cdr:pair
  18275. (lambda (as)
  18276. (sparc.ldi as $r.result (- 4 $tag.pair-tag) $r.result)))
  18277. (define-primop 'set-car!
  18278. (lambda (as x)
  18279. (if (not (unsafe-code))
  18280. (emit-single-tagcheck-assert! as $tag.pair-tag $ex.car #f))
  18281. (emit-setcar/setcdr! as $r.result x 0)))
  18282. (define-primop 'set-cdr!
  18283. (lambda (as x)
  18284. (if (not (unsafe-code))
  18285. (emit-single-tagcheck-assert! as $tag.pair-tag $ex.cdr #f))
  18286. (emit-setcar/setcdr! as $r.result x 4)))
  18287. ; Cells are internal data structures, represented using pairs.
  18288. ; No error checking is done on cell references.
  18289. (define-primop 'make-cell
  18290. (lambda (as)
  18291. (emit-primop.4arg! as 'internal:cons $r.result $r.g0 $r.result)))
  18292. (define-primop 'cell-ref
  18293. (lambda (as)
  18294. (emit-primop.3arg! as 'internal:cell-ref $r.result $r.result)))
  18295. (define-primop 'cell-set!
  18296. (lambda (as r)
  18297. (emit-setcar/setcdr! as $r.result r 0)))
  18298. (define-primop 'syscall
  18299. (lambda (as)
  18300. (millicode-call/0arg as $m.syscall)))
  18301. (define-primop 'break
  18302. (lambda (as)
  18303. (millicode-call/0arg as $m.break)))
  18304. (define-primop 'creg
  18305. (lambda (as)
  18306. (millicode-call/0arg as $m.creg)))
  18307. (define-primop 'creg-set!
  18308. (lambda (as)
  18309. (millicode-call/0arg as $m.creg-set!)))
  18310. (define-primop 'typetag
  18311. (lambda (as)
  18312. (millicode-call/0arg as $m.typetag)))
  18313. (define-primop 'typetag-set!
  18314. (lambda (as r)
  18315. (millicode-call/1arg as $m.typetag-set r)))
  18316. (define-primop 'exact->inexact
  18317. (lambda (as)
  18318. (millicode-call/0arg as $m.exact->inexact)))
  18319. (define-primop 'inexact->exact
  18320. (lambda (as)
  18321. (millicode-call/0arg as $m.inexact->exact)))
  18322. (define-primop 'real-part
  18323. (lambda (as)
  18324. (millicode-call/0arg as $m.real-part)))
  18325. (define-primop 'imag-part
  18326. (lambda (as)
  18327. (millicode-call/0arg as $m.imag-part)))
  18328. (define-primop 'char->integer
  18329. (lambda (as)
  18330. (if (not (unsafe-code))
  18331. (emit-assert-char! as $ex.char2int #f))
  18332. (sparc.srli as $r.result 14 $r.result)))
  18333. (define-primop 'integer->char
  18334. (lambda (as)
  18335. (if (not (unsafe-code))
  18336. (emit-assert-fixnum! as $r.result $ex.int2char))
  18337. (sparc.andi as $r.result #x3FF $r.result)
  18338. (sparc.slli as $r.result 14 $r.result)
  18339. (sparc.ori as $r.result $imm.character $r.result)))
  18340. (define-primop 'not
  18341. (lambda (as)
  18342. (sparc.cmpi as $r.result $imm.false)
  18343. (emit-set-boolean! as)))
  18344. (define-primop 'eq?
  18345. (lambda (as x)
  18346. (emit-primop.4arg! as 'internal:eq? $r.result x $r.result)))
  18347. (define-primop 'eqv?
  18348. (lambda (as x)
  18349. (let ((tmp (force-hwreg! as x $r.tmp0))
  18350. (L1 (new-label)))
  18351. (sparc.cmpr as $r.result tmp)
  18352. (sparc.be.a as L1)
  18353. (sparc.set as $imm.true $r.result)
  18354. (millicode-call/1arg as $m.eqv tmp)
  18355. (sparc.label as L1))))
  18356. (define-primop 'make-bytevector
  18357. (lambda (as)
  18358. (if (not (unsafe-code))
  18359. (emit-assert-positive-fixnum! as $r.result $ex.mkbvl))
  18360. (emit-allocate-bytevector as
  18361. (+ $imm.bytevector-header
  18362. $tag.bytevector-typetag)
  18363. #f)
  18364. (sparc.addi as $r.result $tag.bytevector-tag $r.result)))
  18365. (define-primop 'bytevector-fill!
  18366. (lambda (as rs2)
  18367. (let* ((fault (emit-double-tagcheck-assert! as
  18368. $tag.bytevector-tag
  18369. (+ $imm.bytevector-header
  18370. $tag.bytevector-typetag)
  18371. $ex.bvfill
  18372. rs2))
  18373. (rs2 (force-hwreg! as rs2 $r.argreg2)))
  18374. (sparc.btsti as rs2 3)
  18375. (sparc.bne as fault)
  18376. (sparc.srai as rs2 2 $r.tmp2)
  18377. (sparc.ldi as $r.result (- $tag.bytevector-tag) $r.tmp0)
  18378. (sparc.addi as $r.result (- 4 $tag.bytevector-tag) $r.tmp1)
  18379. (sparc.srai as $r.tmp0 8 $r.tmp0)
  18380. (emit-bytevector-fill as $r.tmp0 $r.tmp1 $r.tmp2))))
  18381. (define-primop 'bytevector-length
  18382. (lambda (as)
  18383. (emit-get-length! as
  18384. $tag.bytevector-tag
  18385. (+ $imm.bytevector-header $tag.bytevector-typetag)
  18386. $ex.bvlen
  18387. $r.result
  18388. $r.result)))
  18389. (define-primop 'bytevector-like-length
  18390. (lambda (as)
  18391. (emit-get-length! as
  18392. $tag.bytevector-tag
  18393. #f
  18394. $ex.bvllen
  18395. $r.result
  18396. $r.result)))
  18397. (define-primop 'bytevector-ref
  18398. (lambda (as r)
  18399. (let ((fault (if (not (unsafe-code))
  18400. (emit-double-tagcheck-assert!
  18401. as
  18402. $tag.bytevector-tag
  18403. (+ $imm.bytevector-header $tag.bytevector-typetag)
  18404. $ex.bvref
  18405. r)
  18406. #f)))
  18407. (emit-bytevector-like-ref! as $r.result r $r.result fault #f #t))))
  18408. (define-primop 'bytevector-like-ref
  18409. (lambda (as r)
  18410. (let ((fault (if (not (unsafe-code))
  18411. (emit-single-tagcheck-assert! as
  18412. $tag.bytevector-tag
  18413. $ex.bvlref
  18414. r)
  18415. #f)))
  18416. (emit-bytevector-like-ref! as $r.result r $r.result fault #f #f))))
  18417. (define-primop 'bytevector-set!
  18418. (lambda (as r1 r2)
  18419. (let ((fault (if (not (unsafe-code))
  18420. (emit-double-tagcheck-assert!
  18421. as
  18422. $tag.bytevector-tag
  18423. (+ $imm.bytevector-header $tag.bytevector-typetag)
  18424. $ex.bvset
  18425. r1)
  18426. #f)))
  18427. (emit-bytevector-like-set! as r1 r2 fault #t))))
  18428. (define-primop 'bytevector-like-set!
  18429. (lambda (as r1 r2)
  18430. (let ((fault (if (not (unsafe-code))
  18431. (emit-single-tagcheck-assert! as
  18432. $tag.bytevector-tag
  18433. $ex.bvlset
  18434. r1)
  18435. #f)))
  18436. (emit-bytevector-like-set! as r1 r2 fault #f))))
  18437. (define-primop 'sys$bvlcmp
  18438. (lambda (as x)
  18439. (millicode-call/1arg as $m.bvlcmp x)))
  18440. ; Strings
  18441. ; RESULT must have nonnegative fixnum.
  18442. ; RS2 must have character.
  18443. (define-primop 'make-string
  18444. (lambda (as rs2)
  18445. (let ((FAULT (new-label))
  18446. (START (new-label)))
  18447. (sparc.label as START)
  18448. (let ((rs2 (force-hwreg! as rs2 $r.argreg2)))
  18449. (if (not (unsafe-code))
  18450. (let ((L1 (new-label))
  18451. (L2 (new-label)))
  18452. (sparc.tsubrcc as $r.result $r.g0 $r.g0)
  18453. (sparc.bvc.a as L1)
  18454. (sparc.andi as rs2 255 $r.tmp0)
  18455. (sparc.label as FAULT)
  18456. (if (not (= rs2 $r.argreg2))
  18457. (sparc.move as rs2 $r.argreg2))
  18458. (sparc.set as (thefixnum $ex.mkbvl) $r.tmp0) ; Wrong code.
  18459. (millicode-call/ret as $m.exception START)
  18460. (sparc.label as L1)
  18461. (sparc.bl as FAULT)
  18462. (sparc.cmpi as $r.tmp0 $imm.character)
  18463. (sparc.bne as FAULT)
  18464. (sparc.move as $r.result $r.argreg3))
  18465. (begin
  18466. (sparc.move as $r.result $r.argreg3)))
  18467. (emit-allocate-bytevector as
  18468. (+ $imm.bytevector-header
  18469. $tag.string-typetag)
  18470. $r.argreg3)
  18471. (sparc.srai as rs2 16 $r.tmp1)
  18472. (sparc.addi as $r.result 4 $r.result)
  18473. (sparc.srai as $r.argreg3 2 $r.tmp0)
  18474. (emit-bytevector-fill as $r.tmp0 $r.result $r.tmp1)
  18475. (sparc.addi as $r.result (- $tag.bytevector-tag 4) $r.result)))))
  18476. (define-primop 'string-length
  18477. (lambda (as)
  18478. (emit-primop.3arg! as 'internal:string-length $r.result $r.result)))
  18479. (define-primop 'string-ref
  18480. (lambda (as r)
  18481. (emit-primop.4arg! as 'internal:string-ref $r.result r $r.result)))
  18482. (define-primop 'string-set!
  18483. (lambda (as r1 r2)
  18484. (emit-string-set! as $r.result r1 r2)))
  18485. (define-primop 'sys$partial-list->vector
  18486. (lambda (as r)
  18487. (millicode-call/1arg as $m.partial-list->vector r)))
  18488. (define-primop 'make-procedure
  18489. (lambda (as)
  18490. (emit-make-vector-like! as
  18491. '()
  18492. $imm.procedure-header
  18493. $tag.procedure-tag)))
  18494. (define-primop 'make-vector
  18495. (lambda (as r)
  18496. (emit-make-vector-like! as
  18497. r
  18498. (+ $imm.vector-header $tag.vector-typetag)
  18499. $tag.vector-tag)))
  18500. (define-primop 'make-vector:0
  18501. (lambda (as r) (make-vector-n as 0 r)))
  18502. (define-primop 'make-vector:1
  18503. (lambda (as r) (make-vector-n as 1 r)))
  18504. (define-primop 'make-vector:2
  18505. (lambda (as r) (make-vector-n as 2 r)))
  18506. (define-primop 'make-vector:3
  18507. (lambda (as r) (make-vector-n as 3 r)))
  18508. (define-primop 'make-vector:4
  18509. (lambda (as r) (make-vector-n as 4 r)))
  18510. (define-primop 'make-vector:5
  18511. (lambda (as r) (make-vector-n as 5 r)))
  18512. (define-primop 'make-vector:6
  18513. (lambda (as r) (make-vector-n as 6 r)))
  18514. (define-primop 'make-vector:7
  18515. (lambda (as r) (make-vector-n as 7 r)))
  18516. (define-primop 'make-vector:8
  18517. (lambda (as r) (make-vector-n as 8 r)))
  18518. (define-primop 'make-vector:9
  18519. (lambda (as r) (make-vector-n as 9 r)))
  18520. (define-primop 'vector-length
  18521. (lambda (as)
  18522. (emit-primop.3arg! as 'internal:vector-length $r.result $r.result)))
  18523. (define-primop 'vector-like-length
  18524. (lambda (as)
  18525. (emit-get-length! as $tag.vector-tag #f $ex.vllen $r.result $r.result)))
  18526. (define-primop 'vector-length:vec
  18527. (lambda (as)
  18528. (emit-get-length-trusted! as $tag.vector-tag $r.result $r.result)))
  18529. (define-primop 'procedure-length
  18530. (lambda (as)
  18531. (emit-get-length! as $tag.procedure-tag #f $ex.plen $r.result $r.result)))
  18532. (define-primop 'vector-ref
  18533. (lambda (as r)
  18534. (emit-primop.4arg! as 'internal:vector-ref $r.result r $r.result)))
  18535. (define-primop 'vector-like-ref
  18536. (lambda (as r)
  18537. (let ((fault (if (not (unsafe-code))
  18538. (emit-single-tagcheck-assert! as
  18539. $tag.vector-tag
  18540. $ex.vlref
  18541. r)
  18542. #f)))
  18543. (emit-vector-like-ref!
  18544. as $r.result r $r.result fault $tag.vector-tag #f))))
  18545. (define-primop 'vector-ref:trusted
  18546. (lambda (as rs2)
  18547. (emit-vector-like-ref-trusted!
  18548. as $r.result rs2 $r.result $tag.vector-tag)))
  18549. (define-primop 'procedure-ref
  18550. (lambda (as r)
  18551. (let ((fault (if (not (unsafe-code))
  18552. (emit-single-tagcheck-assert! as
  18553. $tag.procedure-tag
  18554. $ex.pref
  18555. r)
  18556. #f)))
  18557. (emit-vector-like-ref!
  18558. as $r.result r $r.result fault $tag.procedure-tag #f))))
  18559. (define-primop 'vector-set!
  18560. (lambda (as r1 r2)
  18561. (emit-primop.4arg! as 'internal:vector-set! $r.result r1 r2)))
  18562. (define-primop 'vector-like-set!
  18563. (lambda (as r1 r2)
  18564. (let ((fault (if (not (unsafe-code))
  18565. (emit-single-tagcheck-assert! as
  18566. $tag.vector-tag
  18567. $ex.vlset
  18568. r1)
  18569. #f)))
  18570. (emit-vector-like-set! as $r.result r1 r2 fault $tag.vector-tag #f))))
  18571. (define-primop 'vector-set!:trusted
  18572. (lambda (as rs2 rs3)
  18573. (emit-vector-like-set-trusted! as $r.result rs2 rs3 $tag.vector-tag)))
  18574. (define-primop 'procedure-set!
  18575. (lambda (as r1 r2)
  18576. (let ((fault (if (not (unsafe-code))
  18577. (emit-single-tagcheck-assert! as
  18578. $tag.procedure-tag
  18579. $ex.pset
  18580. r1)
  18581. #f)))
  18582. (emit-vector-like-set! as $r.result r1 r2 fault $tag.procedure-tag #f))))
  18583. (define-primop 'char<?
  18584. (lambda (as x)
  18585. (emit-char-cmp as x sparc.bl.a $ex.char<?)))
  18586. (define-primop 'char<=?
  18587. (lambda (as x)
  18588. (emit-char-cmp as x sparc.ble.a $ex.char<=?)))
  18589. (define-primop 'char=?
  18590. (lambda (as x)
  18591. (emit-char-cmp as x sparc.be.a $ex.char=?)))
  18592. (define-primop 'char>?
  18593. (lambda (as x)
  18594. (emit-char-cmp as x sparc.bg.a $ex.char>?)))
  18595. (define-primop 'char>=?
  18596. (lambda (as x)
  18597. (emit-char-cmp as x sparc.bge.a $ex.char>=?)))
  18598. ; Experimental (for performance).
  18599. ; This makes massive assumptions about the layout of the port structure:
  18600. ; A port is a vector-like where
  18601. ; #0 = port.input?
  18602. ; #4 = port.buffer
  18603. ; #7 = port.rd-lim
  18604. ; #8 = port.rd-ptr
  18605. ; See Lib/iosys.sch for more information.
  18606. (define-primop 'sys$read-char
  18607. (lambda (as)
  18608. (let ((Lfinish (new-label))
  18609. (Lend (new-label)))
  18610. (if (not (unsafe-code))
  18611. (begin
  18612. (sparc.andi as $r.result $tag.tagmask $r.tmp0) ; mask argument tag
  18613. (sparc.cmpi as $r.tmp0 $tag.vector-tag); vector-like?
  18614. (sparc.bne as Lfinish) ; skip if not vector-like
  18615. (sparc.nop as)
  18616. (sparc.ldbi as $r.RESULT 0 $r.tmp1))) ; header byte
  18617. (sparc.ldi as $r.RESULT 1 $r.tmp2) ; port.input? or garbage
  18618. (if (not (unsafe-code))
  18619. (begin
  18620. (sparc.cmpi as $r.tmp1 $hdr.port) ; port?
  18621. (sparc.bne as Lfinish))) ; skip if not port
  18622. (sparc.cmpi as $r.tmp2 $imm.false) ; [slot] input port?
  18623. (sparc.be as Lfinish) ; skip if not active port
  18624. (sparc.ldi as $r.RESULT (+ 1 32) $r.tmp1) ; [slot] port.rd-ptr
  18625. (sparc.ldi as $r.RESULT (+ 1 28) $r.tmp2) ; port.rd-lim
  18626. (sparc.ldi as $r.RESULT (+ 1 16) $r.tmp0) ; port.buffer
  18627. (sparc.cmpr as $r.tmp1 $r.tmp2) ; rd-ptr < rd-lim?
  18628. (sparc.bge as Lfinish) ; skip if rd-ptr >= rd-lim
  18629. (sparc.subi as $r.tmp0 1 $r.tmp0) ; [slot] addr of string@0
  18630. (sparc.srai as $r.tmp1 2 $r.tmp2) ; rd-ptr as native int
  18631. (sparc.ldbr as $r.tmp0 $r.tmp2 $r.tmp2) ; get byte from string
  18632. (sparc.addi as $r.tmp1 4 $r.tmp1) ; bump rd-ptr
  18633. (sparc.sti as $r.tmp1 (+ 1 32) $r.RESULT) ; store rd-ptr in port
  18634. (sparc.slli as $r.tmp2 16 $r.tmp2) ; convert to char #1
  18635. (sparc.b as Lend)
  18636. (sparc.ori as $r.tmp2 $imm.character $r.RESULT) ; [slot] convert to char
  18637. (sparc.label as Lfinish)
  18638. (sparc.set as $imm.false $r.RESULT) ; failed
  18639. (sparc.label as Lend))))
  18640. ; eof
  18641. ; Copyright 1998 Lars T Hansen.
  18642. ;
  18643. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  18644. ;
  18645. ; 9 May 1999 / wdc
  18646. ;
  18647. ; SPARC code generation macros for primitives, part 2:
  18648. ; primitives introduced by peephole optimization.
  18649. (define-primop 'internal:car
  18650. (lambda (as src1 dest)
  18651. (internal-primop-invariant2 'internal:car src1 dest)
  18652. (if (not (unsafe-code))
  18653. (emit-single-tagcheck-assert-reg! as
  18654. $tag.pair-tag src1 #f $ex.car))
  18655. (sparc.ldi as src1 (- $tag.pair-tag) dest)))
  18656. (define-primop 'internal:cdr
  18657. (lambda (as src1 dest)
  18658. (internal-primop-invariant2 'internal:cdr src1 dest)
  18659. (if (not (unsafe-code))
  18660. (emit-single-tagcheck-assert-reg! as
  18661. $tag.pair-tag src1 #f $ex.cdr))
  18662. (sparc.ldi as src1 (- 4 $tag.pair-tag) dest)))
  18663. (define-primop 'internal:cell-ref
  18664. (lambda (as src1 dest)
  18665. (internal-primop-invariant2 'internal:cell-ref src1 dest)
  18666. (sparc.ldi as src1 (- $tag.pair-tag) dest)))
  18667. (define-primop 'internal:set-car!
  18668. (lambda (as rs1 rs2 dest-ignored)
  18669. (internal-primop-invariant2 'internal:set-car! rs1 dest-ignored)
  18670. (if (not (unsafe-code))
  18671. (emit-single-tagcheck-assert-reg! as $tag.pair-tag rs1 rs2 $ex.car))
  18672. (emit-setcar/setcdr! as rs1 rs2 0)))
  18673. (define-primop 'internal:set-cdr!
  18674. (lambda (as rs1 rs2 dest-ignored)
  18675. (internal-primop-invariant2 'internal:set-cdr! rs1 dest-ignored)
  18676. (if (not (unsafe-code))
  18677. (emit-single-tagcheck-assert-reg! as $tag.pair-tag rs1 rs2 $ex.cdr))
  18678. (emit-setcar/setcdr! as rs1 rs2 4)))
  18679. (define-primop 'internal:cell-set!
  18680. (lambda (as rs1 rs2 dest-ignored)
  18681. (internal-primop-invariant2 'internal:cell-set! rs1 dest-ignored)
  18682. (emit-setcar/setcdr! as rs1 rs2 0)))
  18683. ; CONS
  18684. ;
  18685. ; One instruction reduced here translates into about 2.5KB reduction in the
  18686. ; size of the basic heap image. :-)
  18687. ;
  18688. ; In the out-of-line case, if rd != RESULT then a garbage value is left
  18689. ; in RESULT, but it always looks like a fixnum, so it's OK.
  18690. (define-primop 'internal:cons
  18691. (lambda (as rs1 rs2 rd)
  18692. (if (inline-allocation)
  18693. (let ((ENOUGH-MEMORY (new-label))
  18694. (START (new-label)))
  18695. (sparc.label as START)
  18696. (sparc.addi as $r.e-top 8 $r.e-top)
  18697. (sparc.cmpr as $r.e-top $r.e-limit)
  18698. (sparc.ble.a as ENOUGH-MEMORY)
  18699. (sparc.sti as rs1 -8 $r.e-top)
  18700. (millicode-call/ret as $m.gc START)
  18701. (sparc.label as ENOUGH-MEMORY)
  18702. (sparc.sti as (force-hwreg! as rs2 $r.tmp0) -4 $r.e-top)
  18703. (sparc.subi as $r.e-top (- 8 $tag.pair-tag) rd))
  18704. (begin
  18705. (if (= rs1 $r.result)
  18706. (sparc.move as $r.result $r.argreg2))
  18707. (millicode-call/numarg-in-result as $m.alloc 8)
  18708. (if (= rs1 $r.result)
  18709. (sparc.sti as $r.argreg2 0 $r.result)
  18710. (sparc.sti as rs1 0 $r.result))
  18711. (sparc.sti as (force-hwreg! as rs2 $r.tmp1) 4 $r.result)
  18712. (sparc.addi as $r.result $tag.pair-tag rd)))))
  18713. (define-primop 'internal:car:pair
  18714. (lambda (as src1 dest)
  18715. (internal-primop-invariant2 'internal:car src1 dest)
  18716. (sparc.ldi as src1 (- $tag.pair-tag) dest)))
  18717. (define-primop 'internal:cdr:pair
  18718. (lambda (as src1 dest)
  18719. (internal-primop-invariant2 'internal:cdr src1 dest)
  18720. (sparc.ldi as src1 (- 4 $tag.pair-tag) dest)))
  18721. ; Vector operations.
  18722. (define-primop 'internal:vector-length
  18723. (lambda (as rs rd)
  18724. (internal-primop-invariant2 'internal:vector-length rs rd)
  18725. (emit-get-length! as
  18726. $tag.vector-tag
  18727. (+ $imm.vector-header $tag.vector-typetag)
  18728. $ex.vlen
  18729. rs
  18730. rd)))
  18731. (define-primop 'internal:vector-ref
  18732. (lambda (as rs1 rs2 rd)
  18733. (internal-primop-invariant2 'internal:vector-ref rs1 rd)
  18734. (let ((fault (if (not (unsafe-code))
  18735. (emit-double-tagcheck-assert-reg/reg!
  18736. as
  18737. $tag.vector-tag
  18738. (+ $imm.vector-header $tag.vector-typetag)
  18739. rs1
  18740. rs2
  18741. $ex.vref))))
  18742. (emit-vector-like-ref! as rs1 rs2 rd fault $tag.vector-tag #t))))
  18743. (define-primop 'internal:vector-ref/imm
  18744. (lambda (as rs1 imm rd)
  18745. (internal-primop-invariant2 'internal:vector-ref/imm rs1 rd)
  18746. (let ((fault (if (not (unsafe-code))
  18747. (emit-double-tagcheck-assert-reg/imm!
  18748. as
  18749. $tag.vector-tag
  18750. (+ $imm.vector-header $tag.vector-typetag)
  18751. rs1
  18752. imm
  18753. $ex.vref))))
  18754. (emit-vector-like-ref/imm! as rs1 imm rd fault $tag.vector-tag #t))))
  18755. (define-primop 'internal:vector-set!
  18756. (lambda (as rs1 rs2 rs3)
  18757. (internal-primop-invariant1 'internal:vector-set! rs1)
  18758. (let ((fault (if (not (unsafe-code))
  18759. (emit-double-tagcheck-assert-reg/reg!
  18760. as
  18761. $tag.vector-tag
  18762. (+ $imm.vector-header $tag.vector-typetag)
  18763. rs1
  18764. rs2
  18765. $ex.vset))))
  18766. (emit-vector-like-set! as rs1 rs2 rs3 fault $tag.vector-tag #t))))
  18767. (define-primop 'internal:vector-length:vec
  18768. (lambda (as rs1 dst)
  18769. (internal-primop-invariant2 'internal:vector-length:vec rs1 dst)
  18770. (emit-get-length-trusted! as $tag.vector-tag rs1 dst)))
  18771. (define-primop 'internal:vector-ref:trusted
  18772. (lambda (as rs1 rs2 dst)
  18773. (emit-vector-like-ref-trusted! as rs1 rs2 dst $tag.vector-tag)))
  18774. (define-primop 'internal:vector-set!:trusted
  18775. (lambda (as rs1 rs2 rs3)
  18776. (emit-vector-like-ref-trusted! as rs1 rs2 rs3 $tag.vector-tag)))
  18777. ; Strings.
  18778. (define-primop 'internal:string-length
  18779. (lambda (as rs rd)
  18780. (internal-primop-invariant2 'internal:string-length rs rd)
  18781. (emit-get-length! as
  18782. $tag.bytevector-tag
  18783. (+ $imm.bytevector-header $tag.string-typetag)
  18784. $ex.slen
  18785. rs
  18786. rd)))
  18787. (define-primop 'internal:string-ref
  18788. (lambda (as rs1 rs2 rd)
  18789. (internal-primop-invariant2 'internal:string-ref rs1 rd)
  18790. (let ((fault (if (not (unsafe-code))
  18791. (emit-double-tagcheck-assert-reg/reg!
  18792. as
  18793. $tag.bytevector-tag
  18794. (+ $imm.bytevector-header $tag.string-typetag)
  18795. rs1
  18796. rs2
  18797. $ex.sref))))
  18798. (emit-bytevector-like-ref! as rs1 rs2 rd fault #t #t))))
  18799. (define-primop 'internal:string-ref/imm
  18800. (lambda (as rs1 imm rd)
  18801. (internal-primop-invariant2 'internal:string-ref/imm rs1 rd)
  18802. (let ((fault (if (not (unsafe-code))
  18803. (emit-double-tagcheck-assert-reg/imm!
  18804. as
  18805. $tag.bytevector-tag
  18806. (+ $imm.bytevector-header $tag.string-typetag)
  18807. rs1
  18808. imm
  18809. $ex.sref))))
  18810. (emit-bytevector-like-ref/imm! as rs1 imm rd fault #t #t))))
  18811. (define-primop 'internal:string-set!
  18812. (lambda (as rs1 rs2 rs3)
  18813. (internal-primop-invariant1 'internal:string-set! rs1)
  18814. (emit-string-set! as rs1 rs2 rs3)))
  18815. (define-primop 'internal:+
  18816. (lambda (as src1 src2 dest)
  18817. (internal-primop-invariant2 'internal:+ src1 dest)
  18818. (emit-arith-primop! as sparc.taddrcc sparc.subr $m.add src1 src2 dest #t)))
  18819. (define-primop 'internal:+/imm
  18820. (lambda (as src1 imm dest)
  18821. (internal-primop-invariant2 'internal:+/imm src1 dest)
  18822. (emit-arith-primop! as sparc.taddicc sparc.subi $m.add src1 imm dest #f)))
  18823. (define-primop 'internal:-
  18824. (lambda (as src1 src2 dest)
  18825. (internal-primop-invariant2 'internal:- src1 dest)
  18826. (emit-arith-primop! as sparc.tsubrcc sparc.addr $m.subtract
  18827. src1 src2 dest #t)))
  18828. (define-primop 'internal:-/imm
  18829. (lambda (as src1 imm dest)
  18830. (internal-primop-invariant2 'internal:-/imm src1 dest)
  18831. (emit-arith-primop! as sparc.tsubicc sparc.addi $m.subtract
  18832. src1 imm dest #f)))
  18833. (define-primop 'internal:--
  18834. (lambda (as rs rd)
  18835. (internal-primop-invariant2 'internal:-- rs rd)
  18836. (emit-negate as rs rd)))
  18837. (define-primop 'internal:branchf-null?
  18838. (lambda (as reg label)
  18839. (internal-primop-invariant1 'internal:branchf-null? reg)
  18840. (sparc.cmpi as reg $imm.null)
  18841. (sparc.bne.a as label)
  18842. (sparc.slot as)))
  18843. (define-primop 'internal:branchf-pair?
  18844. (lambda (as reg label)
  18845. (internal-primop-invariant1 'internal:branchf-pair? reg)
  18846. (sparc.andi as reg $tag.tagmask $r.tmp0)
  18847. (sparc.cmpi as $r.tmp0 $tag.pair-tag)
  18848. (sparc.bne.a as label)
  18849. (sparc.slot as)))
  18850. (define-primop 'internal:branchf-zero?
  18851. (lambda (as reg label)
  18852. (internal-primop-invariant1 'internal:brancf-zero? reg)
  18853. (emit-bcmp-primop! as sparc.bne.a reg $r.g0 label $m.zerop #t)))
  18854. (define-primop 'internal:branchf-eof-object?
  18855. (lambda (as rs label)
  18856. (internal-primop-invariant1 'internal:branchf-eof-object? rs)
  18857. (sparc.cmpi as rs $imm.eof)
  18858. (sparc.bne.a as label)
  18859. (sparc.slot as)))
  18860. (define-primop 'internal:branchf-fixnum?
  18861. (lambda (as rs label)
  18862. (internal-primop-invariant1 'internal:branchf-fixnum? rs)
  18863. (sparc.btsti as rs 3)
  18864. (sparc.bne.a as label)
  18865. (sparc.slot as)))
  18866. (define-primop 'internal:branchf-char?
  18867. (lambda (as rs label)
  18868. (internal-primop-invariant1 'internal:branchf-char? rs)
  18869. (sparc.andi as rs 255 $r.tmp0)
  18870. (sparc.cmpi as $r.tmp0 $imm.character)
  18871. (sparc.bne.a as label)
  18872. (sparc.slot as)))
  18873. (define-primop 'internal:branchf-=
  18874. (lambda (as src1 src2 label)
  18875. (internal-primop-invariant1 'internal:branchf-= src1)
  18876. (emit-bcmp-primop! as sparc.bne.a src1 src2 label $m.numeq #t)))
  18877. (define-primop 'internal:branchf-<
  18878. (lambda (as src1 src2 label)
  18879. (internal-primop-invariant1 'internal:branchf-< src1)
  18880. (emit-bcmp-primop! as sparc.bge.a src1 src2 label $m.numlt #t)))
  18881. (define-primop 'internal:branchf-<=
  18882. (lambda (as src1 src2 label)
  18883. (internal-primop-invariant1 'internal:branchf-<= src1)
  18884. (emit-bcmp-primop! as sparc.bg.a src1 src2 label $m.numle #t)))
  18885. (define-primop 'internal:branchf->
  18886. (lambda (as src1 src2 label)
  18887. (internal-primop-invariant1 'internal:branchf-> src1)
  18888. (emit-bcmp-primop! as sparc.ble.a src1 src2 label $m.numgt #t)))
  18889. (define-primop 'internal:branchf->=
  18890. (lambda (as src1 src2 label)
  18891. (internal-primop-invariant1 'internal:branchf->= src1)
  18892. (emit-bcmp-primop! as sparc.bl.a src1 src2 label $m.numge #t)))
  18893. (define-primop 'internal:branchf-=/imm
  18894. (lambda (as src1 imm label)
  18895. (internal-primop-invariant1 'internal:branchf-=/imm src1)
  18896. (emit-bcmp-primop! as sparc.bne.a src1 imm label $m.numeq #f)))
  18897. (define-primop 'internal:branchf-</imm
  18898. (lambda (as src1 imm label)
  18899. (internal-primop-invariant1 'internal:branchf-</imm src1)
  18900. (emit-bcmp-primop! as sparc.bge.a src1 imm label $m.numlt #f)))
  18901. (define-primop 'internal:branchf-<=/imm
  18902. (lambda (as src1 imm label)
  18903. (internal-primop-invariant1 'internal:branchf-<=/imm src1)
  18904. (emit-bcmp-primop! as sparc.bg.a src1 imm label $m.numle #f)))
  18905. (define-primop 'internal:branchf->/imm
  18906. (lambda (as src1 imm label)
  18907. (internal-primop-invariant1 'internal:branchf->/imm src1)
  18908. (emit-bcmp-primop! as sparc.ble.a src1 imm label $m.numgt #f)))
  18909. (define-primop 'internal:branchf->=/imm
  18910. (lambda (as src1 imm label)
  18911. (internal-primop-invariant1 'internal:branchf->=/imm src1)
  18912. (emit-bcmp-primop! as sparc.bl.a src1 imm label $m.numge #f)))
  18913. (define-primop 'internal:branchf-char=?
  18914. (lambda (as src1 src2 label)
  18915. (internal-primop-invariant1 'internal:branchf-char=? src1)
  18916. (emit-char-bcmp-primop! as sparc.bne.a src1 src2 label $ex.char=?)))
  18917. (define-primop 'internal:branchf-char<=?
  18918. (lambda (as src1 src2 label)
  18919. (internal-primop-invariant1 'internal:branchf-char<=? src1)
  18920. (emit-char-bcmp-primop! as sparc.bg.a src1 src2 label $ex.char<=?)))
  18921. (define-primop 'internal:branchf-char<?
  18922. (lambda (as src1 src2 label)
  18923. (internal-primop-invariant1 'internal:branchf-char<? src1)
  18924. (emit-char-bcmp-primop! as sparc.bge.a src1 src2 label $ex.char<?)))
  18925. (define-primop 'internal:branchf-char>=?
  18926. (lambda (as src1 src2 label)
  18927. (internal-primop-invariant1 'internal:branchf-char>=? src1)
  18928. (emit-char-bcmp-primop! as sparc.bl.a src1 src2 label $ex.char>=?)))
  18929. (define-primop 'internal:branchf-char>?
  18930. (lambda (as src1 src2 label)
  18931. (internal-primop-invariant1 'internal:branchf-char>=? src1)
  18932. (emit-char-bcmp-primop! as sparc.ble.a src1 src2 label $ex.char>?)))
  18933. (define-primop 'internal:branchf-char=?/imm
  18934. (lambda (as src imm label)
  18935. (internal-primop-invariant1 'internal:branchf-char=?/imm src)
  18936. (emit-char-bcmp-primop! as sparc.bne.a src imm label $ex.char=?)))
  18937. (define-primop 'internal:branchf-char>=?/imm
  18938. (lambda (as src imm label)
  18939. (internal-primop-invariant1 'internal:branchf-char>=?/imm src)
  18940. (emit-char-bcmp-primop! as sparc.bl.a src imm label $ex.char>=?)))
  18941. (define-primop 'internal:branchf-char>?/imm
  18942. (lambda (as src imm label)
  18943. (internal-primop-invariant1 'internal:branchf-char>?/imm src)
  18944. (emit-char-bcmp-primop! as sparc.ble.a src imm label $ex.char>?)))
  18945. (define-primop 'internal:branchf-char<=?/imm
  18946. (lambda (as src imm label)
  18947. (internal-primop-invariant1 'internal:branchf-char<=?/imm src)
  18948. (emit-char-bcmp-primop! as sparc.bg.a src imm label $ex.char<=?)))
  18949. (define-primop 'internal:branchf-char<?/imm
  18950. (lambda (as src imm label)
  18951. (internal-primop-invariant1 'internal:branchf-char<?/imm src)
  18952. (emit-char-bcmp-primop! as sparc.bge.a src imm label $ex.char<?)))
  18953. (define-primop 'internal:eq?
  18954. (lambda (as src1 src2 dest)
  18955. (internal-primop-invariant2 'internal:eq? src1 dest)
  18956. (let ((tmp (force-hwreg! as src2 $r.tmp0)))
  18957. (sparc.cmpr as src1 tmp)
  18958. (emit-set-boolean-reg! as dest))))
  18959. (define-primop 'internal:eq?/imm
  18960. (lambda (as rs imm rd)
  18961. (internal-primop-invariant2 'internal:eq?/imm rs rd)
  18962. (cond ((fixnum? imm) (sparc.cmpi as rs (thefixnum imm)))
  18963. ((eq? imm #t) (sparc.cmpi as rs $imm.true))
  18964. ((eq? imm #f) (sparc.cmpi as rs $imm.false))
  18965. ((null? imm) (sparc.cmpi as rs $imm.null))
  18966. (else ???))
  18967. (emit-set-boolean-reg! as rd)))
  18968. (define-primop 'internal:branchf-eq?
  18969. (lambda (as src1 src2 label)
  18970. (internal-primop-invariant1 'internal:branchf-eq? src1)
  18971. (let ((src2 (force-hwreg! as src2 $r.tmp0)))
  18972. (sparc.cmpr as src1 src2)
  18973. (sparc.bne.a as label)
  18974. (sparc.slot as))))
  18975. (define-primop 'internal:branchf-eq?/imm
  18976. (lambda (as rs imm label)
  18977. (internal-primop-invariant1 'internal:branchf-eq?/imm rs)
  18978. (cond ((fixnum? imm) (sparc.cmpi as rs (thefixnum imm)))
  18979. ((eq? imm #t) (sparc.cmpi as rs $imm.true))
  18980. ((eq? imm #f) (sparc.cmpi as rs $imm.false))
  18981. ((null? imm) (sparc.cmpi as rs $imm.null))
  18982. (else ???))
  18983. (sparc.bne.a as label)
  18984. (sparc.slot as)))
  18985. ; Unary predicates followed by a check.
  18986. (define-primop 'internal:check-fixnum?
  18987. (lambda (as src L1 liveregs)
  18988. (sparc.btsti as src 3)
  18989. (emit-checkcc! as sparc.bne L1 liveregs)))
  18990. (define-primop 'internal:check-pair?
  18991. (lambda (as src L1 liveregs)
  18992. (sparc.andi as src $tag.tagmask $r.tmp0)
  18993. (sparc.cmpi as $r.tmp0 $tag.pair-tag)
  18994. (emit-checkcc! as sparc.bne L1 liveregs)))
  18995. (define-primop 'internal:check-vector?
  18996. (lambda (as src L1 liveregs)
  18997. (sparc.andi as src $tag.tagmask $r.tmp0)
  18998. (sparc.cmpi as $r.tmp0 $tag.vector-tag)
  18999. (sparc.bne as L1)
  19000. (sparc.nop as)
  19001. (sparc.ldi as src (- $tag.vector-tag) $r.tmp0)
  19002. (sparc.andi as $r.tmp0 255 $r.tmp1)
  19003. (sparc.cmpi as $r.tmp1 $imm.vector-header)
  19004. (emit-checkcc! as sparc.bne L1 liveregs)))
  19005. (define-primop 'internal:check-vector?/vector-length:vec
  19006. (lambda (as src dst L1 liveregs)
  19007. (sparc.andi as src $tag.tagmask $r.tmp0)
  19008. (sparc.cmpi as $r.tmp0 $tag.vector-tag)
  19009. (sparc.bne as L1)
  19010. (sparc.nop as)
  19011. (sparc.ldi as src (- $tag.vector-tag) $r.tmp0)
  19012. (sparc.andi as $r.tmp0 255 $r.tmp1)
  19013. (sparc.cmpi as $r.tmp1 $imm.vector-header)
  19014. (sparc.bne as L1)
  19015. (apply sparc.slot2 as liveregs)
  19016. (sparc.srli as $r.tmp0 8 dst)))
  19017. (define (internal-primop-invariant2 name a b)
  19018. (if (not (and (hardware-mapped? a) (hardware-mapped? b)))
  19019. (asm-error "SPARC assembler internal invariant violated by " name
  19020. " on operands " a " and " b)))
  19021. (define (internal-primop-invariant1 name a)
  19022. (if (not (hardware-mapped? a))
  19023. (asm-error "SPARC assembler internal invariant violated by " name
  19024. " on operand " a)))
  19025. ; eof
  19026. ; Copyright 1998 Lars T Hansen.
  19027. ;
  19028. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  19029. ;
  19030. ; SPARC code generation macros for primitives, part 3a:
  19031. ; helper procedures for scalars.
  19032. ; LOGAND, LOGIOR, LOGXOR: logical operations on fixnums.
  19033. ;
  19034. ; Input: Registers rs1 and rs2, both of which can be general registers.
  19035. ; In addition, rs1 can be RESULT, and rs2 can be ARGREG2.
  19036. ; Output: Register dest, which can be a general register or RESULT.
  19037. (define (logical-op as rs1 rs2 dest op excode)
  19038. (define (fail rs1 rs2 L0)
  19039. (if (not (= rs1 $r.result)) (sparc.move as rs1 $r.result))
  19040. (if (not (= rs2 $r.argreg2)) (sparc.move as rs2 $r.argreg2))
  19041. (sparc.set as (thefixnum excode) $r.tmp0)
  19042. (millicode-call/ret as $m.exception L0))
  19043. (let ((L0 (new-label))
  19044. (L1 (new-label)))
  19045. (sparc.label as L0)
  19046. (let ((rs1 (force-hwreg! as rs1 $r.result))
  19047. (rs2 (force-hwreg! as rs2 $r.argreg2))
  19048. (u (unsafe-code))
  19049. (d (hardware-mapped? dest)))
  19050. (cond ((and u d)
  19051. (op as rs1 rs2 dest))
  19052. ((and u (not d))
  19053. (op as rs1 rs2 $r.tmp0)
  19054. (emit-store-reg! as $r.tmp0 dest))
  19055. ((and (not u) d)
  19056. (sparc.orr as rs1 rs2 $r.tmp0)
  19057. (sparc.btsti as $r.tmp0 3)
  19058. (sparc.bz.a as L1)
  19059. (op as rs1 rs2 dest)
  19060. (fail rs1 rs2 L0)
  19061. (sparc.label as L1))
  19062. (else
  19063. (sparc.orr as rs1 rs2 $r.tmp0)
  19064. (sparc.btsti as $r.tmp0 3)
  19065. (sparc.bz.a as L1)
  19066. (op as rs1 rs2 $r.tmp0)
  19067. (fail rs1 rs2 L0)
  19068. (sparc.label as L1)
  19069. (emit-store-reg! as $r.tmp0 dest))))))
  19070. ; LSH, RSHA, RSHL: Bitwise shifts on fixnums.
  19071. ;
  19072. ; Notes for future contemplation:
  19073. ; - The semantics do not match those of MIT Scheme or MacScheme: only
  19074. ; positive shifts are allowed.
  19075. ; - The names do not match the fixnum-specific procedures of Chez Scheme
  19076. ; that have the same semantics: fxsll, fxsra, fxsrl.
  19077. ; - This code checks that the second argument is in range; if it did
  19078. ; not, then we could get a MOD for free. Probably too hardware-dependent
  19079. ; to worry about.
  19080. ; - The range 0..31 for the shift count is curious given that the fixnum
  19081. ; is 30-bit.
  19082. (define (emit-shift-operation as exn rs1 rs2 rd)
  19083. (let ((rs2 (force-hwreg! as rs2 $r.argreg2)))
  19084. (if (not (unsafe-code))
  19085. (let ((L0 (new-label))
  19086. (FAULT (new-label))
  19087. (START (new-label)))
  19088. (sparc.label as START)
  19089. (sparc.btsti as rs1 3) ; RS1 fixnum?
  19090. (sparc.be.a as L0)
  19091. (sparc.andi as rs2 #x7c $r.g0) ; RS2 fixnum and 0 <= RS2 < 32?
  19092. (sparc.label as FAULT)
  19093. (if (not (= rs1 $r.result))
  19094. (sparc.move as rs1 $r.result))
  19095. (if (not (= rs2 $r.argreg2))
  19096. (emit-move2hwreg! as rs2 $r.argreg2))
  19097. (sparc.set as (thefixnum exn) $r.tmp0)
  19098. (millicode-call/ret as $m.exception START)
  19099. (sparc.label as L0)
  19100. (sparc.bne as FAULT)
  19101. (sparc.srai as rs2 2 $r.tmp1))
  19102. (begin
  19103. (sparc.srai as rs2 2 $r.tmp1)))
  19104. (cond ((= exn $ex.lsh)
  19105. (sparc.sllr as rs1 $r.tmp1 rd))
  19106. ((= exn $ex.rshl)
  19107. (sparc.srlr as rs1 $r.tmp1 rd)
  19108. (sparc.andni as rd 3 rd))
  19109. ((= exn $ex.rsha)
  19110. (sparc.srar as rs1 $r.tmp1 rd)
  19111. (sparc.andni as rd 3 rd))
  19112. (else ???))))
  19113. ; Set result on condition code.
  19114. ;
  19115. ; The processor's zero bit has been affected by a previous instruction.
  19116. ; If the bit is set, store #t in RESULT, otherwise store #f in RESULT.
  19117. (define (emit-set-boolean! as)
  19118. (emit-set-boolean-reg! as $r.result))
  19119. ; Set on condition code.
  19120. ;
  19121. ; The processor's zero bit has been affected by a previous instruction.
  19122. ; If the bit is set, store #t in the processor register 'dest', otherwise
  19123. ; store #f in 'dest'.
  19124. (define (emit-set-boolean-reg! as dest)
  19125. (let ((L1 (new-label)))
  19126. (sparc.set as $imm.true dest)
  19127. (sparc.bne.a as L1)
  19128. (sparc.set as $imm.false dest)
  19129. (sparc.label as L1)))
  19130. ; Representation predicate.
  19131. (define (emit-single-tagcheck->bool! as tag)
  19132. (sparc.andi as $r.result $tag.tagmask $r.tmp0)
  19133. (sparc.cmpi as $r.tmp0 tag)
  19134. (emit-set-boolean! as))
  19135. (define (emit-single-tagcheck-assert! as tag1 excode reg2)
  19136. (emit-single-tagcheck-assert-reg! as tag1 $r.result reg2 excode))
  19137. (define (emit-single-tagcheck-assert-reg! as tag1 reg reg2 excode)
  19138. (let ((L0 (new-label))
  19139. (L1 (new-label))
  19140. (FAULT (new-label)))
  19141. (sparc.label as L0)
  19142. (sparc.andi as reg $tag.tagmask $r.tmp0)
  19143. (sparc.cmpi as $r.tmp0 tag1)
  19144. (fault-if-ne as excode #f #f reg reg2 L0)))
  19145. ; Assert that a machine register has a fixnum in it.
  19146. ; Returns the label of the fault code.
  19147. (define (emit-assert-fixnum! as reg excode)
  19148. (let ((L0 (new-label))
  19149. (L1 (new-label))
  19150. (FAULT (new-label)))
  19151. (sparc.label as L0)
  19152. (sparc.btsti as reg 3)
  19153. (fault-if-ne as excode #f #f reg #f L0)))
  19154. ; Assert that RESULT has a character in it.
  19155. ; Returns the label of the fault code.
  19156. (define (emit-assert-char! as excode fault-label)
  19157. (let ((L0 (new-label))
  19158. (L1 (new-label))
  19159. (FAULT (new-label)))
  19160. (sparc.label as L0)
  19161. (sparc.andi as $r.result #xFF $r.tmp0)
  19162. (sparc.cmpi as $r.tmp0 $imm.character)
  19163. (fault-if-ne as excode #f fault-label #f #f L0)))
  19164. ; Generate code for fault handling if the zero flag is not set.
  19165. ; - excode is the nativeint exception code.
  19166. ; - cont-label, if not #f, is the label to go to if there is no fault.
  19167. ; - fault-label, if not #f, is the label of an existing fault handler.
  19168. ; - reg1, if not #f, is the number of a register which must be
  19169. ; moved into RESULT before the fault handler is called.
  19170. ; - reg2, if not #f, is the number of a register which must be moved
  19171. ; into ARGREG2 before the fault handler is called.
  19172. ; - ret-label, if not #f, is the return address to be set up before calling
  19173. ; the fault handler.
  19174. ;
  19175. ; Ret-label and fault-label cannot simultaneously be non-#f; in this case
  19176. ; the ret-label is ignored (since the existing fault handler most likely
  19177. ; sets up the return in the desired manner).
  19178. (define (fault-if-ne as excode cont-label fault-label reg1 reg2 ret-label)
  19179. (if fault-label
  19180. (begin
  19181. (if (and reg2 (not (= reg2 $r.argreg2)))
  19182. (emit-move2hwreg! as reg2 $r.argreg2))
  19183. (sparc.bne as fault-label)
  19184. (if (and reg1 (not (= reg1 $r.result)))
  19185. (sparc.move as reg1 $r.result)
  19186. (sparc.nop as))
  19187. fault-label)
  19188. (let ((FAULT (new-label))
  19189. (L1 (new-label)))
  19190. (sparc.be.a as (or cont-label L1))
  19191. (sparc.slot as)
  19192. (sparc.label as FAULT)
  19193. (if (and reg1 (not (= reg1 $r.result)))
  19194. (sparc.move as reg1 $r.result))
  19195. (if (and reg2 (not (= reg2 $r.argreg2)))
  19196. (emit-move2hwreg! as reg2 $r.argreg2))
  19197. (sparc.set as (thefixnum excode) $r.tmp0)
  19198. (millicode-call/ret as $m.exception (or ret-label L1))
  19199. (if (or (not cont-label) (not ret-label))
  19200. (sparc.label as L1))
  19201. FAULT)))
  19202. ; This is more expensive than what is good for it (5 cycles in the usual case),
  19203. ; but there does not seem to be a better way.
  19204. (define (emit-assert-positive-fixnum! as reg excode)
  19205. (let ((L1 (new-label))
  19206. (L2 (new-label))
  19207. (L3 (new-label)))
  19208. (sparc.label as L2)
  19209. (sparc.tsubrcc as reg $r.g0 $r.g0)
  19210. (sparc.bvc as L1)
  19211. (sparc.nop as)
  19212. (sparc.label as L3)
  19213. (if (not (= reg $r.result))
  19214. (sparc.move as reg $r.result))
  19215. (sparc.set as (thefixnum excode) $r.tmp0)
  19216. (millicode-call/ret as $m.exception l2)
  19217. (sparc.label as L1)
  19218. (sparc.bl as L3)
  19219. (sparc.nop as)
  19220. L3))
  19221. ; Arithmetic comparison with boolean result.
  19222. (define (emit-cmp-primop! as branch_t.a generic r)
  19223. (let ((Ltagok (new-label))
  19224. (Lcont (new-label))
  19225. (r (force-hwreg! as r $r.argreg2)))
  19226. (sparc.tsubrcc as $r.result r $r.g0)
  19227. (sparc.bvc.a as Ltagok)
  19228. (sparc.set as $imm.false $r.result)
  19229. (if (not (= r $r.argreg2))
  19230. (sparc.move as r $r.argreg2))
  19231. (millicode-call/ret as generic Lcont)
  19232. (sparc.label as Ltagok)
  19233. (branch_t.a as Lcont)
  19234. (sparc.set as $imm.true $r.result)
  19235. (sparc.label as Lcont)))
  19236. ; Arithmetic comparison and branch.
  19237. ;
  19238. ; This code does not use the chained branch trick (DCTI) that was documented
  19239. ; in the Sparc v8 manual and deprecated in the v9 manual. This code executes
  19240. ; _much_ faster on the Ultra than the code using DCTI, even though it executes
  19241. ; the same instructions.
  19242. ;
  19243. ; Parameters and preconditions.
  19244. ; Src1 is a general register, RESULT, ARGREG2, or ARGREG3.
  19245. ; Src2 is a general register, RESULT, ARGREG2, ARGREG3, or an immediate.
  19246. ; Src2 is an immediate iff src2isreg = #f.
  19247. ; Branch_f.a is a branch on condition code that branches if the condition
  19248. ; is not true.
  19249. ; Generic is the millicode table offset of the generic procedure.
  19250. (define (emit-bcmp-primop! as branch_f.a src1 src2 Lfalse generic src2isreg)
  19251. (let ((Ltagok (new-label))
  19252. (Ltrue (new-label))
  19253. (op2 (if src2isreg
  19254. (force-hwreg! as src2 $r.tmp1)
  19255. (thefixnum src2)))
  19256. (sub (if src2isreg sparc.tsubrcc sparc.tsubicc))
  19257. (mov (if src2isreg sparc.move sparc.set)))
  19258. (sub as src1 op2 $r.g0)
  19259. (sparc.bvc.a as Ltagok)
  19260. (sparc.slot as)
  19261. ; Not both fixnums.
  19262. ; Must move src1 to result if src1 is not result.
  19263. ; Must move src2 to argreg2 if src2 is not argreg2.
  19264. (let ((move-res (not (= src1 $r.result)))
  19265. (move-arg2 (or (not src2isreg) (not (= op2 $r.argreg2)))))
  19266. (if (and move-arg2 move-res)
  19267. (mov as op2 $r.argreg2))
  19268. (sparc.jmpli as $r.millicode generic $r.o7)
  19269. (cond (move-res (sparc.move as src1 $r.result))
  19270. (move-arg2 (mov as op2 $r.argreg2))
  19271. (else (sparc.nop as)))
  19272. (sparc.cmpi as $r.result $imm.false)
  19273. (sparc.bne.a as Ltrue)
  19274. (sparc.slot as)
  19275. (sparc.b as Lfalse)
  19276. (sparc.slot as))
  19277. (sparc.label as Ltagok)
  19278. (branch_f.a as Lfalse)
  19279. (sparc.slot as)
  19280. (sparc.label as Ltrue)))
  19281. ; Generic arithmetic for + and -.
  19282. ; Some rules:
  19283. ; We have two HW registers src1 and dest.
  19284. ; If src2isreg is #t then src2 may be a HW reg or a SW reg
  19285. ; If src2isreg is #f then src2 is an immediate fixnum, not shifted.
  19286. ; Src1 and dest may be RESULT, but src2 may not.
  19287. ; Src2 may be ARGREG2, the others may not.
  19288. ;
  19289. ; FIXME! This is incomprehensible.
  19290. ; New code below.
  19291. '(define (emit-arith-primop! as op invop generic src1 src2 dest src2isreg)
  19292. (let ((L1 (new-label))
  19293. (op2 (if src2isreg
  19294. (force-hwreg! as src2 $r.tmp1)
  19295. (thefixnum src2))))
  19296. (if (and src2isreg (= op2 dest))
  19297. (begin (op as src1 op2 $r.tmp0)
  19298. (sparc.bvc.a as L1)
  19299. (sparc.move as $r.tmp0 dest))
  19300. (begin (op as src1 op2 dest)
  19301. (sparc.bvc.a as L1)
  19302. (sparc.slot as)
  19303. (invop as dest op2 dest)))
  19304. (let ((n (+ (if (not (= src1 $r.result)) 1 0)
  19305. (if (or (not src2isreg) (not (= op2 $r.argreg2))) 1 0)))
  19306. (mov2 (if src2isreg sparc.move sparc.set)))
  19307. (if (= n 2)
  19308. (mov2 as op2 $r.argreg2))
  19309. (sparc.jmpli as $r.millicode generic $r.o7)
  19310. (cond ((= n 0) (sparc.nop as))
  19311. ((= n 1) (mov2 as op2 $r.argreg2))
  19312. (else (sparc.move as src1 $r.result)))
  19313. ; Generic arithmetic leaves stuff in RESULT, must move to dest if
  19314. ; dest is not RESULT.
  19315. (if (not (= dest $r.result))
  19316. (sparc.move as $r.result dest))
  19317. (sparc.label as L1))))
  19318. ; Comprehensible, but longer.
  19319. ;
  19320. ; Important to be careful not to clobber arguments, and not to leave garbage
  19321. ; in rd, if millicode is called.
  19322. ;
  19323. ; op is the appropriate operation.
  19324. ; invop is the appropriate inverse operation.
  19325. ; RS1 can be any general hw register or RESULT.
  19326. ; RS2/IMM can be any general register or ARGREG2 (op2isreg=#t), or
  19327. ; an immediate (op2isreg=#f)
  19328. ; RD can be any general hw register or RESULT.
  19329. ;
  19330. ; FIXME: split this into two procedures.
  19331. (define (emit-arith-primop! as op invop generic rs1 rs2/imm rd op2isreg)
  19332. (let ((L1 (new-label)))
  19333. (if op2isreg
  19334. (let ((rs2 (force-hwreg! as rs2/imm $r.argreg2)))
  19335. (cond ((or (= rs1 rs2 rd)
  19336. (and (= rs2 rd)
  19337. (= generic $m.subtract)))
  19338. (op as rs1 rs2 $r.tmp0)
  19339. (sparc.bvc.a as L1)
  19340. (sparc.move as $r.tmp0 rd))
  19341. ((= rs1 rd)
  19342. (op as rs1 rs2 rs1)
  19343. (sparc.bvc.a as L1)
  19344. (sparc.slot as)
  19345. (invop as rs1 rs2 rs1))
  19346. ((= rs2 rd)
  19347. (op as rs1 rs2 rs2)
  19348. (sparc.bvc.a as L1)
  19349. (sparc.slot as)
  19350. (invop as rs2 rs1 rs2))
  19351. (else
  19352. (op as rs1 rs2 rd)
  19353. (sparc.bvc.a as L1)
  19354. (sparc.slot as)
  19355. (if (and (not (= rd $r.result)) (not (= rd $r.argreg2)))
  19356. (sparc.clr as rd))))
  19357. (cond ((and (= rs1 $r.result) (= rs2 $r.argreg2))
  19358. ;; Could peephole the INVOP or CLR into the slot here.
  19359. (millicode-call/0arg as generic))
  19360. ((= rs1 $r.result)
  19361. (millicode-call/1arg as generic rs2))
  19362. ((= rs2 $r.argreg2)
  19363. (millicode-call/1arg-in-result as generic rs1))
  19364. (else
  19365. (sparc.move as rs2 $r.argreg2)
  19366. (millicode-call/1arg-in-result as generic rs1))))
  19367. (let ((imm (thefixnum rs2/imm)))
  19368. (op as rs1 imm rd)
  19369. (sparc.bvc.a as L1)
  19370. (sparc.slot as)
  19371. (invop as rd imm rd)
  19372. (if (not (= rs1 $r.result))
  19373. (sparc.move as rs1 $r.result))
  19374. (millicode-call/numarg-in-reg as generic imm $r.argreg2)))
  19375. (if (not (= rd $r.result))
  19376. (sparc.move as $r.result rd))
  19377. (sparc.label as L1)))
  19378. ; Important to be careful not to leave garbage in rd if millicode is called.
  19379. (define (emit-negate as rs rd)
  19380. (let ((L1 (new-label)))
  19381. (cond ((= rs rd)
  19382. (sparc.tsubrcc as $r.g0 rs rs)
  19383. (sparc.bvc.a as L1)
  19384. (sparc.slot as)
  19385. (if (= rs $r.result)
  19386. (begin
  19387. (sparc.jmpli as $r.millicode $m.negate $r.o7)
  19388. (sparc.subr as $r.g0 $r.result $r.result))
  19389. (begin
  19390. (sparc.subr as $r.g0 rs rs)
  19391. (sparc.jmpli as $r.millicode $m.negate $r.o7)
  19392. (sparc.move as rs $r.result))))
  19393. (else
  19394. (sparc.tsubrcc as $r.g0 rs rd)
  19395. (sparc.bvc.a as L1)
  19396. (sparc.slot as)
  19397. (cond ((= rs $r.result)
  19398. (sparc.jmpli as $r.millicode $m.negate $r.o7)
  19399. (sparc.clr as rd))
  19400. ((= rd $r.result)
  19401. (sparc.jmpli as $r.millicode $m.negate $r.o7)
  19402. (sparc.move as rs $r.result))
  19403. (else
  19404. (sparc.clr as rd)
  19405. (sparc.jmpli as $r.millicode $m.negate $r.o7)
  19406. (sparc.move as rs $r.result)))))
  19407. (if (not (= rd $r.result))
  19408. (sparc.move as $r.result rd))
  19409. (sparc.label as L1)))
  19410. ; Character comparison.
  19411. ; r is a register or a character constant.
  19412. (define (emit-char-cmp as r btrue.a excode)
  19413. (emit-charcmp! as (lambda ()
  19414. (let ((l2 (new-label)))
  19415. (sparc.set as $imm.false $r.result)
  19416. (btrue.a as L2)
  19417. (sparc.set as $imm.true $r.result)
  19418. (sparc.label as L2)))
  19419. $r.result
  19420. r
  19421. excode))
  19422. ; op1 is a hw register
  19423. ; op2 is a register or a character constant
  19424. (define (emit-char-bcmp-primop! as bfalse.a op1 op2 L0 excode)
  19425. (emit-charcmp! as (lambda ()
  19426. (bfalse.a as L0)
  19427. (sparc.slot as))
  19428. op1
  19429. op2
  19430. excode))
  19431. ; We check the tags of both by xoring them and seeing if the low byte is 0.
  19432. ; If so, then we can subtract one from the other (tag and all) and check the
  19433. ; condition codes.
  19434. ;
  19435. ; The branch-on-true instruction must have the annull bit set. (???)
  19436. ;
  19437. ; op1 is a hw register
  19438. ; op2 is a register or a character constant.
  19439. (define (emit-charcmp! as tail op1 op2 excode)
  19440. (let ((op2 (if (char? op2)
  19441. op2
  19442. (force-hwreg! as op2 $r.argreg2))))
  19443. (cond ((not (unsafe-code))
  19444. (let ((L0 (new-label))
  19445. (L1 (new-label))
  19446. (FAULT (new-label)))
  19447. (sparc.label as L0)
  19448. (cond ((char? op2)
  19449. (sparc.xori as op1 $imm.character $r.tmp0)
  19450. (sparc.btsti as $r.tmp0 #xFF)
  19451. (sparc.srli as op1 16 $r.tmp0)
  19452. (sparc.be.a as L1)
  19453. (sparc.cmpi as $r.tmp0 (char->integer op2)))
  19454. (else
  19455. (sparc.andi as op1 #xFF $r.tmp0)
  19456. (sparc.andi as op2 #xFF $r.tmp1)
  19457. (sparc.cmpr as $r.tmp0 $r.tmp1)
  19458. (sparc.bne as FAULT)
  19459. (sparc.cmpi as $r.tmp0 $imm.character)
  19460. (sparc.be.a as L1)
  19461. (sparc.cmpr as op1 op2)))
  19462. (sparc.label as FAULT)
  19463. (if (not (eqv? op1 $r.result))
  19464. (sparc.move as op1 $r.result))
  19465. (cond ((char? op2)
  19466. (emit-immediate->register! as
  19467. (char->immediate op2)
  19468. $r.argreg2))
  19469. ((not (eqv? op2 $r.argreg2))
  19470. (sparc.move as op2 $r.argreg2)))
  19471. (sparc.set as (thefixnum excode) $r.tmp0)
  19472. (millicode-call/ret as $m.exception L0)
  19473. (sparc.label as L1)))
  19474. ((not (char? op2))
  19475. (sparc.cmpr as op1 op2))
  19476. (else
  19477. (sparc.srli as op1 16 $r.tmp0)
  19478. (sparc.cmpi as $r.tmp0 (char->integer op2))))
  19479. (tail)))
  19480. ; eof
  19481. ; Copyright 1998 Lars T Hansen.
  19482. ;
  19483. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  19484. ;
  19485. ; SPARC code generation macros for primitives, part 3b:
  19486. ; helper procedures for data structures.
  19487. ; SET-CAR!, SET-CDR!, CELL-SET!
  19488. ;
  19489. ; Input: RS1: a hardware register; has pair pointer (tag check must be
  19490. ; performed by the caller).
  19491. ; RS2: any register; has value to store.
  19492. ; Output: None.
  19493. ;
  19494. ; Having rs1 != RESULT is pretty silly with the current write barrier
  19495. ; but will be less silly with the new barrier.
  19496. (define (emit-setcar/setcdr! as rs1 rs2 offs)
  19497. (cond ((and (write-barrier) (hardware-mapped? rs2))
  19498. (sparc.sti as rs2 (- offs $tag.pair-tag) rs1)
  19499. (if (not (= rs1 $r.result))
  19500. (sparc.move as rs1 $r.result))
  19501. (millicode-call/1arg as $m.addtrans rs2))
  19502. ((write-barrier)
  19503. (emit-move2hwreg! as rs2 $r.argreg2)
  19504. (sparc.sti as $r.argreg2 (- offs $tag.pair-tag) rs1)
  19505. (millicode-call/1arg-in-result as $m.addtrans rs1))
  19506. ((hardware-mapped? rs2)
  19507. (sparc.sti as rs2 (- offs $tag.pair-tag) rs1))
  19508. (else
  19509. (emit-move2hwreg! as rs2 $r.argreg2)
  19510. (sparc.sti as $r.argreg2 (- offs $tag.pair-tag) rs1))))
  19511. ; Representation predicate.
  19512. ;
  19513. ; RESULT has an object. If the tag of RESULT is 'tag1' and the
  19514. ; header byte of the object is 'tag2' then set RESULT to #t, else
  19515. ; set it to #f.
  19516. (define (emit-double-tagcheck->bool! as tag1 tag2)
  19517. (let ((L1 (new-label)))
  19518. (sparc.andi as $r.result $tag.tagmask $r.tmp0)
  19519. (sparc.cmpi as $r.tmp0 tag1)
  19520. (sparc.bne.a as L1)
  19521. (sparc.set as $imm.false $r.result)
  19522. (sparc.ldbi as $r.result (+ (- tag1) 3) $r.tmp0)
  19523. (sparc.set as $imm.true $r.result)
  19524. (sparc.cmpi as $r.tmp0 tag2)
  19525. (sparc.bne.a as L1)
  19526. (sparc.set as $imm.false $r.result)
  19527. (sparc.label as L1)))
  19528. ; Check structure tag.
  19529. ;
  19530. ; RS1 has an object. If the tag of RS1 is not 'tag1', or if the tag is
  19531. ; 'tag1' but the header byte of the object header is not 'tag2', then an
  19532. ; exception with code 'excode' is signaled. The exception call is set
  19533. ; up to return to the first instruction of the emitted code.
  19534. ;
  19535. ; If RS1 is not RESULT then it is moved to RESULT before the exception
  19536. ; is signaled.
  19537. ;
  19538. ; If RS2/IMM is not #f, then it is a register or immediate that is moved
  19539. ; to ARGREG2 before the exception is signaled; it is an immediate iff
  19540. ; imm? = #t.
  19541. ;
  19542. ; RS1 must be a hardware register.
  19543. ; RS2/IMM is a general register, ARGREG2, an immediate, or #f.
  19544. ; RS3 is a general register, ARGREG3, or #f.
  19545. ;
  19546. ; The procedure returns the label of the fault address. If the execution
  19547. ; falls off the end of the emitted instruction sequence, then the following
  19548. ; are true:
  19549. ; - the tag of the object in RS1 was 'tag1' and its header byte was 'tag2'
  19550. ; - the object header word is in TMP0.
  19551. (define (double-tagcheck-assert as tag1 tag2 rs1 rs2/imm rs3 excode imm?)
  19552. (let ((L0 (new-label))
  19553. (L1 (new-label))
  19554. (FAULT (new-label)))
  19555. (sparc.label as L0)
  19556. (sparc.andi as rs1 $tag.tagmask $r.tmp0)
  19557. (sparc.cmpi as $r.tmp0 tag1)
  19558. (sparc.be.a as L1)
  19559. (sparc.ldi as rs1 (- tag1) $r.tmp0)
  19560. (sparc.label as FAULT)
  19561. (if (not (= rs1 $r.result))
  19562. (sparc.move as rs1 $r.result))
  19563. (if rs2/imm
  19564. (cond (imm?
  19565. (sparc.set as (thefixnum rs2/imm) $r.argreg2))
  19566. ((= rs2/imm $r.argreg2))
  19567. (else
  19568. (emit-move2hwreg! as rs2/imm $r.argreg2))))
  19569. (if (and rs3 (not (= rs3 $r.argreg3)))
  19570. (emit-move2hwreg! as rs3 $r.argreg3))
  19571. (sparc.set as (thefixnum excode) $r.tmp0)
  19572. (millicode-call/ret as $m.exception L0)
  19573. (sparc.label as L1)
  19574. (sparc.andi as $r.tmp0 255 $r.tmp1)
  19575. (sparc.cmpi as $r.tmp1 tag2)
  19576. (sparc.bne.a as FAULT)
  19577. (sparc.slot as)
  19578. FAULT))
  19579. (define (emit-double-tagcheck-assert! as tag1 tag2 excode reg2)
  19580. (double-tagcheck-assert as tag1 tag2 $r.result reg2 #f excode #f))
  19581. (define (emit-double-tagcheck-assert-reg/reg! as tag1 tag2 rs1 rs2 excode)
  19582. (double-tagcheck-assert as tag1 tag2 rs1 rs2 #f excode #f))
  19583. (define (emit-double-tagcheck-assert-reg/imm! as tag1 tag2 rs1 imm excode)
  19584. (double-tagcheck-assert as tag1 tag2 rs1 imm #f excode #t))
  19585. ; Get the length of a vector or bytevector structure, with tag checking
  19586. ; included.
  19587. ;
  19588. ; Input: RS and RD are both hardware registers.
  19589. (define (emit-get-length! as tag1 tag2 excode rs rd)
  19590. (if (not (unsafe-code))
  19591. (if tag2
  19592. (emit-double-tagcheck-assert-reg/reg! as tag1 tag2 rs rd excode)
  19593. (emit-single-tagcheck-assert-reg! as tag1 rs rd excode)))
  19594. (emit-get-length-trusted! as tag1 rs rd))
  19595. ; Get the length of a vector or bytevector structure, without tag checking.
  19596. ;
  19597. ; Input: RS and RD are both hardware registers.
  19598. (define (emit-get-length-trusted! as tag1 rs rd)
  19599. (sparc.ldi as rs (- tag1) $r.tmp0)
  19600. (sparc.srli as $r.tmp0 8 rd)
  19601. (if (= tag1 $tag.bytevector-tag)
  19602. (sparc.slli as rd 2 rd)))
  19603. ; Allocate a bytevector, leave untagged pointer in RESULT.
  19604. (define (emit-allocate-bytevector as hdr preserved-result)
  19605. ; Preserve the length field, then calculate the number of words
  19606. ; to allocate. The value `28' is an adjustment of 3 (for rounding
  19607. ; up) plus another 4 bytes for the header, all represented as a fixnum.
  19608. (if (not preserved-result)
  19609. (sparc.move as $r.result $r.argreg2))
  19610. (sparc.addi as $r.result 28 $r.result)
  19611. (sparc.andi as $r.result (asm:signed #xFFFFFFF0) $r.result)
  19612. ; Allocate space
  19613. (sparc.jmpli as $r.millicode $m.alloc-bv $r.o7)
  19614. (sparc.srai as $r.result 2 $r.result)
  19615. ; Setup the header.
  19616. (if (not preserved-result)
  19617. (sparc.slli as $r.argreg2 6 $r.tmp0)
  19618. (sparc.slli as preserved-result 6 $r.tmp0))
  19619. (sparc.addi as $r.tmp0 hdr $r.tmp0)
  19620. (sparc.sti as $r.tmp0 0 $r.result))
  19621. ; Given a nativeint count, a pointer to the first element of a
  19622. ; bytevector-like structure, and a byte value, fill the bytevector
  19623. ; with the byte value.
  19624. (define (emit-bytevector-fill as r-bytecount r-pointer r-value)
  19625. (let ((L2 (new-label))
  19626. (L1 (new-label)))
  19627. (sparc.label as L2)
  19628. (sparc.deccc as r-bytecount)
  19629. (sparc.bge.a as L2)
  19630. (sparc.stbr as r-value r-bytecount r-pointer)
  19631. (sparc.label as L1)))
  19632. ; BYTEVECTOR-REF, BYTEVECTOR-LIKE-REF, STRING-REF.
  19633. ;
  19634. ; The pointer in RS1 is known to be bytevector-like. RS2 is the fixnum
  19635. ; index into the structure. Get the RS2'th element and place it in RD.
  19636. ;
  19637. ; RS1 and RD are hardware registers.
  19638. ; RS2 is a general register or ARGREG2.
  19639. ; 'fault' is defined iff (unsafe-code) = #f
  19640. ; header is in TMP0 iff (unsafe-code) = #f and 'header-loaded?' = #t
  19641. ; if 'charize?' is #t then store result as char, otherwise as fixnum.
  19642. (define (emit-bytevector-like-ref! as rs1 rs2 rd fault charize? header-loaded?)
  19643. (let ((rs2 (force-hwreg! as rs2 $r.argreg2)))
  19644. (if (not (unsafe-code))
  19645. (begin
  19646. ; check that index is fixnum
  19647. (sparc.btsti as rs2 3)
  19648. (sparc.bne as fault)
  19649. (if (not header-loaded?)
  19650. (sparc.ldi as rs1 (- $tag.bytevector-tag) $r.tmp0))
  19651. ; check length
  19652. (sparc.srai as rs2 2 $r.tmp1)
  19653. (sparc.srli as $r.tmp0 8 $r.tmp0)
  19654. (sparc.cmpr as $r.tmp0 $r.tmp1)
  19655. (sparc.bleu as fault)
  19656. ; No NOP or SLOT -- the SUBI below goes into the slot.
  19657. )
  19658. (begin
  19659. (sparc.srai as rs2 2 $r.tmp1)))
  19660. ; Pointer is in RS1.
  19661. ; Shifted index is in TMP1.
  19662. (sparc.addi as rs1 (- 4 $tag.bytevector-tag) $r.tmp0)
  19663. (sparc.ldbr as $r.tmp0 $r.tmp1 $r.tmp0)
  19664. (if (not charize?)
  19665. (sparc.slli as $r.tmp0 2 rd)
  19666. (begin (sparc.slli as $r.tmp0 16 rd)
  19667. (sparc.ori as rd $imm.character rd)))))
  19668. ; As above, but RS2 is replaced by an immediate, IMM.
  19669. ;
  19670. ; The immediate, represented as a fixnum, is guaranteed fit in the
  19671. ; instruction's immediate field.
  19672. (define (emit-bytevector-like-ref/imm! as rs1 imm rd fault charize?
  19673. header-loaded?)
  19674. (if (not (unsafe-code))
  19675. (begin
  19676. (if (not header-loaded?)
  19677. (sparc.ldi as rs1 (- $tag.bytevector-tag) $r.tmp0))
  19678. ; Range check.
  19679. (sparc.srli as $r.tmp0 8 $r.tmp0)
  19680. (sparc.cmpi as $r.tmp0 imm)
  19681. (sparc.bleu.a as fault)
  19682. (sparc.slot as)))
  19683. ; Pointer is in RS1.
  19684. (let ((adjusted-offset (+ (- 4 $tag.bytevector-tag) imm)))
  19685. (if (immediate-literal? adjusted-offset)
  19686. (begin
  19687. (sparc.ldbi as rs1 adjusted-offset $r.tmp0))
  19688. (begin
  19689. (sparc.addi as rs1 (- 4 $tag.bytevector-tag) $r.tmp0)
  19690. (sparc.ldbr as $r.tmp0 imm $r.tmp0)))
  19691. (if (not charize?)
  19692. (sparc.slli as $r.tmp0 2 rd)
  19693. (begin (sparc.slli as $r.tmp0 16 rd)
  19694. (sparc.ori as rd $imm.character rd)))))
  19695. ; BYTEVECTOR-SET!, BYTEVECTOR-LIKE-SET!
  19696. ;
  19697. ; Input: RESULT -- a pointer to a bytevector-like structure.
  19698. ; TMP0 -- the header iff (unsafe-code) = #f and header-loaded? = #t
  19699. ; IDX -- a register that holds the second argument
  19700. ; BYTE -- a register that holds the third argument
  19701. ; Output: Nothing.
  19702. ;
  19703. ; 'Fault' is the address of the error code iff (unsafe-code) = #f
  19704. ;
  19705. ; FIXME:
  19706. ; - Argument values passed to error handler appear to be bogus
  19707. ; (error message is very strange).
  19708. ; - There's no check that the value actually fits in a byte.
  19709. ; - Uses ARGREG3 and and TMP2.
  19710. (define (emit-bytevector-like-set! as idx byte fault header-loaded?)
  19711. (let ((r1 (force-hwreg! as idx $r.tmp1))
  19712. (r2 (force-hwreg! as byte $r.argreg3)))
  19713. (if (not (unsafe-code))
  19714. (begin
  19715. (if (not header-loaded?)
  19716. (sparc.ldi as $r.result (- $tag.bytevector-tag) $r.tmp0))
  19717. ; Both index and byte must be fixnums.
  19718. ; Can't use tsubcc because the computation may really overflow.
  19719. (sparc.orr as r1 r2 $r.tmp2)
  19720. (sparc.btsti as $r.tmp2 3)
  19721. (sparc.bnz as fault)
  19722. ; No NOP -- next instruction is OK in slot.
  19723. ; Index must be in range.
  19724. (sparc.srli as $r.tmp0 8 $r.tmp0) ; limit - in slot
  19725. (sparc.srai as r1 2 $r.tmp1) ; index
  19726. (sparc.cmpr as $r.tmp1 $r.tmp0)
  19727. (sparc.bgeu as fault)
  19728. ; No NOP -- next instruction is OK in slot.
  19729. )
  19730. (begin
  19731. (sparc.srai as r1 2 $r.tmp1)))
  19732. (sparc.srli as r2 2 $r.tmp0)
  19733. ; Using ARGREG2 as the destination is OK because the resulting pointer
  19734. ; value always looks like a fixnum. By doing so, we avoid needing TMP2.
  19735. (sparc.addi as $r.result (- 4 $tag.bytevector-tag) $r.argreg2)
  19736. (sparc.stbr as $r.tmp0 $r.tmp1 $r.argreg2)))
  19737. ; STRING-SET!
  19738. (define (emit-string-set! as rs1 rs2 rs3)
  19739. (let* ((rs2 (force-hwreg! as rs2 $r.argreg2))
  19740. (rs3 (force-hwreg! as rs3 $r.argreg3))
  19741. (FAULT (if (not (unsafe-code))
  19742. (double-tagcheck-assert
  19743. as
  19744. $tag.bytevector-tag
  19745. (+ $imm.bytevector-header $tag.string-typetag)
  19746. rs1 rs2 rs3
  19747. $ex.sset
  19748. #f))))
  19749. ; Header is in TMP0; TMP1 and TMP2 are free.
  19750. (if (not (unsafe-code))
  19751. (begin
  19752. ; RS2 must be a fixnum.
  19753. (sparc.btsti as rs2 3)
  19754. (sparc.bne as FAULT)
  19755. ; Index (in RS2) must be valid; header is in tmp0.
  19756. (sparc.srli as $r.tmp0 8 $r.tmp0) ; limit
  19757. (sparc.srai as rs2 2 $r.tmp1) ; index
  19758. (sparc.cmpr as $r.tmp1 $r.tmp0)
  19759. (sparc.bgeu as FAULT)
  19760. ; RS3 must be a character.
  19761. (sparc.andi as rs3 #xFF $r.tmp0)
  19762. (sparc.cmpi as $r.tmp0 $imm.character)
  19763. (sparc.bne as FAULT)
  19764. ; No NOP -- the SRLI below goes in the slot
  19765. )
  19766. (begin
  19767. (sparc.srai as rs2 2 $r.tmp1)))
  19768. ; tmp1 has nativeint index.
  19769. ; rs3/argreg3 has character.
  19770. ; tmp0 is garbage.
  19771. (sparc.subi as $r.tmp1 (- $tag.bytevector-tag 4) $r.tmp1)
  19772. (sparc.srli as rs3 16 $r.tmp0)
  19773. (sparc.stbr as $r.tmp0 rs1 $r.tmp1)))
  19774. ; VECTORS and PROCEDURES
  19775. ; Allocate short vectors of known length; faster than the general case.
  19776. ; FIXME: can also allocate in-line.
  19777. (define (make-vector-n as length r)
  19778. (sparc.jmpli as $r.millicode $m.alloc $r.o7)
  19779. (sparc.set as (thefixnum (+ length 1)) $r.result)
  19780. (emit-immediate->register! as (+ (* 256 (thefixnum length))
  19781. $imm.vector-header
  19782. $tag.vector-typetag)
  19783. $r.tmp0)
  19784. (sparc.sti as $r.tmp0 0 $r.result)
  19785. (let ((dest (force-hwreg! as r $r.argreg2)))
  19786. (do ((i 0 (+ i 1)))
  19787. ((= i length))
  19788. (sparc.sti as dest (* (+ i 1) 4) $r.result)))
  19789. (sparc.addi as $r.result $tag.vector-tag $r.result))
  19790. ; emit-make-vector-like! assumes argreg3 is not destroyed by alloci.
  19791. ; FIXME: bug: $ex.mkvl is not right if the operation is make-procedure
  19792. ; or make-vector.
  19793. (define (emit-make-vector-like! as r hdr ptrtag)
  19794. (let ((FAULT (emit-assert-positive-fixnum! as $r.result $ex.mkvl)))
  19795. (sparc.move as $r.result $r.argreg3)
  19796. (sparc.addi as $r.result 4 $r.result)
  19797. (sparc.jmpli as $r.millicode $m.alloci $r.o7)
  19798. (if (null? r)
  19799. (sparc.set as $imm.null $r.argreg2)
  19800. (emit-move2hwreg! as r $r.argreg2))
  19801. (sparc.slli as $r.argreg3 8 $r.tmp0)
  19802. (sparc.addi as $r.tmp0 hdr $r.tmp0)
  19803. (sparc.sti as $r.tmp0 0 $r.result)
  19804. (sparc.addi as $r.result ptrtag $r.result)))
  19805. ; VECTOR-REF, VECTOR-LIKE-REF, PROCEDURE-REF
  19806. ;
  19807. ; FAULT is valid iff (unsafe-code) = #f
  19808. ; Header is in TMP0 iff (unsafe-code) = #f and header-loaded? = #t.
  19809. (define (emit-vector-like-ref! as rs1 rs2 rd FAULT tag header-loaded?)
  19810. (let ((index (force-hwreg! as rs2 $r.argreg2)))
  19811. (if (not (unsafe-code))
  19812. (begin
  19813. (if (not header-loaded?)
  19814. (sparc.ldi as rs1 (- tag) $r.tmp0))
  19815. ; Index must be fixnum.
  19816. (sparc.btsti as index 3)
  19817. (sparc.bne as FAULT)
  19818. ; Index must be within bounds.
  19819. (sparc.srai as $r.tmp0 8 $r.tmp0)
  19820. (sparc.cmpr as $r.tmp0 index)
  19821. (sparc.bleu as FAULT)
  19822. ; No NOP; the following instruction is valid in the slot.
  19823. ))
  19824. (emit-vector-like-ref-trusted! as rs1 index rd tag)))
  19825. (define (emit-vector-like-ref-trusted! as rs1 rs2 rd tag)
  19826. (let ((index (force-hwreg! as rs2 $r.argreg2)))
  19827. (sparc.addi as rs1 (- 4 tag) $r.tmp0)
  19828. (sparc.ldr as $r.tmp0 index rd)))
  19829. ; VECTOR-REF/IMM, VECTOR-LIKE-REF/IMM, PROCEDURE-REF/IMM
  19830. ;
  19831. ; 'rs1' is a hardware register containing a vectorish pointer (to a
  19832. ; vector-like or procedure).
  19833. ; 'imm' is a fixnum s.t. (immediate-literal? imm) => #t.
  19834. ; 'rd' is a hardware register.
  19835. ; 'FAULT' is the label of the error code iff (unsafe-code) => #f
  19836. ; 'tag' is the tag of the pointer in rs1.
  19837. ; 'header-loaded?' is #t iff the structure header word is in $r.tmp0.
  19838. (define (emit-vector-like-ref/imm! as rs1 imm rd FAULT tag header-loaded?)
  19839. (if (not (unsafe-code))
  19840. (begin
  19841. (if (not header-loaded?) (sparc.ldi as rs1 (- tag) $r.tmp0))
  19842. ; Check bounds.
  19843. (sparc.srai as $r.tmp0 10 $r.tmp0)
  19844. (sparc.cmpi as $r.tmp0 imm)
  19845. (sparc.bleu as FAULT)
  19846. (sparc.nop as)))
  19847. (emit-vector-like-ref/imm-trusted! as rs1 imm rd tag))
  19848. ; 'rs1' is a hardware register containing a vectorish pointer (to a
  19849. ; vector-like or procedure).
  19850. ; 'imm' is a fixnum s.t. (immediate-literal? imm) => #t.
  19851. ; 'rd' is a hardware register.
  19852. ; 'tag' is the tag of the pointer in rs1.
  19853. (define (emit-vector-like-ref/imm-trusted! as rs1 imm rd tag)
  19854. (let* ((offset (* imm 4)) ; words->bytes
  19855. (adjusted-offset (+ (- 4 tag) offset)))
  19856. (if (immediate-literal? adjusted-offset)
  19857. (begin
  19858. (sparc.ldi as rs1 adjusted-offset rd))
  19859. (begin
  19860. (sparc.addi as rs1 (- 4 tag) $r.tmp0)
  19861. (sparc.ldi as $r.tmp0 offset rd)))))
  19862. ; VECTOR-SET!, VECTOR-LIKE-SET!, PROCEDURE-SET!
  19863. ;
  19864. ; It is assumed that the pointer in RESULT is valid. We must check the index
  19865. ; in register x for validity and then perform the side effect (by calling
  19866. ; millicode). The tag is the pointer tag to be adjusted for.
  19867. ;
  19868. ; The use of vector-set is ok even if it is a procedure.
  19869. ; fault is valid iff (unsafe-code) = #f
  19870. ; header is in tmp0 iff (unsafe-code) = #f and header-loaded? = #t
  19871. (define (emit-vector-like-set! as rs1 rs2 rs3 fault tag header-loaded?)
  19872. (let ((rs2 (force-hwreg! as rs2 $r.tmp1))
  19873. (rs3 (force-hwreg! as rs3 $r.argreg2)))
  19874. (if (not (unsafe-code))
  19875. (begin
  19876. (if (not header-loaded?)
  19877. (sparc.ldi as $r.result (- tag) $r.tmp0))
  19878. (sparc.btsti as rs2 3)
  19879. (sparc.bne as fault)
  19880. (sparc.srai as $r.tmp0 8 $r.tmp0)
  19881. (sparc.cmpr as $r.tmp0 rs2)
  19882. (sparc.bleu as fault)))
  19883. (emit-vector-like-set-trusted! as rs1 rs2 rs3 tag)))
  19884. ; rs1 must be a hardware register.
  19885. ; tag is the pointer tag to be adjusted for.
  19886. (define (emit-vector-like-set-trusted! as rs1 rs2 rs3 tag)
  19887. (let ((rs2 (force-hwreg! as rs2 $r.tmp1))
  19888. (rs3 (force-hwreg! as rs3 $r.argreg2)))
  19889. ;; The ADDR can go in the delay slot of a preceding BLEU.
  19890. (sparc.addr as rs1 rs2 $r.tmp0)
  19891. (cond ((not (write-barrier))
  19892. (sparc.sti as rs3 (- 4 tag) $r.tmp0))
  19893. ((= rs1 $r.result)
  19894. (cond ((= rs3 $r.argreg2)
  19895. (sparc.jmpli as $r.millicode $m.addtrans $r.o7)
  19896. (sparc.sti as rs3 (- 4 tag) $r.tmp0))
  19897. (else
  19898. (sparc.sti as rs3 (- 4 tag) $r.tmp0)
  19899. (millicode-call/1arg as $m.addtrans rs3))))
  19900. (else
  19901. (cond ((= rs3 $r.argreg2)
  19902. (sparc.sti as rs3 (- 4 tag) $r.tmp0)
  19903. (millicode-call/1arg-in-result as $m.addtrans rs1))
  19904. (else
  19905. (sparc.sti as rs3 (- 4 tag) $r.tmp0)
  19906. (sparc.move as rs1 $r.result)
  19907. (millicode-call/1arg as $m.addtrans rs3)))))))
  19908. ; eof
  19909. ; Copyright 1998 Lars T Hansen.
  19910. ;
  19911. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  19912. ;
  19913. ; 9 May 1999 / wdc
  19914. ;
  19915. ; SPARC code generation macros for primitives, part 3:
  19916. ; fixnum-specific operations.
  19917. ;
  19918. ; Constraints for all the primops.
  19919. ;
  19920. ; RS1 is a general hardware register or RESULT.
  19921. ; RS2 is a general register or ARGREG2.
  19922. ; IMM is an exact integer in the range -1024 .. 1023.
  19923. ; RD is a general hardware register or RESULT.
  19924. ; FIXME
  19925. ; Missing fxquotient, fxremainder
  19926. ; When new pass1 in place:
  19927. ; Must add code to pass1 to allow n-ary calls to be rewritten as binary
  19928. ; Must add compiler macro for fxabs.
  19929. ; most-negative-fixnum, most-positive-fixnum.
  19930. (define-primop 'most-negative-fixnum
  19931. (lambda (as)
  19932. (emit-immediate->register! as (asm:signed #x80000000) $r.result)))
  19933. (define-primop 'most-positive-fixnum
  19934. (lambda (as)
  19935. (emit-immediate->register! as (asm:signed #x7FFFFFFC) $r.result)))
  19936. ; fx+, fx- w/o immediates
  19937. (define-primop 'fx+
  19938. (lambda (as rs2)
  19939. (emit-fixnum-arithmetic as sparc.taddrcc sparc.addr $r.result rs2 $r.result
  19940. $ex.fx+)))
  19941. (define-primop 'internal:fx+
  19942. (lambda (as rs1 rs2 rd)
  19943. (emit-fixnum-arithmetic as sparc.taddrcc sparc.addr rs1 rs2 rd $ex.fx+)))
  19944. (define-primop 'fx-
  19945. (lambda (as rs2)
  19946. (emit-fixnum-arithmetic as sparc.tsubrcc sparc.subr $r.result rs2 $r.result
  19947. $ex.fx-)))
  19948. (define-primop 'internal:fx-
  19949. (lambda (as rs1 rs2 rd)
  19950. (emit-fixnum-arithmetic as sparc.tsubrcc sparc.subr rs1 rs2 rd $ex.fx-)))
  19951. (define-primop 'fx--
  19952. (lambda (as)
  19953. (emit-fixnum-arithmetic as sparc.tsubrcc sparc.subr
  19954. $r.g0 $r.result $r.result $ex.fx--)))
  19955. (define-primop 'internal:fx--
  19956. (lambda (as rs rd)
  19957. (emit-fixnum-arithmetic as sparc.tsubrcc sparc.subr $r.g0 rs rd $ex.fx--)))
  19958. (define (emit-fixnum-arithmetic as op-check op-nocheck rs1 rs2 rd exn)
  19959. (if (unsafe-code)
  19960. (let ((rs2 (force-hwreg! as rs2 $r.argreg2)))
  19961. (op-nocheck as rs1 rs2 rd))
  19962. (let ((rs2 (force-hwreg! as rs2 $r.argreg2))
  19963. (L0 (new-label))
  19964. (L1 (new-label)))
  19965. (sparc.label as L0)
  19966. (op-check as rs1 rs2 $r.tmp0)
  19967. (sparc.bvc.a as L1)
  19968. (sparc.move as $r.tmp0 rd)
  19969. (if (not (= exn $ex.fx--))
  19970. (begin
  19971. (if (not (= rs1 $r.result)) (sparc.move as rs1 $r.result))
  19972. (if (not (= rs2 $r.argreg2)) (sparc.move as rs2 $r.argreg2)))
  19973. (begin
  19974. (if (not (= rs2 $r.result)) (sparc.move as rs2 $r.result))))
  19975. (sparc.set as (thefixnum exn) $r.tmp0)
  19976. (millicode-call/ret as $m.exception L0)
  19977. (sparc.label as L1))))
  19978. ; fx* w/o immediate
  19979. (define-primop 'fx*
  19980. (lambda (as rs2)
  19981. (emit-multiply-code as rs2 #t)))
  19982. ; fx+, fx- w/immediates
  19983. (define-primop 'internal:fx+/imm
  19984. (lambda (as rs imm rd)
  19985. (emit-fixnum-arithmetic/imm as sparc.taddicc sparc.addi
  19986. rs imm rd $ex.fx+)))
  19987. (define-primop 'internal:fx-/imm
  19988. (lambda (as rs imm rd)
  19989. (emit-fixnum-arithmetic/imm as sparc.tsubicc sparc.subi
  19990. rs imm rd $ex.fx-)))
  19991. (define (emit-fixnum-arithmetic/imm as op-check op-nocheck rs imm rd exn)
  19992. (if (unsafe-code)
  19993. (op-nocheck as rs (thefixnum imm) rd)
  19994. (let ((L0 (new-label))
  19995. (L1 (new-label)))
  19996. (sparc.label as L0)
  19997. (op-check as rs (thefixnum imm) $r.tmp0)
  19998. (sparc.bvc.a as L1)
  19999. (sparc.move as $r.tmp0 rd)
  20000. (if (not (= rs $r.result)) (sparc.move as rs $r.result))
  20001. (sparc.set as (thefixnum imm) $r.argreg2)
  20002. (sparc.set as (thefixnum exn) $r.tmp0)
  20003. (millicode-call/ret as $m.exception L0)
  20004. (sparc.label as L1))))
  20005. ; fx=, fx<, fx<=, fx>, fx>=, fxpositive?, fxnegative?, fxzero? w/o immediates
  20006. (define-primop 'fx=
  20007. (lambda (as rs2)
  20008. (emit-fixnum-compare as sparc.bne.a $r.result rs2 $r.result $ex.fx= #f)))
  20009. (define-primop 'fx<
  20010. (lambda (as rs2)
  20011. (emit-fixnum-compare as sparc.bge.a $r.result rs2 $r.result $ex.fx< #f)))
  20012. (define-primop 'fx<=
  20013. (lambda (as rs2)
  20014. (emit-fixnum-compare as sparc.bg.a $r.result rs2 $r.result $ex.fx<= #f)))
  20015. (define-primop 'fx>
  20016. (lambda (as rs2)
  20017. (emit-fixnum-compare as sparc.ble.a $r.result rs2 $r.result $ex.fx> #f)))
  20018. (define-primop 'fx>=
  20019. (lambda (as rs2)
  20020. (emit-fixnum-compare as sparc.bl.a $r.result rs2 $r.result $ex.fx>= #f)))
  20021. (define-primop 'internal:fx=
  20022. (lambda (as rs1 rs2 rd)
  20023. (emit-fixnum-compare as sparc.bne.a rs1 rs2 rd $ex.fx= #f)))
  20024. (define-primop 'internal:fx<
  20025. (lambda (as rs1 rs2 rd)
  20026. (emit-fixnum-compare as sparc.bge.a rs1 rs2 rd $ex.fx< #f)))
  20027. (define-primop 'internal:fx<=
  20028. (lambda (as rs1 rs2 rd)
  20029. (emit-fixnum-compare as sparc.bg.a rs1 rs2 rd $ex.fx<= #f)))
  20030. (define-primop 'internal:fx>
  20031. (lambda (as rs1 rs2 rd)
  20032. (emit-fixnum-compare as sparc.ble.a rs1 rs2 rd $ex.fx> #f)))
  20033. (define-primop 'internal:fx>=
  20034. (lambda (as rs1 rs2 rd)
  20035. (emit-fixnum-compare as sparc.bl.a rs1 rs2 rd $ex.fx>= #f)))
  20036. ; Use '/imm' code for these because the generated code is better.
  20037. (define-primop 'fxpositive?
  20038. (lambda (as)
  20039. (emit-fixnum-compare/imm as sparc.ble.a $r.result 0 $r.result
  20040. $ex.fxpositive? #f)))
  20041. (define-primop 'fxnegative?
  20042. (lambda (as)
  20043. (emit-fixnum-compare/imm as sparc.bge.a $r.result 0 $r.result
  20044. $ex.fxnegative? #f)))
  20045. (define-primop 'fxzero?
  20046. (lambda (as)
  20047. (emit-fixnum-compare/imm as sparc.bne.a $r.result 0 $r.result
  20048. $ex.fxzero? #f)))
  20049. (define-primop 'internal:fxpositive?
  20050. (lambda (as rs rd)
  20051. (emit-fixnum-compare/imm as sparc.ble.a rs 0 rd $ex.fxpositive? #f)))
  20052. (define-primop 'internal:fxnegative?
  20053. (lambda (as rs rd)
  20054. (emit-fixnum-compare/imm as sparc.bge.a rs 0 rd $ex.fxnegative? #f)))
  20055. (define-primop 'internal:fxzero?
  20056. (lambda (as rs rd)
  20057. (emit-fixnum-compare/imm as sparc.bne.a rs 0 rd $ex.fxzero? #f)))
  20058. ; fx=, fx<, fx<=, fx>, fx>= w/immediates
  20059. (define-primop 'internal:fx=/imm
  20060. (lambda (as rs imm rd)
  20061. (emit-fixnum-compare/imm as sparc.bne.a rs imm rd $ex.fx= #f)))
  20062. (define-primop 'internal:fx</imm
  20063. (lambda (as rs imm rd)
  20064. (emit-fixnum-compare/imm as sparc.bge.a rs imm rd $ex.fx< #f)))
  20065. (define-primop 'internal:fx<=/imm
  20066. (lambda (as rs imm rd)
  20067. (emit-fixnum-compare/imm as sparc.bg.a rs imm rd $ex.fx<= #f)))
  20068. (define-primop 'internal:fx>/imm
  20069. (lambda (as rs imm rd)
  20070. (emit-fixnum-compare/imm as sparc.ble.a rs imm rd $ex.fx> #f)))
  20071. (define-primop 'internal:fx>=/imm
  20072. (lambda (as rs imm rd)
  20073. (emit-fixnum-compare/imm as sparc.bl.a rs imm rd $ex.fx>= #f)))
  20074. ; fx=, fx<, fx<=, fx>, fx>=, fxpositive?, fxnegative?, fxzero? w/o immediates
  20075. ; for control.
  20076. (define-primop 'internal:branchf-fx=
  20077. (lambda (as rs1 rs2 L)
  20078. (emit-fixnum-compare as sparc.bne.a rs1 rs2 #f $ex.fx= L)))
  20079. (define-primop 'internal:branchf-fx<
  20080. (lambda (as rs1 rs2 L)
  20081. (emit-fixnum-compare as sparc.bge.a rs1 rs2 #f $ex.fx< L)))
  20082. (define-primop 'internal:branchf-fx<=
  20083. (lambda (as rs1 rs2 L)
  20084. (emit-fixnum-compare as sparc.bg.a rs1 rs2 #f $ex.fx<= L)))
  20085. (define-primop 'internal:branchf-fx>
  20086. (lambda (as rs1 rs2 L)
  20087. (emit-fixnum-compare as sparc.ble.a rs1 rs2 #f $ex.fx> L)))
  20088. (define-primop 'internal:branchf-fx>=
  20089. (lambda (as rs1 rs2 L)
  20090. (emit-fixnum-compare as sparc.bl.a rs1 rs2 #f $ex.fx>= L)))
  20091. (define-primop 'internal:branchf-fxpositive?
  20092. (lambda (as rs1 L)
  20093. (emit-fixnum-compare/imm as sparc.ble.a rs1 0 #f $ex.fxpositive? L)))
  20094. (define-primop 'internal:branchf-fxnegative?
  20095. (lambda (as rs1 L)
  20096. (emit-fixnum-compare/imm as sparc.bge.a rs1 0 #f $ex.fxnegative? L)))
  20097. (define-primop 'internal:branchf-fxzero?
  20098. (lambda (as rs1 L)
  20099. (emit-fixnum-compare/imm as sparc.bne.a rs1 0 #f $ex.fxzero? L)))
  20100. ; fx=, fx<, fx<=, fx>, fx>= w/immediates for control.
  20101. (define-primop 'internal:branchf-fx=/imm
  20102. (lambda (as rs imm L)
  20103. (emit-fixnum-compare/imm as sparc.bne.a rs imm #f $ex.fx= L)))
  20104. (define-primop 'internal:branchf-fx</imm
  20105. (lambda (as rs imm L)
  20106. (emit-fixnum-compare/imm as sparc.bge.a rs imm #f $ex.fx< L)))
  20107. (define-primop 'internal:branchf-fx<=/imm
  20108. (lambda (as rs imm L)
  20109. (emit-fixnum-compare/imm as sparc.bg.a rs imm #f $ex.fx<= L)))
  20110. (define-primop 'internal:branchf-fx>/imm
  20111. (lambda (as rs imm L)
  20112. (emit-fixnum-compare/imm as sparc.ble.a rs imm #f $ex.fx> L)))
  20113. (define-primop 'internal:branchf-fx>=/imm
  20114. (lambda (as rs imm L)
  20115. (emit-fixnum-compare/imm as sparc.bl.a rs imm #f $ex.fx>= L)))
  20116. ; Trusted fixnum comparisons.
  20117. (define-primop '=:fix:fix
  20118. (lambda (as rs2)
  20119. (emit-fixnum-compare-trusted as sparc.bne.a $r.result rs2 $r.result #f)))
  20120. (define-primop '<:fix:fix
  20121. (lambda (as rs2)
  20122. (emit-fixnum-compare-trusted as sparc.bge.a $r.result rs2 $r.result #f)))
  20123. (define-primop '<=:fix:fix
  20124. (lambda (as rs2)
  20125. (emit-fixnum-compare-trusted as sparc.bg.a $r.result rs2 $r.result #f)))
  20126. (define-primop '>:fix:fix
  20127. (lambda (as rs2)
  20128. (emit-fixnum-compare-trusted as sparc.ble.a $r.result rs2 $r.result #f)))
  20129. (define-primop '>=:fix:fix
  20130. (lambda (as rs2)
  20131. (emit-fixnum-compare-trusted as sparc.bl.a $r.result rs2 $r.result #f)))
  20132. (define-primop 'internal:=:fix:fix
  20133. (lambda (as rs1 rs2 rd)
  20134. (emit-fixnum-compare-trusted as sparc.bne.a rs1 rs2 rd #f)))
  20135. (define-primop 'internal:<:fix:fix
  20136. (lambda (as rs1 rs2 rd)
  20137. (emit-fixnum-compare-trusted as sparc.bge.a rs1 rs2 rd #f)))
  20138. (define-primop 'internal:<=:fix:fix
  20139. (lambda (as rs1 rs2 rd)
  20140. (emit-fixnum-compare-trusted as sparc.bg.a rs1 rs2 rd #f)))
  20141. (define-primop 'internal:>:fix:fix
  20142. (lambda (as rs1 rs2 rd)
  20143. (emit-fixnum-compare-trusted as sparc.ble.a rs1 rs2 rd #f)))
  20144. (define-primop 'internal:>=:fix:fix
  20145. (lambda (as rs1 rs2 rd)
  20146. (emit-fixnum-compare-trusted as sparc.bl.a rs1 rs2 rd #f)))
  20147. ; With immediates.
  20148. (define-primop 'internal:=:fix:fix/imm
  20149. (lambda (as rs imm rd)
  20150. (emit-fixnum-compare/imm-trusted as sparc.bne.a rs imm rd #f)))
  20151. (define-primop 'internal:<:fix:fix/imm
  20152. (lambda (as rs imm rd)
  20153. (emit-fixnum-compare/imm-trusted as sparc.bge.a rs imm rd #f)))
  20154. (define-primop 'internal:<=:fix:fix/imm
  20155. (lambda (as rs imm rd)
  20156. (emit-fixnum-compare/imm-trusted as sparc.bg.a rs imm rd #f)))
  20157. (define-primop 'internal:>:fix:fix/imm
  20158. (lambda (as rs imm rd)
  20159. (emit-fixnum-compare/imm-trusted as sparc.ble.a rs imm rd #f)))
  20160. (define-primop 'internal:>=:fix:fix/imm
  20161. (lambda (as rs imm rd)
  20162. (emit-fixnum-compare/imm-trusted as sparc.bl.a rs imm rd #f)))
  20163. ; Without immediates, for control.
  20164. (define-primop 'internal:branchf-=:fix:fix
  20165. (lambda (as rs1 rs2 L)
  20166. (emit-fixnum-compare-trusted as sparc.bne.a rs1 rs2 #f L)))
  20167. (define-primop 'internal:branchf-<:fix:fix
  20168. (lambda (as rs1 rs2 L)
  20169. (emit-fixnum-compare-trusted as sparc.bge.a rs1 rs2 #f L)))
  20170. (define-primop 'internal:branchf-<=:fix:fix
  20171. (lambda (as rs1 rs2 L)
  20172. (emit-fixnum-compare-trusted as sparc.bg.a rs1 rs2 #f L)))
  20173. (define-primop 'internal:branchf->:fix:fix
  20174. (lambda (as rs1 rs2 L)
  20175. (emit-fixnum-compare-trusted as sparc.ble.a rs1 rs2 #f L)))
  20176. (define-primop 'internal:branchf->=:fix:fix
  20177. (lambda (as rs1 rs2 L)
  20178. (emit-fixnum-compare-trusted as sparc.bl.a rs1 rs2 #f L)))
  20179. ; With immediates, for control.
  20180. (define-primop 'internal:branchf-=:fix:fix/imm
  20181. (lambda (as rs imm L)
  20182. (emit-fixnum-compare/imm-trusted as sparc.bne.a rs imm #f L)))
  20183. (define-primop 'internal:branchf-<:fix:fix/imm
  20184. (lambda (as rs imm L)
  20185. (emit-fixnum-compare/imm-trusted as sparc.bge.a rs imm #f L)))
  20186. (define-primop 'internal:branchf-<=:fix:fix/imm
  20187. (lambda (as rs imm L)
  20188. (emit-fixnum-compare/imm-trusted as sparc.bg.a rs imm #f L)))
  20189. (define-primop 'internal:branchf->:fix:fix/imm
  20190. (lambda (as rs imm L)
  20191. (emit-fixnum-compare/imm-trusted as sparc.ble.a rs imm #f L)))
  20192. (define-primop 'internal:branchf->=:fix:fix/imm
  20193. (lambda (as rs imm L)
  20194. (emit-fixnum-compare/imm-trusted as sparc.bl.a rs imm #f L)))
  20195. ; Range check: 0 <= src1 < src2
  20196. (define-primop 'internal:check-range
  20197. (lambda (as src1 src2 L1 livregs)
  20198. (let ((src2 (force-hwreg! as src2 $r.argreg2)))
  20199. (emit-fixnum-compare-check
  20200. as src2 src1 sparc.bleu L1 livregs))))
  20201. ; Trusted fixnum comparisons followed by a check.
  20202. (define-primop 'internal:check-=:fix:fix
  20203. (lambda (as src1 src2 L1 liveregs)
  20204. (emit-fixnum-compare-check
  20205. as src1 src2 sparc.bne L1 liveregs)))
  20206. (define-primop 'internal:check-<:fix:fix
  20207. (lambda (as src1 src2 L1 liveregs)
  20208. (emit-fixnum-compare-check
  20209. as src1 src2 sparc.bge L1 liveregs)))
  20210. (define-primop 'internal:check-<=:fix:fix
  20211. (lambda (as src1 src2 L1 liveregs)
  20212. (emit-fixnum-compare-check
  20213. as src1 src2 sparc.bg L1 liveregs)))
  20214. (define-primop 'internal:check->:fix:fix
  20215. (lambda (as src1 src2 L1 liveregs)
  20216. (emit-fixnum-compare-check
  20217. as src1 src2 sparc.ble L1 liveregs)))
  20218. (define-primop 'internal:check->=:fix:fix
  20219. (lambda (as src1 src2 L1 liveregs)
  20220. (emit-fixnum-compare-check
  20221. as src1 src2 sparc.bl L1 liveregs)))
  20222. (define-primop 'internal:check-=:fix:fix/imm
  20223. (lambda (as src1 imm L1 liveregs)
  20224. (emit-fixnum-compare/imm-check
  20225. as src1 imm sparc.bne L1 liveregs)))
  20226. (define-primop 'internal:check-<:fix:fix/imm
  20227. (lambda (as src1 imm L1 liveregs)
  20228. (emit-fixnum-compare/imm-check
  20229. as src1 imm sparc.bge L1 liveregs)))
  20230. (define-primop 'internal:check-<=:fix:fix/imm
  20231. (lambda (as src1 imm L1 liveregs)
  20232. (emit-fixnum-compare/imm-check
  20233. as src1 imm sparc.bg L1 liveregs)))
  20234. (define-primop 'internal:check->:fix:fix/imm
  20235. (lambda (as src1 imm L1 liveregs)
  20236. (emit-fixnum-compare/imm-check
  20237. as src1 imm sparc.ble L1 liveregs)))
  20238. (define-primop 'internal:check->=:fix:fix/imm
  20239. (lambda (as src1 imm L1 liveregs)
  20240. (emit-fixnum-compare/imm-check
  20241. as src1 imm sparc.bl L1 liveregs)))
  20242. ; Below, 'target' is a label or #f. If #f, RD must be a general hardware
  20243. ; register or RESULT, and a boolean result is generated in RD.
  20244. (define (emit-fixnum-compare as branchf.a rs1 rs2 rd exn target)
  20245. (if (unsafe-code)
  20246. (emit-fixnum-compare-trusted as branchf.a rs1 rs2 rd target)
  20247. (let ((rs2 (force-hwreg! as rs2 $r.argreg2))
  20248. (L0 (new-label))
  20249. (L1 (new-label)))
  20250. (sparc.label as L0)
  20251. (sparc.orr as rs1 rs2 $r.tmp0)
  20252. (sparc.btsti as $r.tmp0 3)
  20253. (sparc.be.a as L1)
  20254. (sparc.cmpr as rs1 rs2)
  20255. (if (not (= rs1 $r.result)) (sparc.move as rs1 $r.result))
  20256. (if (not (= rs2 $r.argreg2)) (sparc.move as rs2 $r.argreg2))
  20257. (sparc.set as (thefixnum exn) $r.tmp0)
  20258. (millicode-call/ret as $m.exception L0)
  20259. (sparc.label as L1)
  20260. (emit-evaluate-cc! as branchf.a rd target))))
  20261. ; Below, 'target' is a label or #f. If #f, RD must be a general hardware
  20262. ; register or RESULT, and a boolean result is generated in RD.
  20263. (define (emit-fixnum-compare-trusted as branchf.a rs1 rs2 rd target)
  20264. (let ((rs2 (force-hwreg! as rs2 $r.argreg2)))
  20265. (sparc.cmpr as rs1 rs2)
  20266. (emit-evaluate-cc! as branchf.a rd target)))
  20267. ; rs must be a hardware register.
  20268. (define (emit-fixnum-compare/imm as branchf.a rs imm rd exn target)
  20269. (if (unsafe-code)
  20270. (emit-fixnum-compare/imm-trusted as branchf.a rs imm rd target)
  20271. (let ((L0 (new-label))
  20272. (L1 (new-label)))
  20273. (sparc.label as L0)
  20274. (sparc.btsti as rs 3)
  20275. (sparc.be.a as L1)
  20276. (sparc.cmpi as rs (thefixnum imm))
  20277. (if (not (= rs $r.result)) (sparc.move as rs $r.result))
  20278. (sparc.set as (thefixnum imm) $r.argreg2)
  20279. (sparc.set as (thefixnum exn) $r.tmp0)
  20280. (millicode-call/ret as $m.exception L0)
  20281. (sparc.label as L1)))
  20282. (emit-evaluate-cc! as branchf.a rd target))
  20283. ; rs must be a hardware register.
  20284. (define (emit-fixnum-compare/imm-trusted as branchf.a rs imm rd target)
  20285. (sparc.cmpi as rs (thefixnum imm))
  20286. (emit-evaluate-cc! as branchf.a rd target))
  20287. ; Range checks.
  20288. (define (emit-fixnum-compare-check
  20289. as src1 src2 branch-bad L1 liveregs)
  20290. (internal-primop-invariant1 'emit-fixnum-compare-check src1)
  20291. (let ((src2 (force-hwreg! as src2 $r.argreg2)))
  20292. (sparc.cmpr as src1 src2)
  20293. (emit-checkcc! as branch-bad L1 liveregs)))
  20294. (define (emit-fixnum-compare/imm-check
  20295. as src1 imm branch-bad L1 liveregs)
  20296. (internal-primop-invariant1 'emit-fixnum-compare/imm-check src1)
  20297. (sparc.cmpi as src1 imm)
  20298. (emit-checkcc! as branch-bad L1 liveregs))
  20299. ; eof
  20300. ; Copyright 1998 Lars T Hansen.
  20301. ;
  20302. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  20303. ;
  20304. ; SPARC machine assembler flags.
  20305. ;
  20306. ; 12 April 1999
  20307. ; INTERNAL!
  20308. (define short-effective-addresses
  20309. (make-twobit-flag 'short-effective-addresses))
  20310. (define runtime-safety-checking
  20311. (make-twobit-flag 'runtime-safety-checking))
  20312. (define catch-undefined-globals
  20313. (make-twobit-flag 'catch-undefined-globals))
  20314. (define inline-allocation
  20315. (make-twobit-flag 'inline-allocation))
  20316. ;(define inline-assignment
  20317. ; (make-twobit-flag 'inline-assignment))
  20318. (define write-barrier
  20319. (make-twobit-flag 'write-barrier))
  20320. (define peephole-optimization
  20321. (make-twobit-flag 'peephole-optimization))
  20322. (define single-stepping
  20323. (make-twobit-flag 'single-stepping))
  20324. (define fill-delay-slots
  20325. (make-twobit-flag 'fill-delay-slots))
  20326. ; For backward compatibility.
  20327. ;(define unsafe-code
  20328. ; (make-twobit-flag 'unsafe-code))
  20329. (define (unsafe-code . args)
  20330. (if (null? args)
  20331. (not (runtime-safety-checking))
  20332. (runtime-safety-checking (not (car args)))))
  20333. (define (display-assembler-flags which)
  20334. (case which
  20335. ((debugging)
  20336. (display-twobit-flag single-stepping))
  20337. ((safety)
  20338. (display-twobit-flag write-barrier)
  20339. ;(display-twobit-flag unsafe-code)
  20340. (display-twobit-flag runtime-safety-checking)
  20341. (if (runtime-safety-checking)
  20342. (begin (display " ")
  20343. (display-twobit-flag catch-undefined-globals))))
  20344. ((optimization)
  20345. (display-twobit-flag peephole-optimization)
  20346. (display-twobit-flag inline-allocation)
  20347. ; (display-twobit-flag inline-assignment)
  20348. (display-twobit-flag fill-delay-slots))
  20349. (else #t)))
  20350. (define (set-assembler-flags! mode)
  20351. (case mode
  20352. ((no-optimization)
  20353. (set-assembler-flags! 'standard)
  20354. (peephole-optimization #f)
  20355. (fill-delay-slots #f))
  20356. ((standard)
  20357. (short-effective-addresses #t)
  20358. (catch-undefined-globals #t)
  20359. (inline-allocation #f)
  20360. ; (inline-assignment #f)
  20361. (peephole-optimization #t)
  20362. (runtime-safety-checking #t)
  20363. (write-barrier #t)
  20364. (single-stepping #f)
  20365. (fill-delay-slots #t))
  20366. ((fast-safe default)
  20367. (set-assembler-flags! 'standard)
  20368. ; (inline-assignment #t)
  20369. (inline-allocation #t))
  20370. ((fast-unsafe)
  20371. (set-assembler-flags! 'fast-safe)
  20372. (catch-undefined-globals #f)
  20373. (runtime-safety-checking #f))
  20374. (else
  20375. (error "set-assembler-flags!: unknown mode " mode))))
  20376. (set-assembler-flags! 'default)
  20377. ; eof
  20378. ; Copyright 1998 Lars T Hansen.
  20379. ;
  20380. ; $Id: twobit.sch,v 1.3 1999/08/23 19:14:26 lth Exp $
  20381. ;
  20382. ; SPARC disassembler.
  20383. ;
  20384. ; (disassemble-instruction instruction address)
  20385. ; => decoded-instruction
  20386. ;
  20387. ; (disassemble-codevector codevector)
  20388. ; => decoded-instruction-list
  20389. ;
  20390. ; (print-instructions decoded-instruction-list)
  20391. ; => unspecified
  20392. ; Also takes an optional port and optionally the symbol "native-names".
  20393. ;
  20394. ; (format-instruction decoded-instruction address larceny-names?)
  20395. ; => string
  20396. ;
  20397. ; A `decoded-instruction' is a list where the car is a mnemonic and
  20398. ; the operands are appropriate for that mnemonic.
  20399. ;
  20400. ; A `mnemonic' is an exact nonnegative integer. It encodes the name of
  20401. ; the instruction as well as its attributes (operand pattern and instruction
  20402. ; type). See below for specific operations on mnemonics.
  20403. (define (disassemble-codevector cv)
  20404. (define (loop addr ilist)
  20405. (if (< addr 0)
  20406. ilist
  20407. (loop (- addr 4)
  20408. (cons (disassemble-instruction (bytevector-word-ref cv addr)
  20409. addr)
  20410. ilist))))
  20411. (loop (- (bytevector-length cv) 4) '()))
  20412. (define disassemble-instruction) ; Defined below.
  20413. ; Mnemonics
  20414. (define *asm-annul* 1)
  20415. (define *asm-immed* 2)
  20416. (define *asm-store* 4)
  20417. (define *asm-load* 8)
  20418. (define *asm-branch* 16)
  20419. (define *asm-freg* 32)
  20420. (define *asm-fpop* 64)
  20421. (define *asm-no-op2* 128)
  20422. (define *asm-no-op3* 256)
  20423. (define *asm-bits*
  20424. `((a . ,*asm-annul*) (i . ,*asm-immed*) (s . ,*asm-store*)
  20425. (l . ,*asm-load*) (b . ,*asm-branch*) (f . ,*asm-freg*)
  20426. (fpop . ,*asm-fpop*) (no-op2 . ,*asm-no-op2*) (no-op3 . ,*asm-no-op3*)))
  20427. (define *asm-mnemonic-table* '())
  20428. (define mnemonic
  20429. (let ((n 0))
  20430. (lambda (name . rest)
  20431. (let* ((probe (assq name *asm-mnemonic-table*))
  20432. (code (* 1024
  20433. (if probe
  20434. (cdr probe)
  20435. (let ((code n))
  20436. (set! n (+ n 1))
  20437. (set! *asm-mnemonic-table*
  20438. (cons (cons name code)
  20439. *asm-mnemonic-table*))
  20440. code)))))
  20441. (for-each (lambda (x)
  20442. (set! code (+ code (cdr (assq x *asm-bits*)))))
  20443. rest)
  20444. code))))
  20445. (define (mnemonic:name mnemonic)
  20446. (let ((mnemonic (quotient mnemonic 1024)))
  20447. (let loop ((t *asm-mnemonic-table*))
  20448. (cond ((null? t) #f)
  20449. ((= (cdar t) mnemonic) (caar t))
  20450. (else (loop (cdr t)))))))
  20451. (define (mnemonic=? m name)
  20452. (= (quotient m 1024) (quotient (mnemonic name) 1024)))
  20453. (define (mnemonic:test bit)
  20454. (lambda (mnemonic)
  20455. (not (zero? (logand mnemonic bit)))))
  20456. (define (mnemonic:test-not bit)
  20457. (lambda (mnemonic)
  20458. (zero? (logand mnemonic bit))))
  20459. (define mnemonic:annul? (mnemonic:test *asm-annul*))
  20460. (define mnemonic:immediate? (mnemonic:test *asm-immed*))
  20461. (define mnemonic:store? (mnemonic:test *asm-store*))
  20462. (define mnemonic:load? (mnemonic:test *asm-load*))
  20463. (define mnemonic:branch? (mnemonic:test *asm-branch*))
  20464. (define mnemonic:freg? (mnemonic:test *asm-freg*))
  20465. (define mnemonic:fpop? (mnemonic:test *asm-fpop*))
  20466. (define mnemonic:op2? (mnemonic:test-not *asm-no-op2*))
  20467. (define mnemonic:op3? (mnemonic:test-not *asm-no-op3*))
  20468. ; Instruction disassembler.
  20469. (let ()
  20470. ;; Useful constants
  20471. (define two^3 (expt 2 3))
  20472. (define two^5 (expt 2 5))
  20473. (define two^6 (expt 2 6))
  20474. (define two^8 (expt 2 8))
  20475. (define two^9 (expt 2 9))
  20476. (define two^12 (expt 2 12))
  20477. (define two^13 (expt 2 13))
  20478. (define two^14 (expt 2 14))
  20479. (define two^16 (expt 2 16))
  20480. (define two^19 (expt 2 19))
  20481. (define two^21 (expt 2 21))
  20482. (define two^22 (expt 2 22))
  20483. (define two^24 (expt 2 24))
  20484. (define two^25 (expt 2 25))
  20485. (define two^29 (expt 2 29))
  20486. (define two^30 (expt 2 30))
  20487. (define two^32 (expt 2 32))
  20488. ;; Class 0 has branches and weirdness, like sethi and nop.
  20489. ;; We dispatch first on the op2 field and then on the op3 field.
  20490. (define class00
  20491. (let ((b-table
  20492. (vector (mnemonic 'bn 'b)
  20493. (mnemonic 'be 'b)
  20494. (mnemonic 'ble 'b)
  20495. (mnemonic 'bl 'b)
  20496. (mnemonic 'bleu 'b)
  20497. (mnemonic 'bcs 'b)
  20498. (mnemonic 'bneg 'b)
  20499. (mnemonic 'bvs 'b)
  20500. (mnemonic 'ba 'b)
  20501. (mnemonic 'bne 'b)
  20502. (mnemonic 'bg 'b)
  20503. (mnemonic 'bge 'b)
  20504. (mnemonic 'bgu 'b)
  20505. (mnemonic 'bcc 'b)
  20506. (mnemonic 'bpos 'b)
  20507. (mnemonic 'bvc 'b)
  20508. (mnemonic 'bn 'a 'b)
  20509. (mnemonic 'be 'a 'b)
  20510. (mnemonic 'ble 'a 'b)
  20511. (mnemonic 'bl 'a 'b)
  20512. (mnemonic 'bleu 'a 'b)
  20513. (mnemonic 'bcs 'a 'b)
  20514. (mnemonic 'bneg 'a 'b)
  20515. (mnemonic 'bvs 'a 'b)
  20516. (mnemonic 'ba 'a 'b)
  20517. (mnemonic 'bne 'a 'b)
  20518. (mnemonic 'bg 'a 'b)
  20519. (mnemonic 'bge 'a 'b)
  20520. (mnemonic 'bgu 'a 'b)
  20521. (mnemonic 'bcc 'a 'b)
  20522. (mnemonic 'bpos 'a 'b)
  20523. (mnemonic 'bvc 'a 'b)))
  20524. (fb-table
  20525. (vector (mnemonic 'fbn 'b)
  20526. (mnemonic 'fbne 'b)
  20527. (mnemonic 'fblg 'b)
  20528. (mnemonic 'fbul 'b)
  20529. (mnemonic 'fbl 'b)
  20530. (mnemonic 'fbug 'b)
  20531. (mnemonic 'fbg 'b)
  20532. (mnemonic 'fbu 'b)
  20533. (mnemonic 'fba 'b)
  20534. (mnemonic 'fbe 'b)
  20535. (mnemonic 'fbue 'b)
  20536. (mnemonic 'fbge 'b)
  20537. (mnemonic 'fbuge 'b)
  20538. (mnemonic 'fble 'b)
  20539. (mnemonic 'fbule 'b)
  20540. (mnemonic 'fbo 'b)
  20541. (mnemonic 'fbn 'a 'b)
  20542. (mnemonic 'fbne 'a 'b)
  20543. (mnemonic 'fblg 'a 'b)
  20544. (mnemonic 'fbul 'a 'b)
  20545. (mnemonic 'fbl 'a 'b)
  20546. (mnemonic 'fbug 'a 'b)
  20547. (mnemonic 'fbg 'a 'b)
  20548. (mnemonic 'fbu 'a 'b)
  20549. (mnemonic 'fba 'a 'b)
  20550. (mnemonic 'fbe 'a 'b)
  20551. (mnemonic 'fbue 'a 'b)
  20552. (mnemonic 'fbge 'a 'b)
  20553. (mnemonic 'fbuge 'a 'b)
  20554. (mnemonic 'fble 'a 'b)
  20555. (mnemonic 'fbule 'a 'b)
  20556. (mnemonic 'fbo 'a 'b)))
  20557. (nop (mnemonic 'nop))
  20558. (sethi (mnemonic 'sethi)))
  20559. (lambda (ip instr)
  20560. (let ((op2 (op2field instr)))
  20561. (cond ((= op2 #b100)
  20562. (if (zero? (rdfield instr))
  20563. `(,nop)
  20564. `(,sethi ,(imm22field instr) ,(rdfield instr))))
  20565. ((= op2 #b010)
  20566. `(,(vector-ref b-table (rdfield instr))
  20567. ,(* 4 (imm22field instr))))
  20568. ((= op2 #b110)
  20569. `(,(vector-ref fb-table (rdfield instr))
  20570. ,(* 4 (imm22field instr))))
  20571. (else
  20572. (disasm-error "Can't disassemble " (number->string instr 16)
  20573. " at ip=" ip
  20574. " with op2=" op2)))))))
  20575. ;; Class 1 is the call instruction; there's no choice.
  20576. (define (class01 ip instr)
  20577. `(,(mnemonic 'call) ,(* 4 (imm30field instr))))
  20578. ;; Class 2 is for the ALU. Dispatch on op3 field.
  20579. (define class10
  20580. (let ((op3-table
  20581. `#((,(mnemonic 'add) ,(mnemonic 'add 'i))
  20582. (,(mnemonic 'and) ,(mnemonic 'and 'i))
  20583. (,(mnemonic 'or) ,(mnemonic 'or 'i))
  20584. (,(mnemonic 'xor) ,(mnemonic 'xor 'i))
  20585. (,(mnemonic 'sub) ,(mnemonic 'sub 'i))
  20586. (,(mnemonic 'andn) ,(mnemonic 'andn 'i))
  20587. (,(mnemonic 'orn) ,(mnemonic 'orn 'i))
  20588. (,(mnemonic 'xnor) ,(mnemonic 'xnor 'i))
  20589. (0 0)
  20590. (0 0)
  20591. (0 0) ; 10
  20592. (,(mnemonic 'smul) ,(mnemonic 'smul 'i))
  20593. (0 0)
  20594. (0 0)
  20595. (0 0)
  20596. (,(mnemonic 'sdiv) ,(mnemonic 'sdiv 'i))
  20597. (,(mnemonic 'addcc) ,(mnemonic 'addcc 'i))
  20598. (,(mnemonic 'andcc) ,(mnemonic 'andcc 'i))
  20599. (,(mnemonic 'orcc) ,(mnemonic 'orcc 'i))
  20600. (,(mnemonic 'xorcc) ,(mnemonic 'xorcc 'i))
  20601. (,(mnemonic 'subcc) ,(mnemonic 'subcc 'i)) ; 20
  20602. (0 0)
  20603. (0 0)
  20604. (0 0)
  20605. (0 0)
  20606. (0 0)
  20607. (0 0)
  20608. (,(mnemonic 'smulcc) ,(mnemonic 'smulcc 'i))
  20609. (0 0)
  20610. (0 0)
  20611. (0 0) ; 30
  20612. (,(mnemonic 'sdivcc) ,(mnemonic 'sdivcc 'i))
  20613. (,(mnemonic 'taddcc) ,(mnemonic 'taddcc 'i))
  20614. (,(mnemonic 'tsubcc) ,(mnemonic 'tsubcc 'i))
  20615. (0 0)
  20616. (0 0)
  20617. (0 0)
  20618. (,(mnemonic 'sll) ,(mnemonic 'sll 'i))
  20619. (,(mnemonic 'srl) ,(mnemonic 'srl 'i))
  20620. (,(mnemonic 'sra) ,(mnemonic 'sra 'i))
  20621. (,(mnemonic 'rd) 0) ; 40
  20622. (0 0)
  20623. (0 0)
  20624. (0 0)
  20625. (0 0)
  20626. (0 0)
  20627. (0 0)
  20628. (0 0)
  20629. (,(mnemonic 'wr) ,(mnemonic 'wr 'i))
  20630. (0 0)
  20631. (0 0) ; 50
  20632. (0 0)
  20633. (0 0)
  20634. (0 0)
  20635. (0 0)
  20636. (0 0)
  20637. (,(mnemonic 'jmpl) ,(mnemonic 'jmpl 'i))
  20638. (0 0)
  20639. (0 0)
  20640. (0 0)
  20641. (,(mnemonic 'save) ,(mnemonic 'save 'i)) ; 60
  20642. (,(mnemonic 'restore) ,(mnemonic 'restore 'i))
  20643. (0 0)
  20644. (0 0))))
  20645. (lambda (ip instr)
  20646. (let ((op3 (op3field instr)))
  20647. (if (or (= op3 #b110100) (= op3 #b110101))
  20648. (fpop-instruction ip instr)
  20649. (nice-instruction op3-table ip instr))))))
  20650. ;; Class 3 is memory stuff.
  20651. (define class11
  20652. (let ((op3-table
  20653. `#((,(mnemonic 'ld 'l) ,(mnemonic 'ld 'i 'l))
  20654. (,(mnemonic 'ldb 'l) ,(mnemonic 'ldb 'i 'l))
  20655. (,(mnemonic 'ldh 'l) ,(mnemonic 'ldh 'i 'l))
  20656. (,(mnemonic 'ldd 'l) ,(mnemonic 'ldd 'i 'l))
  20657. (,(mnemonic 'st 's) ,(mnemonic 'st 'i 's))
  20658. (,(mnemonic 'stb 's) ,(mnemonic 'stb 'i 's))
  20659. (,(mnemonic 'sth 's) ,(mnemonic 'sth 'i 's))
  20660. (,(mnemonic 'std 's) ,(mnemonic 'std 'i 's))
  20661. (0 0)
  20662. (0 0)
  20663. (0 0) ; 10
  20664. (0 0)
  20665. (0 0)
  20666. (0 0)
  20667. (0 0)
  20668. (0 0)
  20669. (0 0)
  20670. (0 0)
  20671. (0 0)
  20672. (0 0)
  20673. (0 0) ; 20
  20674. (0 0)
  20675. (0 0)
  20676. (0 0)
  20677. (0 0)
  20678. (0 0)
  20679. (0 0)
  20680. (0 0)
  20681. (0 0)
  20682. (0 0)
  20683. (0 0) ; 30
  20684. (0 0)
  20685. (,(mnemonic 'ldf 'f 'l) ,(mnemonic 'ldf 'i 'f 'l))
  20686. (0 0)
  20687. (0 0)
  20688. (,(mnemonic 'lddf 'f 'l) ,(mnemonic 'lddf 'i 'f 'l))
  20689. (,(mnemonic 'stf 'f 's) ,(mnemonic 'stf 'i 'f 's))
  20690. (0 0)
  20691. (0 0)
  20692. (,(mnemonic 'stdf 'f 's) ,(mnemonic 'stdf 'i 'f 's))
  20693. (0 0) ; 40
  20694. (0 0)
  20695. (0 0)
  20696. (0 0)
  20697. (0 0)
  20698. (0 0)
  20699. (0 0)
  20700. (0 0)
  20701. (0 0)
  20702. (0 0)
  20703. (0 0) ; 50
  20704. (0 0)
  20705. (0 0)
  20706. (0 0)
  20707. (0 0)
  20708. (0 0)
  20709. (0 0)
  20710. (0 0)
  20711. (0 0)
  20712. (0 0)
  20713. (0 0) ; 60
  20714. (0 0)
  20715. (0 0)
  20716. (0 0))))
  20717. (lambda (ip instr)
  20718. (nice-instruction op3-table ip instr))))
  20719. ;; For classes 2 and 3
  20720. (define (nice-instruction op3-table ip instr)
  20721. (let* ((op3 (op3field instr))
  20722. (imm (ifield instr))
  20723. (rd (rdfield instr))
  20724. (rs1 (rs1field instr))
  20725. (src2 (if (zero? imm)
  20726. (rs2field instr)
  20727. (imm13field instr))))
  20728. (let ((op ((if (zero? imm) car cadr) (vector-ref op3-table op3))))
  20729. `(,op ,rs1 ,src2 ,rd))))
  20730. ;; Floating-point operate instructions
  20731. (define (fpop-instruction ip instr)
  20732. (let ((rd (rdfield instr))
  20733. (rs1 (rs1field instr))
  20734. (rs2 (rs2field instr))
  20735. (fpop (fpop-field instr)))
  20736. `(,(cdr (assv fpop fpop-names)) ,rs1 ,rs2 ,rd)))
  20737. (define fpop-names
  20738. `((#b000000001 . ,(mnemonic 'fmovs 'fpop 'no-op2))
  20739. (#b000000101 . ,(mnemonic 'fnegs 'fpop 'no-op2))
  20740. (#b000001001 . ,(mnemonic 'fabss 'fpop 'no-op2))
  20741. (#b001000010 . ,(mnemonic 'faddd 'fpop))
  20742. (#b001000110 . ,(mnemonic 'fsubd 'fpop))
  20743. (#b001001010 . ,(mnemonic 'fmuld 'fpop))
  20744. (#b001001110 . ,(mnemonic 'fdivd 'fpop))
  20745. (#b001010010 . ,(mnemonic 'fcmpd 'fpop 'no-op3))))
  20746. ;; The following procedures pick apart an instruction
  20747. (define (op2field instr)
  20748. (remainder (quotient instr two^22) two^3))
  20749. (define (op3field instr)
  20750. (remainder (quotient instr two^19) two^6))
  20751. (define (ifield instr)
  20752. (remainder (quotient instr two^13) 2))
  20753. (define (rs2field instr)
  20754. (remainder instr two^5))
  20755. (define (rs1field instr)
  20756. (remainder (quotient instr two^14) two^5))
  20757. (define (rdfield instr)
  20758. (remainder (quotient instr two^25) two^5))
  20759. (define (imm13field instr)
  20760. (let ((x (remainder instr two^13)))
  20761. (if (not (zero? (quotient x two^12)))
  20762. (- x two^13)
  20763. x)))
  20764. (define (imm22field instr)
  20765. (let ((x (remainder instr two^22)))
  20766. (if (not (zero? (quotient x two^21)))
  20767. (- x two^22)
  20768. x)))
  20769. (define (imm30field instr)
  20770. (let ((x (remainder instr two^30)))
  20771. (if (not (zero? (quotient x two^29)))
  20772. (- x two^30)
  20773. x)))
  20774. (define (fpop-field instr)
  20775. (remainder (quotient instr two^5) two^9))
  20776. (set! disassemble-instruction
  20777. (let ((class-table (vector class00 class01 class10 class11)))
  20778. (lambda (instr addr)
  20779. ((vector-ref class-table (quotient instr two^30)) addr instr))))
  20780. 'disassemble-instruction)
  20781. ; Instruction printer
  20782. ;
  20783. ; It assumes that the first instruction comes from address 0, and prints
  20784. ; addresses (and relative addresses) based on that assumption.
  20785. ;
  20786. ; If the optional symbol native-names is supplied, then SPARC register
  20787. ; names is used, and millicode calls are not annotated with millicode names.
  20788. (define (print-instructions ilist . rest)
  20789. (define port (current-output-port))
  20790. (define larceny-names? #t)
  20791. (define (print-ilist ilist a)
  20792. (if (null? ilist)
  20793. '()
  20794. (begin (display (format-instruction (car ilist) a larceny-names?)
  20795. port)
  20796. (newline port)
  20797. (print-ilist (cdr ilist) (+ a 4)))))
  20798. (do ((rest rest (cdr rest)))
  20799. ((null? rest))
  20800. (cond ((port? (car rest))
  20801. (set! port (car rest)))
  20802. ((eq? (car rest) 'native-names)
  20803. (set! larceny-names? #f))))
  20804. (print-ilist ilist 0))
  20805. (define format-instruction) ; Defined below
  20806. (define *format-instructions-pretty* #t)
  20807. ; Instruction formatter.
  20808. (let ()
  20809. (define use-larceny-registers #t)
  20810. (define sparc-register-table
  20811. (vector "%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
  20812. "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%o6" "%o7"
  20813. "%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
  20814. "%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%i6" "%i7"))
  20815. (define larceny-register-table
  20816. (make-vector 32 #f))
  20817. (define (larceny-register-name reg . rest)
  20818. (if (null? rest)
  20819. (or (and use-larceny-registers
  20820. (vector-ref larceny-register-table reg))
  20821. (vector-ref sparc-register-table reg))
  20822. (vector-set! larceny-register-table reg (car rest))))
  20823. (define millicode-procs '())
  20824. (define (float-register-name reg)
  20825. (string-append "%f" (number->string reg)))
  20826. (define op car)
  20827. (define op1 cadr)
  20828. (define op2 caddr)
  20829. (define op3 cadddr)
  20830. (define tabstring (string #\tab))
  20831. (define (heximm n)
  20832. (if (>= n 16)
  20833. (string-append tabstring "! 0x" (number->string n 16))
  20834. ""))
  20835. (define (millicode-name offset . rest)
  20836. (if (null? rest)
  20837. (let ((probe (assv offset millicode-procs)))
  20838. (if probe
  20839. (cdr probe)
  20840. "[unknown]"))
  20841. (set! millicode-procs
  20842. (cons (cons offset (car rest)) millicode-procs))))
  20843. (define (millicode-call offset)
  20844. (string-append tabstring "! " (millicode-name offset)))
  20845. (define (plus/minus n)
  20846. (cond ((< n 0)
  20847. (string-append " - " (number->string (abs n))))
  20848. ((and (= n 0) *format-instructions-pretty*) "")
  20849. (else
  20850. (string-append " + " (number->string n)))))
  20851. (define (srcreg instr extractor)
  20852. (if (mnemonic:freg? (op instr))
  20853. (float-register-name (extractor instr))
  20854. (larceny-register-name (extractor instr))))
  20855. (define (sethi instr)
  20856. (string-append (number->string (* (op1 instr) 1024)) ", "
  20857. (larceny-register-name (op2 instr))
  20858. (heximm (* (op1 instr) 1024))))
  20859. (define (rrr instr)
  20860. (string-append (larceny-register-name (op1 instr)) ", "
  20861. (larceny-register-name (op2 instr)) ", "
  20862. (larceny-register-name (op3 instr))))
  20863. (define (rir instr)
  20864. (string-append (larceny-register-name (op1 instr)) ", "
  20865. (number->string (op2 instr)) ", "
  20866. (larceny-register-name (op3 instr))
  20867. (heximm (op2 instr))))
  20868. (define (sir instr)
  20869. (string-append (srcreg instr op3) ", [ "
  20870. (larceny-register-name (op1 instr))
  20871. (plus/minus (op2 instr)) " ]"))
  20872. (define (srr instr)
  20873. (string-append (srcreg instr op3) ", [ "
  20874. (larceny-register-name (op1 instr)) "+"
  20875. (larceny-register-name (op2 instr)) " ]"))
  20876. (define (lir instr)
  20877. (string-append "[ " (larceny-register-name (op1 instr))
  20878. (plus/minus (op2 instr)) " ], "
  20879. (srcreg instr op3)))
  20880. (define (lrr instr)
  20881. (string-append "[ " (larceny-register-name (op1 instr)) "+"
  20882. (larceny-register-name (op2 instr)) " ], "
  20883. (srcreg instr op3)))
  20884. (define (bimm instr addr)
  20885. (string-append "#" (number->string (+ (op1 instr) addr))))
  20886. (define (jmpli instr)
  20887. (string-append (larceny-register-name (op1 instr))
  20888. (plus/minus (op2 instr)) ", "
  20889. (larceny-register-name (op3 instr))
  20890. (if (and (= (op1 instr) $r.globals)
  20891. use-larceny-registers)
  20892. (millicode-call (op2 instr))
  20893. (heximm (op2 instr)))))
  20894. (define (jmplr instr)
  20895. (string-append (larceny-register-name (op1 instr)) "+"
  20896. (larceny-register-name (op2 instr)) ", "
  20897. (larceny-register-name (op3 instr))))
  20898. (define (call instr addr)
  20899. (string-append "#" (number->string (+ (op1 instr) addr))))
  20900. (define (rd instr)
  20901. (string-append "%y, " (srcreg instr op3)))
  20902. (define (wr instr imm?)
  20903. (if imm?
  20904. (string-append (larceny-register-name (op1 instr)) ", "
  20905. (number->string (op2 instr)) ", %y"
  20906. (larceny-register-name (op3 instr)))
  20907. (string-append (larceny-register-name (op1 instr)) ", "
  20908. (larceny-register-name (op2 instr)) ", %y")))
  20909. (define (fpop instr op2-used? op3-used?)
  20910. (string-append (float-register-name (op1 instr)) ", "
  20911. (cond ((and op2-used? op3-used?)
  20912. (string-append
  20913. (float-register-name (op2 instr)) ", "
  20914. (float-register-name (op3 instr))))
  20915. (op2-used?
  20916. (float-register-name (op2 instr)))
  20917. (else
  20918. (float-register-name (op3 instr))))))
  20919. ;; If we want to handle instruction aliases (clr, mov, etc) then
  20920. ;; the structure of this procedure must change, because as it is,
  20921. ;; the printing of the name is independent of the operand values.
  20922. (define (format-instr i a larceny-names?)
  20923. (set! use-larceny-registers larceny-names?)
  20924. (let ((m (car i)))
  20925. (string-append (number->string a)
  20926. tabstring
  20927. (symbol->string (mnemonic:name m))
  20928. (if (mnemonic:annul? m) ",a" "")
  20929. tabstring
  20930. (cond ((mnemonic:store? m)
  20931. (if (mnemonic:immediate? m) (sir i) (srr i)))
  20932. ((mnemonic:load? m)
  20933. (if (mnemonic:immediate? m) (lir i) (lrr i)))
  20934. ((mnemonic:fpop? m)
  20935. (fpop i (mnemonic:op2? m) (mnemonic:op3? m)))
  20936. ((mnemonic:branch? m) (bimm i a))
  20937. ((mnemonic=? m 'sethi) (sethi i))
  20938. ((mnemonic=? m 'nop) "")
  20939. ((mnemonic=? m 'jmpl)
  20940. (if (mnemonic:immediate? m) (jmpli i) (jmplr i)))
  20941. ((mnemonic=? m 'call) (call i a))
  20942. ((mnemonic=? m 'rd) (rd i))
  20943. ((mnemonic=? m 'wr) (wr i (mnemonic:immediate? m)))
  20944. ((mnemonic:immediate? m) (rir i))
  20945. (else (rrr i))))))
  20946. (larceny-register-name $r.tmp0 "%tmp0")
  20947. (larceny-register-name $r.result "%result")
  20948. (larceny-register-name $r.argreg2 "%argreg2")
  20949. (larceny-register-name $r.argreg3 "%argreg3")
  20950. (larceny-register-name $r.tmp1 "%tmp1")
  20951. (larceny-register-name $r.tmp2 "%tmp2")
  20952. (larceny-register-name $r.reg0 "%r0")
  20953. (larceny-register-name $r.reg1 "%r1")
  20954. (larceny-register-name $r.reg2 "%r2")
  20955. (larceny-register-name $r.reg3 "%r3")
  20956. (larceny-register-name $r.reg4 "%r4")
  20957. (larceny-register-name $r.reg5 "%r5")
  20958. (larceny-register-name $r.reg6 "%r6")
  20959. (larceny-register-name $r.reg7 "%r7")
  20960. (larceny-register-name $r.e-top "%etop")
  20961. (larceny-register-name $r.e-limit "%elim")
  20962. (larceny-register-name $r.timer "%timer")
  20963. (larceny-register-name $r.millicode "%millicode")
  20964. (larceny-register-name $r.globals "%globals")
  20965. (larceny-register-name $r.stkp "%stkp") ; note: after elim
  20966. (millicode-name $m.alloc "alloc")
  20967. (millicode-name $m.alloci "alloci")
  20968. (millicode-name $m.gc "gc")
  20969. (millicode-name $m.addtrans "addtrans")
  20970. (millicode-name $m.stkoflow "stkoflow")
  20971. (millicode-name $m.stkuflow "stkuflow")
  20972. (millicode-name $m.creg "creg")
  20973. (millicode-name $m.creg-set! "creg-set!")
  20974. (millicode-name $m.add "+")
  20975. (millicode-name $m.subtract "- (binary)")
  20976. (millicode-name $m.multiply "*")
  20977. (millicode-name $m.quotient "quotient")
  20978. (millicode-name $m.remainder "remainder")
  20979. (millicode-name $m.divide "/")
  20980. (millicode-name $m.modulo "modulo")
  20981. (millicode-name $m.negate "- (unary)")
  20982. (millicode-name $m.numeq "=")
  20983. (millicode-name $m.numlt "<")
  20984. (millicode-name $m.numle "<=")
  20985. (millicode-name $m.numgt ">")
  20986. (millicode-name $m.numge ">=")
  20987. (millicode-name $m.zerop "zero?")
  20988. (millicode-name $m.complexp "complex?")
  20989. (millicode-name $m.realp "real?")
  20990. (millicode-name $m.rationalp "rational?")
  20991. (millicode-name $m.integerp "integer?")
  20992. (millicode-name $m.exactp "exact?")
  20993. (millicode-name $m.inexactp "inexact?")
  20994. (millicode-name $m.exact->inexact "exact->inexact")
  20995. (millicode-name $m.inexact->exact "inexact->exact")
  20996. (millicode-name $m.make-rectangular "make-rectangular")
  20997. (millicode-name $m.real-part "real-part")
  20998. (millicode-name $m.imag-part "imag-part")
  20999. (millicode-name $m.sqrt "sqrt")
  21000. (millicode-name $m.round "round")
  21001. (millicode-name $m.truncate "truncate")
  21002. (millicode-name $m.apply "apply")
  21003. (millicode-name $m.varargs "varargs")
  21004. (millicode-name $m.typetag "typetag")
  21005. (millicode-name $m.typetag-set "typetag-set")
  21006. (millicode-name $m.break "break")
  21007. (millicode-name $m.eqv "eqv?")
  21008. (millicode-name $m.partial-list->vector "partial-list->vector")
  21009. (millicode-name $m.timer-exception "timer-exception")
  21010. (millicode-name $m.exception "exception")
  21011. (millicode-name $m.singlestep "singlestep")
  21012. (millicode-name $m.syscall "syscall")
  21013. (millicode-name $m.bvlcmp "bvlcmp")
  21014. (millicode-name $m.enable-interrupts "enable-interrupts")
  21015. (millicode-name $m.disable-interrupts "disable-interrupts")
  21016. (millicode-name $m.alloc-bv "alloc-bv")
  21017. (millicode-name $m.global-ex "global-exception")
  21018. (millicode-name $m.invoke-ex "invoke-exception")
  21019. (millicode-name $m.global-invoke-ex "global-invoke-exception")
  21020. (millicode-name $m.argc-ex "argc-exception")
  21021. (set! format-instruction format-instr)
  21022. 'format-instruction)
  21023. ; eof
  21024. ; ----------------------------------------------------------------------
  21025. (define (twobit-benchmark type . rest)
  21026. (let ((k (if (null? rest) 1 (car rest))))
  21027. (run-benchmark
  21028. "twobit"
  21029. k
  21030. (lambda ()
  21031. (case type
  21032. ((long)
  21033. (compiler-switches 'fast-safe)
  21034. (benchmark-block-mode #f)
  21035. (compile-file "benchmarks/twobit-input-long.sch"))
  21036. ((short)
  21037. (compiler-switches 'fast-safe)
  21038. (benchmark-block-mode #t)
  21039. (compile-file "benchmarks/twobit-input-short.sch"))
  21040. (else
  21041. (error "Benchmark type must be `long' or `short': " type))))
  21042. (lambda (result)
  21043. #t))))
  21044. ; eof