Upload
lixue
View
61
Download
0
Embed Size (px)
DESCRIPTION
שפות ביניים: יצירת הקוד. Aho, Sethi and Ullman – Ch. 8. int fib(int n) { if (n
Citation preview
יצירת קוד – דוגמא פשוטה 'מהחיים'
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
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 }