שפות ביניים: יצירת הקוד

30
דדדד דדדדדד: דדדדד דדדדAho, Sethi and Ullman – Ch. 8

Upload: lixue

Post on 16-Jan-2016

61 views

Category:

Documents


0 download

DESCRIPTION

שפות ביניים: יצירת הקוד. Aho, Sethi and Ullman – Ch. 8. int fib(int n) { if (n

TRANSCRIPT

שפות ביניים: יצירת הקוד

Aho, Sethi and Ullman – Ch. 8

יצירת קוד – דוגמא פשוטה 'מהחיים'

int fib(int n){ if (n<=1) return 1; return fib(n-1) + fib(n-2);}

“gcc –S fib.c” creates fib.s:

.fib: mflr 0 ; r0 := lr stw 29,-12(1) ; *r1-12 := r29 stw 31,-4(1) ; *r1-4 := r31 stw 0,8(1) ; *r1+8 := r0 (lr) stwu 1,-72(1) ; r1 := r1-72, *r1=r1 mr 31,1 ; r31 := r1 stw 3,96(31) ; *r31+96 := r3 (‘n’) lwz 0,96(31) ; r0 := *r31+96 (‘n’) cmpwi 0,0,1 ; cr0 := r0 ~ 1 bgt 0,L..3 ; if cr0.gt goto L..3

li 3,1 ; r3 := 1 b L..2 ; goto L..2 (return 1)L..3:

L..3: lwz 9,96(31) ; r9 := *r31+96 (‘n’) addi 0,9,-1 ; r0 := r9 - 1 mr 3,0 ; r3 := r0 bl .fib ; call fib(n-1) mr 29,3 ; r29 := r3 lwz 9,96(31) ; r9 := *r31+96 (‘n’) addi 0,9,-2 ; r0 := r9 - 2 mr 3,0 ; r3 := r0 bl .fib ; call fib(n-2) mr 9,3 ; r9 := r3 add 0,29,9 ; r0 := r29 + r9 mr 3,0 ; r3 := r0 b L..2 ; goto L..2L..2: lwz 1,0(1) ; r1 := *r1 lwz 0,8(1) ; r0 := *r1+8 mtlr 0 ; lr := r0 lwz 29,-12(1) ; r29 := *r1-12 lwz 31,-4(1) ; r31 := *r1-4 blr ; goto lr (return)

יצירת קוד

צבירת קוד במשתני ביניים של אפשרות א' –(codeהמהדר )בתכונות מסוג

יצירת קובץ המכיל את הקוד תוך אפשרות ב' –כדי תהליך הקומפילציה

אפשרות זו מעשית אם לכל חוק דקדוק תכונת של אגף שמאל של החוק מתקבלת codeה-

של הלא-טרמינלים codeמשרשור תכונות ה- באגף ימין של החוק על פי סדר הופעתן )אולי

בצירוף מחרוזות נוספות(

משפטי השמה

P → M D

M → D → D ; D | id : T proc id ; N D1 ; S

N →

דקדוק המסגרת

ביטויים ומשפטי השמה

הערה – ניתן לעשות שימוש חוזר במשתנים זמניים על ידי ניהולם במחסנית

S → id := E{ p := lookup ) id.name ( ; if p nil then emit ) p ' := ' E.place ( else error ( }

E → E1 + E2{ E.place := newtemp)( ; emit ) E.place ' := ' E1.place ' + ' E2.place ( }

E → E1 * E2{ E.place := newtemp)( ; emit ) E.place ' := ' E1.place ' * ' E2.place ( }

E → – E1{ E.place := newtemp)( ; emit ) E.place ' := ' ' uminus ' E1.place ( }

E → ) E1 ({ E.place := E1.place }

E → id{ p := lookup ) id.name(; if p nil then E.place := p else error }

הכרזות מקוננות

ביטויים בוליאניים

false – 0

true – 1

הערה – כתובת המטרה ניתנת לחישוב תוך כדי יצירת הקוד

E → E1 or E2{ E.place := newtemp)( ; emit ) E.place ' := ' E1.place ' or ' E2.place ( }

E → E1 and E2{ E.place := newtemp)( ; emit ) E.place ' := ' E1.place ' and ' E2.place ( }

E → not E1{ E.place := newtemp)( ; emit ) E.place ' := ' ' not ' E1.place ( }

E → ) E1 ({ E.place := E1.place }

E → id1 relop id2{ E.place := newtemp)( ;

emit ) ' if ' id1.place 'relop.op id2.place ' goto ' nextstat + 3 ( ;

emit ) E.place ' := ' ' 0 ' ( ; emit ) ' goto ' nextstat + 2 ( ;

emit ) E.place ' := ' ' 1 ' ( }

E → true{ E.place := newtemp)( ; emit ) E.place ' := ' ' 1 ' ( }

E → false{ E.place := newtemp)( ; emit ) E.place ' := ' ' 0 ' ( }

ייצוג נומרי

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

100:if a < b goto 103101:T1 := 0102:goto 104103:T1 := 1104:

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

100:if a < b goto 103101:T1 := 0102:goto 104103:T1 := 1104:if c < d goto 107

105:T2 := 0106:goto 108107:T2 := 1108:

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

100:if a < b goto 103101:T1 := 0102:goto 104103:T1 := 1104:if c < d goto 107

105:T2 := 0106:goto 108107:T2 := 1108:if e < f goto 111

109:T3 := 0110:goto 112111:T3 := 1112:

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

100:if a < b goto 103101:T1 := 0102:goto 104103:T1 := 1104:if c < d goto 107

105:T2 := 0106:goto 108107:T2 := 1108:if e < f goto 111

109:T3 := 0110:goto 112111:T3 := 1112:T4 := T2 and T3

ביטויים בוליאניים בייצוג מספרי – דוגמא

f<ed<c

EandEb<a

EorE

E

100:if a < b goto 103101:T1 := 0102:goto 104103:T1 := 1104:if c < d goto 107

105:T2 := 0106:goto 108107:T2 := 1108:if e < f goto 111

109:T3 := 0110:goto 112111:T3 := 1112:T4 := T2 and T3

113:T5 := T1 or T4

ביטויים בוליאניים – חישוב מקוצר

בניגוד לביטויים אריתמטיים, בביטויים בוליאניים ניתן לעיתים לדעת מה התוצאה

כבר באמצע הדרך.

true הוא E1, אם E1 or E2למשל, בביטוי !E2הרי שלא חשוב לנו מה ערכו של

אוlazy evaluationחישוב כזה נקרא short circuit boolean evaluation.

ביטויים בוליאניים – חישוב מקוצר

100: if a < b goto 103

101: T1 := 0

102: goto 104

103: T1 := 1

104: if c < d goto 107

105: T2 := 0

106: goto 108

107: T2 := 1

108: if e < f goto 111

109: T3 := 0

110: goto 112

111: T3 := 1

112: T4 := T2 and T3

113: T5 := T1 and T4

100: if a < b goto 105

101: if !)c < d( goto 103

102: if e < f goto 105

103: T := 0

104: goto 106

105: T := 1

106:

a < b or )c < d and e < f(

ביטויים בוליאניים – חישוב מקוצר

האם החישוב המקוצר שקול לחלוטין לחישוב הרגיל?

להשתמש בחישוב מקוצר?אסורמתי

להשתמש בחישוב מקוצר?חייביםמתי

ביטויים בוליאניים – ייצוג באמצעות הפניית בקרה

ההקשר – משפטים מותנים

השיטה – לכל ביטוי נצמיד שתי תויותB.true התווית אליה החישוב צריך לעבור אם – B הוא trueB.false התווית אליה החישוב צריך לעבור אם – B הוא false

S →

|

|

if B then S1

if B then S1 else S2

while B do S1

משפטים מותנים

if–then

הן תכונות נורשותS.next ו- B.falseהערה –

S מיד אחרי הקוד של : S.nextהערה – צריך להוסיף קוד ליצירת התווית

הערה – המדובר בכתובות סימבוליות

. . .B.false:

S1.codeB.true:

B.code→ to B.true

→ to B.false

S → if B then S1{B.true := newlabel)( ;

B.false := S.next ;

S1.next := S.next ;

S.code := B.code || gen ) B.true ' : ' ( || S1.code

}

משפטים מותנים

if–then–else→ to B.true

→ to B.false

S → if B then S1 else S2{B.true := newlabel )(;

B.false := newlabel )(;

S1.next := S.next ;

S2.next := S.next ;

S.code := B.code || gen ) B.true ' : ' ( || S1.code ||

gen ) ' goto ' S.next ( || gen ) B.false ' : ' ( || S2.code }

B.code

B.true:S1.code

goto S.next

B.false:S2.code

S.next:. . .

חישוב ביטויים בוליאניים על ידי הפנית בקרה

איזו צורת חישוב מוצגת כאן?

B → B1 or B2{ B1.true := B.true ; B1.false := newlable)( ; B2.true := B.true ;

B2.false := B.false ; B.code := B1.code || gen ) B1.false ' : '( || B2.code }

B → B1 and B2{ B1.true := newlabel )(; B1.false := B.false ; B2.true := B.true ;

B2.false := B.false ; B.code := B1.code || gen ) B1.true ' : )' || B2.code }

B → not B1{ B1.true := B.false ; B1.false := B.true ; B.code := B1.code }

B → ) B1 ({ B1.true := B.true ; B1.false := B.false ; B.code := B1.code }

B → id1 relop id2{ B.code := gen ) ' if ' id1.place relop.op id2.place ' goto ' B.true ( ||

gen ) ' goto ' B.false ( }

B → true{ B.code := gen ) ' goto ' B.true ( }

B → false{ B.code := gen ) ' goto ' B.false ( }

backpatchingתיקון לאחור –

קושי – זו אינה סכימה ש"קל לחשב": היא לאS-attributed)יש גם תכונות נורשות( היא לאL-attributed התכונות הנורשות אינן(

בהכרח נורשות-משמאל( לכן צריך לחשב אותה בעזרת האלגוריתם

הכללי, ואי אפשר לעשות זאת תוך כדי הניתוח.

ניהול רשימת דרך מקובלת לפתור בעיה זו – ותיקונן בהמשךהתחייבויות

זו דרך כללית להמיר כל תכונה נורשת בתכונהנוצרת

backpatchingתיקון לאחור –

.backpatchingה"תיקון בהמשך" נקרא

טכניקהmakelist ) i ( יצירת רשימת התחייבויות חדשה –

. התוצאה – מצביע לרשימהiהמכילה את iהוא מספר שורה ברשימת הרביעיות שלנו

merge ) p1, p2 ( איחוד הרשימות אליהם – . מחזיר מצביע לתוצאה. p2ו- p1מצביעים

backpatch ) p, i ( הכנסת – i כתווית בכל אחת pמהרביעיות שברשימה אליה מצביע

backpatchingתיקון לאחור –

אגירת הקוד הנוצר:

בשיטה הקודמת לא ידענו מה יהיה סדר החישוב של התכונות

זה היה תלוי במיון טופולוגי

לכן היינו צריכים לאגור את הקוד הנוצר בתכונה code ולדאוג בעצמנו שהוא יופיע בסדר הנכון ,

)ע"י שרשור(

לדוגמא:B → B1 and B2{ B1.true := newlabel)( ; B1.false := B.false ; B2.true := B.true ;

B2.false := B.false ; B.code := B1.code || gen ) B1.true ' : '( || B2.code }

backpatchingתיקון לאחור –

אגירת הקוד הנוצר:

כעת סדר החישוב ידוע:הניתוח הסמנטי יתבצע במהלך הניתוח התחבירי הסדר יהיהbottom-up נניח תמיד ניתוח( LR)

codeלא חייבים לאגור את הקוד בתכונה

)buffer )emitאפשר מייד להדפיס אותו ל- צריך לדאוג להדפיס את הקוד בסדר הנכון -אין חרטות", פרט ל"backpatch

את הפקודה מחזירה gen: gen ל- emitההבדל בין .buffer מדפיסה אותה ל- emitשנוצרה;

תיקון לאחור

nextquadהרביעיה הבאה –

truelist רשימת התחייבויות למקרה – true

falselist רשימת התחייבויות למקרה – falseB → B1 or M B2{ backpatch ) B1.falselist, M.quad ( ;

B.truelist := merge ) B1.truelist, B2.truelist ( ; B.falselist := B2.falselist }

B → B1 and M B2{ backpatch ) B1.truelist, M.quad ( ; B.truelist := B2.truelist ;

B.falselist := merge ) B1.falselist, B2.falselist ( }

B → not B1{ B.truelist := B1.falselist ; B.falselist := B1.truelist }

B → ) B1 ({ B.truelist := B1.truelist ; B.falselist := B1.falselist }

B → id1 relop id2{ B.truelist := makelist ) nextquad ( ;

B.falselist := makelist ) nextquad + 1 ( ;

emit ) ' if ' id1.place relop.op id2.place ' goto_ ' ( ; emit ) ' goto_ ' ( }

B → true{ B.truelist := makelist ) nextquad ( ; emit ) ' goto_ ' ( }B → false{ B.falselist := makelist ) nextquad ( ; emit ) ' goto_ ' ( }

M → { M.quad := nextquad }

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

100

101

if a < b goto ___

goto ___

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

100

101

if a < b goto ___

goto ___102

103

if c < d goto ___

goto ___

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

100

101

if a < b goto ___

goto ___102

103

if c < d goto ___

goto ___104

105

if e < f goto ___

goto ___

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

100

101

if a < b goto ___

goto ___102

103

if c < d goto 104

goto ___104

105

if e < f goto ___

goto ___

תיקון לאחור

<ec < fd

<a and M.q = 104b

or

B.t = {104}

B.f = {105}B.t = {102}

B.f = {103}

B.t = {104}

B.f = {103, 105}M.q = 102

B.t = {100}

B.f = {101}

B.t = {100, 104}

B.f = {103, 105}

100

101

if a < b goto ___

goto 102102

103

if c < d goto 104

goto ___104

105

if e < f goto ___

goto ___

תיקון לאחור – הפנית בקרה

S → if B then M1 S1 N else M2 S2

{ backpatch ) B.truelist , M1.quad ( ; { backpatch ) B.falselist , M2.quad ( ;

S.next := merge ) S1.nextlist, N.nextlist, S2.nextlist ( }

N → { N.nextlist := makelist ) nextquad ( ; emit ) ' goto_ ' ( }M → { M.quad := nextquad }B → ) B1 ({ B.truelist := B1.truelist ; B.falselist := B1.falselist }

S → if B then M S1

{ backpatch )B.truelist , M.quad ( ;

S.nextlist := merge ) B.falselist, S1.nextlist ( }

S → while M1 B do M2 S1

{ backpatch ) S1.nextlist, M1.quad ( ; backpatch ) B.truelist , M2.quad ( } ;

S.nextlist := B.falselist ; emit ) ' goto_ ' M1.quad ( }

S → begin L end{ S.nextlist := L.nextlist }S → A{ S.nextlist := makelist ) ( }L → L1 ; M S { backpatch )L1.nextlist , M.quad ( ; L.nextlist := S.nextlist }

L → S{ L.nextlist := S.nextlist }