Đơn xin ly hôn với LLVM
(github.com/ziglang)- Dự án Zig đặt mục tiêu loại bỏ hoàn toàn các phụ thuộc vào thư viện LLVM, Clang, LLD khỏi tệp thực thi zig chính
- Các việc còn lại được chia thành loại bỏ LLD, loại bỏ các lời gọi LLVM API, tiến độ của các backend C/x86/wasm/aarch64, loại bỏ việc dùng tiền xử lý và các lệnh con phụ thuộc Clang, triển khai thay thế
zig ar, v.v. - Backend LLVM hiện đã xuất được tệp
.bc, nhưng trình biên dịch Zig sẽ không còn có chức năng biên dịch.bcthành tệp object; trong trường hợp này cần cài đặt Clang riêng - Các hiệu quả kỳ vọng gồm đơn giản hóa việc build từ mã nguồn và bootstrap, tránh các vấn đề liên quan LLVM/Clang/LLD của các bản phân phối Linux và Homebrew, giảm kích thước binary từ khoảng 150 MiB → 5 MiB
- Zig đưa ra định hướng tự triển khai các optimization pass riêng và có thể thu hút các dự án nghiên cứu như alive2, cũng như đóng góp trực tiếp từ các nhà sản xuất chip Intel, ARM, RISC-V
Các phụ thuộc muốn loại bỏ khỏi tệp thực thi Zig
- Mục tiêu của issue này là loại bỏ hoàn toàn các thư viện LLVM, Clang, LLD khỏi dự án Zig
- Các điểm kết nối còn lại được phân loại thành các mảng LLD, LLVM, Clang và
zig ar
Việc còn lại liên quan đến LLD
- completely eliminate dependency on LLD #8726: Còn việc loại bỏ hoàn toàn phụ thuộc LLD
Việc còn lại liên quan đến LLVM
- Mảng LLVM bao gồm xuất LLVM bitcode, tỷ lệ vượt qua test của backend, và việc loại bỏ LLVM API
- directly output LLVM bitcode rather than using LLVM's IRBuilder API #13265: Xuất trực tiếp LLVM bitcode thay vì dùng IRBuilder API của LLVM
- C backend hiện vượt qua 1742/1792 test, tỷ lệ 97%
- enable the x86 backend by default for debug builds on x86_64-linux #22257: Bật x86 backend mặc định cho các debug build trên x86_64-linux
- wasm backend hiện vượt qua 1611/1765 test, tỷ lệ 91%
- 100% behavior tests passing for the aarch64 backend #21172: Đưa behavior test của aarch64 backend đạt 100%
- ability to create import libs from def files without LLVM #17807: Khả năng tạo import libs từ tệp def mà không cần LLVM
- Avoid LLVM API for setting a module's code model and PIC/PIE levels #21238: Tránh dùng LLVM API khi thiết lập code model và mức PIC/PIE của module
- completely eliminate dependency on LLVM library API calls #25492: Loại bỏ hoàn toàn phụ thuộc vào các lời gọi LLVM library API
Việc còn lại liên quan đến Clang
- Các tệp mã nguồn C++ trong kho Zig đang được build bằng clang khi bootstrap
- src/windows_sdk.cpp: port to Zig #15657: Port
src/windows_sdk.cppsang Zig
- src/windows_sdk.cpp: port to Zig #15657: Port
zig cc,zig c++,zig translate-cand other subcommands without a clang/llvm dependency in the compiler binary #20875: Cung cấpzig cc,zig c++,zig translate-cvà các lệnh con khác mà không có phụ thuộc clang/llvm trong binary trình biên dịch- make resinator use aro's preprocessor instead of clang #17752: Chuyển resinator sang dùng bộ tiền xử lý của aro thay vì clang
- make mingw .def.in file parsing use aro's preprocessor instead of clang #17753: Chuyển việc phân tích tệp mingw
.def.insang dùng bộ tiền xử lý của aro thay vì clang - move
@cImportto the build system #20630: Chuyển@cImportsang hệ thống build
Các ràng buộc trong xử lý zig ar và tệp .bc
- zig ar: a drop-in llvm-ar replacement #9828: Còn việc biến
zig arthành bản thay thế tương thích trực tiếp cho llvm-ar - Backend LLVM hiện đã xuất được tệp
.bc, nhưng trình biên dịch Zig sẽ không còn có chức năng biên dịch tệp.bcthành tệp object - Để xử lý use case này, cần cài đặt Clang riêng
Những thay đổi kỳ vọng từ việc loại bỏ phụ thuộc
- Tất cả lỗi phía Zig sẽ nằm trong phạm vi trách nhiệm của dự án Zig
- Quá trình build trình biên dịch từ mã nguồn và bootstrap sẽ đơn giản hơn; trên hệ thống host chỉ cần có trình biên dịch C
- Các bản phân phối Linux và trình quản lý gói như Homebrew sẽ không còn phải xử lý các vấn đề liên quan đến LLVM, Clang, LLD
- Kích thước binary của trình biên dịch Zig giảm từ khoảng 150 MiB xuống 5 MiB
- Tốc độ biên dịch có thể nhanh hơn theo cấp nhiều bậc độ lớn
- Zig có thể tự triển khai các optimization pass riêng để đẩy trình độ điện toán lên mức mới nhất
- Có thể thu hút các dự án nghiên cứu như alive2
- Có thể khuyến khích đóng góp trực tiếp từ các bên liên quan muốn có machine code tốt hơn trên CPU của họ, như các nhà sản xuất chip Intel, ARM, RISC-V
2 bình luận
Liệu có thể đạt được mức tối ưu hóa hay hỗ trợ nền tảng như LLVM không..
Ý kiến trên Hacker News
Andrew vốn là người cực kỳ sắc bén nên một khi đã tuyên bố đó là mục tiêu thì có lẽ cả đội cuối cùng sẽ làm được
Tuy vậy, từ góc nhìn của người không hiểu rõ khó khăn của Zig liên quan đến LLVM, quyết định này trông như đang chuyển năng lực của đội sang các công cụ phụ trợ kiểu binutils hơn là bản thân Zig
Khi chỉ nhìn tiêu đề thì tôi còn tưởng họ định bỏ luôn trình biên dịch, và với một dự án như Zig thì việc giữ LLVM dường như vẫn mang lại nhiều lợi ích
Dù vậy, ý tưởng viết lại nhiều đoạn mã trong LLVM bằng Zig thay vì C++ vẫn khá ngầu và đầy tham vọng. Cũng có thể xem là tham vọng ngang với nỗ lực của Lattner khi tạo ra LLVM
Nhưng những đoạn mã vô tình rơi vào độ phức tạp thời gian bậc hai thì Zig cũng sẽ khó tránh khỏi nếu một ngày nó trở nên phổ biến và hữu dụng như LLVM
Đại ý là: “Nếu một sứ mệnh không tái sử dụng tên lửa hiện có, thì dự án đó sẽ trở thành dự án phát triển tên lửa, còn mọi thứ khác từng được coi là cốt lõi của sứ mệnh đều trở thành thứ yếu”
Tôi còn nhớ thêm một ý nữa là có kèm theo tiền đề “thay vì thỏa hiệp để phù hợp với tên lửa hiện có, người ta có thể nghĩ rằng làm một tên lửa riêng cho sứ mệnh cụ thể sẽ rẻ hơn và hiệu quả hơn”
Một phần thành công của Rust cũng nằm ở mức độ tương thích tương tự với C/C++
Rất khó hình dung Zig có thể thành công nếu không có năng lực tương tự, nên tôi hy vọng họ sẽ không cứ thế thúc đẩy cột mốc này
Vì GCC không sẵn sàng cho phép hoặc triển khai những gì Apple muốn hay cần
Nếu tập trung hơn như TCC, thì phần lớn công việc sẽ là ở phía sinh mã cho nhiều kiến trúc khác nhau
Ở đây có hai vấn đề. Một là sinh mã, hai là bootstrap
Theo kinh nghiệm của tôi thì các optimization pass của trình biên dịch khá dễ viết và thú vị. Muốn hiểu register allocation và dạng SSA thì phải đọc bài báo, nhưng phần mã cho IR đi qua nhiều optimization pass rồi dần được gọt giũa thì khá vui để viết
Có thể tạo ra các optimization pass chất lượng cao ngay cả khi không dùng LLVM. Nhưng giai đoạn tuyến tính hóa IR thành mã máy thì lại là công việc chán và tầm thường, trừ khi bạn thật sự thích mọi cách mà lệnh “mov [eax+8*ebx], 123” được mã hóa trên x86-32/64
Nếu tối ưu kích thước nhị phân, liệu bạn có muốn đo xem trên nền tảng nào “push eax; push eax; push eax” ngắn hơn “add rsp,12” không? Đó mới chỉ là câu chuyện của x86, và nếu nhân lên với các kiến trúc không phải x86 — vốn lại chẳng quan trọng với đa số lập trình viên — thì còn lớn hơn nhiều
Cũng rất có khả năng là những lỗi lớn trong code generator cho các kiến trúc ít dùng sẽ không bị phát hiện suốt nhiều năm
Vấn đề thứ hai là bootstrap. Trình biên dịch Zig viết bằng Zig sẽ được biên dịch bằng gì? Chẳng hạn có thể dùng một trình biên dịch Zig tối thiểu, không tối ưu, viết bằng C để biên dịch trình biên dịch Zig
Nhưng nếu nó không tối ưu thì sau đó lại phải dùng trình biên dịch Zig đã tối ưu để biên dịch lại chính trình biên dịch Zig. Không phải bài toán không giải được, nhưng một quy trình build dài và phức tạp có thể đẩy lùi những người muốn đóng góp
Zig đã quảng bá rất nhiều việc nó có thể biên dịch C, thậm chí có thể cả C++, mà giờ lại muốn loại bỏ LLVM hoàn toàn thì trông khá cực đoan
Trừ khi có nhiều người hơn hẳn tham gia hỗ trợ, còn không thì khả năng tiến gần mức hỗ trợ nền tảng của LLVM cũng có vẻ rất thấp
Tôi có thể hiểu kế hoạch thêm backend riêng cho những ai muốn, nhưng bỏ hẳn LLVM thì có vẻ vội vàng
Bây giờ là lúc đội ngũ thu thập phản hồi, tìm hiểu các use case bị ảnh hưởng và ước lượng tính khả thi, nên tôi thấy nó gần như là điều ngược lại với sự vội vàng
Việc phải bundle một bản sao LLVM hơn 100MB dù không cần cho trường hợp phổ biến quả là hơi kỳ, nên như vậy cũng có lý. Nếu là lập trình viên thì nhiều người cũng đã cài sẵn rồi
Tuy vậy, có thể sẽ khó đảm bảo Zig đã cài đặt hoạt động đúng với phiên bản LLVM của hệ thống. Cứ phải chờ xem
https://github.com/ziglang/zig/issues/13265
Gần đây tôi có đọc thêm về Zig, và còn thử dùng nó như một cách dễ dàng để biên dịch C++ với LLVM mà không phải vật lộn với package hệ thống. Việc có thể chuyển từ C/C++ sang Zig là một điểm bán hàng rất lớn
Nó quá đột ngột và ngoài dự đoán. Tôi không biết điều đó đúng hay sai với dự án, nhưng từ góc nhìn của tôi thì nó thật sự rất bất ngờ
Một mặt, tôi tôn trọng sự kỹ lưỡng trong ý chí giảm phụ thuộc, nhưng cái giá phải trả có vẻ khá nghiêm trọng
Mất khả năng tương thích C++ về cơ bản sẽ xóa đi lợi thế mà các fan Zig quanh tôi nhắc đến nhiều nhất
Tổn thất hiệu năng, dù chỉ là tạm thời, cũng là một điểm cốt lõi khác mà họ thường nhắc cùng với điều đó
Nói cho những ai chỉ đọc lướt thì đây không phải quyết định đã chốt, mà là đề xuất
Tôi đã viết toàn bộ các dự án và thư viện nhúng bằng Zig suốt khoảng 4 năm, giờ là nhiều kiến trúc được hỗ trợ tier 1 sẽ bị loại bỏ luôn sao?
Ngôn ngữ là của họ nên họ có thể làm theo ý mình, nhưng nếu vậy thì tôi cũng muốn họ điều chỉnh lại branding cho phù hợp
Có lẽ hỗ trợ tier 1 sẽ được chia thành hai nhóm: tier 1 tích hợp sẵn, và tier 1 thông qua backend LLVM tùy chọn
Nếu một kiến trúc nào đó đã có hỗ trợ tier 1, thì tôi không thấy lý do gì việc biến backend LLVM thành phụ thuộc tùy chọn lại khiến hỗ trợ đó biến mất
Như Andrew đã viết trong đề xuất, cách này thậm chí có thể mở ra con đường hỗ trợ tốt hơn cho các kiến trúc hiếm gặp hơn. Nếu có một backend Zig cho một kiến trúc bộ xử lý thú vị nào đó thì tôi sẵn sàng làm, nhưng tôi sẽ không bao giờ đóng góp cho LLVM. Làm việc với C++ không phải thứ tôi muốn làm như một thú vui
Lợi ích của việc đó là gì? Chẳng phải là lãng phí nguồn lực sao?
DLang có 3 trình biên dịch
gdc dựa trên backend của bộ công cụ biên dịch Gnu, ldc dựa trên backend LLVM, còn dmd dựa trên bộ sinh mã x86 mà tôi đã viết cho Zortech/Symantec/Digital Mars
Mỗi cái có ưu và nhược điểm riêng cũng như đối tượng sử dụng khác nhau, nhưng ngôn ngữ D mà chúng hỗ trợ thì giống nhau
Nhìn chung người dùng thích có lựa chọn, và một số còn dùng song song từ hai cái trở lên
Nếu đúng là vậy thì tôi thích cách tiếp cận của Zig
Điều đó rất hữu ích vì trong quá trình phát triển bạn có thể dùng trình biên dịch nhanh nhất, còn khi phát hành bản cuối thì có thể dùng trình biên dịch cho runtime nhanh nhất hoặc mức dùng bộ nhớ thấp nhất
Ngoài ra, khi có một đặc tả ngôn ngữ mà mọi trình biên dịch đều tuân theo, ngôn ngữ sẽ có được sự ổn định và đảm bảo không bị hỏng đột ngột từ tầng bên dưới
Dĩ nhiên, các ngôn ngữ như Zig — nơi bạn vẫn có thể thay đổi điều mình muốn để làm ngôn ngữ nhất quán, gọn gàng và mạnh mẽ hơn — cũng có điểm hay. Nhưng dạo gần đây tôi đánh giá cao kiểu ổn định kia hơn nhiều, vì nó cho phép tập trung tạo ra giá trị thực cho người dùng thay vì cứ phải chạy theo công cụ phát triển
Một trong những lý do chính khiến Zig hấp dẫn là nó có thể được cắm vào ngay như một lựa chọn thay thế cho trình biên dịch C/C++
Bạn bè tôi nói rằng trên Windows, cài Zig làm trình biên dịch C/C++ dễ hơn bất kỳ lựa chọn thay thế nào khác
Nếu đề xuất này được chấp nhận, cá nhân tôi nghĩ độ phổ biến của Zig sẽ tụt xuống mức của Hare hay các ngôn ngữ cực kỳ ngách khác
Để khiến đồng nghiệp chịu thử Zig dù chỉ một lần, tôi còn phải gửi cho họ cả bài viết nói Uber dùng nó trong production. Nếu nó không có giá trị tức thì với các dự án hiện có, họ đã chẳng thèm nghĩ lần hai
Dù vậy, tôi vẫn hiểu bối cảnh của đề xuất này. Thời gian biên dịch của LLVM có thể tệ đến mức khó chịu, và nếu có bytecode riêng thì cũng có thể triển khai những kỹ thuật tối ưu hóa rất hay. Xử lý bug của LLVM thì gần như là việc khó mà đụng vào được, và tôi cũng đã thấy điều đó trong hệ sinh thái Julia
Nếu lời khuyên của tôi có giá trị gì đó, thì tôi nghĩ Zig nên 1) dùng bytecode tùy chỉnh cho bản build debug để có thời gian build nhanh và debug nhanh, và 2) dùng LLVM cho bản build release để có hiệu năng runtime cao
Nếu vẫn có thể làm được phần 1) mà giữ nguyên hỗ trợ cross-compile C/C++, ví dụ chỉ chuyển riêng phần đó cho LLVM, thì dù phải đánh đổi bằng việc bảo trì thêm mã backend, đó có thể là phương án thỏa hiệp tốt nhất
Nó đòi hỏi một bộ kỹ năng riêng, khác với công việc ở trình biên dịch Julia cấp cao, và đôi khi cũng mất nhiều thời gian để các bản sửa lỗi được hợp nhất lên upstream
Nhưng trên thực tế, chúng tôi có mối quan hệ khá tốt và hiệu quả với upstream, và nếu quyết định loại bỏ LLVM thì dự án hẳn đã làm được ít việc hơn rất nhiều
Đặc biệt là hỗ trợ GPU và hỗ trợ HPC, chẳng hạn như PPC, đều phụ thuộc vào LLVM
Vì thế chúng tôi giữ quan điểm rằng Julia phải được build theo patchset/fork của mình, và chúng tôi không dành thời gian cho các bug phát sinh từ những bản build Julia không dùng các patch đó. Điều này đặc biệt hay xảy ra với các bản build từ distro
Nhìn từ góc độ đã theo dõi các nỗ lực làm backend không dùng LLVM ở những ngôn ngữ khác, thì đề xuất được liên kết toát ra sự ngạo mạn quá mạnh
Nếu người viết không phải là chính người đó, tôi đã xem nó như một GitHub issue viết qua loa của một người mới với Zig
Nó đánh giá thấp khối lượng công việc cần thiết, ngầm hạ thấp toàn bộ công sức đã đổ vào LLVM, và từng câu đều toát lên sự tự tin cùng vẻ macho kiểu “rõ ràng chúng ta có thể làm nó rẻ hơn, nhanh hơn, tốt hơn”. Thật đáng thất vọng
Trước giờ tôi thực sự tôn trọng công việc của Andrew, nên tôi muốn thiện chí cho rằng có thể anh ấy viết vội hoặc viết ngẫu hứng nên không để ý là nó sẽ bị đọc theo cách đó
Nhưng bài viết này không tạo cảm giác đáng tin, cũng không khiến tôi nhìn đề xuất đó với tâm thế cởi mở hơn
Webpack và esbuild là ví dụ như vậy
Thời điểm thích hợp để xây dựng thứ gì đó không dùng LLVM là vài năm trước. Nhưng ở thời điểm hiện tại, nếu bỏ tính năng C++ thì rất có thể đó sẽ là dấu chấm hết cho Zig
Tôi ngạc nhiên là thay vì loại bỏ dần theo từng bước, họ lại không công bố kế hoạch viết trình biên dịch C++ riêng bằng Zig
Tôi cũng không chắc một cá nhân bắt đầu vào sinh nhật 18 tuổi của mình có thể viết được một trình biên dịch C++. Có khi quãng đời còn lại cũng chưa đủ để làm ra một trình biên dịch hoạt động được
Zig muốn trở thành C mới của thế giới, chứ không hẳn muốn trở thành C++ mới của thế giới
Ngay trong đề xuất này cũng có thể thấy rằng biên dịch chéo cho C vẫn sẽ tiếp tục được hỗ trợ
Đây có thể là một lựa chọn đúng. C hiện được dùng rất nhiều trong thế giới nhúng, và ở mảng đó LLVM không tốt
Nếu là Zig, tôi sẽ muốn nhắm tới mọi vi điều khiển, và đây là con đường thực tế duy nhất để đạt được điều đó