יצירת קוד asu פרק 9. 2 יצירת קוד syntax analysis semantic analysis code...

Post on 18-Dec-2015

222 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

יצירת קוד

ASU 9פרק

2

יצירת קוד

syntax analysis

semantic analysis

code generation

syntax tree

intermediate code

דרישות)יצירת קוד בעל איכות טובה )ניצול יעיל של משאבי המכונה האלגוריתמים ליצירת קוד צריכים להיות יעילים במידה סבירה

, עושים שימוש NP-complete)מכיוון שחלק מהבעיות הן באלגוריתמים היוריסטיים(

3

code generatorשיקולים עיקריים בבניית

תכנון נאות של שפת הביניים, כולל העברה של )הנחה – אין שגיאות בקוד front endאינפורמציה מה-

הביניים(

שפת המטרהabsolute machine code

תוכניותcom-ב DOSלא ממש קיים בארכיטקטורות מודרניות

relocatable code קבציobj קבצי( tpu)'וכו ,

assembly language

4

code generatorשיקולים עיקריים בבניית

ניהול זיכרון?היכן נמצא משתנה במהלך הביצועמיפוי התוכנית לזיכרון; חישוב תוויות

בחירת פקודות מכונה

( pairing, assignment, allocation)הקצאת רגיסטרים

וב- pipeliningבחירת סדר החישוב תוך התחשבות ב- caching

5

מבנה מכונת המטרה

הנחות לצורך הדיוןbyte addressability4-byte wordsn – רגיסטרים R0, . . . Rn-1

מבנה הפקודותOP source, destination

צורת האופרנדים

modeformaddressadded cost

absoluteMM1

registerRR0

indexedc ) R (c + content ) R (1

indirect register* Rcontent ) R (0

indirect indexed* c ) R (content ) c + content ) R ( ( 1

literal# cc )constant – not an address(1

6

דוגמאות

MOV R0,123

בזכרון.123 לכתובת 0העתק את הערך של רגיסטר .2עלות כוללת =

ADD 4)R0(,123

.123{, לכתובת 0 ועוד ערך רגיסטר 4הוסף את הערך שבכתובת הזכרון }.3עלות כוללת =

SUB *4)R0(,R1

.R1, מ-R0+4החסר את הערך שבתא הזכרון, שכתובתו נמצאת בכתובת )R1:= R1 - *)4+R0(( = 2 עלות כוללת.

MOV #1,R0

.R0" ל-1כתוב את הערך ".2עלות כוללת =

7

run time storage management

call, return, haltנתרכז בפקודות

הקצאה סטטית )לא ע"ג מחסנית(

three address code

/* code for c */

action1

call p

action2

halt/* code for p */

action3

return

activation record for c )64 bytes(

activation record for p )88 bytes(

0:return address0:return address8:arr4:buf

56:i60:j

84:n

goto *callee.static_area

move #here + 20 , callee.static_area

goto callee.code_area

8

run time storage managementדוגמא –

/* code for c */100:ACTION1

120:MOV # 140 , 364/* save return address 140 */132:GOTO 200/* call P */140:ACTION2

160:HALT. . .

/* code for p */200:ACTION3

220:GOTO *364/* return to address saved in location 364 */. . .

/* 300-363 hold activation record for c */300:/* return address */304:/* local data for c */

. . ./* 364-451 hold activation record for p */

364:/* return address */368:/* local data for p */

9

run time storage managementניהול מחסנית –

main

MOV #stackstart , SP

… code for the first procedure …

HALT

calling a procedure

ADD #caller.recordsize , SP

MOV #here + 16 , *SP

GOTO callee.code_area

SUB #caller.recordsize , SP

return from a procedure

GOTO *0 ) SP (

הוא ערך סטטיcaller.recordziseהנחה סמויה –

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

10

ניהול מחסנית – דוגמא

three address code

/* code for s */

action1

call q

action2

halt

/* code for p */

action3

return

/* code for q */

action4

call p

action5

call q

action6

call q

return

11

code for scode for q100:MOVE #600,SPinitialize the stack300:ACTION4conditional jump108:ACTION1320:ADD #qsize,SP128:ADD #ssize,SPcall sequence begins328:MOV #344,*SPpush return address136:MOV #152,*SPpush return address336:GOTO 200call p144:GOTO 300call q344:SUB #qsize,SP152:SUB #ssize,SPrestore SP352:ACTION5

160:ACTION2372:ADD #qsize,SP180:HALT380:MOV #396,*SPpush return address

. . .388:GOTO 300call qcode for p396:SUB #qsize,SP

200:ACTION3404:ACTION6

220:GOTO *0)SP(return424:ADD #qsize,SP. . .432:MOV #448,*SPpush return address

440:GOTO 300call q448:SUB #qsize,SP456:GOTO *0)SP(return

. . .600:stack starts here

ניהול מחסנית – דוגמא

12

המקור תוכנית היא שורה בx := 0דוגמא – נניח ש-

הקצאה סטטית -נניח שx( אמור להמצא בהיסט ( offset12static [12] := 0( רביעיה – קוד ביניים) נקבל:100אם האזור הסטטי מתחיל בכתובת ,

MOV #0, 112קוד מכונה –

הקצאה מקומית במחסנית -נניח שx משתנה מקומי ה'חי' ברשומה המוצבעת ע"י

SP

t1 := 12 + SP

* t1 := 0– בפקודות מכונה MOV #0, 12 ) SP (

קוד ביניים )רביעות(

MOV #0, 112קוד מכונה –

חישוב כתובות עבור משתנים

13

basic blocks and flow graphs

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

היציאה היא אולי הפניה או הפניה מותנה של הבקרה

z ו- y- ב משתמש וx את מגדיר x := y + zמשפט מהסוג בנקודה נתונה אם נעשה שימוש בערך שלו לאחר חימשתנה הוא

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

t1:= a * a

t2:= a * b

t3:= 2 * t2

t4:= t1 + t3

t5:= b * b

t6:= t4 + t5

14

פירוק תוכנית לבלוקים בסיסיים

Input: A sequence of three-address statements

Output: A list of basic blocks with each three-address statement in exactly one block

Method We first determine the set of leaders, the first statements

of basic blocks. The rules we use are the following: The first statement is a leader Any statement that is the target of a conditional of

unconditional goto is a leader Any statement that immediately follows a goto or

conditional goto statement is a leader For each leader, its basic block consists of a leader and

all statements up to but not including the next leader or the end of the program

15

פירוק תוכנית לבלוקים בסיסיים– דוגמא פשוטה 'מהחיים'

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)

16

טרנספורמציות בתוך בלוקים בסיסיים

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

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

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

נורמליתצריך לשמור על הטיפוס

החלפת סדר בין פקודות

פישוטים אלגבריים

a:= b + cb:= a – dc:= b + cd:= a – d

:= y ^ 2x:= x * 1x:= x + 0x

d := b

x := y * y

17

(control )flow graph

– הבלוקים הבסיסייםצמתי הגרף

– קשת מקשרת שני בלוקים קשתות הגרףאם קיימת הפנית בקרה מהראשון לשני

)או פשוט המשך ישיר של זרימת הבקרה(

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

– טבעת ללא תת-טבעותלולאה פנימית

הערה – עושים שימוש בשמות הבלוקים הבסיסיים ולא במספרים סידוריים של

הרביעיות המתאימות )על מנת לאפשר הזזה של הבלוקים בסיסיים(

B1

prod := 0

i := 1

B2

t1 := 4 * i

t2 := a [ t1 ]

t3 := 4 * i

t4 := b [ t3 ]

t5 := t2 * t4

t6 := prod + t5

prod := t6

t7 := i + 1

i := t7

if i <= 20 goto B2

18

next-use information

עבור כל שורה בבלוק נתון, נרצה לשמור )עבור כל משתנה אליו מתייחסת שורה זו(:

האם המשתנה חי.מתי השימוש הבא במשתנה

, j בשורה x ואם משתמשים ב- x מבצעים השמה ל- iאם בשורה , אזי x ללא השמה נוספת ל- j ל- iואם יש אפשרות לזרימת בקרה מ-

i שחושב ב- xשימוש ב- ישנו jב-

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

החישוב נעשה על-ידי סריקה של הבלוק מסופו לעבר תחילתו

כל המשתנים שאינם מקומיים בבלוק, חיים בסוף הנחות שמרניות:הבלוק )כלומר, נעשה בהם שימוש בהמשך(.

.סריקות מתקדמות יותר מאפשרות דיוק רב יותר

19

next use information

– ברמת הבלוק הבודד – מהסוף להתחלה. next-useחישוב ה- . נניח שבטיפול מהסוף להתחלה הגענו symbol tableנעזר ב- למשפט

i: x := y op z

z ו- y, x על symbol table את האינפורמציה שנאספה ב- iנצמיד ל-

symbol tableנקבע ב-

x"לא חי"; "אין שימוש בהמשך" –

symbol tableנקבע ב-

y, z -חיים"; "השימוש הבא – ב" – i"

– חשוב3 ו- 2הערה – הסדר בין 1.

xyלמשל, במקרה בו 1.

20

תהליך פשוט ליצירת קוד

הגישה – ניצור קוד כך שעבור כל פקודה נזכור היכן נמצאים האופרנדים

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

יש צורך ברגיסטר למטרה אחרתצריך לסגור את הבלוק

a := b + cדוגמאות

...next-useלפי מידע ה- איך יודעים אם "אפשר לוותר"?

ADD Rj, Ri אםb -ו c ברגיסטרים ואפשר לוותר על b ולהשאיר במקומו aאת

ADD C, Ri אםRi מכיל את b ואפשר לוותר עליו, אבל cבזכרון

MOV C, Rj

ADD Rj, Ri

שובcאם נצטרך את

21

מעקב אחרי משתנים ורגיסטרים

(descriptorsעבור רגיסטרים – רושמים מה יש בכל רגיסטר )בתחילת כל בלוק כל הרגיסטרים ריקיםבמהלך ייצור הקוד, כל רגיסטר יכיל משתנה אחד או יותר

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

במספר מקומות

22

code generation algorithm

Input: A sequence of three-address statements constituting a basic block.

For each three-address statement x := y op z we perform the following:

1. Invoke the function getreg to determine the location L where the result of the computation y op z should be stored. L will usually be a register, but it could also be a memory location.

2. Consult the address descriptor for y to determine y', )one of( the current location)s( of y. Prefer the register for y' if the value of y is currently both in memory and a register. If the value of y is not already in L, generate the instruction MOV y', L to place a copy of y in L.

3. Generate the instruction OP z', L, where z' is the current location of z. Again, prefer a register to a memory location if z is in both. Update the address descriptor of x to indicate that x is in location L. If L is a register, update its descriptor to indicate that it contains the value of x.

4. If the current values of y and/or z have no next uses, are not live on exit from the block, and are in registers, alter the register descriptor to indicate that, after execution of x:= y op z, those registers no longer will contain y and/or z, respectively.

23

יצירת קוד – הערות

הטיפול בפעולות אונריות – דומה

x := yמצריך עדכון המתארים

עם סיום העבודה ברמת הבלוק הבסיסי שומרים את ערכי המשתנים (live-dead)אלא אם יש לנו אינפורמציה של

24

(getregהקצאת רגיסטר )הפונקציה

x := y op zנתון –

xהמטרה – הקצאת רגיסטר ל-

שאינו משמש לאכסון משתנים נוספים, ואם ל- L ברגיסטר yאם 1.y אין שימוש בהמשך, החזר את L עדכן את מתארי הכתובת ,

והרגיסטר. זכרו כי הוראות מסוגx := y גורמות לרגיסטר להחזיק את

הערך של כמה משתנים בו-זמנית.

והחזר אותו.L נכשל, מצא רגיסטר פנוי 1אם 2.

. L יש שימוש בהמשך, מצא רגיסטר תפוס x נכשל, ואם ל- 2אם 3. בזיכרון )אם אינו נמצא שם(, עדכן את Lשמור את הערך של

.Lמתארי הכתובת והרגיסטר והחזר את -המשתנה )או משתנים( שהיה לפני-כן בL שמור עכשיו בזכרון

בלבד. איך בוחרים איזה רגיסטר לפנות לטובתx?

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

25

הקצאת רגיסטרים

statementscode generatedregister descriptoraddress descriptor

registers empty

t := a – bMOV a, R0

SUB b, R0

R0 contains tt in R0

u := a – cMOV a, R1

SUB c, R1

R0 contains t

R1 contains u

t in R0

u in R1

v := t + uADD R1, R0R0 contains v

R1 contains u

u in R1

v in R0

d := v + uADD R1, R0

MOV R0, d

R0 contains dd in R0

d in R0 and memory

d := )a – b( + )a – c( + )a – c(

26

יצירת קוד לטיפול במערכים

statementi in register Rii in memory Mii in stack

codecostcodecostcodecost

a:= b [ i ]MOV b)Ri(, R2MOV Mi, R

MOV b)R(, R4

MOV Si)A(, R

MOV b)R(, R4

a [ i ] := bMOV b, a)Ri(3MOV Mi, R

MOV b, a)R(5

MOV Si)A(, R

MOV b, a)R(5

offset -יחסית לתחילת ה activation record

activation recordתחילת ה-

הוא משתנה סטטיaמניחים ש-

27

טיפול במצביעים

statementp in register Rpp in memory Mpp in stack

codecostcodecostcodecost

a:= * pMOV *Rp, a2MOV Mp, R

MOV *R, R3

MOV Sp)A(, R

MOV *R, R4

* p := aMOV a, *Rp2MOV Mp, R

MOV a, *R4

MOV a, R

MOV R, *Sp)A(5

28

register allocation and assignment

allocation?איזו אינפורמציה תאוכסן ברגיסטר –

assignment?למה בדיוק יוקצה כל רגיסטר –

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

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

כתובת חזרהערך מוחזראכסון מצביע לראש המחסנית

הקצאה גלובלית

29

global register allocation

המטרה – הימנעות משמירת ערכים המצויים ברגיסטרים בסוף כל בלוק על ידי מעקב גלובלי

.גלובלי" עשוי עדיין להיות מקומי – בתוך אותה פרוצדורה, למשל"

דגש מיוחד על הלולאות הפנימיות

(C בשפת registerהמלצות המתכנת )המלה השמורה

usage countגישה כמותית – מקצים מקום ברגיסטר למשתנה בו נעשה שימוש נרחבחשיבות מיוחדת לאינדקס הרץ של לולאותמטפלים בלולאות הפנימיות תחילהלאחר מכן, הקצאת רגיסטרים ללולאות החיצוניות

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

30

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

(מכונה אבסטרקטיתנניח שמספר הרגיסטרים לא חסום ונייצר קוד )1.

תהיה קטנהspillנקצה רגיסטרים כך שעלות ה- 2.

register interference graphבניה וניתוח של ה-

הצמתים – הרגיסטרים הסימבוליים1.

במקום בו השני חיקשת בגרף מקשרת שני צמתים אם אחד מהם 2.מוגדר

נצבע את הגרף במספר קטן של צבעים – כמספר הרגיסטרים 3.הפיזיים

הבעיה היאNP Completeמשתמשים באלגוריתמים היוריסטיים

לעניבות הפנימיותspill codeהערה – צריך להשתדל להימנע מלהכניס

31

DAGייצוג החישוב של בלוק בסיסי בעזרת

עלים – משתנים )שונים( או קבועים )שונים(

צמתים פנימיים מסומנים על ידי האופרטורים המתאימים

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

t1 := 4 * i

t2 := a [ t1 ]

t3 := 4 * i

t4 := b [ t3 ]

t5 := t2 * t4

t6 := prod + t5

prod := t6

t7 := i + 1

i := t7

if i <= 20 goto )1(

)1(

1i04ba

20t7, i+t1, t3 *

)1(<=t4[ ]t2[ ]

t5*prod0

t6, prod+

32

DAGבנית ה-

מטפלים בכל משפט בבלוק

x := y + z

z ו- yמוצאים איפה נמצא הערך הנוכחי של

ומחברים אותו לשני הבנים )אם לא +בונים צומת חדש המסומן xקיים כזה(; מסמנים אותו ב-

( כבר מסומן, יש לבטל את הסימון הקודם x0 )לאxאם

אין יוצרים צומת חדש עבור משפטי השמה פשוטים

x := y

33

DAGsייצוג בלוקים בסיסיים כ-

עלים – משתנים )שונים( או קבועים )שונים(

צמתים פנימיים מסומנים על ידי האופרטורים המתאימים

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

t1 := 4 * i

t2 := a [ t1 ]

t3 := 4 * i

t4 := b [ t3 ]

t5 := t2 * t4

t6 := prod + t5

prod := t6

t7 := i + 1

i := t7

if i <= 20 goto )1(

)1(

1i04ba

20t7, i+t1, t3 *

)1(<=t4[ ]t2[ ]

t5*prod0

t6, prod+

t1

prod := prod + t5

i := i + 1

34

כייצוג של בלוקים בסיסייםDAGsשימושים של

זיהוי אוטומטי של ביטויים משותפים

זיהוי המשתנים בהם נעשה שימוש בבלוק

זיהוי הפקודות בהן חושבו ערכים בעלי שימוש בסוף הבלוק

ייצור קוד יעיל )בפרט – אין צורך בהשמות(

זיהוי המשתנים החיים

סדר חישוב קביל – באמצעות מיון טופולוגי

35

side effects

aliasingהקושי –

הפתרון – השמה לאיבר של מערך מבטלת את האפשרות להשתמש בצמתים המכילים התייחסות אליו

הערה – בעיה דומה נגרמת על ידי מצביעים

הערה – בעיה דומה נגרמת על ידי פרוצדורות

הוא מכשול מרכזי לאופטימיזציה של תוכניותaliasingנושא ה-

x := a [ i ]

a [ j ] := y

z := a [ i ]

x := a [ i ]

a [ j ] := y

z := x

top related