Skip to content

مترجم (حاجز ٣/F2): تخطيط بنية C-متوافق بلا ترويسة — @تمثيل_سي ينجز الربط الخارجيّ (RFC #53 F2-ب)#280

Merged
SalehKadah merged 1 commit into
devfrom
feat/ffi-crepr-f2b
Jul 25, 2026
Merged

مترجم (حاجز ٣/F2): تخطيط بنية C-متوافق بلا ترويسة — @تمثيل_سي ينجز الربط الخارجيّ (RFC #53 F2-ب)#280
SalehKadah merged 1 commit into
devfrom
feat/ffi-crepr-f2b

Conversation

@SalehKadah

Copy link
Copy Markdown
Collaborator

الحاجز ٣ (FFI بنيويّ) / F2-ب — تخطيط بنية C-ABI متوافق

يُكمل هذا الـPR F2-ب من RFC #53 (سدّ الحاجز ٣ لخارطة الاستضافة الذاتيّة rfcs#52)، بعد F2-أ المدموجة (#277).

المشكلة (الحاجب الحقيقيّ للـFFI البنيويّ)

بنى ص تُمثَّل داخليًّا كأصناف SIR بترويسة مؤشّر vtable في الحقل 0: { ptr, i64, i64 }. هذا يزيح حقول المستخدم 8 بايت مقابل بنية C نظيرة، فتمرير بنية ص إلى دالّة C يقرأ/يكتب إزاحات خاطئة — غير متوافق مع C-ABI.

الحلّ

تفعيل سمة @تمثيل_سي (نظير Rust #[repr(C)]، المقبولة في F2-أ) لإسقاط ترويسة vtable: النوع يصير { i64, i64 }، فالحقل 0 عند الإزاحة 0 — مطابقٌ لـstruct { long؛ long؛ } في C.

نوع البنية malloc
@تمثيل_سي { i64, i64 } 16 بايت
بنية عاديّة { ptr, i64, i64 } 24 بايت

التغييرات

  • SIRClass::isCRepr يُنقل من StructDecl::isCRepr؛ cReprClasses تُملأ في preprocessClasses.
  • preprocessClasses: تخطّي دفع مؤشّر الترويسة للحقل 0 لبنى C-repr.
  • getFieldStructIndex: بلا إزاحة لـC-repr؛ مركزة كلّ إزاحات إنشاء الكائن المبرمَجة صلبًا عليه (mem_alloca/objects_arrays_ops/oop_ops).
  • storeVtablePtr: حارس يتخطّى C-repr.
  • buildClassVtables: بنية C-repr لا تُبنى لها vtable ⇒ استدعاء الطُّرق عليها إرسالٌ مباشر (حارس أمان C-1: منع قراءة الحقل 0 كمؤشّر vtable).
  • حجم malloc يتقلّص آليًّا (24→16) عبر getTypeAllocSize.

البراهين الحيّة

  • سلوكيّ (FFI): memset خارجيّة تصفّر أوّل 8 بايتات ⇒ الحقل الأوّل يصير 0 (عند الإزاحة 0)؛ الضبط ⇒ يبقى 111 (الحقل عند 8).
  • طريقة على بنية @تمثيل_سي42 بإرسال مباشر (لا انهيار C-1).

الاختبارات والمراجعة

  • اختبار جديد: 052_c_repr_method_direct_dispatch (تكافؤ مزدوج، يحرس ضدّ C-1).
  • انحدار صفريّ: 2459/2460 (الفشل الوحيد b2_recursion_accumulator انهيار انحدار عميق مسبق في المفسّر، غير ذي صلة، مُتحقَّق على الأساس النظيف).
  • مراجعة أميليا خصميّة (جولتان): الجولة ١ كشفت ثغرة أمان ذاكرة حرجة (C-1: طريقة على بنية C-repr تقرأ الحقل 0 كـvtable ⇒ انهيار) — سُدّت بحارس buildClassVtables. الجولة ٢: SAFE للدمج، حصر مغلق لكلّ قارئ/كاتب للحقل 0.

ديون مؤجَّلة موثَّقة (لا تحجب — تشخيصيّة لا أمان-ذاكرة)

  • H-2: حقول أيّ/نص/مصفوفة داخل @تمثيل_سي ليست C-متوافقة تخطيطيًّا (موثَّق قيدًا في RFC test(errors): مراجعة أميليا (وكيل فرعي) لترحيل reportError — إصلاح 4 علل #53؛ النطاق: العدديّات).
  • M-1: تخمين الصنف عند غياب objectClassMap (دَين قائم سلفًا).
  • F2-ج (التالي): تمرير/إرجاع بنية بالقيمة حسب تصنيف ABI (System V/Win64). تمرير المؤشّر المؤنمَط (ptr بدل i64) يعمل اليوم بتطابق العرض على x86-64.

🤖 Generated with Claude Code

…سي ينجز الربط الخارجيّ (RFC #53 F2-ب)

بنى ص تُمثَّل داخليًّا كأصناف SIR بترويسة مؤشّر vtable في الحقل 0 (`{ ptr, i64, i64 }`)،
فتُزاح حقول المستخدم 8 بايت مقابل بنية C نظيرة — وهو الحاجب الحقيقيّ للـFFI البنيويّ:
تمرير بنية ص إلى دالّة C يقرأ/يكتب إزاحات خاطئة.

هذه اللبنة تُفعّل سمة @تمثيل_سي (المُقرّة والمقبولة في F2-أ، #277) لتُسقِط ترويسة vtable:
النوع يصير `{ i64, i64 }`، فالحقل 0 عند الإزاحة 0 — مطابقٌ لـ`struct { long؛ long؛ }` في C.

التغييرات:
- SIRClass::isCRepr يُنقل من StructDecl::isCRepr (المُحلَّل في F2-أ).
- context_info_.cReprClasses تُملأ في preprocessClasses.
- preprocessClasses: تخطّي دفع مؤشّر الترويسة للحقل 0 لبنى C-repr (كبنى ADT سلفًا).
- getFieldStructIndex: يُرجِع i (بلا إزاحة) لـC-repr، وi+1 لغيرها. مركزة كلّ إزاحات
  إنشاء الكائن المبرمَجة صلبًا (mem_alloca/objects_arrays_ops/oop_ops) عليه.
- storeVtablePtr: حارس مبكّر يتخطّى C-repr (لئلّا يطمس بيانات الحقل 0).
- buildClassVtables: بنية C-repr لا تُبنى لها vtable (تبقى غائبة عن classVtableLayout/
  classVtableGlobals) ⇒ استدعاء طريقةٍ عليها إرسالٌ مباشر لا افتراضيّ (حارس أمان C-1 من
  مراجعة أميليا: منع قراءة الحقل 0 كمؤشّر vtable). الهدم محفوظ بالاسم.
- حجم malloc يتقلّص آليًّا (24→16) عبر getTypeAllocSize.

البراهين الحيّة:
- سلوكيّ: memset خارجيّة تصفّر أوّل 8 بايتات ⇒ الحقل الأوّل يصير 0 (عند الإزاحة 0)؛
  الضبط (بنية عاديّة) ⇒ يبقى 111 (الحقل عند 8). IR: `{ i64, i64 }`+malloc(16) مقابل
  `{ ptr, i64, i64 }`+malloc(24).
- طريقة على بنية @تمثيل_سي ⇒ 42 بإرسال مباشر (لا انهيار C-1).

اختبار: 052_c_repr_method_direct_dispatch (تكافؤ مزدوج). انحدار صفريّ: 2459/2460
(الفشل الوحيد b2_recursion_accumulator انهيار انحدار عميق مسبق في المفسّر، غير ذي صلة).
مراجعة أميليا خصميّة (جولتان): SAFE؛ ديون مؤجَّلة موثَّقة (H-2 حقول غير عدديّة، تخمين الصنف).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

📚 تذكير مزامنة دليل المطوّرين

هذا الـPR يلمس مصادر موثَّقة في دليل المطوّرين. راجع الفصول الآتية وحدّثها إن تغيّر سلوكها، ثم ثبّت البصمات هناك (python scripts/check_sync.py --update):

بندٌ في معيار الإنجاز. تذكيرٌ آليّ — لا يحجب الدمج.

@SalehKadah
SalehKadah merged commit b25055d into dev Jul 25, 2026
18 checks passed
@SalehKadah
SalehKadah deleted the feat/ffi-crepr-f2b branch July 25, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant