1 יצירת קוד asu פרק 9. 2 2 יצירת קוד syntax analysis semantic analysis code...
Post on 20-Dec-2015
229 views
TRANSCRIPT
1
יצירת קוד
ASU 9פרק
22
יצירת קוד
syntax analysis
semantic analysis
code generation
syntax tree
intermediate code
דרישות)יצירת קוד בעל איכות טובה )ניצול יעיל של משאבי המכונה האלגוריתמים ליצירת קוד צריכים להיות יעילים במידה סבירה
, עושים שימוש NP-complete)מכיוון שחלק מהבעיות הן באלגוריתמים היוריסטיים(
33
code generatorשיקולים עיקריים בבניית
תכנון נאות של שפת הביניים, כולל העברה של )הנחה – אין שגיאות בקוד front endאינפורמציה מה-
הביניים(
שפת המטרהabsolute machine code
תוכניותcom-ב DOSלא ממש קיים בארכיטקטורות מודרניות
relocatable code קבציobj קבצי( tpu)'וכו ,
assembly language
44
code generatorשיקולים עיקריים בבניית
ניהול זיכרון?היכן נמצא משתנה במהלך הביצועמיפוי התוכנית לזיכרון; חישוב תוויות
בחירת פקודות מכונה
( pairing, assignment, allocation)הקצאת רגיסטרים
וב- pipeliningבחירת סדר החישוב תוך התחשבות ב- caching
55
מבנה מכונת המטרה
הנחות לצורך הדיון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
66
דוגמאות
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עלות כוללת =
77
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
88
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 */
99
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הנחה סמויה –
רגיסטר מיוחד, מצביע לראש המחסנית. יצביע לראש רשומת ההפעלה הנוכחית.
1010
ניהול מחסנית – דוגמא
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
1111
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
ניהול מחסנית – דוגמא
1212
המקור תוכנית היא שורה בx := 0דוגמא – נניח ש-
הקצאה סטטית -נניח שx( אמור להמצא בהיסט ( offset12static [12] := 0( רביעיה – קוד ביניים) נקבל:100אם האזור הסטטי מתחיל בכתובת ,
MOV #0, 112קוד מכונה –
הקצאה מקומית במחסנית -נניח שx משתנה מקומי ה'חי' ברשומה המוצבעת ע"י
SP
t1 := 12 + SP
* t1 := 0– בפקודות מכונה MOV #0, 12 ) SP (
קוד ביניים )רביעות(
MOV #0, 112קוד מכונה –
חישוב כתובות עבור משתנים
1313
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
1414
פירוק תוכנית לבלוקים בסיסיים
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
1515
טרנספורמציות בתוך בלוקים בסיסיים
ביטויים משותפים
ביטול "קוד מת"השמה למשתנה שלא חי לאחר מכן
החלפת שם של משתנה זמני אפשר תמיד להשתמש בשמות חדשים ולקבל בלוק בצורה
נורמליתצריך לשמור על הטיפוס
החלפת סדר בין פקודות
פישוטים אלגבריים
a:= b + cb:= a – dc:= b + cd:= a – d
:= y ^ 2x:= x * 1x:= x + 0x
d := b
x := y * y
1616
(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
1717
next-use information
עבור כל שורה בבלוק נתון, נרצה לשמור )עבור כל משתנה אליו מתייחסת שורה זו(:
האם המשתנה חי.מתי השימוש הבא במשתנה
, j בשורה x ואם משתמשים ב- x מבצעים השמה ל- iאם בשורה , אזי x ללא השמה נוספת ל- j ל- iואם יש אפשרות לזרימת בקרה מ-
i שחושב ב- xשימוש ב- ישנו jב-
קריאות לפרוצדורות...( החישוב נעשה ברמת הבלוק הבודד )זהירות:
החישוב נעשה על-ידי סריקה של הבלוק מסופו לעבר תחילתו
כל המשתנים שאינם מקומיים בבלוק, חיים בסוף הנחות שמרניות:הבלוק )כלומר, נעשה בהם שימוש בהמשך(.
.סריקות מתקדמות יותר מאפשרות דיוק רב יותר
1818
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.
1919
תהליך פשוט ליצירת קוד
הגישה – ניצור קוד כך שעבור כל פקודה נזכור היכן נמצאים האופרנדים
הנחותהתאמה טובה בין שפת הרביעיות לשפת המכונהנשמור תוצאות ברגיסטרים אלא אם
יש צורך ברגיסטר למטרה אחרתצריך לסגור את הבלוק
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אם נצטרך את
2020
מעקב אחרי משתנים ורגיסטרים
(descriptorsעבור רגיסטרים – רושמים מה יש בכל רגיסטר )בתחילת כל בלוק כל הרגיסטרים ריקיםבמהלך ייצור הקוד, כל רגיסטר יכיל משתנה אחד או יותר
מתאר הכתובות עוקב היכן נמצא כל משתנה )רגיסטר, מחסנית, , משתנה ימצא store או loadמקום בזיכרון...(. כשיש פקודת
במספר מקומות
2121
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.
2222
יצירת קוד – הערות
הטיפול בפעולות אונריות – דומה
x := yמצריך עדכון המתארים
עם סיום העבודה ברמת הבלוק הבסיסי שומרים את ערכי המשתנים (live-dead)אלא אם יש לנו אינפורמציה של
2323
(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רגיסטר מתאים, החזר את כתובתו בזיכרון של
2424
הקצאת רגיסטרים
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(
2525
יצירת קוד לטיפול במערכים
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מניחים ש-
2626
טיפול במצביעים
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
2727
register allocation and assignment
allocation?איזו אינפורמציה תאוכסן ברגיסטר –
assignment?למה בדיוק יוקצה כל רגיסטר –
חשיבות הנושאהקטנת הקודייעול התוכנית
גישות עיקריותהקצאה קבועה של רגיסטרים לצרכים מיוחדים
כתובת חזרהערך מוחזראכסון מצביע לראש המחסנית
הקצאה גלובלית
2828
global register allocation
המטרה – הימנעות משמירת ערכים המצויים ברגיסטרים בסוף כל בלוק על ידי מעקב גלובלי
.גלובלי" עשוי עדיין להיות מקומי – בתוך אותה פרוצדורה, למשל"
דגש מיוחד על הלולאות הפנימיות
(C בשפת registerהמלצות המתכנת )המלה השמורה
usage countגישה כמותית – מקצים מקום ברגיסטר למשתנה בו נעשה שימוש נרחבחשיבות מיוחדת לאינדקס הרץ של לולאותמטפלים בלולאות הפנימיות תחילהלאחר מכן, הקצאת רגיסטרים ללולאות החיצוניות
השיטה דומה. אם אין מספיק רגיסטרים הן ללולאה חיצונית לפני הכניסה ללולאה הפנימיתspillוהן לפנימית, מבצעים
2929
הקצאת רגיסטרים באמצעות צביעה של גרפים
(מכונה אבסטרקטיתנניח שמספר הרגיסטרים לא חסום ונייצר קוד )1.
תהיה קטנהspillנקצה רגיסטרים כך שעלות ה- 2.
register interference graphבניה וניתוח של ה-
הצמתים – הרגיסטרים הסימבוליים1.
במקום בו השני חיקשת בגרף מקשרת שני צמתים אם אחד מהם 2.מוגדר
נצבע את הגרף במספר קטן של צבעים – כמספר הרגיסטרים 3.הפיזיים
הבעיה היאNP Completeמשתמשים באלגוריתמים היוריסטיים
לעניבות הפנימיותspill codeהערה – צריך להשתדל להימנע מלהכניס