תורת הקומפילציה 236360 הרצאה 9 שפות ביניים intermediate...

63
1 הההה הההההההההה236360 ההההה9 הההה ההההההIntermediate Languages/Representations Aho, Sethi and Ullman – Chapter 6 Cooper and Torczon – Chapter 5

Upload: vinaya

Post on 12-Jan-2016

94 views

Category:

Documents


0 download

DESCRIPTION

תורת הקומפילציה 236360 הרצאה 9 שפות ביניים Intermediate Languages/Representations. Aho, Sethi and Ullman – Chapter 6 Cooper and Torczon – Chapter 5. יצירת קוד ביניים. syntax analysis. syntax tree. semantic analysis. decorated syntax tree. intermediate code generator. intermediate code. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

1

236360תורת הקומפילציה 9 הרצאה

שפות ביניים Intermediate Languages/Representations

Aho, Sethi and Ullman – Chapter 6

Cooper and Torczon – Chapter 5

Page 2: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

2

יצירת קוד ביניים

syntax analysis

semantic analysis

intermediate code generator

machine independent optimizations

syntax tree

decorated syntax tree

intermediate code

intermediate code

code generator

Page 3: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

3

חשיבות קוד הביניים

שימוש בשיטות אופטימיזציה שאינן תלויות במכונה מסויימת

front endאפשרות לייצר קוד עבור מכונות שונות באמצעות אותו

front ends עבור שפות שונות – מספר back endשימוש באותו

, אז ניתן לשלב אותם ולקבל n back ends ו-m front-endsאם כתבנו n*m.קומפיילרים

C Java Pascal C#

IntelCrayPowerPC

Intermediate Language

Page 4: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

4

intermediateייצוג ביניים – representation

ייצוגים אפשרייםsyntax treepostfix notationthree address code.זו הצורה שאנו נבחר לעבוד איתה –

.שני אופרנדים ותוצאה אחת

בד"כ עובדים בשני שלבים: תרגום מונחה דקדוק יוצר עץ ניתוח תחבירי + סימונים בצמתים -את העץ מתרגמים לthree address code

DAGנדבר ראשית על ייצוג העץ, לפעמים נשתמש ב- (Directed Acyclic Graph).במקום בעץ

Page 5: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

5

שלושה ייצוגים אפשריים:decorated syntax trees, DAGs-ו ,postfix

a := b * –c + b * –cנתון:

DAGייצוג כ-

assign assign

+ a + a

* * *

uminus b uminus b uminus b

c c c

ייצוג כעץ

postfixייצוג ב- a b c uminus * b c uminus * + assign

Page 6: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

6

תרגום מונחה דקדוק ליצירת עץ מעוטרדוגמה:

פונקציות עזרmkleafיצירת עלה – mkunodeיצירת צומת חדש עבור אופרטור אונרי – mknodeיצירת צומת חדש עבור אופרטור בינארי – id.placeמצביע לטבלת הסמלים –

בפונקציות mknode, ו- mkleaf, mkunodeהערה – אפשר להחליף את DAGהמחזירות מצביע לצמתים קיימים על מנת ליצור

semantic rule productionS.nptr := mknode ( ' assign ' , mkleaf ( id , id.place ), E.nptr ) S → id := EE.nptr := mknode ( ' + ' , E1.nptr , E2.nptr ) E → E1 + E2

E.nptr := mknode ( ' * ' , E1.nptr , E2.nptr ) E → E1 * E2

E.nptr := mkunode ( ' uminus ' , E1.nptr ) E → – E1

E.nptr := E1.nptr E → ( E1 )

E.nptr := mkleaf ( id , id.place ) E → id

Page 7: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

7

* *

uminus uminus

cid cid

bid bid

assign

+

aid

b id 0

c id 1

1 uminus 2

2 0 * 3

b id 4

c id 5

5 uminus 6

6 4 * 7

7 3 + 8

a id 9

8 9 assign 10

· · · 11

ייצוג בזיכרון של עץ מעוטרa := b * –c + b * –c

Page 8: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

8

three address code

אחרי שבונים את העץ, צריך לתרגם לשפת הביניים שבחרנו.

. three-address-codeאנו נעבוד עם

הצורה הכללית של פקודה:

x := y op z

x, y-ו ,z שמות, קבועים, או משתנים זמניים שנוצרו ע"י הקומפיילר.3 הם

op.הוא אופרטור כלשהו

האופרטורים שנשתמש בהם יהיו פשוטים, כך שיהיה קל לעבור מהם לשפת מכונה.

↑ ↑ ↑ הכתובות3

אופרטור

Page 9: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

9

three address code

cc

unimusbunimusb

**

+a

assign

t5:=at2 + t4:=t5

b * t3:=t4

– c:=t3

b * t1:=t2

– c:=t1

c

unimusb

*

+a

assign

t3:=at2 + t2:=t3

b * t1:=t2

– c:=t1

Page 10: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

10

קוד ביניים – סוגי המשפטים

1.

משפטי השמה עם פעולה בינארית

x := y op z

2.

משפטי השמה עם פעולה אונרית

x := op y

3.

משפטי העתקה x := y

4.

קפיצה בלתי מותנה goto L

5.

קפיצה מותנה if x relop y goto L

6.

פרמטרים וקריאה לפרוצדורות param x

call p, n

return y

7.

indexed assignments x := y [ i ]

x [ i ] := y

8.

השמה של כתובות ומצביעים x := addr y

x := * y

* x := y

relop = relational op (==, >=, etc.)

n = actual number of parameters

קריאה לפרוצדורה:

param x1…param xncall p,n

Page 11: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

11

איך בוחרים אופרטורים?

הבחירה של אוסף פקודות מתאים היא חשובה.

אוסף מצומצם: ,קל ליצור קוד מכונה -הקוד יהיה פחות יעיל, ומעמסה גדולה יותר תיפול על הoptimizerהקוד יהיה ארוך והטיפול בו יהיה מסורבלאי ניצול יכולות של מכונות חכמות

אופרטורים רבים: קוד יותר יעיל אך קשה יותר לייצרו וממנו קשה לייצר קוד עבור

מכונות פשוטות.

Page 12: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

12

כתובות על ידי תרגום 3יצירת קוד ביניים בעל מונחה דקדוק

כך שדברים מחושבים לפני שמשתמשים bottom-up parsingככלל, נניח בתוצאת החישוב.

השיטה – שימוש במשתנים זמניים

S.code או) E.code תכונה המכילה את הקוד הנוצר עבור – (S או) E .(

E.var שם של משתנה שעתיד להכיל את הערך של – E

newtempפונקציה המחזירה שם של משתנה חדש –

Page 13: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

13

כתובות על ידי תרגום 3יצירת קוד ביניים בעל מונחה דקדוק

semantic rule production

S.code := E.code || gen ( id.var ' := ' E.var ) S → id := E

E.var := newtemp;E.code := E1.code || E2.code || gen ( E.var ' := ' E1.var ' + ' E2.var )

E → E1 + E2

E.var := newtemp;E.code := E1.code || E2.code || gen ( E.var ' := ' E1.var ' * ' E2.var )

E → E1 * E2

E.var := newtemp;E.code := E1.code || gen ( E.var ' := ' ' uminus ' E1.var )

E → – E1

E.var := E1.var

E.code := ‘(’ || E1.code || ‘)’

E → ( E1 )

E.var := id.var ;E.code := ' '

E → id

Page 14: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

14

)labels: דוגמא לשימוש בתוויות (whileפסוק

S.begin := newlabel ;S.after := newlabel ;S.code := gen ( S.begin ' : ' ) || E.code || gen ( ' if ' E.var ' = ' ' 0 ' ' goto ' S.after ) || S1.code || gen ( ' goto ' S.begin ) || gen (S.after ' : ' )

S → while E do S1

semantic ruleproduction

E.codeS.begin:

if E.var = 0 goto S.after

S1.code

goto S.begin

· · · S.after:

נוסיף תכונות למשתנים, ותוויות.

newlabel פונקציה היוצרת תווית –חדשה

S.begin תווית המסמנת את תחילת – הקוד

S.afterתווית המסמנת את סוף הקוד –

false – מייצג את 0

S → while E do S1

Page 15: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

15

:address code-3מבנה נתונים לייצוג של

ייצוג סטנדרטי הוא ע"י רביעיות כך שכל שורה נכתבת לתוך משתנה זמני.

op, arg1, arg2, result

יתרון: פשוט + אין בעיה להעתיק ולהזיז קטעי קוד (וזה חשוב לאופטימיזציות).

בטבלת הסמליםtemporariesעלות – מחייב לשמור את ה-

↑ ↑ ↑מצביעים לטבלת הסמלים

at5=:(5)

t5t4t2+(4)

t4t3b*(3)

t3cuminus(2)

t2t1b*(1)

t1cuminus(0)

resultarg 2arg 1op

t1 = - c

t2 = b * t1

t3 = - c

t4 = b * t3

t5 = t2 * t4

a = t5

Page 16: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

16

address code-3ייצוג נוסף של

(התוצאה מובנת כמספר op, arg1, arg2שלשות : השורה)

resultאין צורך ב-

דורשת שתי x [ i ] := yאבל: אי אפשר להזיז קוד + פעולה טרנרית כמו שורות

↑ ↑מצביעים לטבלת הסמלים או למספר הסידורי של השורה המחשבת את הערך

(4)aassign(5)(3)(1)+(4)(2)b*(3)

cuminus(2)(0)b*(1)

cuminus(0)arg 2arg 1op

y(0)assign(1)ix[ ] =(0)

arg 2arg 1op

(0)xassign(1)iy= [ ](0)

arg 2arg 1op

x [ i ] := y x := y [ i ]

Page 17: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

17

Execution Order

101101

1512

address code-3ייצוג שלישי של

indirect triplesהשלשות מופרדות מהסדר ביניהן –

עתה ניתן לשנות סדר ביצוע, להזיז קטעי קוד, ולחסוך במקום אם קיימות שלשות זהות

(לא פותר את הפעולה הכפולה עבור פעולות טרנריות.)

(4)aassign

(3)(1)+

(2)b*

cuminus

(0)b*

cuminus

arg 2arg 1op

5

4

3

2

1

0

רשימת פקודות לפי סדר הביצוע

הרצוי שלהן

Page 18: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

18

Typesוהקצאות זיכרון למשתנים

חשוב מאד לבדיקת שגיאות, typesניתוח ה-

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

כתובות בתוך מערכים.

...

...

רשומת הפעלה למתודה

employeeמקום למשתנה

משתנים קודמים

employeeל-

employee

Offset for variable employee

Page 19: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

19

הכרזות והקצאת זכרון. offset תרגום מונחה דקדוק עם פעולות סמנטיות לחישוב ה- דוגמא:

עם גודל השטח שהוקצה עד עתה.offsetנשמור משתנה גלובלי

.offsetלכל משתנה בפרוצדורה – נכניס לטבלת הסמלים ונקבע לו

semantic rule production

{ offset := 0 } P →P D

D → D D

{ enter ( id.name, T.type, offset ); offset := offset + T.width } D → T id ;

{ T.type := integer ; T.width := 4 } T → integer

{ T.type := real ; T.width := 8 } T → real

{ T.type := array ( num.val, T1.type ) ;

T.width := num.val T1.width }

T → T1 [ num ]

T.type := pointer (T1.type ) ; T.width := 4 } T → *T1

Page 20: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

20

הכרזותP

D2D1

D4

T1id

int count

T2id

real money

T1.type = int

T1.width = 4

enter(count, int, 0) offset = offset + 4

id.name = count

D5

T3 id

balancesT4[ num ]

int 98

T2.type = real

T2.width = 4

enter(money, real, 4) offset = offset + 4

id.name = money

Page 21: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

21

הכרזות והקצאת זיכרון שבו נפעיל את top-down בהתחלה עובד מצוין לניתוח offsetהאיפוס של

P → D בתור הכלל הראשון. אך מה עושים עם ניתוחbottom-up?

LR וכלל שתמיד נראה ראשון, גם ב-markerטריק סטנדרטי: נוסיף parsingsemantic rule production

{ offset := 0 } P →P D

D → D D

{ enter ( id.name, T.type, offset ); offset := offset + T.width } D → T id ;

{ T.type := integer ; T.width := 4 } T → integer

{ T.type := real ; T.width := 8 } T → real

{ T.type := array ( num.val, T1.type ) ;

T.width := num.val T1.width }

T → T1 [ num ]

T.type := pointer (T1.type ) ; T.width := 4 } T → *T1

Page 22: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

22

הכרזות והקצאת זיכרוןבתור P → D שבו נפעיל את top-downהשיטה עובדת מצוין לניתוח

כנדרש. אך מה עושים עם ניתוח offsetהכלל הראשון ונאפס את bottom-up?

LR וכלל שתמיד נראה ראשון, גם ב-markerטריק סטנדרטי: נוסיף parsing

semantic rule production

{ offset := 0 }{ offset := 0 }

P → MDM → Є

P →P D

D → D D

{ enter ( id.name, T.type, offset ); offset := offset + T.width } D → T id ;

{ T.type := integer ; T.width := 4 } T → integer

{ T.type := real ; T.width := 8 } T → real

{ T.type := array ( num.val, T1.type ) ;

T.width := num.val T1.width }

T → [ num ] T1

T.type := pointer (T1.type ) ; T.width := 4 } T → *T1

_____________

P

M D

Є

Page 23: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

23

לסיכום – ייצוג של קוד ביניים

שתלוי front-endקוד ביניים סטנדרטי הוא חשוב, ניתן להפריד בין ה- שתלוי במכונת היעד, ולשלב כל back-endבשפת המקור, לבין ה-

front-end עם כל back-end .

)attributesהשלבים הקודמים בונים עץ מעוטר (עם

שהיא שפת ביניים סטנדרטית.three-address-codeנתרגם אותו אל

אפשר לעשות זאת ע"י פעולות סמנטיות בתרגום מונחה דקדוק. .אוספים את הקוד לתוויות של משתני הדקדוק

Three-address-code ניתן לייצוג ע"י רביעיות או שלשות (ישירות או עקיפות).

חיוני עבור קביעת מקום למשתנים בזיכרון, וגם את זה types ניתוח ה-ניתן לעשות באמצעות פעולות סמנטיות בתרגום מונחה דקדוק...

Page 24: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

24

יצירת קוד ביניים

Page 25: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

25

יצירת קוד

של משתנים בעץ הגזירה (למשל, attributesצבירת קוד ב- אפשרות א' –). כך עשינו עד עתה.codeבתכונות מסוג

יצירת קובץ המכיל את הקוד תוך כדי תהליך הקומפילציה אפשרות ב' – אפשרות זו מעשית (לגזירתbottom-up אם לכל חוק דקדוק תכונת (

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

בצירוף מחרוזות נוספות) .חסרון: לא מאפשר מניפולציות על הקוד במספר שקפים הקרובים נדגים את אפשרות ב'. כמובן שניתן בקלות

לחזור לצבירת קוד בתכונות של משתני הדקדוק שבגזירה.

Page 26: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

26

התוכנית מכילה הגדרות של משתנים (כמו קודם) דקדוק המסגרת:ופרוצדורות.

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

Lookup .מחזיר את הכתובת של המשתנה בזיכרון

Emit פולט שורת קוד מתאימה בפורמט three-address-code.לתוך הקובץ

ולכן מקצים bottom-up parsing הטיפול כאן (ובד"כ בהמשך) הוא לפי למשתנה מקום בפעם הראשונה שפוגשים אותו = כמשתנה השמאלי בכלל

הדקדוק.

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

D → D ; D | T id { N D1 ; S }

N →

P → M DM →

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

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

Page 27: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

27

התוכנית מכילה הגדרות של משתנים (כמו קודם) דקדוק המסגרת:ופרוצדורות.

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

ניתן לייעל במקום הדרוש למשתנים זמניים: כשיוצאים מתת-עץ אין יותר שימוש במשתנים הפנימיים שלו. ניתן לנהל את המשתנים במחסנית.

D → D ; D | T id { N D1 ; S }

N →

P → M DM →

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

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

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

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

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

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

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

Page 28: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

28

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

. 1 כ-true ואת 0 כ-falseנייצג את

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

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

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

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

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

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

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

Page 29: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

29

חישוב ביטויים בוליאניים ע"י קפיצה

. 1 כ-true ואת 0 כ-falseנייצג את

למה זה מועיל? לחישוב מקוצר... אבל נראה קודם דוגמא.

{ E.var := newtemp() ; (lookup (נחפף את emit ( ' if ' id1.var 'relop.op id2.var ' goto ' nextstat + 2 ) ;

emit ( E.var ' := ' ' 0 ' ) ; emit ( ' goto ' nextstat + 1 ) ; emit ( E.var ' := ' ' 1 ' ) }

E → id1 relop id2

Page 30: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

30

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

f<ed<c

EandEb<a

EorE

E

Page 31: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

31

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

f<ed<c

EandEb<a

EorE

E

if a < b goto 103 100:T1 := 0 101:goto 104 102:T1 := 1 103:

Page 32: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

32

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

f<ed<c

EandEb<a

EorE

E

if a < b goto 103 100:T1 := 0 101:goto 104 102:T1 := 1 103:

if c < d goto 107 104:T2 := 0 105:goto 108 106:T2 := 1 107:

Page 33: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

33

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

f<ed<c

EandEb<a

EorE

E

if a < b goto 103 100:T1 := 0 101:goto 104 102:T1 := 1 103:

if c < d goto 107 104:T2 := 0 105:goto 108 106:T2 := 1 107:

if e < f goto 111 108:T3 := 0 109:goto 112 110:T3 := 1 111:

112:

Page 34: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

34

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

f<ed<c

EandEb<a

EorE

E

if a < b goto 103 100:T1 := 0 101:goto 104 102:T1 := 1 103:

if c < d goto 107 104:T2 := 0 105:goto 108 106:T2 := 1 107:

if e < f goto 111 108:T3 := 0 109:goto 112 110:T3 := 1 111:T4 := T2 and T3 112:

Page 35: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

35

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

f<ed<c

EandEb<a

EorE

E

if a < b goto 103 100:T1 := 0 101:goto 104 102:T1 := 1 103:

if c < d goto 107 104:T2 := 0 105:goto 108 106:T2 := 1 107:

if e < f goto 111 108:T3 := 0 109:goto 112 110:T3 := 1 111:T4 := T2 and T3 112:T5 := T1 or T4 113:

Page 36: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

36

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

בניגוד לביטויים אריתמטיים, בביטויים בוליאניים ניתן לחסוך בחישוב כי לעיתים ניתן לדעת מה התוצאה כבר באמצע החישוב.

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

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

Page 37: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

37

דוגמא:

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) ניזכר בביטוי של קודם:

חישוב מקוצר:

Page 38: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

38

תכונות של חישוב מקוצר

האם החישוב מקוצר שקול לחישוב רגיל?1.

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

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

תשובות: לחישוב ביטוי בוליאני. side-effectsלא – יתכנו 1.

if ( (i > 0) and (i++ < 10) ) A[i]=i elseדוגמא קלאסית: B[i]=i ;

כאשר הגדרת השפה לא מרשה זאת. 2.

כאשר הגדרת השפה מחייבת קיצור, והמתכנת עלול להתבסס על כך.3.דוגמא קלאסית:

if ( (file=open(“c:\grades”) or (die) ) printfile(file);

Page 39: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

39

. if, else, while טיפול בהפניות בקרה:

) בשם קוד. attributeנחזור לאגור את הקוד בתכונה ( מדפיסה emit את הפקודה שנוצרה; מחזירה gen: gen ל- emitההבדל בין

. bufferאותה ל-

נתבונן בקפיצות מותנות:

, ואז S לייצר קוד ל-Bאפשרות אחת היא לעבוד כמו קודם, לייצר קוד ל-. B כתלות בערך של S או סוף Sלייצר קפיצה לתחילת

יקפוץ Bאבל באופן יעיל יותר, אפשר פשוט לייצר קוד שבזמן החישוב של . Bלמקום הנכון ברגע שיתגלה מה ערכו של

if B then S1

if B then S1 else S2

while B do S1

S →||

Page 40: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

40

. if, else, while טיפול בהפניות בקרה:

מסתבר שיש כאן בעיה עם ההחלטה לאן לקפוץ בזמן הניתוח...

” לא יודעים למה if B then S עבור "Bכאשר מנתחים את העץ שנפרש מ-S יתפתח ואיפה מתחיל ונגמר הקוד של S אבל צריך לייצר קפיצות ,

למקומות אלו.

שהן התוויות B.false, ו- B.true נצמיד שתי תוויות: Bביטוי השיטה – לכל בהתאמה). false (או true הוא Bאליהן החישוב צריך לעבור אם

שאומרת מה הכתובת של הקוד שאחריו.next נחזיק תווית Sפסוק לכל

S

if B then S

משוואה סמנטיות מתאימה:

B.false = S.next

, נייצר B.trueלגבי label בין הקוד של

B לקוד של S ונייחס לו את

B.true.

Page 41: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

41

nextהתכונה

, נייצר את הקוד עם התווית שאחריו:Sבגזירה של פסוק

היא נורשת: הילד מקבל אותה כשהוא נגזר מאביו.S.nextהתכונה

היא נוצרת: האבא מקבל אותה בעת גזירת ילדיו.codeתכונת ה-

היא סימבולית. הכתובת המתאימה לה תיוודע רק אחרי label S.nextה-.Sשנגזור את כל הביטוי של

S.next = newlabel() ;P.code = S.code || label(S.next) ;

S1.next = newlabel() ;

S2.next = S.next;

S.code = S1.code || label(S1.next) || S2.code

P → S

S → S1 S2

Page 42: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

42

If B then S

B.false -ו S1.nextהן תכונות נורשות

S.codeהיא תכונה נוצרת

. . .B.false:

:SB.trueקוד לחישוב

עם Bקוד לחישוב קפיצות החוצה

→ to B.true

→ to B.false

B.true := newlabel() ;B.false := S.next ;S1.next := S.next ;

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

}

{S → if B then S1

Page 43: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

43

If B then S1 else S2

→ to B.true

→ to B.false

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 }

{ S → if B then S1 else S2

B.code

S1.code B.true:

goto S.next

S2.code B.false:

. . . S.next:

נורש

נוצר

B.True-ו B.false לא נקבעים ע"י ההורים

ולא ע"י הילדים. אבל הם נקבעים בזמן

הוא ילד Bגזירה שבה ולכן נחשבים נורשים.

Page 44: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

44

חישוב ביטויים בוליאניים על ידי הפנית בקרה אם הוא B.false ול-B true אם הערך של B.trueנייצר קוד שקופץ ל-

false.

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

{ 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 or 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 → B1 and B2

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

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

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

gen ( ' goto ' B.false ) }

B → id1 relop id2

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

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

Page 45: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

45

חישוב ביטויים בוליאניים על ידי הפנית בקרה אם הוא B.false ול-B true אם הערך של B.trueנייצר קוד שקופץ ל-

false.

. label B1.falseנתבונן לדוגמא ב-

B1 ניתנת לחישוב רק אחרי שנדע את כל הקוד של labelהכתובת של ה-.B1וכל הקוד שלפני

סימבוליים, ואחרי כן נבצע labelsלמעשה, אנו נייצר את כל הקוד עם סימבולי, ולעדכן את labelמעבר נוסף על העץ כדי לקבוע כתובת לכל

כתובות הקפיצה בפקודות המתאימות.

{ 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 or B2

Page 46: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

46

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

מטרתנו להסתפק במעבר אחד על העץ בזמן היצירה שלו, ללא המעבר הנוסף.

:נשמור לכל השיטה label את אוסף הכתובות של פקודות שמדלגות אליו.

-ברגע שנדע את הכתובת של הlabel נלך על רשימת הכתובות ונכניס ,. labelבפקודות הקפיצה המתאימות את הכתובת האמיתית של ה-

יתרון: מעברDFS.(חישבו על אלפי שורות קוד) יחיד יספיק .חסרון: נצטרך להקצות מקום לרשימות של הכתובות

נדגיש שפתרונות שהזכרנו בעבר לא יעבדו. הגזירה אינהS-attributed יש גם תכונות נורשות, למשל) next.( היא לאL-attributed(התכונות הנורשות אינן בהכרח נורשות-משמאל) .לכן לא נוכל לחשב את התכונות תוך כדי הניתוח

Page 47: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

47

דוגמא להבהרת הקושי

.if-then-elseחישבו על פסוק

צריך כבר לדעת את הקוד של כל הבלוקים S1.nextעל-מנת לחשב את B, S1-ו ,S2 .(כדי לדעת מהי הכתובת שאחריהם)

, או S1.next צריך להעביר לו את S1מצד שני, כדי לחשב את הקוד של S.next אבל ערך זה לא ידוע לפני החישוב של ,S1 .

עם כל כתובות הקפיצה, אבל S1כאמור, לא נוכל לחשב את הקוד של נוכל לחשב אותו עד כדי "השארת מקום" להכנסה מאוחרת יותר של

S1.next .

נבנה את הקוד ונשאיר לעצמנו רשימה עבור backpatchingבשיטת ה- של כל שורות הקוד שבהן יש קפיצה אליו.S1.next הסימבולי labelה-

, נעבור על הרשימה ונעדכן. S1.nextכשנדע את ערכו של

if B

S

then elseS1 S2

Page 48: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

48

פונקציות ליצירה וטיפול בהתחייבויות

makelist ( addr ) יצירת רשימת התחייבויות חדשה המכילה את – . התוצאה – מצביע לרשימה של כתובות של פקודות.addrהכתובת

addrהוא מספר שורה ברשימת הרביעיות שלנו המשמעות: יש לתקן את הפקודה שבשורהaddr כשיתקבל מידע

רלוונטי

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

.כלומר, שתי הרשימות מכילות פקודות שצריכות לקפוץ לאותו מקום

backpatch ( p, addr ) קביעת הכתובת – addr ככתובת הקפיצה בכל pאחת מהפקודות (רביעיות) שברשימה אליה מצביע

Page 49: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

49

אגירת הקוד

כך שהקוד נוצר בסדר הנכון (שמאל bottom-up ניתוח נניח (כהרגלנו)לימין, מלמטה למעלה).

הניתוח הסמנטי יתבצע במהלך הניתוח התחבירי והקוד ייפלט לתוך buffer עם פקודת emit פשוט כדי שיהיה נוח לחשוב על כתובות של)

פקודות).

אפשר גם לאסוף את הקוד בתוך תכונה, כל עוד יש דרך לשמור מצביע ). backpatchעל שורת קוד (שעליה יתבצע

שהן התוויות B.false, ו- B.true הצמדנו שתי תוויות: Bביטוי כזכור, לכל בהתאמה). false (או true הוא Bאליהן החישוב צריך לעבור אם

שאומרות B.falselist, ו- B.truelistעתה תהיינה לנו גם זוג רשימות : B.false, ו- B.trueבאילו פקודות צריך לחזור ולעדכן את הכתובות של :

כשמגלים את ערכיהם.

, נחזיק עתה S.next סימבולי label שעבורו החזקנו Sבנוסף, לכל פסוק .S.nextlistגם רשימה

Page 50: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

50

אגירת הקוד - המשך

B.truelist-ו ,B.falselist הן תכונות נוצרות: הצאצאים מספרים לאב איפה יש קוד שצריך לתקן.

עצמו, נדע מה הכתובת הרלוונטית ונוכל לבצע Bכאשר עולים לאב של backpatch .ולהכניס אותה לכל הפקודות שנרשמו ברשימה

תכונות דומות. S.nextlistבאופן דומה, ל-

שתחזיר את הכתובת של הפקודה הבאה.nextinstrנשתמש בפונקציה

Page 51: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

51

חישוב ביטויים בוליאניים על ידי הפנית בקרה.B לפי הערך של B.false או ל-B.trueכזכור, הקוד שקופץ ל-

קודם היה:

:backpatchingועכשיו עם

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

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

gen ( ' goto ' B.false ) }

B → id1 relop id2

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

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

{ B.truelist := makelist ( nextinstr ) ; B.falselist := makelist ( nextinstr + 1 ) ; emit ( ' if ' id1.var relop.op id2.var ' goto_ ' ) || emit ( ' goto_ ' ) }

B → id1 relop id2

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

Page 52: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

52

חישוב ביטויים בוליאניים על ידי הפנית בקרה.B לפי הערך של B.false או ל-B.trueכזכור, הקוד שקופץ ל-

קודם היה:

:backpatchingועכשיו עם

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

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

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

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

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

Page 53: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

53

חישוב ביטויים בוליאניים על ידי הפנית בקרה.B לפי הערך של B.false או ל-B.trueכזכור, הקוד שקופץ ל-

קודם היה:

:backpatchingועכשיו עם

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

{ 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 or 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 → B1 and B2

{ backpatch ( B1.falselist, M.instr ) ;

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

B → B1 or M B2

{ backpatch ( B1.truelist, M.instr ) ; B.truelist := B2.truelist ;

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

B → B1 and M B2

{ M.instr := nextinstr } M →

Page 54: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

54

הסטנדרטיmarkerטריק ה-

.M → ו- B → B1 or M B2 למשל:

. B1 משיגים את הכתובת של תחילת Mבזמן הגזירה של

B1 or

B

M B1

Page 55: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

55

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

Page 56: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

56

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

100101

if a < b goto ___goto ___

Page 57: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

57

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

100101

if a < b goto ___goto ___

102103

if c < d goto ___goto ___

Page 58: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

58

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

100101

if a < b goto ___goto ___

102103

if c < d goto ___goto ___

104105

if e < f goto ___goto ___

Page 59: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

59

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

100101

if a < b goto ___goto ___

102103

if c < d goto 104goto ___

104105

if e < f goto ___goto ___

Page 60: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

60

תיקון לאחור

<ec < fd

<a and M.i = 104b

or

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

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

B.t = {104}B.f = {103, 105}M.i = 102

B.t = {100}B.f = {101}

B.t = {100, 104}B.f = {103, 105}

100101

if a < b goto ___goto 102

102103

if c < d goto 104goto ___

104105

if e < f goto ___goto ___

Page 61: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

61

IFפסוקים עם הפנית בקרה: S → if B then M1 S1 N else M2 S2

{ backpatch ( B.truelist , M1.instr ) ;

backpatch ( B.falselist , M2.instr ) ;

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

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

S → if B then M S1

{ backpatch (B.truelist , M.instr ) ; S.nextlist := merge ( B.falselist, S1.nextlist ) }

Page 62: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

62

Whileפסוקים עם הפנית בקרה:

S → while M1 B do M2 S1

{ backpatch ( S1.nextlist, M1.instr ) ;

backpatch ( B.truelist , M2.instr ) } ;

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

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

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

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

Page 63: תורת הקומפילציה 236360 הרצאה 9 שפות ביניים  Intermediate Languages/Representations

63

לסיכום

יצירת קוד משולבת בניתוח הסמנטי (בפעולות הסמנטיות)

, או שאוספים את הקוד כתכונה emitאו שפולטים קוד לבפר באמצעות S של המשתנה ההתחלתי codeשל המשתנים הנגזרים, וכשגומרים, ה-

הוא הקוד הנדרש.

הניתוח של ביטויים לוגיים ופסוקי הפניית הבקרה הם יותר מסובכים.

ראשית צריך להחליט על ביצוע מקוצר (או לא).

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

סימבוליים ומעבר נוסף לעידכונם labelsאפשרות אחת: שימוש ב-לכתובת אמיתית.

: מעבר יחיד על העץ, אך שמירת backpatchingאפשרות שניה - labelרשימה של כל המקומות אליהן צריך להכניס את הכתובת של

, מעדכנים את כל הפקודות לפי labelמסוים. כשמגלים את מיקום ה-הכתובות שברשימה.