TIE448 Kääntäjätekniikka, syksy 2009 Antti-Juhani Kaijanaho TIETOTEKNIIKAN LAITOS 13. lokakuuta 2009
Sisällys
Sisällys
Seuraava deadline Vaihe C tiistai 20.10. klo 10 kielivirheiden diagnoosi, sokerin pilkkominen Vaihe D tiistai 3.11. klo 10 välikielen generointi
Kääntäjän rakenne lähdeohjelma SELAAJA sanasjono JÄSENTÄJÄ VÄLIKOODIN GENEROIJA KOHDEKOODIN GENEROIJA rakennepuu välikoodi kohdeohjelma TARKASTAJA SOKERINPILKKOJA OPTIMOIJA OPTIMOIJA
Välikoodin generointi tavoitteena muuttaa ohjelma muotoon, joka muistuttaa lopullista suorituskelpoista ohjelmaa muutamia yksinkertaistuksia välikielen generoinnin ja käsittelyn helpottamiseksi mahdollista kirjoittaa välikielelle tulkki ( virtuaalikone ) esim. testausta varten olennainen käsitteellinen jako: lokaali (hyppyjen välit) globaali eli aliohjelman sisäinen interproseduraalinen eli aliohjelmien välinen
Tämä luento näkökulma interproseduraalinen Tarkastellaan aliohjelmien toteutuksen perusongelmia. Nimellisesti D-vaiheen luento mutta sisältää myös myöhempien vaiheiden asiaa.
Sisällys
Aliohjelman aktivaatio Kun aliohjelmaa kutsutaan, sen paikallisista muuttujista (myös parametrit) muodostetaan uudet esiintymät. Näiden paikallisten muuttujien esiintymien kokoelmaa kutsutaan aliohjelman aktivaatioksi. Aktivaatio pääsääntöisesti tuhotaan aliohjelman suorituksen päättyessä. Aliohjelmasta voi olla samanaikaisesti useita aktivaatioita. Muinaisella 1950- ja 1960-luvulla aliohjelman aktivaatiolle varattiin usein tietty muistialue, jolloin aktivaatioita saattoi olla kerrallaan vain yksi.
Aktivaatioiden samanaikaisuus Säikeet Eri säikeissä voi olla samanaikaisesti sama aliohjelma käynnissä. Rekursio Jos aliohjelma kutsuu itseään (vaikka epäsuorasti), on siitä samassa säikeessä olemassa yhtä aikaa useita aktivaatioita. Muita syitä callcc (Scheme, ML) ensiluokkaiset
Aktivaation tulee tietää aliohjelman saamat parametrit aliohjelman paikallisten muuttujien tähän aktivaatioon liittyvät esiintymät Mihin osoitteeseen tulee hypätä aliohjelman tultua valmiiksi? Mihin aliohjelma-aktivaatioon siirrytään aliohjelman tultua valmiiksi? ns. dynaaminen linkki Jos kyseessä on aliohjelman A sisäinen aliohjelma B, missä A:n aktivaatiossa esiintyvät B:n tarvitsemat A:n paikalliset muuttujat? ns. staattinen linkki Jos kyseessä on olion metodi, osoitin olion ilmentymään ns. this-osoitin Nämä tiedot sisältävää tietorakennetta sanotaan aktivaatiotietueeksi.
Sisällys
Väliaikainen oletus: ei ensiluokkaisia aliohjelmia Seuraavassa oletetaan, että ainakin toinen seuraavista ehdoista pitää paikkaansa: Aliohjelmia ei voi määritellä toisen aliohjelman sisällä. C-kielessä on näin Pascal-kielessä ei ole näin Aliohjelmaa ei voi palauttaa aliohjelmasta eikä tallettaa muuttujaan (muutoin kuin mahdollisesti aliohjelman argumenttina). C-kielessä ei ole näin Pascal-kielessä on näin Nämä eivät päde esimerkkikielelle, mutta pätevät useimmille harjoitustöille. Lisäksi oletetaan, että kieli ei tue callcc:tä tai muita vastaavia jekkuja.
Aktivaatiopino Saman säikeen aliohjelma-aktivaatiot muodostavat pinon... toteutettuna yksinkertaisesti linkittynä listana (linkkinä dynaaminen linkki) Aliohjelmaa kutsuttaessa sille muodostetaan aktivaatiotietue, joka lisätään pinon päällimmäiseksi. Aliohjelman päättyessä sen aktivaatiotietue on pinon päällimmäisenä; poistetaan se pinosta ja tuhotaan se. Tavallisesti aktivaatiopino rakennetaan niin, että aktivaatiopinot ovat fyysisestikin päällekäin muistissa. Näin aktivaatiotietueen luominen ja tuhoaminen on erittäin nopeaa. Jos on useita säikeitä, jokaisella on oma aktivaatiopinonsa.
Terminologiaa Aktivaatiopino kutsupino (engl. call stack) funktiopino (engl. function stack) pino (engl. the stack) ietue (pinossa) pinokehys (engl. stack frame) kutsukehys (engl. call frame)
Aktivaatiopinon rautatuki Käytännössä kaikki ISA:t sisältävät tukea aktivaatiopinon käsittelyyn. Yleensä yksi rekisteri on varattu pino-osoittimen käyttöön -osoitin osoittaa yleensä pinon päällimmäisenä olevaan sanaan. Usein myös erityiset PUSH- ja POP-käskyt Tosin aktivaatiotietue kannattaa yleensä luoda kerralla eikä yksittäinen muuttuja kerrallaan muuttamalla pino-osoittimen arvoa suoraan. Usein aktivaatiopino kasvaa alaspäin. Tällöin pinon päällimmäisenä oleva sana on pienimmässä muistiosoitteessa.
Rekisteri-ikkuna Joissakin ISA:issa on tuki rekisteri-ikkunalle. alun perin Berkeley RISC -koneessa myös SPARC ja MMIX ei kuitenkaan IA32 ja AMD64 Idea: rekisteristö on pinon jatke. Päällimmäinen aktivaatiotietue sijaitsee rekistereissä. Erityinen käsky siirtää sen muistissa olevaan pinoon ja vapauttaa rekisterit uuden aktivaatiotietueen käyttöön. Yleensä nämä ikkunat menevät osittain päällekäin, jolloin tätä päällekkäistä aluetta käytetään parametrinvälitykseen.
ietueen koko yleensä tiedossa käännösaikana Tällöin FP ja pino-osoitin ovat käännösaikana tiedossa olevan siirtymän päässä toisistaan. FP:lle ei tällöin tarvitse varata rekisteriä Jos kuitenkin jokin paikallisen muuttujan koko riippuu ajon aikana annettavasta tiedosta (esim. taulukko, jonka koko riippuu syötteestä), ei näin ole.
Sisällys
ietueen rakenne pinossa ietueen rakenteen määrää käytettävä ABI-standardi. Voi toki määritellä omankin, mutta silloin ei pysty kutsumaan esim. C-kielistä aliohjelmaa. tyypillinen rakenne: 1. aliohjelman parametrit 2. this-osoitin (jos tarpeen) 3. paluuosoite 4. dynaaminen linkki 5. staattinen linkki (jos tarpeen) 6. paikalliset muuttujat (pinon päällimmäisenä) Tyypillisesti aktivaatiotietueen osoitin (ns. frame pointer) osoittaa dynaamiseen linkkiin. Tällöin aktivaatiotietueessa on tavaraa tietueen osoitteesta laskien sekä negatiivisessa että positiivisessä siirtymässä.
ietueen rakentaminen 1 Kutsuva aliohjelma aloittaa aktivaatiotietueen rakentamisen: Se laittaa pinoon oman aktivaatiotietueensa päälle argumentit ja tarvittaessa this-osoittimen. Sitten se laittaa pinoon paluuosoitteeksi osoitteen kutsua seuraavaan käskyyn ja hyppää aliohjelmaan. yleensä molemmat samalla CALL-käskyllä Kutsuttava aliohjelma jatkaa rakentamista: Se laittaa pinon päällimmäiseksi kutsujan aktivaatiotietueen osoitteen (joka on ollut tallennettuna sille varattuun rekisteriin FP). Sitten se pistää aktivaatiotietueensa osoitteen FP-rekisteriin. Sitten se varaa pinosta tilaa lopulle aktivaatiotietueelleen ja alustaa tarvittavat osat. 1 Rakentamisjärjestyksen ja työnjaon kutsujan ja kutsuttavan välillä määrittelee ABI-standardi. Tässä esitetty on vain yksi mahdollinen tapa.
ietueen purkaminen 2 Palaava aliohjelma aloittaa aktivaatiotietueen purkamisen: Se poistaa ensin pinosta aktivaatiotietueen päällimmäisen osan dynaamiseen linkkiin asti (poistamtta dynaamista linkkiä). Sitten se lataa dynaamisen linkin FP-rekisteriin ja poistaa sen pinosta. Sitten se poistaa pinosta argumentit ja siirtää paluuosoitteen pinoon päällimmäiseksi. Sitten se poistaa pinosta paluuosoitteen ja hyppää siihen. yleensä molemmat samalla RET-käskyllä Jatkavalle aliohjelmalle ei jää enää tehtävää. Usein tosin argumenttien poisto jätetään jatkavan aliohjelman tehtäväksi. 2 Purkamisjärjestyksen ja työnjaon palaajan ja jatkajan välillä määrittelee ABI-standardi. Tässä esitetty on vain yksi mahdollinen tapa.
Häntäkutsun poistaminen Jos aliohjelma kutsuu viimeisenä tekonaan jotain toista aliohjelmaa, kyseessä on häntäkutsu (engl. tail call). Java-tyylisessä kielessä häntäkutsu on muotoa return f(...). Häntäkutsu voi olla myös muunlainen; häntäkutsujen tunnistaminen tapahtuu helpoiten erillisellä rakennepuun läpikäynnillä. Häntäkutsussa kutsuja 1. purkaa oman aktivaatiotietueensa (hyppäämättä kuitenkaan paluuosoitteeseen) ja 2. kutsuu sitten normaaliin tapaan häntäkutsuttavaa aliohjelmaa (aloittaen sen aktivaatiotietueen rakentamisen) 3. ja antaa itselleen annetun paluuosoitteen häntäkutsuttavan aliohjelman paluuosoitteeksi! Tämä temppu ei onnistu kovin helposti, jos argumentit poistaa joku muu kuin ne saava aliohjelma itse.
Parametrinvälitys Edellä on esitetty, että parametrit kulkevat aina pinossa. Tämä on hidasta, sillä muistin käsittely on hidasta. Useimmat tarvitsevat vain kourallisen parametreja. Niinpä fiksua on välittää muutama ensimmäinen parametri rekistereissä ja vasta loput pinossa. Toimintatapa riippuu ABI-standardista. Esim. AMD64-Linux käyttää rekistereitä, IA32-Linux ei.
Sisällys
Aliohjelma on ensiluokkainen (engl. first class), jos se rikkoo molempia edellä esitettyjä oletuksia, eli se voidaan määritellä jonkin toisen aliohjelman sisällä ja se voidaan palauttaa aliohjelman paluuarvona tai tallettaa muuttujaan vapaasti. Kaksi ongelmaa: Kun aliohjelma tallennetaan muuttujaan tai palautetaan paluuarvona, mitä sinne muuttujaan tai paluuarvoon oikeasti laitetaan? Aliohjelma voi viitata jonkin toisen aliohjelman paikallisiin muuttujiin sen jälkeen kun ko. aliohjelma on jo lopettanut toimintansa!
Sulkeuma Sulkeuma on aliohjelmaa (ei sen aktivaatiota) ajon aikana edustava tietue. Se sisältää riittävästi tietoa aliohjelmasta, että sen perusteella ko. aliohjelmaa voidaan kutsua tietämättä mitä aliohjelmaa ollaan kutsumassa. Sulkeuma sisältää osoitteen, johon hypätään aliohjelmaa kutsuttaessa aliohjelman tarvitseman staattisen linkin mahdollisesti muutakin tietoa (esim. this-osoitin) Mutta miten ratkaistaan se, että staattisen linkin kohteena oleva aktivaatiotietue saattaa olla jo tuhottu sulkeuman kautta kutsuttaessa?
Yksinkertainen ratkaisu Ei käytetä ISA:n tarjoamaa pinoa lainkaan. Allokoidaan jokainen aktivaatiotietue keosta ja käytetään muistinsiivousta. Jos muistinsiivousalgoritmi valitaan fiksusti, tämä ei juurikaan hidasta ohjelman toimintaa. Tämä tapa on käytännössä pakollinen, jos callcc on tarjolla.
Vähän fiksumpi tapa Jaetaan aktivaatiotietue kahteen eri tietueeseen. Allokoidaan keosta tietue, jonne tallennetaan pakenevat (engl. escaping) paikalliset muuttujat. kehykseen jää kaikki muu sekä osoitin keossa olevaan pakenevien muuttujien tietueeseen. Aliohjelman staattinen linkki ei osoita enää pinokehykseen vaan pakenevien muuttujien tietueeseen.
Milloin muuttuja pakenee? Tarkka analyysi on mahdoton. Huonokin approksimaatio on usein riittävä. Sen tulee olla konservatiivinen eli se saa julistaa muuttujan pakenevaksi vaikka se ei pakenesikaan (mutta ei missään nimessä toisin päin!) Yksinkertainen approksimaatio: muuttuja pakenee jos jokin sisäinen aliohjelma käyttää sitä.
Sisällys
Seuraava deadline Vaihe C tiistai 20.10. klo 10 kielivirheiden diagnoosi, sokerin pilkkominen Vaihe D tiistai 3.11. klo 10 välikielen generointi