صفحات التوثيق
الأهداف
يسرد sultanc targets أهداف الترجمة المسجلة وعددها 38. وتسجل هذه الصفحة لكل هدف منها الخلفية التي تولد شيفرته،
ودعم المكتبة القياسية المتوفر له، وطريقة ربط ملفه التنفيذي، وطريقة التحقق منه. وتصف أيضا مواضع الشيفرة الخاصة
بكل هدف في المستودع، للمساهمين الذين يضيفون هدفا أو ينقلون اللغة إلى هدف جديد.
الخلفيات
للسلطان خلفيتان لتوليد الشيفرة، تُختاران بـ--backend=native أو --backend=llvm.
الخلفية الأصلية هي مولد الشيفرة الخاص بالسلطان، ولا تحتاج مع الروابط (linker) المدمجة إلى أي سلسلة أدوات
خارجية. وهي متاحة لأهداف x86_64 وaarch64 في Linux وAndroid وFreeBSD وmacOS وWindows (x86_64-linux
وaarch64-linux-gnu وx86_64-android وaarch64-android وx86_64-freebsd وaarch64-freebsd وarm64-darwin
وx86_64-darwin وx86_64-windows-msvc وaarch64-windows-msvc)، ولـwasm32-wasi وwasm32-browser. وطلبها لأي
هدف آخر يُبلغ عنه بـSULTANC-BACKEND-UNAVAILABLE.
خلفية LLVM متاحة لكل الأهداف، وتتطلب مترجما بُني مع LLVM (./build.sh --enable-llvm). وهي تنتج ملفات كائنات لكل
الأهداف. والأهداف التي لا صيغة لملفات الكائنات فيها (NVPTX، XCore) تُترجم بـ--emit=asm، الذي يعمل مع كل الأهداف.
وتُسجَّل حالة كل هدف مع خلفية LLVM، وما شُغّل منه وما بُني فقط، في
تقدم أهداف LLVM (بالإنجليزية).
يحمل عمود الدعم في مخرجات sultanc targets إحدى ثلاث قيم: مضيف ذاتي (arm64-darwin وx86_64-linux)،
وترجمة متقاطعة (كل الأهداف الأخرى)، وتجريبي (لا هدف اليوم). ويترجم المترجم نفسه أيضا على أهداف x86_64 وaarch64
في Android وFreeBSD؛ ويسجل قسم الاستضافة الذاتية على Android وFreeBSD
كيف تُحقق من ذلك.
مصفوفة الأهداف
أهداف أنظمة التشغيل
لهذه الأهداف المكتبة القياسية كاملة، بما فيها الملفات والعمليات والمقابس والخيوط (إلا حيث يُذكر غير ذلك). وكلها تستعمل استدعاءات النواة الخام أو واجهة النظام في المنصة، ولا تربط أي libc؛ وتسرد صفحة اعتماديات المنصات كل ما يُستورد.
| الهدف | المعمارية | الخلفية | الملف التنفيذي | التشغيل المتحقق منه |
|---|---|---|---|---|
x86_64-linux |
x86_64 | الأصلية، LLVM | رابط ELF مدمج | أصلي |
aarch64-linux-gnu |
aarch64 | الأصلية، LLVM | رابط ELF مدمج | qemu-user |
riscv64-linux-gnu |
riscv64 | LLVM | رابط ELF مدمج | qemu-user |
loongarch64-linux-gnu |
loongarch64 | LLVM | رابط ELF مدمج | qemu-user |
powerpc64le-linux-gnu |
powerpc64le | LLVM | رابط ELF مدمج | qemu-user |
s390x-linux-gnu |
s390x | LLVM | رابط ELF مدمج | qemu-user |
mips64el-linux-gnuabi64 |
mips64el (n64) | LLVM | رابط ELF مدمج | qemu-user |
sparcv9-linux-gnu |
sparcv9 | LLVM | رابط ELF مدمج | qemu-user |
i686-linux-gnu |
x86 | LLVM | رابط ELF مدمج | qemu-user |
armv7-linux-gnueabihf |
arm | LLVM | رابط ELF مدمج | qemu-user |
x86_64-android |
x86_64 | الأصلية، LLVM | رابط ELF مدمج | أصلي (ملف تنفيذي ساكن على نواة Linux) |
aarch64-android |
aarch64 | الأصلية، LLVM | رابط ELF مدمج | qemu-user |
armv7-android |
arm | LLVM | رابط ELF مدمج | qemu-user |
arm64-darwin |
aarch64 | الأصلية، LLVM | رابط Mach-O مدمج | أصليا على arm64 (الخلفية الأصلية) |
x86_64-darwin |
x86_64 | الأصلية، LLVM | رابط Mach-O مدمج | بُني |
x86_64-windows-msvc |
x86_64 | الأصلية، LLVM | رابط COFF مدمج | Wine |
aarch64-windows-msvc |
aarch64 | الأصلية، LLVM | رابط COFF مدمج | بُني |
x86_64-freebsd |
x86_64 | الأصلية، LLVM | رابط ELF مدمج | آلة افتراضية FreeBSD 14.5 تحت qemu |
aarch64-freebsd |
aarch64 | الأصلية، LLVM | رابط ELF مدمج | آلة افتراضية FreeBSD 14.5 تحت qemu |
riscv64-freebsd |
riscv64 | LLVM | رابط ELF مدمج | آلة افتراضية FreeBSD 14.5 تحت qemu |
تستعمل أهداف Linux وAndroid الواجهة الثنائية لنواة Linux مباشرة. وتستعمل الأهداف ذات 32 بت (i686-linux-gnu،
armv7-linux-gnueabihf، armv7-android) استدعاءات النظام الخاصة بـtime64 وبالملفات الكبيرة. وعلى هذه الأهداف،
وعلى كل هدف آخر يفتقر إلى تعليمة قسمة أو إلى قسمة عريضة، توسّع الخلفية القسمة في التمثيل الوسيط (IR) فلا يُربط compiler-rt (انظر
ما الذي يقع أين).
تستعمل أهداف FreeBSD استدعاءات النظام الخام بلا libc. وتتطلب FreeBSD 13 أو أحدث (من أجل close_range)، وتُبنى
على ترويسات الإصدار 14.2. والملف التنفيذي ساكن (static)، مع ELFOSABI_FREEBSD وملاحظة الواجهة الثنائية
.note.tag، التي يحتفظ بها الرابط المدمج ويغطيها برأس PT_NOTE.
الربط
المترجم هو من يختار الرابط؛ ولا خيار لاختياره.
| المخرج | الرابط |
|---|---|
| ملفات ELF التنفيذية لـx86_64 وaarch64 (Linux وAndroid وFreeBSD)، وriscv64 (Linux وFreeBSD)، وloongarch64 وi686 وarmv7 (Linux وAndroid) وpowerpc64le وs390x وmips64el وsparcv9 على Linux | رابط ELF الخاص بالسلطان (compiler/link/elf): صور ELF64 وELF32 بترتيبي البايت الأصغر والأكبر أولا. ويُنتج لـriscv64 وloongarch64 والأهداف ذات 32 بت وذات ترتيب البايت الأكبر أولا ملفات تنفيذية ساكنة فقط، وهي ما تكونه برامج السلطان. |
| ملفات Mach-O وCOFF وWebAssembly التنفيذية | روابط Mach-O وCOFF وwasm الخاصة بالسلطان |
| الأهداف المستقلة وأهداف المسرعات | لا رابط: ملفات كائنات أو شيفرة تجميع (وتُربط صور Cortex-M خارج المترجم، انظر أهداف Cortex-M) |
لا يُربط هدف ELF نظامي لا يخطط رابط ELF صوره بالأمر ld.lld -static -e _start
(compiler/driver/external_linker.sn) إلا إذا سمّت سياسة هدفه ld.lld، ولا هدف يسميه الآن.
يُبحث عن ld.lld بهذا الترتيب: $SULTANC_LINKER؛ ثم bin/ld.lld في تثبيت LLVM الذي رُبط المترجم بمكتبته libLLVM
(الدليل المجاور لدليل lib/ فيه)؛ ثم ld.lld في PATH.
ويُبلَّغ عن مدخل ربط لا يقرؤه رابط الهدف (ليس كائنا ولا أرشيفا ولا مكتبة ولا سكربت ربط) بالتشخيص
SULTANC-LINK-INPUT-UNSUPPORTED مع مساره. وفي macOS وiOS تقوم المكتبة النصية البديلة في حزمة تطوير Apple
(.tbd، مثل MacOSX.sdk/usr/lib/libSystem.tbd) مقام المكتبة التي يسميها اسم تثبيتها، كما في ld64: تحمّل الصورة
تلك المكتبة وتربط بها الرموز التي تصدّرها المكتبة النصية.
WebAssembly
| الهدف | الخلفية | الملف التنفيذي | ملاحظات |
|---|---|---|---|
wasm32-wasi |
الأصلية، LLVM | رابط wasm مدمج | المكتبة القياسية كاملة فوق WASI preview 1؛ والمقابس مقصورة على المفتوحة مسبقا؛ ولا عمليات ولا خيوط ولا أقفال ملفات. يعمل تحت مشغل متوافق مع wasmtime. |
wasm32-browser |
الأصلية، LLVM | رابط wasm مدمج | مستقل عن نظام التشغيل (freestanding): نواة اللغة فقط. لا استيرادات للوحدة؛ وتعيد _start قيمة main، ويشغلها node. |
wasm64-unknown-unknown |
LLVM | ملفات كائنات | مستقل عن نظام التشغيل: نواة اللغة فقط. ولا يرتب رابط wasm إلا الذواكر ذات 32 بت. |
الأهداف المستقلة وأهداف المسرعات
ليس لهذه الأهداف طبقة نظام تشغيل؛ فالبرامج تستعمل نواة اللغة ووحدات std التي لا تعتمد على نظام تشغيل.
| الهدف | المعمارية | المخرجات |
|---|---|---|
riscv32-unknown-elf |
riscv32 | ملفات كائنات، شيفرة تجميع |
avr-unknown-unknown |
avr | ملفات كائنات، شيفرة تجميع |
msp430-unknown-elf |
msp430 | ملفات كائنات، شيفرة تجميع |
hexagon-unknown-elf |
hexagon | ملفات كائنات، شيفرة تجميع |
lanai-unknown-unknown |
lanai | ملفات كائنات، شيفرة تجميع |
bpfel-unknown-none |
bpf | ملفات كائنات، شيفرة تجميع |
amdgcn-amd-amdhsa |
amdgpu | ملفات كائنات، شيفرة تجميع |
spirv64-unknown-unknown |
spirv64 | ملفات كائنات SPIR-V، شيفرة تجميع |
nvptx64-nvidia-cuda |
nvptx64 | شيفرة تجميع فقط |
xcore-unknown-unknown |
xcore | شيفرة تجميع فقط |
thumbv6m-none-eabi |
arm (ARMv6-M) | ملفات كائنات، شيفرة تجميع؛ صور Cortex-M |
thumbv7m-none-eabi |
arm (ARMv7-M) | ملفات كائنات، شيفرة تجميع؛ صور Cortex-M |
thumbv7em-none-eabi |
arm (ARMv7E-M) | ملفات كائنات، شيفرة تجميع؛ صور Cortex-M |
thumbv7em-none-eabihf |
arm (ARMv7E-M مع وحدة الفاصلة العائمة) | ملفات كائنات، شيفرة تجميع؛ صور Cortex-M |
لا يستطيع السلطان ربط هذه الأهداف في ملف تنفيذي: فطلب exe يُبلغ عنه بـSULTANC-LINK-OUTPUT-UNSUPPORTED.
استعمل -c أو --emit=obj لملفات الكائنات، و--emit=asm لشيفرة التجميع. ويُترجم tests/ar/target/language_core.sn
(السجلات والاتحادات الموسومة والأنواع العامة والعمليات الحسابية الصحيحة بكل عرض) لكل منها. أما البرنامج الذي يستعمل خدمة
من نظام التشغيل (الطباعة، الملفات) فيُرفض لها عند check بـSULTANC-TARGET-FEATURE-UNSUPPORTED؛ والمترجم نفسه برنامج
كهذا، فلا ينجح sultanc check compiler/main.sn إلا للأهداف المستضافة الـ21. وقيم الدوال إغلاقات تخصص بيئة التشغيل
بيئتها، ولا مخصص في هذه الأهداف، فيُرفض لها البرنامج الذي يأخذ قيمة دالة (SULTANC-BACKEND-UNSUPPORTED-CONSTRUCT).
وليس في BPF قبل الإصدار v4 من مجموعة تعليماته قسمة ذات إشارة؛ فتُقسم المقادير هناك. وليس في eBPF أعداد عائمة،
فيرفض LLVM العمليات الحسابية العائمة له.
أهداف Cortex-M
أهداف Arm ذات الملف M الأربعة أهداف ELF على العتاد مباشرة لخلفية LLVM (فليس في الخلفية الأصلية مولد شيفرة لـArm ذي
32 بت). وشروط الهدف لها الهدف.المعمارية == "arm" مع الهدف.المنصة == "freestanding"، وبيئتها eabi أو eabihf.
| الهدف | الأنوية | أساس المعالج | الفاصلة العائمة | القسمة | ذريات std | لوحات QEMU |
|---|---|---|---|---|---|---|
thumbv6m-none-eabi |
Cortex-M0 وM0+ وM1 | cortex-m0، +strict-align,+atomics-32 |
لا شيء | توسَّع في IR | تحميل وتخزين وسياج بعرض 32 بت | microbit |
thumbv7m-none-eabi |
Cortex-M3 | cortex-m3 |
لا شيء | SDIV/UDIV | تحميل وتخزين وسياج بعرض 32 بت | lm3s6965evb، mps2-an385 |
thumbv7em-none-eabi |
Cortex-M4 وM7 | cortex-m4 (DSP)، بلا وحدة فاصلة عائمة |
لا شيء | SDIV/UDIV | تحميل وتخزين وسياج بعرض 32 بت | mps2-an386، mps2-an500 |
thumbv7em-none-eabihf |
Cortex-M4F وM7 | cortex-m4، +vfp4d16sp (FPv4-SP-D16) |
f32 في العتاد | SDIV/UDIV | تحميل وتخزين وسياج بعرض 32 بت | mps2-an386، mps2-an500 |
تقع هذه الحقائق في compiler/backend/target/target_registry.sn (صنف الملف M هو معالج الهدف، صنف_ذراع_إم في
target_model.sn)، وتُمرر إلى LLVM نصوصا للمعالج والميزات (أساس_توليد_ذراع_إم).
- الواجهة الثنائية: AAPCS، وملفات كائنات ELF32 قابلة لإعادة التموضع بترتيب البايت الأصغر أولا، مع سمات بناء Arm (اسم
المعالج، وملف المعمارية
M، وTag_ABI_align_preserved: محاذاة المكدس 8 بايتات عند كل واجهة عامة). يمررeabiالأعداد العائمة في السجلات العامة، ويستعملeabihfالصيغة AAPCS-VFP (s0-s15،d0-d7) التي يختارها LLVM من البيئة. - لا مكتبة تشغيل. لا يربط السلطان libgcc ولا compiler-rt، فلا يشير أي ملف كائنات لهذه الأهداف إلى روتين
__aeabi_*. وتوسَّع القسمة بعرض 64 بت في IR كما في كل هدف ذي 32 بت. وفي ARMv6-M، الذي ليس فيه تعليمة قسمة ولا ضرب 32 × 32 -> 64 ولا إزاحة بعرض 64 بت، توسَّع كذلك القسمة بعرض 32 بت والضرب بعرض 64 بت والإزاحة بعرض 64 بت بمقدار متغير (compiler/backend/provider/llvm/freestanding_routines.sn) بدلا من استدعاء__aeabi_uidivو__aeabi_lmulو__aeabi_llslو__aeabi_llsrو__aeabi_lasr. - الفاصلة العائمة. العملية العائمة التي لا تقدر عليها وحدة الفاصلة العائمة تستدعي روتينا برمجيا (
__aeabi_fadd،__aeabi_dmul،__aeabi_f2d...)، فتُرفض بدلا من ذلك بـSULTANC-TARGET-FEATURE-UNSUPPORTEDعند الجملة المصدرية التي فيها العملية، مع اسم العملية ونوعها والدالة المصدرية: كل عملية حسابية أو مقارنة أو تحويل عائم في أهدافeabi، وكل عملية على f64 فيthumbv7em-none-eabihf، وfremفي كل منها. ويُسمح بتحميل الأعداد العائمة وتخزينها ونقلها، وبالنفي وabsوcopysign. ويشغّل Cortex-M7 شيفرةthumbv7em-none-eabihf؛ أما وحدته FPv5-D16 ذات الدقة المضاعفة فتحتاج إلى اختيار معالج لا يقدمه السجل بعد. - الذريات. ليس في ARMv6-M وصول حصري (LDREX/STREX)، وهو في ARMv7-M بعرض 32 بت فقط. فتصرّح
std.sync.atomicفي هذه الأهداف بالتحميل والتخزين الذريين بعرض 32 بت وبالأسيجة (ذرة_ط32،أنشئ_ذرة_ط32،احمل_ط32،اخزن_ط32،سياج_ذاكرة)، وهي LDR/STR مع DMB. أما صيغ 64 بت وذرة_طبيعيوكل عملية قراءة وتعديل وكتابة فمصرح بها لأهداف أخرى فقط (SULTANC-TARGET-FEATURE-UNSUPPORTEDللأسماء العربية؛ والمرادفات الإنجليزية تُبلغ عنها بـSULTANC-NAME-UNKNOWN). ولا تميز شروط الهدف التي تحللها مترجمات الإقلاع ARMv6-M من ARMv7-M، فلا تُقدم بعد ذريات القراءة والتعديل والكتابة بعرض 32 بت في ARMv7-M. وترفض الخلفية كل ذرية أعرض مما ينفذه الهدف مباشرة. - كسائر الأهداف المستقلة، ليس لهذه الأهداف مخصص ذاكرة: فتُرفض النصوص والمتجهات والإغلاقات.
شيفرة البدء والربط
يُصدر المترجم شيفرة البدء في ملف الكائنات لكل برنامج Cortex-M له مدخل، كما يُصدر _start للأهداف المستضافة
(compiler/backend/provider/llvm/cortex_m_entry.sn)، فلا حاجة إلى مجمّع ولا إلى سلسلة أدوات C:
.vector_table: مؤشر المكدس الابتدائي__stack_top، وReset_Handler، والاستثناءات النظامية الأربعة عشر، كل منها اسم ضعيف بديل لـDefault_Handlerالذي يدور في مكانه؛- ينسخ
Reset_Handlerالقسم.dataمن FLASH إلى RAM، ويصفّر.bss، ويفعّل وحدة الفاصلة العائمة فيthumbv7em-none-eabihf(CP10/CP11 في CPACR)، ويشغّل.init_array، ويستدعيmainويمرر الكلمة الدنيا من ناتجها إلى__sultanc_exit، الذي يوقف المعالج افتراضيا في حلقةWFI؛ __sultanc_semihosting_exit(SYS_EXIT_EXTENDEDفي الاستضافة شبه الكاملة لـArm) و__sultanc_semihosting_fault(حالة الخروج 132؛ فخ السلطان هوUDFالذي يتصاعد إلى HardFault)، للتشغيل تحت QEMU أو المنقح.
بتعليمات ARMv6-M فقط، فتخدم السلسلة نفسها كل الأصناف. ونصوص الربط في library/std/os/platform/none/arm/cortex_m ملفات
بيانات تُعطى للرابط صراحة:
| الملف | المحتوى |
|---|---|
cortex_m.ld |
تخطيط الأقسام: جدول المتجهات في أول FLASH، ثم .text و.rodata و.init_array و.ARM.extab/.ARM.exidx في FLASH، و.data في RAM محمّلا من FLASH، و.bss في RAM، و__stack_top في آخر RAM، والحدود التي يقرؤها معالج إعادة التشغيل |
board_mps2.ld، board_lm3s6965.ld، board_nrf51.ld |
منطقتا FLASH وRAM للوحات QEMU، ثم INCLUDE cortex_m.ld |
semihosting.ld |
__sultanc_exit = __sultanc_semihosting_exit; وHardFault_Handler = __sultanc_semihosting_fault;، لتشغيلات QEMU والمنقح فقط: فعلى عتاد بلا منقح يُحدث BKPT عطلا |
لا يربط السلطان هذه الأهداف: فطلب exe يُبلغ عنه بـSULTANC-LINK-OUTPUT-UNSUPPORTED. فليس في رابط ELF المدمج بعد
إزاحات Arm ولا دعم لنصوص الربط. اربط الصورة بـld.lld، مثلا:
./build/sultanc --backend=llvm --target=thumbv7m-none-eabi --emit=obj program.sn -o program.o
D=library/std/os/platform/none/arm/cortex_m
ld.lld -T $D/board_mps2.ld -L $D --gc-sections program.o $D/semihosting.ld -o program.elf
qemu-system-arm -M mps2-an385 -nographic -monitor none -serial none \
-semihosting-config enable=on,target=native -kernel program.elf; echo $?
ويفعل tools/tests/cortex_m_tests.sh ذلك لكل اختبار في tests/{en,ar}/target يسمي هدف Cortex-M، ويشغّل كل صورة على
لوحات QEMU لهدفها.
ما لم يُدعم بعد: ve-linux-gnu
يُترجم ve-linux-gnu (NEC Vector Engine) إلى ملفات كائنات وشيفرة تجميع، لكن ليس له طبقة نظام تشغيل في المكتبة القياسية. فلا
يوجد في VE مصيدة نواة: استدعاء النظام طلب يُرسل إلى خدمة VEOS. يُخزن الرقم والوسائط في منطقة ذاكرة مشتركة خاصة بكل
خيط، يضع بدء التشغيل في VEOS وglibc عنوانها في كتلة التحكم بالخيط (tcbhead_t.shm_offset، glibc-ve
sysdeps/unix/sysv/linux/ve/sysdep.h)، ثم تُنفذ monc. ويحتاج النقل إلى بروتوكول بدء التشغيل ذاك، وإلى عتاد VE أو
محاكٍ للتحقق منه.
ما الذي يقع أين
| الطبقة | المالك | ملاحظات |
|---|---|---|
| الواجهة الثنائية للنواة (أرقام استدعاءات النظام، الرايات، تخطيطات السجلات، ترتيب البايتات) | المكتبة القياسية: library/std/os/platform/** |
تُولد جداول Linux من ترويسات UAPI لنواة كل معمارية (tools/generate/generate_linux_syscalls.py، generate_linux_uapi.py). وتأخذ الواجهات الثنائية ذات 32 بت صفوف ilp32: من tools/generate/registry/linux_syscalls.def (clock_gettime64، ppoll_time64، mmap2، _llseek، fcntl64). وتُولد جداول FreeBSD من ترويساته (releng/14.2) في platform/unix/freebsd: جدول واحد لاستدعاءات النظام لكل المعماريات (generate_freebsd_syscalls.py، registry/freebsd_syscalls.def، ولكل صف نموذجه من syscalls.master)، وقيم الرايات وإزاحات struct stat وتصنيف errno (generate_freebsd_uapi.py، تُقرأ بـclang -E -dM وoffsetof). |
| مزودات نظام التشغيل (الملفات، العمليات، المقابس، الذاكرة، الساعات) | المكتبة القياسية | فرع واحد محروس لكل نظام تشغيل في library/std/os/*.sn. ويخدم مزود النواة المباشر في platform/unix/linux نظام FreeBSD أيضا: فهو يأخذ أرقامه من الجدول المختار (syscalls/selection.sn) وثوابته من قيم النواة المختارة (linux/uapi.sn أو freebsd/uapi.sn، بأسماء الدوال نفسها). وحيث يختلف استدعاء FreeBSD، تتولاه كتلة خاصة بـFreeBSD: fstatat بدل statx، وسجلات getdirentries، و__getcwd، وwait4 بدل waitid، وfork بدل clone، وgetrlimit/setrlimit بدل prlimit64، وhw.pagesize عبر __sysctl بدل auxv في procfs. |
تعليمة الدخول إلى النواة، و_start، وتوحيد راية الخطأ |
الخلفية (compiler/backend/provider/llvm/{lowering,entry}.sn) |
الشيفرة الوحيدة الخاصة بكل معمارية خارج المكتبة القياسية. في i386 يُمرر الرقم والوسيط السادس عبر كتلة في المكدس حتى يمكن حفظ EBP. ويشير FreeBSD إلى الأخطاء براية الحمل (amd64، arm64) أو بـt0 (riscv) مع errno موجب، وتحوله التعليمات إلى -errno. وتأخذ _start فيه كتلة الوسائط من rdi أو x0 أو a0، ويحمل الملف التنفيذي ملاحظة الواجهة الثنائية .note.tag (osrel 1402000) إلى جانب ELFOSABI_FREEBSD. |
| العمليات الحسابية التي يفتقر إليها الهدف | الخلفية (compiler/backend/provider/llvm/wide_division.sn؛ والضرب المتحقق منه في lowering.sn) |
توسّع في التمثيل الوسيط فلا يُربط compiler-rt. تُوسّع القسمة على 64 بت في الأهداف ذات 32 و16 بت، وكذلك القسمة بكل عرض في الأهداف التي لا تعليمة قسمة فيها (ARMv7-A، الذي لا يضمن SDIV/UDIV؛ وAVR؛ وMSP430؛ وHexagon؛ وLanai)، بدالة واحدة لكل عرض تعتمد الإزاحة والطرح مع الاستعادة (sultanc.udivmodN). ويقسم SPARC V9 المعاملات ذات 8 و16 و32 بت على 64 بت (SDIVX/UDIVX) بدل SDIV/UDIV المهملتين اللتين تعتمدان على السجل Y، لأن sdiv في QEMU 8.2 يقسم أيضا على المقسوم عليه الممدد بالأصفار ويعطي حواصل قسمة ضيقة ذات إشارة خاطئة. وحيث لا يوجد ناتج ضرب بعرض 128 بت (WebAssembly، وSPARC V9، والأهداف ذات 32 بت)، يُبنى الضرب المتحقق منه على 64 بت من أنصاف ذات 32 بت، ويُستبدل بالتوسيع نفسه بعد خط التحسين كل llvm.*mul.with.overflow.i64 يكوّنه المحسن (إذ يحوّل InstCombine الاختبار b > MAX / a إلى واحد منها)، لأن LLVM كان سيستدعي __multi3. ويقسم BPF القيم ذات الإشارة عبر مقاديرها. |
| فضاءات العناوين | الخلفية (compiler/backend/provider/llvm/values.sn) |
خانات المكدس في AMDGPU تقع في فضاء العناوين الخاص؛ فتُحوَّل كل منها إلى مؤشر مسطح بجوار تعليمة حجزها. |
| الربط | الروابط المدمجة (ELF؛ وMach-O؛ وCOFF؛ وwasm) | ملفات تنفيذية ساكنة بلا libc. انظر الربط. |
لا تحتاج الخلفية الأصلية لمعمارية جديدة إلا إلى الدخول إلى النواة و_start؛ أما طبقة المكتبة القياسية فمشتركة مع خلفية LLVM.
التحقق
يُتحقق من كل هدف بأقوى مستوى تسمح به بيئته.
| المستوى | الأهداف | المعنى |
|---|---|---|
| التشغيل الأصلي | x86_64-linux وx86_64-android؛ وarm64-darwin على جهاز Mac بمعالج arm64 |
يعمل الملف التنفيذي المبني على المضيف |
| qemu-user | aarch64 وriscv64 وloongarch64 وpowerpc64le وs390x وmips64el وsparcv9 وi686 وarmv7 على Linux؛ وaarch64 وarmv7 على Android | تعمل الأمثلة تحت qemu-<arch> وتُقارن مخرجاتها بمخرجات x86_64 |
| Wine | x86_64-windows-msvc |
يعمل الملف التنفيذي PE تحت Wine |
| آلة FreeBSD الافتراضية | x86_64-freebsd وaarch64-freebsd وriscv64-freebsd تحت محاكاة النظام في qemu |
تعمل الأمثلة واختبارات الأهداف في نظام FreeBSD 14.5 ضيف |
| أداة تحويل استدعاءات النظام | x86_64-freebsd |
تعمل الأمثلة على Linux تحت tools/tests/freebsd_abi_emulator.c (البرامج ذات الخيط الواحد) |
| مشغل WASI | wasm32-wasi |
wasmtime |
| node | wasm32-browser |
ناتج _start في الوحدة هو حالة الخروج |
| البناء | x86_64-darwin، aarch64-windows-msvc |
يُربط الملف التنفيذي؛ ويتحقق tools/audit/macos_imports_audit.py من استيرادات Mach-O مقابل SDK |
| qemu-system-arm | thumbv6m-none-eabi (microbit)، thumbv7m-none-eabi (lm3s6965evb، mps2-an385)، thumbv7em-none-eabi وthumbv7em-none-eabihf (mps2-an386، mps2-an500) |
يربط tools/tests/cortex_m_tests.sh الصور بـld.lld ونصوص الربط، ويشغلها بالاستضافة شبه الكاملة، ويقارن حالة الخروج |
| ملفات الكائنات وشيفرة التجميع | سائر الأهداف المستقلة وأهداف المسرعات | ينتج المترجم ملفات كائنات أو شيفرة تجميع |
يشغّل tools/tests/target_tests.sh الاختبارات في tests/{en,ar}/target على كل هدف يسميه ترويس // أهداف: فيها:
check، ثم ملف تنفيذي (أو ملف كائنات أو شيفرة تجميع)، ثم التشغيل حيث يستطيع المضيف تشغيله، مع مقارنة حالة الخروج والخرج
القياسي. وعلى مضيف x86_64 Linux فيه qemu-user وwasmtime وnode وWine، يشغّل 192 زوجا من أزواج الاختبار والهدف الـ296،
ويبني الأزواج الـ104 الباقية.
ويعطي كل برنامج في examples/en (90 من الملفات الـ93؛ والثلاثة الباقية مساعدا وحدتين، ومثال على استدعاء مكتبة C)
المخرجات وحالة الخروج نفسيهما اللتين يعطيهما على x86_64 Linux: تحت qemu-user على كل معمارية من Linux وAndroid، وتحت wasmtime
(إلا الأمثلة التي تحتاج إلى العمليات أو بيئة المضيف)، وعلى آلات FreeBSD الافتراضية x86_64 وaarch64 وriscv64 مع
اختبارات الأهداف. وتجد الأعداد لكل هدف في تقدم أهداف LLVM. ويشغل
tools/tests/freebsd_examples.sh أمثلة x86_64 على مضيف Linux عبر أداة تحويل لاستدعاءات النظام تعتمد على ptrace
(tools/tests/freebsd_abi_emulator.c).
التحقق المتقاطع من هدف Linux
./build/sultanc --backend=llvm --target=riscv64-linux-gnu examples/ar/fs/files.sn -o files
qemu-riscv64 ./files
إعادة توليد جداول FreeBSD
لا تقرأ المولدات إلا ترويسات sys/ وinclude/ من شجرة مصدر FreeBSD.
git clone --depth 1 -b releng/14.2 https://github.com/freebsd/freebsd-src
python3 tools/generate/generate_freebsd_syscalls.py --src freebsd-src
python3 tools/generate/generate_freebsd_uapi.py --src freebsd-src
تشغيل FreeBSD تحت qemu
تعمل صور الآلات الافتراضية الرسمية تحت محاكاة النظام في qemu (TCG؛ ولا حاجة إلى KVM). وعلى Ubuntu 24.04 الحزم
هي qemu-system-arm qemu-system-misc qemu-efi-aarch64 u-boot-qemu opensbi. والصور موجودة في
https://download.freebsd.org/releases/VM-IMAGES/14.5-RELEASE/{aarch64,riscv64}/Latest/:
FreeBSD-14.5-RELEASE-arm64-aarch64-ufs.qcow2.xz و
FreeBSD-14.5-RELEASE-riscv-riscv64-ufs.qcow2.xz. تحقق منها مقابل CHECKSUM.SHA256. ولم يعد الإصدار 14.2
موجودا على المرآة؛ والإصدار 14.5 يشغل الملفات التنفيذية المبنية على ترويسات 14.2. وتحويل الصورة بـ
qemu-img convert -c -O qcow2 يخفض حجمها إلى النصف.
# aarch64: برنامج UEFI الثابت، وأجهزة virtio PCI، وSSH على المنفذ 2223 في المضيف
qemu-system-aarch64 -M virt -cpu cortex-a72 -smp 4 -m 2048 -display none \
-bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-drive file=arm64-aarch64.qcow2,if=none,id=hd0,format=qcow2 -device virtio-blk-pci,drive=hd0 \
-netdev user,id=n0,hostfwd=tcp:127.0.0.1:2223-:22 -device virtio-net-pci,netdev=n0 \
-serial unix:ser-aarch64.sock,server,nowait -monitor none
# riscv64: يبدأ OpenSBI، ثم U-Boot (في النمط S)، الذي يُقلع محمّل EFI في الصورة؛ وSSH على المنفذ 2224
qemu-system-riscv64 -M virt -smp 4 -m 2048 -display none \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.bin \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin \
-drive file=riscv-riscv64.qcow2,if=none,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 \
-netdev user,id=n0,hostfwd=tcp:127.0.0.1:2224-:22 -device virtio-net-device,netdev=n0 \
-serial unix:ser-riscv64.sock,server,nowait -monitor none
تُدخل الصور المستخدم root في وحدة التحكم التسلسلية بلا كلمة مرور. وعبر مقبس وحدة التحكم، ثبّت مفتاحا في
/root/.ssh/authorized_keys، وأضف PermitRootLogin prohibit-password إلى /etc/ssh/sshd_config، ثم شغّل
sysrc sshd_enable=YES; service sshd keygen; service sshd start (فـsshd معطل في الصور، وتوليد مفاتيح المضيف
يستغرق عدة دقائق على riscv64 تحت TCG). انسخ البرنامج بـscp -P 2223 (أو 2224) وشغّله عبر ssh. وتحت TCG على
مضيف رباعي النوى، تُقلع الآلة الافتراضية aarch64 في نحو 3 دقائق والآلة riscv64 في نحو 10، وتعمل برامج riscv64
أبطأ بنحو عشر مرات من برامج aarch64.
لا تطبع صورة amd64 إلا على شاشة الفيديو. ومع ذلك يمكن قيادة التشغيل من المضيف دون شبكة: يكتب الأمر sendkey في
شاشة مراقبة QEMU على الطرفية (root، ثم سطر أوامر)، ويعرض screendump الشاشة، ويكتب الضيف نتائجه إلى المنفذ
التسلسلي (... > /dev/cuau0) الذي يسلمه -serial unix:... إلى المضيف. وتصل البرامج إلى الضيف على صورة ISO
(genisoimage -R) تُركب بـmount_cd9660 (بـ-cdrom على amd64، وvirtio-scsi على aarch64، وvirtio-blk-device
للقراءة فقط على riscv64، حيث تكون /dev/vtbd1).
الاستضافة الذاتية على Android وFreeBSD
المترجم المبني لـx86_64-android أو aarch64-android أو x86_64-freebsd أو aarch64-freebsd يعمل هناك، ويترجم
البرامج لمنصته افتراضيا، ويترجم نفسه. ابنه من مضيف x86_64 Linux بالخلفية الأصلية (ومصدر الوحدة أدناه يستبعد مزود
LLVM كما يفعل ./build.sh للمترجم المبني بلا LLVM):
./build/sultanc --target=x86_64-freebsd \
--module-source=compiler.backend.provider.llvm.llvm_codegen=compiler/backend/provider/llvm/unavailable.sn \
compiler/main.sn -o sultanc
وعلى الهدف، شغّله من دليل فيه compiler/ وlibrary/ (أو اضبط SULTANC_STD). ويعرف المترجم أين يعمل من هوية بيئة
المضيف في compiler/runtime/host_environment_model.sn، وفي رموز منصاتها Android (6) وFreeBSD (7)؛ ويربطها
compiler/backend/target/target_registry.sn بالأهداف المسجلة، فيبني sultanc program.sn بلا --target للمنصة
التي يعمل عليها.
| الهدف | check compiler/main.sn --target |
بناء المترجم وربطه | التشغيل (برنامج التحية؛ والمترجم يترجم نفسه) |
|---|---|---|---|
x86_64-android |
ينجح | نعم (ELF ساكن، 33 ميغابايت) | أصليا على نواة Linux: يطبع برنامج التحية خرجه؛ والمترجم الذي يبنيه مطابق له بايتا ببايت |
aarch64-android |
ينجح | نعم (ELF ساكن، 31 ميغابايت) | qemu-aarch64: يطبع برنامج التحية خرجه؛ والمترجم الذي يبنيه مطابق له بايتا ببايت (نحو 3 دقائق) |
x86_64-freebsd |
ينجح | نعم (ELF ساكن، 33 ميغابايت، مع ملاحظة ABI لـFreeBSD) | أداة تحويل استدعاءات النظام: يطبع برنامج التحية خرجه؛ والمترجم الذي يبنيه مطابق له بايتا ببايت |
aarch64-freebsd |
ينجح | نعم (ELF ساكن، 31 ميغابايت، مع ملاحظة ABI لـFreeBSD) | آلة FreeBSD 14.5 arm64 افتراضية (qemu -cpu neoverse-n1): ينجح check، ويطبع برنامج التحية خرجه؛ والمترجم الذي يبنيه (في نحو 9 دقائق، و1.3 غيغابايت من الذاكرة المقيمة) مطابق بايتا ببايت لما يبنيه مترجم x86_64 Linux من دليل المصدر نفسه، ويترجم برنامج التحية من جديد |
يسجل المترجم المسارات المطلقة لمصادره، فلا يتطابق بناءان إلا إذا ترجما من الدليل نفسه.
على هذه الأهداف (وعلى Linux وWindows) تستعمل شيفرة aarch64 العمليات الذرية من ARMv8.0، أي حلقات
LDAXR/STLXR، في الخلفية الأصلية وفي خلفية LLVM (انظر التزامن)، فتعمل الملفات التنفيذية
على أنوية ARMv8.0 مثل Cortex-A53 وA57 وA72 (Raspberry Pi 3 و4) وعلى ما بعدها: يتحقق مترجم aarch64-linux-gnu
من compiler/main.sn ويترجم برنامج التحية تحت qemu-aarch64 -cpu cortex-a57. ولا يستعمل عمليات LSE الذرية من
ARMv8.1 (LDADDAL وCASAL وغيرهما) إلا arm64-darwin، إذ تملكها كل أنوية Apple Silicon. ولا يتاح
sultanc run على هذه المضيفات: فجسر نواة المضيف في المفسر موجود لـLinux وحده، ويُبلغ التشغيل عن
SULTANC-INTERPRETER-UNSUPPORTED-MACHINE-PRIMITIVE. ترجم البرنامج وشغّل ملفه التنفيذي بدلا من ذلك.
القيود
- تغطي الخلفية الأصلية أهداف أنظمة التشغيل على x86_64 وaarch64 وwasm32؛ وكل هدف آخر يحتاج إلى خلفية LLVM.
- لا يتاح
sultanc runعلى مضيفات Android وFreeBSD. - ليس لـ
ve-linux-gnuطبقة نظام تشغيل في المكتبة القياسية. - لا تنتج الأهداف المستقلة وأهداف المسرعات إلا ملفات كائنات أو شيفرة تجميع؛ وتُربط صور Cortex-M بـ
ld.lldخارج المترجم. - Cortex-M: لا روتينات فاصلة عائمة برمجية (تُرفض العمليات العائمة التي لا تدعمها وحدة الفاصلة العائمة)، ولا اختيار لوحدة الدقة المضاعفة في Cortex-M7، ولا في std إلا التحميل والتخزين الذريان بعرض 32 بت والأسيجة.
- يُبنى
x86_64-darwinوaarch64-windows-msvcلكنهما لا يُشغلان. - لا ينتج
wasm64-unknown-unknownإلا ملفات كائنات. - لا ينجح
sultanc check compiler/main.snإلا للأهداف المستضافة: فالمترجم يستعمل الملفات والعمليات. - ليس في
wasm32-wasiعمليات ولا خيوط ولا أقفال ملفات، ومقابسه مقصورة على المفتوحة مسبقا.
انظر أيضا
- اعتماديات المنصات: كل واجهة نظام تستوردها المكتبة القياسية، لكل منصة.
- التزامن: دعم الخيوط في كل نظام تشغيل.
- MSIR وتوليد الشيفرة: كيف تتكامل الخلفيات والروابط.
- الإقلاع الذاتي: بناء المترجم مع LLVM أو بدونه.