Hồ Chí Minh Tháng 7 năm 2003 Từ khóa: Trình biên dịch, bộ phân tích từ vựng, từ, sơ đồ dịch, bộ phân tích hướng đến cú pháp, bộ phân tích cú pháp, bộ phân tích cú pháp từ trên xuống, b
Trang 1ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN
-
Luận Văn Cao Học
Đề tài
XÂY DỰNG CHƯƠNG TRÌNH TỰ ĐỘNG SINH MÃ
TRUNG GIAN VÀ TỐI ƯU MÃ
TP HỒ CHÍ MINH, tháng 07 năm 2003
Giáo viên hướng dẫn : PGS.TS Phan Thị Tươi Học viên thực hiện : Tạ Duy Công Chiến Khóa : 11
Trang 2CÔNG TRÌNH ĐƯỢC HOÀN THÀNH TẠI TRƯỜNG ĐẠI HỌC BÁCH KHOA ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
Cán bộ hướng dẫn khoa học :
PGS.TS PHAN THỊ TƯƠI
Cán bộ chấm nhận xét 1 :
Cán bộ chấm nhận xét 2 :
Luận án cao học được bảo vệ tại HỘI ĐỒNG CHẤM BẢO VỆ LUẬN ÁN CAO HỌC TRƯỜNG ĐẠI HỌC BÁCH KHOA TP HỒ CHÍ MINH ngày … tháng … năm 2003
Trang 3ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC BÁCH KHOA CỘNG HÒA XÃ HỘI CHỦ NGHĨA VIỆT NAM Độc Lập -Tự Do - Hạnh Phúc
- -
NHIỆM VỤ LUẬN ÁN CAO HỌC
Họ và tên học viên: TẠ DUY CÔNG CHIẾN Phái: Nam
Ngày tháng năm sinh: 06-11-1965 Nơi sinh: LONG AN
Chuyên ngành: CÔNG NGHỆ THÔNG TIN
I- TÊN ĐỀ TÀI: XÂY DỰNG CHƯƠNG TRÌNH TỰ ĐỘNG SINH MÃ
TRUNG GIAN VÀ TỐI ƯU MÃ
II- NHIỆM VỤ VÀ NỘI DUNG:
III- NGÀY GIAO NHIỆM VỤ (Ngày bảo vệ đề cương):
IV- NGÀY HOÀN THÀNH NHIỆM VỤ (Ngày bảo vệ luận án tốt nghiệp):
V- HỌ VÀ TÊN CÁN BỘ HƯỚNG DẪN: PGS.TS PHAN THỊ TƯƠI
Trang 4PHÒNG QLKH-SĐH CHỦ NHIỆM NGÀNH
Trang 5LỜI CẢM ƠN
Tôi chân thành cảm ơn Cô – PGS TS Phan Thị Tươi, Giáo viên hướng dẫn, đã tận tình chỉ bảo, nhiệt tình hướng dẫn tôi hoàn thành Luận văn cao học này
Chân thành cảm ơn Quý Thầy Cô - giảng viên trường Đại học Bách Khoa Tp Hồ Chí Minh, trường Đại học Khoa học tự nhiên Tp Hồ Chí Minh đã tận tình giảng dạy, giúp đỡ tôi trong quá trình học tập
Chân thành cảm ơn TS , TS , TS đã giúp chúng tôi rất nhiều bằng những góp ý, chỉ dẫn và các tài liệu quý giá trong quá trình thực hiện Luận văn này
Tp Hồ Chí Minh, ngày …… tháng …… năm 2003 Tạ Duy Công Chiến
Trang 6Xây Dựng Chương Trình Tự Động Sinh Mã Trung Gian và
Tối Ưu Mã
Tạ Duy Công Chiến Đại Học Bách Khoa TP Hồ Chí Minh
Tháng 7 năm 2003
Từ khóa:
Trình biên dịch, bộ phân tích từ vựng, từ, sơ đồ dịch, bộ phân tích hướng đến cú pháp, bộ phân tích cú pháp, bộ phân tích cú pháp từ trên xuống, bộ phân tích cú pháp từ dưới lên, định nghĩa hướng đến cú pháp, định nghĩa thuộc tính, thuộc tính tổng hợp, thuộc tính kế thừa, ngữ nghĩa, tối ưu hóa, khối cơ bản, dòng điều khiển, dòng dữ liệu, chi phối, đồ thị dòng, biến sống, đồ thị có hướng không vòng, đồ thị giao thoa, thanh ghi ký hiệu, lập thời biểu, ống lệnh, đồ thị độc lập, dừng
Tóm tắt:
Sinh mã và tối ưu mã là các giai đoạn quan trọng của trình biên dịch Trong mô hình phân tích tổng hợp của một trình biên dịch, biên dịch phía trước sẽ dịch chương trình nguồn sang dạng biểu diễn trung gian để sau đó sinh ra mã đích Mặc dù chương trình nguồn có thể được biên dịch trực tiếp sang ngôn ngữ máy mà không cần sinh mã trung gian, nhưng một số ưu điểm của việc sinh mã trung gian là:
o Tiết kiệm thời gian khi tạo ra một trình biên dịch cho các máy khác nhau
o Có thể áp dụng bộ tối ưu mã độc lập với máy dích
Việc sinh mã trung gian thường tạo ra một số lệnh dư thừa làm cho
trình biên dịch không hiệu quả Thông qua giai đoạn tối ưu, mã sinh ra sẽ hiệu quả hơn, kích thước mã được thu giảm, chương trình thực thi nhanh hơn
Trang 7Trong luận văn này, chúng tôi xây dựng một chương trình tự động sinh mã trung gian, cải tiến và thiết kế các giải thuật tối ưu nhằm cải thiện mã trung gian tốt hơn, đánh giá hiệu suất trước và sau khi tối ưu mã Các kết quả này cho thấy tính hiệu quả của các phương pháp giải thuật mà chúng tôi đã xây dựng được.
Trang 8
Building A Program for Automatic Code Generation and
syntax-Abstract:
Code generation and optimization are the important steps in compiler implementation In the analysis-synthesis model of a compiler, the front end translates a source program into an intermediate representation form which the back end generates target code Although a source program can be translated directly into the target language, some benefits of using a machine independent intermediate form are:
o A compiler for a different machine can be create by attaching a back end for the new machine to an exiting front end
o A machine-independent code optimizer can be applied
to the intermediate representation
Trang 9The task of generating intermediate code usually creates redundant code that makes the compiler less efficient Code optimization will alter the program code to improve the generated code, so more efficient target code can be generated, and speedup program execution or reduce code size
In this thesis, we build a program for automatic code generation, improved and designed optimization algorithms that improve the intermediate code, reduce code size without taking into consideration any properties of the target machine
We also calculate the efficiency of algorithms before and after performing code optimization These results prove that they are be acceptable.
Trang 10Mục Lục
Chương 1: Đặt vấn đề ……… 1
1.1 Giới thiệu ……… ……… ………… 1
1.2 Tình hình ngiên cứu việc tự động sinh mã trung gian và tối ưu mã trung gian ……… 2
1.3 Mục tiêu đề tài ……… 4
1.4 Phương pháp luận ……… 4
1.5 Các đóng góp của luận văn ……… ……… 6
Chương 2 : Tổng quan về trình biên dịch ……… 8
2.1 Giới thiệu về trình biên dịch ……… 8
2 2 Trình biên dịch trực tiếp cú pháp ……… 8
2.3 Tối ưu mã ………… ……… … 10
Chương 3: Trình biên dịch hướng đến cú pháp …… … 12
3.1 Phân tích từ vựng ……… ……… 12
3.2 Biên dịch hướng đến cú pháp ……… 16
3.3.1 Sinh Mã Trung Gian ……… 23
Chương 4 : Tối ưu mã trung gian … ……… 39
4.1 Tối ưu hóa thanh ghi bằng giải thuật tô màu đồ thị ……41
4.2 Tối ưu hóa bằng lập thời biểu cho các lệnh ……… 62
Chương 5 : Giải thuật và chương trình ……… 77
5.1 Định nghĩa chính qui ……… …… 77
5.2 Văn phạm ngôn ngữ Pascal ………… ……… …… 77
5.3 Các giải thuật xây dựng trình biên dịch hướng đến cú pháp 78 5.4 Sinh mã trung gian … ……….82
Chương 6 : Kết Luận …….……… 91
6.1 Kết luận ……… ………91
6.2 Kết quả đạt được ……… ……….… 91
Trang 11Tài Liệu Tham Khảo ……….93
Trang 12Quá trình biên dịch đều phải qua một số giai đoạn nhất định nhằm mục đích là chuyển chương trình của người sử dụng ở ngôn ngữ cấp cao sang chương trình đích ở ngôn ngữ cấp thấp mà máy tính hiểu được thể hiện qua H.1.1
H.1.1 Trình bày khái niệm về trình biên dịch
Khi biên dịch từ chương trình nguồn sang chương trình đích, trình biên dịch đi qua một số giai đoạn sau:
H.1.2 Các giai đoạn của quá trình biên dịch
Qua H.1.2, việc sinh mã trung gian là quá trình không thể thiếu được trong một trình biên dịch Sau khi mã trung gian được sinh ra ở trình biên dịch phía trước, chúng có thể được tối ưu trong bộ tối ưu mã, cũng có thể không cần tối ưu Tuy nhiên một trình biên dịch có thể tối ưu mã thì sẽ làm cho quá trình biên dịch hiệu
Trình biêndịch Chương trình đích (Ngôn ngữ cấp thấp)
Trang 13Vấn đề sinh mã tối ưu về lý thuyết là rất khó Song trong thực tế chúng ta có thể chọn một số kỹ thuật để tạo mã tốt, nhưng không nhất thiết là tốt nhất Việc cải tiến mã có thể đạt được thông qua một số kỹ thuật biến đổi gọi là tối ưu Trình biên dịch mà áp dụng các biến đổi cải tiến mã gọi là trình biên dịch tối ưu
Đề tài : “Xây dựng chương trình tự động sinh mã trung gian và thực hiện tối ưu mã trung gian” là một trong các quan tâm đó
1.2 Tình hình nghiên cứu việc tự động sinh mã trung gian và tối ưu mã trung gian 1.2.1 Trong nước
Hiện nay các đề tài liên quan đến việc sinh mã và tối ưu hóa mã còn rất ít được nghiên cứu ở các trường đại học cũng như các viện nghiên cứu Một số đề tài tốt nghiệp liên quan đến việc tối ưu mã
- Xây dựng giải thuật tối ưu mã trung gian của trình biên dịch, Lê Hồng Sơn, luận văn tốt nghiệp đại học, 2001 [15]
Tác giã trình bày một số giải thuật tối ưu mã trung gian như: loại bỏ biểu thức con chung, loại bỏ biến quy nạp, thu giảm cường lực
- Tối ưu mã trình biên dịch, Nguyễn Anh Tuấn, luận văn tốt nghiệp cao học,
2002 [14]
Tác giã trình bày một số giải thuật tối ưu mã trung gian như : loại bỏ biểu thức con chung, loại bỏ biến quy nạp, thu giảm cường lực, lan truyền sao chép, tối ưu hóa đại số, tính hiệu suất của các giải thuật
1.2.2 Nước ngoài
Việc tự động sinh mã trung gian và tối ưu mã đã được nghiên cứu rất rộng rãi trên thế giới trong nhiều năm qua đặc biệt là tối ưu mã Riêng đối với quá trình sinh mã trung gian thì hầu như rất ít, chỉ dừng lại ở các giải thuật có sẵn trong các sách giảng dạy đại học Hiện nay đã và đang có rất nhiều đề tài về tối ưu mã mà các giải thuật cố gắng làm cho thời gian biên dịch ngắn hơn và chương trình chạy nhanh hơn, ví dụ như :
Trang 14- Advanced Compiler - Design and Implemention, Steven S.Muchnick,1997 [20]
Giới thiệu một số giải thuật sinh mã hiệu quả như loại bỏ biểu thức con chung, tô màu đồ thị, lập thời biểu cho các lệnh, loại bỏ mã chết, dịch chuyển mã…
- Code generation for expressions with common subexpressions, Aho, A.V S C Iohnson , and J D UllMan, 1997 [9]
Nhóm nghiên cứu đã đưa ra ngôn ngữ xử lý cây (Twig language) một ngôn ngữ được xây dựng giúp cho quá trinh sinh mã và tối ưu hóa mã Dựa trên ngôn ngữ này, Alfred V.Aho và Steven W.K.Tjiang của AT&T Laboratories đã đưa ra một giải thuật sinh mã dựa trên việc so trùng cây biểu thức và lập trình động
- Efficient Symbolic Analysis for Optimization Compilers [12]
Được nghiên cứu ở trường đại học Florida State University, liên quan đến các vấn đề:
+ Phân tích phụ thuộc dữ liệu
+ Song song hóa các vòng lặp và biến đổi vòng lặp
Tuy nhiên các nghiên cứu ở đây chỉ là bước đầu chưa có kết quả khích lệ
- Register Allocation and splilling via graph coloring [18]
Nhóm nghiên cứu việc tối ưu thanh ghi trong trình biên dịch Thông thường một chương trình viết ở ngôn ngữ cấp cao thường ít tham khảo đến các thanh ghi Mục tiêu của trình biên dịch là giữ các toán hạng có nhiều tính toán trong thanh ghi hơn là trong bộ nhớ để giảm đến mức tối thiểu các hoạt động nạp (load) và lưu trữ (store)[18] Chỉ giải quyết cho một số trường hợp giới hạn, chưa có kết quả tối ưu nhất
- Optimizing and Parallelizing Compilers [13]
Đề cập đến các nghiên cứu về việc phát hiện song song hóa nhỏ và/ hoặc song song lớn, các thể hiện trung gian, phân tích dòng và tối ưu, phân phối thanh ghi
Trang 15Các đề tài nghiên cứu cho việc sinh mã và tối ưu mã về trình biên dịch được thực hiện rất nhiều, nhưng các kết quả chỉ là bước đầu góp phần xây dựng trình biên dịch ngày càng hiệu quả hơn và mở ra nhiều hướng nghiên cứu về trình biên dịch
1.3 Mục tiêu đề tài
Luận văn cao học “Xây dựng chương trình tự động sinh mã trung gian và thực
hiện tối ưu mã trung gian” nghiên cứu thiết kế và hiện thực một trình biên dịch đơn giản, sinh mã trung gian và thực hiện một số giải thuật tối ưu mã
Các mục tiêu chủ yếu của đề tài là:
- Hiện thực toàn bộ một trình biên dịch phía trước đơn giản theo các phương pháp của [6]
- Thực hiện quá trình tự động sinh mã trung gian cho
o Các biểu thức kể cả phép gán
o Các cấu trúc có điều kiện, cấu trúc vòng lặp
o Gọi thủ tục, hàm, chương trình con
- Tối ưu mã trung gian : hiện thực các giải thuật tối ưu mã cho chương trình sau khi sinh mã trung gian
- Đánh giá hiệu suất của giải thuật tối ưu mã trung gian
1.4 Phương pháp luận
Cấu trúc hoàn chỉnh của một trình biên dịch phải trải qua một số giai đoạn, mỗi giai đoạn sẽ đảm nhận một vai trò khác nhau và có tính kế thừa từ giai đoạn trước đó
Kể từ khi máy tính ra đời, các nhà khoa học không ngừng cải tiến và phát triển cả về phần cứng và phần mềm sao cho máy tính ngày càng tốt hơn Thông thường tốc độ xử lý của máy tính đối với một phần mềm ứng dụng không chỉ phụ thuộc vào phần cứng mà còn phụ thuộc rất nhiều đến cấu trúc dữ liệu, ngôn ngữ lập trình và đặc biệt là trình biên dịch xử lý chúng
Trang 16Việc xây dựng trình biên dịch đòi hỏi phải hiểu biết nhiều lãnh vực: ngôn ngữ lập trình, kiến trúc máy tính, các thuật toán và công nghệ phần mềm Nếu hiểu được những quá trình xảy ra trong trong lúc biên dịch một chương trình có thể cho phép những lập trình viên tránh được các sai sót trong khi viết
Hầu hết các nhà lập trình đều mong muốn là trình biên dịch sinh được mã đích có chất lượng giống như lúc chúng được viết bằng thủ công [5][9][10] Việc sinh mã của trình biên dịch có thể làm cho chương trình chạy nhanh hoặc ít tốn bộ nhớ hơn hoặc cả hai Để đạt được điều này, các trình biên dịch phải sử dụng các kỹ thuật tối ưu trong quá trình sinh mã Do đó, tối ưu hoá mã trở thành một giai đoạn quan trọng không thể thiếu trong tất cả các trình biên dịch
Mã trung gian để thực hiện tối ưu là mã trung gian ba địa chỉ, với mã ba địa chỉ cùng với các thông tin dòng dữ liệu được tính toán, máy tính sẽ thực hiện các phép biến đổi dựa trên các phương pháp kỹ thuật tối ưu để tạo ra mã ba địa chỉ mới tốt hơn và hiệu quả hơn cho việc sinh mã Đó là các kỹ thuật:
- Xây dựng đồ thị có hướng không lặp vòng (Directed acyclic graph–
DAG)[5] dùng để hổ trợ khi thực hiện biến đổi trong các khối cơ bản
(basic block) DAG sẽ xác định được các biểu thức con chung cần
thiết cho việc tối ưu
- Phân tích dòng điều khiển (control flow analysis) dùng để phân hoạch các khối cơ bản của chương trình Trên cơ sở đó máy tính sẽ tiến tới xây dựng đồ thị dòng (flow graph), tính toán các chi phối (dominator – DOM), phát hiện ra các vòng lặp (loops)
- Kỹ thuật phân tích dòng dữ liệu (data flow analysis) [3] nhằm thu thập các thông tin về cách dùng các biến, các định nghĩa trong chương trình Tất cả các thông tin này được thu thập từ nhiều nơi (có thể ở các khối khác nhau) và có thể liên quan với nhau theo một hệ phương trình đó là phương trình dòng dữ liệu cần thiết cho quá trình tối ưu hoá Các thông tin tính toán về biến sống, đạt đến sự định
Trang 17nghĩa, chuỗi sử dụng-định nghĩa, chuỗi định nghĩa-sử dụng, … dùng trong việc tính toán đường đi của dòng dữ liệu Trên cơ sở đó các thông tin này sẽ quyết định cho các giải pháp tối ưu
Tối ưu trình biên dịch là vấn đề lớn mà các nhà nghiên cứu luôn quan tâm Trên cơ sở đó, có thể phát triển nghiên cứu theo các hướng sau:
- Cấp phát và gán thanh ghi cho các biến trong quá trình biên dịch Với số lượng thanh ghi của máy có giới hạn, trình biên dịch phải có chiến lược cấp phát sử dụng các thanh ghi máy một cách hợp lý và tối ưu nhất
- Tính toán và giải quyết sự phụ thuộc dữ liệu trong chương trình Khả năng song song hóa các vòng lặp sẽ làm giảm thời gian thực thi của chương trình cũng như tiết kiệm được thời gian biên dịch
- Lập thời biểu cho các lệnh, trong mô hình Neumann việc thực thi của một lệnh chỉ bắt đầu sau khi các lệnh trước nó hoàn thành Do đó vấn đề ở đây là việc nghiên cứu giải quyết lịch thực thi các lệnh có thể theo ống lệnh (pipeline), khi CPU có số đơn vị tính toán nhiều hơn một để giảm thời gian thực thi
Tuy nhiên việc tối ưu trình biên dịch cũng có một số khó khăn:
- Việc sinh mã đích có chất lượng giống như viết thủ công thường chỉ ở một số trường hợp giới hạn và rất khó thực hiện
- Không có kỹ thuật tối ưu tổng quát và triệt để, thường là mỗi kỹ thuật tối ưu chỉ áp dụng cho một loại mã nào đó
- Biến đổi chương trình không được gây ra lỗi, sai ý nghĩa
- Công việc gỡ lỗi trong môt trình biên dịch đã tối ưu trở nên phức tạp hơn so với khi chưa tối ưu [5]
1.5 Các đóng góp của luận văn
- Thiết kế và xây dựng bộ phân tích từ vựng
- Thiết kế và xây dựng bộ biên dịch hướng đến cú pháp
Trang 18- Thiết kế và xây dựng bộ sinh mã trung gian ba địa chỉ cho các phát biểu gán, các biểu thức, các cấu trúc rẽ nhánh, các cấu trúc điều khiển, các thủ tục và các hàm
- Tối ưu mã trung gian theo một số giải thuật:
Giải thuật tối ưu thanh ghi bằng phương pháp tô màu đồ thị trong trường hợp thanh ghi không giới hạn
Giải thuật tối ưu thanh ghi bằng phương pháp tô màu đồ thị trong trường hợp thanh ghi có giới hạn
Tối ưu mã bằng phương pháp lập thời biểu cho các lệnh
- Tính toán hiệu suất đạt được của các giải thuật sau khi tối ưu
Trang 19Chương 2
TỔNG QUAN VỀ TRÌNH BIÊN DỊCH
2.1 Giới thiệu về trình biên dịch
Trình biên dịch có thể chia thành các khối như H.2.1 Trong đề tàichúng tôi tập trung ở hai khối đầu: trình biên dịch hướng đến cú pháp và bộ tối ưu mã trung gian H.2.1 trình bày các giai đoạn của quá trình biên dịch
như sau
2.2 Trình biên dịch hướng đến cú pháp
Trình biên dịch hướng đến cú pháp còn được gọi là trình biên dịch phía trước ( front end compiler) Trình biên dịch phía trước sẽ dịch chương trình nguồn của người sử dụng và sinh ra mã trung gian
H.2.2 trình bày cấu trúc của một trình biên dịch hướng đến cú pháp
H.2.2 Trình biên dịch hướng đến cú pháp
Dòng token
Dòng
ký tự
Bộ phân tích từ vựng Bộ biên dịch hướng đến cú
pháp
Kết quả đánh giá
Mã trung gian
Chương
trình
nguồn
Mã trung gian chưa tối ưu
Mã đối tượng
Mã trung gian đã Tối ưu
Bộ sinh mã đối tượng
Bộ đánh giá mã đối tượng
H.2.1 Các khối của trình biên dịch
Trang 202.2.2 Bộ biên dịch hướng đến cú pháp
H.2.3 trình bày bộ biên dịch hướng đến cú pháp
H.2.3 Bộ biên dịch hướng đến cú pháp
Bộ biên dịch hướng đến cú pháp sử dụng các định nghĩa hướng đến cú pháp và sơ đồ dịch để xây dựng cây phân tích cú pháp khi nhận các token từ bộ phân tích từ vựng, sau đó duyệt cây khi cần đánh giá các quy tắc ngữ nghĩa tại các nút của cây Trong quá trình đánh giá các quy tắc ngữ nghĩa có thể làm phát sinh mã, lưu thông tin vào bảng danh biểu, đưa ra các thông báo lỗi hoặc thực hiện một số hành động khác
Tuy nhiên trong quá trình hiện thực không nhất thiết phải tuân thủ theo các giai đoạn như H.2.3 Các trường hợp đặc biệt của định nghĩa hướng đến cú pháp có thể cài đặt một lần bằng cách đánh giá các quy tắc trong khi phân tích cú pháp mà không cần phải xây dựng cây cú pháp hay đồ thị phụ thuộc
Quá trình biên dịch sẽ nhận các token từ bộ phân tích từ vựng, thực hiện phân tích cú pháp, phát hiện và khắc phục các lỗi cú pháp để có thể xử lý phần còn lại trong giai đọan phân tích cú pháp Có một số phương pháp để tiếp cận :
- Phân tích cú pháp từ dưới lên
- Phân tích cú pháp từ trên xuống
- Phân tích cú pháp LR
2.2.3 Sinh mã trung gian
1 Tác dụng của quá trình sinh mã trung gian
Theo H.2.2, trước tiên trình biên dịch sẽ dịch chương trình nguồn thành một dạng biểu diễn trung gian để bước sau sinh ra mã đích
Để việc sinh mã trung gian độc lập với mã đích, người ta thường chọn mã
Cây phân tích cú pháp
Đồ thị Phụ thuộc
Mã trung gian
Token từ bộ phân
tích từ vựng
Thứ tự đánh giá các quy tắc ngữ nghĩa
Trang 21- Thuận lợi khi cần thay đổi giai đoạn sau (back-end phrase), có thể tạo ra một trình biên dịch cho nhiều máy tính khác bằng cách thay đổi giai đoạn sau
- Có thể tạo một bộ tối ưu mã độc lập với mã đích
2 Chọn lựa ngôn ngữ trung gian
Yêu cầu của đề tài là chọn mã ba địa chỉ làm ngôn ngữ trung gian Mã ba địa chỉ là một lệnh có dạng tổng quát x : = y op z Trong đó x,
y, z là các tên, hằng hoặc các tên tạm do trình biên dịch sinh ra, op là một toán tử bất kỳ
Ví dụ Biểu thức x+y*z có thể được dịch thành mã ba địa chỉ
t1 := y * z t2 := x + t1 trong đó t1 và t2 là các tên tạm do trình biên dịch sinh ra
Việc phân tích các biểu thức số học phức tạp thành các biểu thức con đơn giản đã làm cho mã ba địa chỉ trở thành một ngôn ngữ thiết yếu trong việc sinh mã đích và tối ưu mã
Lý do dùng thuật ngữ “mã ba địa chỉ” đó là mỗi câu lệnh thường chứa
ba địa chỉ, hai địa chỉ dành cho hai toán hạng và một địa chỉ dành cho kết quả Mã ba địa chỉ có nhiều loại lệnh, các lệnh trong mã ba địa chỉ có nhiều điểm tương đồng với mã hợp ngữ
2.3 Tối ưu mã
Quá trình tối ưu mã trung gian được thực hiện như sau
Phân tích dòng dữ liệu
Trang 222.3.1 Tiêu chuẩn cho việc tối ưu mã
- Trong quá trình tối ưu mã, mọi biến đổi phải giữ nguyên nghĩa của chương trình Mọi tối ưu không được thay đổi dữ liệu đầu vào (input), đầu ra (output) của chương trình, không gây ra lỗi, không gây ra phép chia bởi zero
- Mọi biến đổi phải làm cho chương trình nhanh hơn, và thu giảm thanh ghi trong việc sinh mã đối tượng
2.3.2 Phân tích dòng điều khiển (control flow analysis)
Phân tích dòng điều khiển bao gồm:
- Nhận diện các khối cơ bản (basic blocks)
- Phân tích đồ thị dòng điều khiển (control flow graph)
- Xác định chi phối (dominator) của một nút trong đồ thị
- Xác định các cấu trúc điều khiển của một chương trình
- Xác định các thủ tục
- Nhận diện các vòng lặp
2.3.3 Phân tích dòng dữ liệu (data flow analysis)
Để tối ưu và làm tốt việc sinh mã, một trình biên dịch cần thu thập toàn bộ thông tin của chương trình và phân bố các thông tin này đến mỗi khối trong đồ thị dòng
Phân tích dòng dữ liệu là xác định dữ liệu dùng trong chương trình và dùng kết quả phân tích này để xác định các tối ưu là hợp lệ Phân tích này có thể thực hiện
- Cục bộ (bên trong một khối) : phân tích ảnh hưởng của mỗi lệnh, giải quyết các ảnh hưởng ở đầu/cuối mỗi khối
- Toàn cục (bên trong các procedure) : xem ảnh hưởng của các dòng điều khiển trong chương trình
Trang 23Chương 3
TRÌNH BIÊN DỊCH HƯỚNG ĐẾN CÚ PHÁP
3.1 Phân Tích Từ Vựng
Để cài đặt bộ phân tích từ vựng ta có hai phương pháp
- Phương pháp thủ công
- Phương pháp tự động
Phương pháp thủ công xây dựng bộ phân tích từ vựng bằng cách tạo ra một sơ đồ miêu tả các trạng thái mà bộ phân tích từ vựng sẽ trải qua khi nhận dạng token của ngôn ngữ nguồn rồi chuyển sơ đồ thành chương trình tìm kiếm các token
Phương pháp tự động đặc tả mẫu của các token bằng các biểu thức chính quy và dùng một bộ sinh, chẳng hạn như Lex và Jlex để tạo ra bộ phân tích từ vựng bằng cách biến đổi các biểu thức chính quy thành các automat hữu hạn rồi từ đó sinh ra chương trình mô phỏng các automat
Vấn đề trọng tâm của đề tài là sinh mã trung gian và tối ưu mã trung gian nên chúng tôi chọn phương pháp thủ công để xây dựng bộ phân tích từ vựng
3.1.1 Quá trình nhận dạng TOKEN
Token là các đơn vị từ vựng nhỏ nhất có nghĩa, nó biểu thị cho: danh biểu, hằng, các toán tử, các từ khóa của ngôn ngữ lập trình, các ký tự phân cách v.v…
Ví dụ 3.1 Cho văn phạm G, có tập luật sinh P như sau:
stmt → if exp then stmt│if exp then stmt else stmt │є
exp → term relop term │term
term → id │num
Các ký hiệu kết thúc là if, then, else, relop, num, chính là các token được định nghĩa chính quy như sau:
if → if
Trang 24then → then
relop → <│ < = │ >│ > =│ < >│ =
id → letter (letter│ digit)*
num → digit + (.digit +│є) ((E (+│ - │є) digit+)│є )
Dựa vào ngôn ngữ được đặc tả bởi biểu thức chính quy trên, bộ phân tích từ
vựng sẽ nhận dạng các token if, then, else, relop, id, num
Bộ phân tích từ vựng còn phải nhận dạng các khoảng trắng để loại bỏ Chúng
ta thêm định nghĩa chính quy cho dấu trắng và chuỗi dấu trắng bằng hai định nghĩa sau:
delim → blank │tab│newline
else else
id id Con trỏ chỉ đến bảng danh biểu
Trang 253.1.2 Sơ Đồ Dịch
Sơ đồ dịch là bước trung gian trong việc xây dựng bộ phân tích từ vựng
Sơ đồ dịch miêu tả các hành vi của bộ phân tích từ vựng khi nhận dạng các token
Ví dụ 3.2
3.1.3 Hiện thực sơ đồ dịch bằng chương trình
Chuỗi các sơ đồ dịch sẽ được chuyển thành chương trình tìm kiếm token, là bộ phân tích từ vựng Ứng với mỗi trạng thái của sơ đồ dịch là một đoạn chương trình Nếu có một số cạnh xuất phát từ một trạng thái thì đoạn chương trình của trạng thái đó phải có lệnh đọc và lựa chọn cạnh nào là cạnh tiếp theo Thủ tục nextchar được dùng để đọc ký tự kế tiếp trong bộ đệm nhập Nếu một cạnh có tên trùng với ký tự vừa được đọc, hoặc có tên là lớp ký tự, có chứa ký tự vừa được đọc thì sự điều khiển của chương trình sẽ chuyển đến đoạn chương trình của trạng thái sắp tới do cạnh đó chỉ đến
Nếu không có cạnh nào trùng tên với ký tự vừa được đọc và trạng thái hiện tại cũng không là trạng thái kết thúc của việc nhận dạng một token, thì trở lại vị trí để bắt đầu sự tìm kiếm token khác bằng sơ đồ dịch kế tiếp Nếu tất cả các sơ đồ dịch không thể nhận dạng được một token nào đó thì bộ phân tích từ vựng sẽ thông báo lỗi
- Sơ đồ dịch cho danh biểu
10
Trang 26Token đã nhận dạng sẽ được gửi sang bộ phân tích cú pháp (parser) bằng hai thông tin thông qua cặp biến < id, vị trí > cho token loại danh biểu và < num, trị > cho số
Ví dụ 3.3 Với sơ đồ dịch H.3.2 , ta có đoạn chương trình sau
case ‘<’: state = 5; break;
case ‘>’: state = 6; break;
Trang 273.2 Biên Dịch Hướng Đến Cú Pháp
Mỗi ngôn ngữ lập trình đều có các quy tắc để miêu tả cấu trúc cú pháp của chương trình hợp lệ Cú pháp của ngôn ngữ lập trình được miêu tả bằng văn phạm phi ngữ cảnh hoặc ký pháp BNF (Backus-Naur Form) Từ các lớp văn phạm, ta có thể thiết kế tự động bộ phân tích cú pháp, nó xác định xem một chương trình nguồn có đúng cú pháp không
Quá trình biên dịch hướng đến cú pháp bao gồm nhận các chuỗi nhập vào, xây dựng cây phân tích cú pháp, sau đó duyệt cây khi cần đánh giá các quy tắc ngữ nghĩa tại các nút của cây Quá trình đánh giá này có thể làm phát sinh mã, lưu thông tin vào bảng danh hiệu, đưa ra các thông báo lỗi …
Để biên dịch hướng đến cú pháp chúng ta cần định nghĩa hướng đến cú pháp
hay lược đồ dịch
3.2.1 Định nghĩa hướng đến cú pháp
Là văn phạm phi ngữ cảnh, trong đó mỗi ký hiệu văn phạm có một tập thuộc tính đi kèm Thuộc tính có thể là thuộc tính tổng hợp hay thuộc tính kế thừa
Một thuộc tính có thể biểu diễn bất kỳ điều gì chúng ta chọn: chuỗi, số, kiểu, vị trí bộ nhớ Giá trị của thuộc tính tại một nút của cây phân tích cú pháp được định nghĩa bởi luật ngữ nghĩa đi kèm với luật sinh được dùng tại nút đó Giá trị của một thuộc tính tổng hợp tại một nút được tính từ giá trị của các nút con của nó trong cây Giá trị của thuộc tính kế thừa được tính từ giá trị thuộc tính của những nút anh em và cha của nó
Luật ngữ nghĩa thiết lập phụ thuộc giữa các thuộc tính có thể được biểu diễn bằng một đồ thị Từ đồ thị phụ thuộc chúng ta tìm ra một thứ tự đánh giá các luật ngữ nghĩa
Một cây phân tích cú pháp trình bày giá trị các thuộc tính tại mỗi nút được gọi là cây phân tích cú pháp có chú thích (annotated parse tree) Quá trình tính giá trị các thuộc tính tại các nút gọi là chú thích (annotate) cho cây phân tích cú pháp
Trang 283.2.2 Hình thái của một định nghĩa hướng đến cú pháp
Trong một định nghĩa hướng đến cú pháp, mỗi luật sinh AỈ α có thể được liên kết với một tập các luật ngữ nghĩa có dạng b:=f(c1, c2,c3,…, ck) trong đó f là một hàm, c1, c2… ck là các thuộc tính của các ký hiệu văn phạm trong luật sinh và
• b là một thuộc tính tổng hợp của A hoặc
• b là một thuộc tính kế thừa của một trong các ký hiệu ở vế phải của luật sinh
Ví dụ 3.4 Các định nghĩa hướng đến cú pháp đơn giản của một máy tính bỏ túi
T.val := T1.val * F.val T.val := F.val
F.val := E.val
F.val := digit.lexval
Token digit có thuộc tính tổng hợp lexval với gía trị được giả định do phần phân tích từ vựng cung cấp Luật ngữ nghĩa đi kèm với luật sinh LỈEn
chỉ là một thủ tục in ra giá trị của biểu thức số học sinh bởi E
3.2.2.1 Thuộc tính tổng hợp
Một định nghĩa hướng đến cú pháp chỉ sử dụng các thuộc tính tổng hợp được gọi là định nghĩa thuộc tính S (S-attributed definition) Một cây phân tích cú pháp cho một định nghĩa thuộc tính S có thể được chú thích bằng cách đánh giá các luật ngữ nghĩa cho các thuộc tính tại mỗi nút theo hướng đi từ lá đến gốc
Trang 29Ví dụ 3.5 Định nghĩa thuộc tính S trong ví dụ 3.4 cho một biểu thức số học
3 * 5 + 4n có cây cú pháp như H.3.4
Giã sử xét nút tương ứng với luật sinh T Ỉ T * F Giá trị thuộc tính T.val tại nút này được định nghĩa như sau:
TỈT1 * F T.val = T1.val * F.val
3.3.2.2 Thuộc tính kế thừa
Thuộc tính kế thừa là thuộc tính của một nút xác định theo thuộc tính nút cha và/hoặc các nút anh em của nó Thuộc tính kế thừa rất có ích cho việc diễn tả sự phụ thuộc của cấu trúc ngôn ngữ vào bối cảnh mà nó xuất hiện Ta có thể dùng thuộc tính kế thừa để xác định kiểu dữ liệu cho khai báo biến như
ở ví dụ 3.6
Ví dụ 3.6 Định nghĩa hướng đến cú pháp với thuộc tính kế thừa L.in
Luật sinh Quy tắc ngữ nghĩa
DỈ T L
T Ỉ int
L.in := T.type T.type := integer
L
nE.val =19
Trang 30T Ỉ real
L ỈL1, id
L Ỉ digit
T.type := real L1.in := L.in addtype (id.entry, L.in) addType(id.entry, L.in)
3.2.2.3 Định nghĩa thuộc tính L
Định nghĩa thuộc tính L (L-attributed definition) là một lớp của định nghĩa hướng đến cú pháp, gần như chứa đựng hầu hết tất cả các hành động dịch có thể được thực hiện mà không cần phải xây dựng cây phân tích cú pháp Một định nghĩa hướng đến cú pháp là định nghĩa thuộc tính L nếu mỗi thuộc tính kế thừa của Xj ở vế phải của luật sinh A Ỉ X1X2….Xn, với 1 <= j
<= n, chỉ phụ thuộc vào
• Các thuộc tính của các ký hiệu X1, X2,….,Xj-1 ở bên trái của Xj
trong luật sinh và
• Các thuộc tính kế thừa của A
Mọi định nghĩa thuộc tính S đều thuộc tính L
3.2.3 Phân tích cú pháp
Bộ phân tích cú pháp nhận chuỗi các token từ bộ phân tích từ vựng để tạo ra cấu trúc cú pháp của chương trình nguồn
Vai trò của bộ phân tích cú pháp được miêu tả trong H.3.5
Có hai phương pháp phân tích cú pháp cơ bản cho ngôn ngữ lập trình
Yêu cầu token
Token Bộ phân tích Cây cú pháp
cú pháp
Bộ phân tích
từ vựng
Bảng danh biểu
Các bộ phận khác của TBD
H.3.5 Bộ phân tích cú pháp trong trình biên dịch
Trang 31o Phân tích cú pháp từ dưới lên (bottom-up parser)
Hai phương pháp này áp dụng trên các lớp văn phạm LL(1) hoặc LR(1), là văn phạm của các ngôn ngữ lập trình Cả hai phương pháp này đều có thể dùng để sinh tự động bộ phân tích cú pháp
Một dạng đặc biệt của phương pháp phân tích cú pháp từ trên xuống là phương pháp đoán nhận trước bao gồm
- Phân tích cú pháp đoán nhận trước đệ quy
• Với phương pháp này, văn phạm của ngôn ngữ lập trình phải thỏa mãn điều kiện không có đệ quy trái
• Từ văn phạm ta có thể xây dựng lược đồ dịch cho từng ký hiệu không kết thúc của văn phạm Sau đó lược đồ dịch sẽ được chuyển thành chương trình phân tích cú pháp đoán nhận trước Phương pháp này thích hợp cho quá trình phân tích thủ công
- Phân tích cú pháp đoán nhận trước không đệ quy
• Hoạt động theo cơ chế Automat Push-down Stack
Phương pháp phân tích từ dưới làm việc trên lớp văn phạm LR(1) Từ lớp văn phạm này người ta đã xây dựng bộ sinh tự động bộ phân phân tích cú pháp từ dưới lên không bị quay lui
Với mục đích của đề tài nhằm hiện thực một trình biên dịch hướng đến cú pháp đơn giản và thủ công, nên chúng tôi đã chọn phương pháp đón nhận trước có đệ qui
3.2.4 Phân tích cú pháp đoán nhận trước đệ qui
Để biên dịch từ trên xuống, các định nghĩa thuộc tính L được cài đặt trong phần phân tích cú pháp đoán nhận trước Ta dùng lược đồ dịch thay cho định nghĩa hướng đến cú pháp để thấy rõ được các hành vi ngữ nghĩa Vì phần lớn các toán tử số học đều kết hợp trái nên sẽ tự nhiên hơn khi dùng các văn phạm đệ qui trái cho các biểu thức và do đó thao tác khử bỏ đệ qui trái ra khỏi lược đồ dịch là điều tất yếu Ví dụ sau đây minh họa quá trình xây dựng bộ phân tích cú pháp theo phương pháp đoán nhận trước
Trang 32Lược đồ dịch trong quá trình phân tích cú pháp này phải có đặc điểm sau:
- Mỗi ký hiệu không kết thúc ở vế trái của luật sinh có một sơ đồ
- Tên các cạnh là token và là các ký hiệu không kết thúc ở vế phải của luật sinh
Sự truyền trên token sẽ được thực hiện nếu ký hiệu nhập trùng với token đó Nếu có sự truyền trên ký hiệu không kết thúc A thì ta thực hiện một lệnh gọi thủ tục A Sau đó
1 Tạo trạng thái bắt đầu và kết thúc
2 Với mỗi luật sinh có dạng AỈX1, X2,…Xn, ta xây dựng đường đi từ trạng thái bắt đầu đến trạng thái kết thúc sao cho các cạnh có tên X1,
H.3.6 trình bày sơ đồ dịch cho từng ký hiệu không kết thúc của G, tương ứng với vế trái của luật sinh
Trang 34
Sau khi có sơ đồ dịch, ta bắt đầu xây dựng bộ phân tích cú pháp đoán nhận trước đệ quy cho văn phạm G Sử dụng thủ tục đọc ký hiệu nhập kế tiếp nextchar, với c là biến chứa ký hiệu nhập kế tiếp Match là thủ tục so trùng Error là thủ tục báo lỗi
Giải thuật xây dựng bộ phân tích cú pháp đoán nhận trước từ sơ đồ dịch H.3.7
else error;
end; {F}
begin F;
while c =’*’ do F ; end {T}
begin T;
while c = ‘+’ do T;
end; {E}
3.3 Sinh mã trung gian
Trong quá trình biên dịch, ở giai đoạn đầu trình biên dịch sẽ dịch chương trình nguồn thành dạng biểu diễn trung gian để từ đó giai đoạn sau sinh ra mã đích Người thiết kế trình biên dịch có xu hướng chọn mã trung gian độc lập với mã đích nhằm mục đích:
1 Thuận lợi khi cần thay đổi mã đích
2 Có thể áp dụng bộ tối ưu hóa mã trung gian độc lập với máy đích Để đơn giản, chúng ta giả thiết rằng chương trình nguồn đã được phân tích cú pháp và kiểm tra kiểu tĩnh Phần lớn các định nghĩa hướng đến cú pháp trong chương này được cài đặt trong quá trình phân tích cú pháp từ trên xuống, vì thế quá trình sinh mã trung gian có thể được ghép chung với phân tích cú pháp nếu cần
Trang 353.3.1 Ngôn ngữ trung gian
Cây cú pháp và ký pháp hậu vị là hai loại dạng biểu diễn trung gian Một loại
thứ ba được gọi là mã ba địa chỉ ( three-address code)
3.3.1.1 Dạng biểu diễn đồ thị
Cây cú pháp mô tả cấu trúc phân cấp tự nhiên của một chương trình nguồn Tương tự DAG cũng biểu diễn thông tin cho chương trình nguồn nhưng các biểu thức chung được làm cho đồng nhất với nhau H.3.10 trình bày cây cú pháp và DAG cho biểu thức a := b* (- c) + b* (- c)
Ký pháp hậu vị là dạng biểu diễn tuyến tính của cây cú pháp; đó là một danh sách các nút của cây, trong đó một nút là toán tử xuất hiện ngay sau các con của nó Ký pháp hậu vị cho cây cú pháp ở H.3.10(a) là
a b c uminus * b c nminus * + assign Các cạnh trong một cây cú pháp không xuất hiện trong ký pháp hậu vị
Cây cú pháp được tạo bởi các định nghĩa hướng đến cú pháp Ví dụ như các định nghĩa trong H.3.11 dùng để xây dựng cây cú pháp cho các lệnh gán
H.3.10 Cách biểu diễn đồ thị của a := b* (- c) + b* (- c)
(a) Cây cú pháp (b)DAG
Trang 36H.3.10(a) là cây cú pháp cho biểu thức a := b* (- c) + b* (- c)
Định nghĩa hướng đến cú pháp sẽ sinh dạng DAG H.3.10(b) nếu hàm mkunode(op, child) và mknode(op, left, right) trả về một con trỏ chỉ đến một nút đã có thay vì tạo ra các nút mới Token id có thuộc tính place chỉ đến vị trí của nó trong bảng danh biểu
3.3.1.2 Mã ba địa chỉ
Mã ba địa chỉ (three-address code) là một dãy câu lệnh có dạng tổng quát
x := y op z, trong đó x, y, z là các tên, hằng hoặc các tên tạm do trình biên dịch sinh ra; op là một toán tử bất kỳ, chẳng hạn toán tử số học trên các số nguyên hay số thực hoặc một toán tử logic nhận trị boole
Ví dụ biểu thức x+y*z có thể được dịch thành một dãy các lệnh mã ba địa chỉ t1 := y * z
t2 := x + t1
trong đó t1 và t2 là các tên tạm do trình biên dịch sinh ra
Mã ba địa chỉ là một biểu diễn tuyến tính hóa của cây cú pháp hoặc của DAG, trong đó các toán hạng tương ứng với các nút lá của đồ thị Cây cú pháp và DAG trong H.3.10 được biểu diễn lại bằng mã ba địa chỉ trong H.3.12 Tên biến có thể xuất hiện hướng đến trong mã ba địa chỉ
a : = t5
(b) Mã cho dag
H.3.12 Các loại mã ba địa chỉ
Trang 373.3.1.3 Các loại mã ba địa chỉ
Mã ba địa chỉ có nhiều điểm tương đồng với mã hợp ngữ Các câu lệnh có tên gợi nhớ và có các câu lệnh điều khiển Dưới đây là các câu lệnh ba địa chỉ thông dụng và được dùng trong chương trình
1 Các câu lệnh gán có dạng x :=y op z, trong đó op là một phép toán số học hoặc phép toán logic hai ngôi
2 Các chỉ thị gán có dạng x := op y, trong đó op là một phép toán một ngôi.Các phép toán một ngôi chủ yếu gồm có phép đổi dấu, phép phủ định logic, toán tử đẩy (shift) và toán tử chuyển đổi kiểu, chẳng hạn đổi một số thập phân có dấu chấm cố định thành một số thập phân có dấu chấm di động
3 Các câu lệnh sao chép (copy statement) có dạng x:= y trong đó giá trị
của y được gán cho x
4 Lệnh nhảy vô điều kiện goto L Câu lệnh ba địa chỉ có nhãn L là câu
lệnh được thực thi tiếp theo
5 Các lệnh nhảy điều kiện như if x relop y goto L, với relop là các toán
tử quan hệ ( < ,=, >=, <=, <>) Sự điều khiển trương trình sẽ nhảy đến câu lệnh có nhãn L nếu biểu thức x relop y cho trị đúng
6 Lệnh param x 1 , param x 2 …, param x n được sinh ra tương ứng với các
thông số thực x1,x2,…,xn và lệnh call p, n dùng cho lời gọi thủ tục hay hàm với n thông số thực p(x 1 , x 2 ,…x n )
7 Các phép gán liên quan đến mảng có dạng x := y[i] và x [i] :=y Phép gán thứ nhất cho x bằng với giá trị nằm ở vị trí i đơn vị bộ nhớ sau y Câu lệnh x[i]:=y đặt giá trị của y vào trong vị trí i đơn vị bộ nhớ sau x
8 Phép gán địa chỉ và con trỏ có dạng x := &y, x :=* y và * x:=y Phép gán thứ nhất đặt giá trị của x bằng vị trí của y trong bộ nhớ Trong câu lệnh x:=* y, gán giá trị x bằng với giá trị của đối tượng mà y đang chỉ tới Cuối cùng *x:=y đặt giá trị của đối tượng được chỉ bởi x bằng giá trị của y
Trang 383.3.2 Biên dịch hướng đến cú pháp sang mã ba địa chỉ
Khi phát sinh mã ba địa chỉ, các tên tạm được tạo ra cho các nút trung gian của cây cú pháp Giá trị của ký hiệu không kết thúc E ở vế trái của luật sinh EỈE1+ E2 sẽ được thay bằng một tên tạm t mới Nói chung mã ba địa chỉ id := E gồm có mã để tính trị E và lưu vào một tên tạm t nào đó, theo sau là phép gán id.place := t
Nếu một biểu thức chỉ là một danh biểu, như y chẳng hạn, thì chính y sẽ giữ giá trị của biểu thức
Ví dụ 3.8 Xét lại biểu thức a := b * (- c) + b * (- c)
H.3.12(a) trình bày kết quả sinh mã ba địa chỉ dựa trên định nghĩa thuộc tính
S trong hình H.3.13
S Ỉ id :=E S.code := E.code || gen (id.place ‘:=’ E.place)
E Ỉ E 1 + E 2 E.place := newtemp;
E.code := E1code || E2code ||
gen (E.place ‘=’ E1.place ‘+’ E2.place)
E Ỉ E1 * E2 E.place := newtemp;
E.code := E1.code || E2.code ||
gen (E.place’:=’E1.place ‘*’ E2.place)
H.3.13 Định nghĩa hướng đến cú pháp sinh mã ba địa chỉ cho phát biểu gán
- E.code : đoạn mã ba địa chỉ dùng để tính giá trị của E
- E.place: là tên sẽ giữ giá trị của E
- newtemp: hàm trả về các tên khác nhau t1, t2,…, tn cho cáclần gọi khác nhau, và gen(x ‘:=’ y ‘+’ z) biểu diễn cho câu lệnh ba địa chỉ x :=y +z
Trang 39Các phát biểu điều khiển có thể được đưa vào định nghĩa hướng đến cú pháp
như phát biểu while trong H.3.14 Mã cho phát biểu S Ỉ while E do S 1 được sinh ra bằng cách dùng hai thuộc tính mới S.begin và S.after, là nhãn cho câu lệnh đầu tiên trong đoạn mã cho E và câu lệnh theo sau đoạn mã while Những thuộc tính này biểu diễn cho các nhãn được tạo ra bởi hàm newlabel, trả về một nhãn mới mỗi khi được gọi Khi giá trị của E bằng zero, quyền điều khiển rời khỏi đoạn mã của while
S Ỉ while E do S1 S.begin := newlabel;
S.after : = newlabel;
S.code : =gen (S.begin ‘:’ || E.code||
gen (‘if’ E.place ‘=’ ‘0’ ‘goto’ S.after) ||
S1.code || gen (‘goto’ S.begin) ||
gen ( S.after ‘:’)
H.3.14 Định nghĩa hướng đến cú pháp sinh mã cho phát biểu while-do
3.3.3 Hiện thực các lệnh mã ba địa chỉ
Một lệnh ba địa chỉ là một dạng trừu tượng của mã trung gian Trong trình biên dịch, những lệnh này có thể được cài đặt như các mẫu tin với các trường dành cho toán tử và các toán hạng Sau đây sẽ trình bày các phương pháp hiện thực mã
ba địa chỉ cho các biểu thức cơ bản
3.3.3.1 Lệnh gán
Các biểu thức hay danh biểu có thể thuộc kiểu số nguyên, số thực, mảng Để dịch lệnh gán thành mã ba địa chỉ, ta tìm kiếm các danh biểu trong bảng danh biểu và truy xuất các phần tử trong mảng
…
E.code
if E.place = 0 goto S.after
S1.codeGoto S.beginS.begin:
S.after:
Trang 40H.3.15 trình bày cách tìm các danh biểu trong bảng danh biểu, token id được
biểu diễn bằng thuộc tính id.name Thao tác lookup (id name) kiểm tra xem có id
trong bảng danh biểu hay không Nếu có thì trả về một con trỏ chỉ đến danh biểu
được tìm thấy; nếu không lookup sẽ trả về nil Các hành động ngữ nghĩa trong H.3.15 sử dụng thủ tục emit để xuất mã ba địa chỉ vào một tập tin
S Ỉ id : = E {p : = lookup (id name);
H 3.15 Sơ đồ biên dịch sinh mã ba địa chỉ cho câu lệnh gán
3.3.3.2 Mảng và địa chỉ các phần tử của mảng
Các phần tử của một mảng có thể được truy xuất nhanh chóng nếu chúng được lưu ở các vị trí liên tiếp nhau trong bộ nhớ Giả sữ ta có mảng một chiều A,nếu kích thước của mỗi phần tử mảng là w thì phần tử thứ i của mảng A sẽ bắt đầu
ở vị trí base + (i - low) * w, trong đó low là cận dưới của mảng và base là địa chỉ
tương đối của mảng A
Biểu thức trên có thể được tính trị vào lúc biên dịch nếu như nó được viết lại
là i * w + (base - low * w)
Biểu thức con c = base - low * w có thể được tính trị khi gặp khai báo của mảng Giả thiết rằng c được lưu trong bảng danh biểu cho A, vì thế địa chỉ tương đối của A[i] sẽ bằng i * w + c