Vượt qua spike thô sơ của hello-world, Sprint 18 đặt ra nhiệm vụ chính quy hóa LLVM backend. Chúng tôi không thể dùng một script thô để gọi llc bên ngoài nữa. Trình biên dịch DUY (duyc) phải tự sinh ra file LLVM IR hoàn chỉnh từ cấu trúc DUY IR, sau đó tự điều phối công cụ để tạo ra Object File (.o) và gọi linker để ra sản phẩm cuối cùng.
Đây là lúc compiler chạm vào "luật ngầm" của hệ điều hành.
Mỗi khi dịch một hàm, compiler phải phát biểu đúng cấu trúc ABI của nền tảng host: cách truyền tham số qua thanh ghi (System V AMD64 ABI trên macOS/Linux), cách tổ chức stack frame, cách bảo toàn các callee-saved registers. Việc ánh xạ các khối điều hướng cơ bản (basic blocks) của DUY IR sang các nhãn nhảy và phi-node của LLVM đòi hỏi checker phải cực kỳ chính xác về kiểu. Chỉ cần một biến được gán sai kiểu ở một nhánh, LLVM verifier phía dưới sẽ lập tức từ chối sinh mã.
Tôi nhớ mình đã mất ba đêm trắng để dò lỗi linker. Linker liên tục báo lỗi "Undefined symbol" hoặc crash với mã lỗi SegFault khi chạy file thực thi đầu ra. Thủ phạm hóa ra là do tôi đã sinh thiếu nhãn bắt đầu của hàm main theo đúng định dạng Mach-O của macOS (yêu cầu có dấu gạch dưới _main, trong khi ELF của Linux thì không cần).
Khi Object file (.o) được sinh ra thành công, công việc vẫn chưa xong. Linker (ld hoặc lld) phải gom các symbol từ file .o của người dùng, liên kết chúng với runtime stdlib của DUY, và tổ chức file nhị phân theo đúng định dạng ELF hoặc Mach-O. Nhìn thấy file .o đầu tiên được tạo ra từ lệnh duy build --backend llvm và tự động liên kết thành binary chạy được mà không hề có sự xuất hiện của bất kỳ dòng code C trung gian nào là một khoảnh khắc giải phóng. Compiler bắt đầu hiểu ngôn ngữ của linker và linker bắt đầu công nhận artifact của DUY là một công dân chính quy của hệ thống.
Bình luận (0)
Đang tải bình luận...