Tập 38: IR ra đời — Ngọn hải đăng trung gian

Trong những ngày đầu, compiler DUY đi trực tiếp từ AST (Abstract Syntax Tree) sang việc sinh mã (codegen). Đó là con đường ngắn nhất để có demo. Nhưng khi ngôn ngữ lớn lên, con đường ngắn nhất nhanh chóng trở thành con đường lầy lội nhất. Việc thực hiện type check, move checking, effect propagation và optimize trực tiếp trên một cây AST cồng kềnh đầy cú pháp ngọt ngào giống như việc cố gắng xây nhà mà không có bản vẽ kỹ thuật chi tiết.

Sprint 11 giải quyết vấn đề này bằng cách khai sinh DUY IR (Intermediate Representation) V0.

AST (cú pháp người dùng)
  -> Lowering
  -> DUY IR (cấu trúc tối giản, có kiểu)
  -> Codegen

DUY IR không phải là một chuỗi văn bản. Nó là một cấu trúc dữ liệu trung gian biểu diễn chương trình bằng các khối lệnh tuần tự (basic blocks) tối giản, nơi mọi phép toán phức tạp đã được hạ xuống thành các bước cơ bản nhất. Mọi biến đều có kiểu rõ ràng, mọi cú pháp rườm rà biến mất, chỉ còn lại bản chất thuần túy của dòng điều khiển và dòng dữ liệu.

Sự ra đời của IR chia compiler thành hai thế giới rõ rệt. Frontend lo việc đọc mã, bắt lỗi cú pháp và dựng ý định. Backend chỉ cần biết cách dịch một tập hợp IR tối giản thành machine code (LLVM hoặc C). Nếu ngày mai chúng tôi muốn thêm một kiến trúc CPU mới, chúng tôi không cần viết lại type checker. Chúng tôi chỉ cần viết một backend mới hiểu DUY IR.

Tuy nhiên, việc duy trì một tầng IR cũng đòi hỏi kỷ luật cao. Nó làm tăng thời gian biên dịch (compiler latency) và buộc chúng tôi phải viết các pass chuyển đổi AST → IR cực kỳ cẩn thận để không làm mất thông tin vị trí dòng code ban đầu (source spans). Nếu IR bị sai, compiler sẽ sinh ra mã độc hại. IR dạy tôi rằng việc lùi lại một bước — thêm một tầng trừu tượng trung gian — đôi khi lại là cách nhanh nhất để tiến lên một cách vững chắc.


Bình luận (0)

Đang tải bình luận...