Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 66 trang
THÔNG TIN TÀI LIỆU
Nội dung
Thực hành CHƯƠNG TRÌNH DỊCH Bài 5: Sinh mã Phạm Đăng Hải haipd@soict.hut.edu.vn Các thực hành Xây dựng bảng ký hiệu • • Giới thiệu máy ngăn xếp Vấn đề xây dựng bảng ký hiệu Sinh mã cho câu lệnh • • Giới thiệu thơng dịch KPLrun Sinh mã cho câu lệnh gán, rẽ nhánh, lặp Sinh mã lấy địa chỉ/giá trị • • • Lấy địa chỉ/giá trị biến, phần tử mảng tham số hình thức Sinh mã lấy địa giá trị trả hàm Sinh mã gọi thủ tục • 09/20/23 Sinh mã tham số thực tế Sinh mã đích Phân tích từ vựng Phân tích cú pháp Phân tích ngữ nghĩa Sinh mã 09/20/23 • Sinh mã cơng đoạn biến đổi từ cấu trúc ngữ pháp chương trình thành chuỗi lệnh thực thi máy đích • Cấu trúc ngữ pháp định phân tích cú pháp • Các lệnh máy đích đặc tả kiến trúc thực thi máy đích – KPL sử dụng kiến trúc máy ngăn xếp Máy ngăn xếp • Máy ngăn xếp hệ thống tính toán – Sử dụng ngăn xếp để lưu trữ kết trung gian q trình tính tốn – Kiến trúc đơn giản – Bộ lệnh đơn giản • Máy ngăn xếp có hai vùng nhớ – Khối lệnh: • Chứa mã thực thi chương trình – Ngăn xếp: • Lưu trữ kết trung gian 09/20/23 Máy ngăn xếp PC, B, T ghi máy PC JMP INC LA 0,4 LC ST Code buffer 09/20/23 T RV DL RA SL P1 P2 V1 V2 tmp1 B T Stack Máy ngăn xếp Thanh ghi • PC (program counter): – Con trỏ lệnh trỏ tới lệnh thực thi đệm chương trình • B (base): – Con trỏ trỏ tới địa sở vùng nhớ cục Các biến cục truy xuất gián tiếp qua trỏ • T (top); – Con trỏ, trỏ tới đỉnh ngăn xếp 09/20/23 Máy ngăn xếp Bản hoạt động (stack frame) • Khơng gian nhớ cấp phát cho chương trình (hàm/thủ tục/chương trình chính) chúng kích hoạt – Lưu giá trị tham số – Lưu giá trị biến cục – Lưu thông tin quan trọng khác: • RV, DL, RA, SL • Một chương trình có nhiều hoạt động 09/20/23 Máy ngăn xếp Bản hoạt động (stack frame) • RV (return value): – Lưu trữ giá trị trả cho hàm • DL (dynamic link): – Địa sở hoạt động chương trình gọi tới (caller) – Được sử dụng để hồi phục ngữ cảnh chương trình gọi (caller) chương trình gọi (called) kết thúc • RA (return address): – Địa lệnh quay kết thúc chương trình – Sử dụng để tìm tới lệnh caller called kết thúc • SL (static link): – Địa sở hoạt động chương trình bao ngồi – Sử dụng để truy nhập biến phi cục 09/20/23 Máy ngăn xếp Bản hoạt động Procedure P(I : integer); Var a : integer; Function Q; Var x : char; Begin … return End; Procedure R(X: integer); Var y : char; Begin … y = Call Q; … End; Begin … Call R(1); … End; 09/20/23 Ví dụ Stack … RV DL RA SL Param I Local a … RV DL RA SL param x Local y … RV RV DL RA SL Local x P frame R frame Q frame Máy ngăn xếp Lệnh • Lệnh máy có dạng : Op p q – Op : Mã lệnh – p, q : Các tốn hạng • Các tốn hạng tồn đầy đủ, có tốn hạng, khơng tồn • Ví dụ J1 % Nhảy đến địa LA 0, % Nạp địa từ số 0+4 lên đỉnh stack HT 09/20/23 %Kết thúc chương trình 10 Lấy địa chỉ/giá trị biến • Khi lấy địa chỉ/giá trị biến cần tính đến phạm vi biến – Biến cục lấy từ frame – Biến phi cục lấy theo StaticLink với cấp độ lấy theo “độ sâu” phạm vi so với phạm vi thời • Hàm computeNestedLevel(Scope* scope) trả độ sâu biến Level = 0; Scope* tmp = symtab->currentScope; While (tmp != scope) {tmp = tmp ->outer, level++ }; 09/20/23 52 Lấy địa chỉ/giá trị biến • Tìm vị trí biến stack – Level = computeNestedLevel(Scope* scope) – Offset = OFFFSET(Var) • Lấy giá trị biến Var – genLV(Level, Offset) • Lấy địa biến Var – genLA(Level, Offset) 09/20/23 53 Lấy địa tham số hình thức • Khi LValue tham số, cần tính độ sâu biến • Việc lấy giá trị, phụ thuộc vào tham trị hay tham biến – Nếu tham trị: • Địa /giá trị giống với biến – Nếu tham biến: • 09/20/23 Địa biến địa truyền vào cho hàm/thủ tục 54 Lấy địa tham số hình thức • Tìm vị trí biến tham số stack – Level = computeNestedLevel(Scope* scope) – Offset = OFFFSET(Var) • Nếu tham trị, nạp giá trị lên stack • genLV(Level, Offset) • Nếu tham biến, nạp địa tham số: – genLA(Level, Offset) 09/20/23 55 Ví dụ Truyền theo giá trị Program Exp; Var N : integer; Procedure Add(a:integer; b:integer); Begin N := a+b; End; Begin N := 10; Call add(N,20*10); End 09/20/23 0: J 1: J 2: INT 3: LA 1,4 4: LV 0,4 5: LV 0,5 6: AD 7: ST 8: EP 9: INT 10: LA 0,4 11: LC 10 12: ST 13: INT 14: LV 0,4 15: LC 20 16: LC 10 17: ML 18: DCT 19: CALL 0,1 20: HL 56 Ví dụ Truyền theo biến Program Example1; Var N : integer; Procedure Add(Var a:integer); Begin a := 10*a; End; Begin Call add(N); Call WRITEI(N); End 09/20/23 0: J 10 1: J 2: INT 3: LV 0,4 4: LC 10 5: LV 0, 6: LI 7:ML 8: ST 9: EP 10: INT 11: INT 12: LA 0,4 13: DCT 14: CALL 0,1 15: LV 0,4 16: WRI 17: HL 57 Lấy địa giá trị trả hàm • Giá trị trả ln nằm offset frame • Chỉ cần tính độ sâu giống với biến hay tham số hình thức Program Exp; Var N : integer; Function Sqrt(a:integer): integer; Begin Sqrt := A * A; End; Begin N := Sqrt(10); Call WRITEI(N); End 09/20/23 0: J 1: J 2: INT 3: LA 0,0 4: LV 0,4 5: LV 0,4 6: ML 7: ST 8: EF 9: INT 10: LA 0,4 11: INT 12: LC 10 13: DCT 14: CALL 0,1 15: ST 16: HL 58 Sinh lời gọi hàm/thủ tục • Lời gọi – Hàm gặp sinh mã cho factor – Thủ tục gặp sinh mã lệnh CallSt • Trước sinh lời gọi hàm/thủ tục cần phải nạp giá trị cho tham số hình thức lên stack cách – Tăng giá trị T lên (bỏ qua RV,DL,RA,SL) – Sinh mã cho k tham số thực tế • Đặt tham số(giá trị/ địa chỉ) lên đỉnh stack – Giảm giá trị T + k genDCT(4+k) – Sinh mã cho lệnh CALL genFun/ProcCall(obj) 09/20/23 59 Lệnh CALL (p, q) Lệnh CALL có hai tham số: – p: Độ sâu lệnh CALL, chứa static link Base(p) = base frame chương trình chứa khai báo chương trình A – q: Địa lệnh mới: địa dãy lệnh cần thực gọi A CALL (p, q) s[t+2]:=b; // Lưu lại dynamic link s[t+3]:=pc; // Lưu lại return address s[t+4]:=base(p); // Lưu lại static link b:=t+1; 09/20/23 pc:=q; // Base return value // địa lệnh 60 Lệnh CALL (p, q) • Điều khiển pc chuyển đến địa bắt đầu chương trình /* pc = p */ • Lệnh thơng thường lệnh nhảy J để bỏ qua mã lệnh khai báo chương trình cục đoạn mã • Lệnh lệnh INT tăng T kích thước frame – Mục đích: bỏ qua frame chứa vùng nhớ tham số biến cục 09/20/23 61 Lệnh CALL (p, q) • Thực lệnh stack biến đổi tương ứng • Khi kết thúc – Thủ tục (lệnh EP): toàn frame giải phóng, trỏ T đặt lên đỉnh frame cũ – Hàm (lệnh EF): frame giải phóng, chừa giá trị trả offset 0, trỏ T đặt lên đầu frame thời (offset 0) 09/20/23 62 Sinh địa phần tử mảng • Biến mảng khai báo A : array(.n1.) of of array(.nk.) of integer/char chiếm n1 * …* nk nhớ frame • Phần tử A(.i1.) (.ik.) định vị địa = A + i1 * n2 *…* nk + i2* n3 *…* nk +… + ik-1 * nk + ik //Chỉ số • Địa tính tích lũy theo tiến trình duyệt số 09/20/23 63 Sinh địa phần tử mảng Program Exm; Var N : Array(.4.) of Array(.5.) of array(.6.) of integer; Begin 0: J 1: INT 124 N(.3.)(.4.)(.5.) := 10; 2: LA 0,4 End 9: ML 3: 4: 5: 6: 7: 8: 09/20/23 LC LC 30 ML AD LC LC 10: 11: 12: 13: 14: 15: 16: 17: AD LC LC ML AD LC 10 ST HL 64 Nhiệm vụ Bổ sung vào codegen.c • int computeNestedLevel(Scope* scope); • void genVariableAddress(Object* var) • void genVariableValue(Object* var) • void genParameterAddress(Object* param) • void genParameterValue(Object* param) • void genReturnValueAddress(Object* func) – Gán giá trị trả cho hàm • void genReturnValueValue(Object* func) • void genProcedureCall(Object* proc) • void genFunctionCall(Object* func) 09/20/23 65 Nhiệm vụ • • • • Cập nhật parser.c Type* compileLValue(void); void compileCallSt(void); Type* compileFactor(void); Type* compileIndexes(Type* arrayType); 09/20/23 66