1 पॉइंट द्वारा GN⁺ 2025-04-14 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • rustc_codegen_clr एक project है जो Rust code को C और .NET side के लिए generate करता है, और test pass rate में सुधार के साथ Rust Week presentation की तैयारी में है
  • Rust core tests की pass rate दो महीने पहले 92% से बढ़कर 95.9% हो गई है, और बचे हुए लगभग 65 tests के कारण भी एक-दूसरे से मिलते-जुलते लग रहे हैं
  • हाल के fixes 128-bit integer intrinsics, checked arithmetic और subslicing पर केंद्रित रहे हैं, और .NET side भी Rust core tests के 96.3% चला पाने में सक्षम हो गया है
  • अधिक C compilers को target करने के लिए output को C99 या ANSI C के करीब रखने और standard POSIX API इस्तेमाल करने का लक्ष्य है; कुछ ANSI C compilers पर बहुत सरल Rust programs चलाने में सफलता मिली है
  • बड़े पैमाने पर C code generation में file size घटाने वाली optimizations और internal IR refactoring साथ-साथ चल रही हैं, जिससे पुराने या specialized platforms पर Rust चलाने का दायरा बढ़ाने की बुनियाद बन रही है

Rust Week presentation और project की प्रगति

  • rustc_codegen_clr project की presentation Netherlands के Utrecht में होने वाले Rust Week में scheduled है
  • presentation का लक्ष्य beginners के लिए approachable रहते हुए Rust-to-C compilation जैसे advanced topic को cover करने का संतुलन बनाना है
  • पिछले कुछ महीनों में test fixes, C compiler compatibility, performance improvements और internal refactoring साथ-साथ किए गए हैं

Rust core test pass rate में बढ़ोतरी

  • Rust core tests की pass rate दो महीने पहले 92% से बढ़कर 95.9% हो गई है
  • अभी भी लगभग 65 tests बचे हैं, लेकिन कारण एक-दूसरे से मिलते-जुलते दिखते हैं, इसलिए बाकी fixes का scope अपेक्षाकृत सीमित हो चुका है
  • .NET side भी उन्हीं fixes से प्रभावित होकर Rust core tests के 96.3% चला पाने में सक्षम हो गया है

128-bit integers और checked arithmetic fixes

  • improvements का बड़ा हिस्सा 128-bit intrinsics, checked arithmetic और subslicing fixes से आया है
  • C के popcount intrinsics तीन तरह के हैं: __builtin_popcount, __builtin_popcountl, __builtin_popcountll
    • नाम के उलट __builtin_popcountll, __int128_t पर नहीं बल्कि unsigned long long पर काम करता है
    • x86_64 Linux और GCC के हिसाब से unsigned long और unsigned long long दोनों 64-bit हैं
  • पुराने implementation में bit counting intrinsics पर 128-bit integers को चुपचाप 64-bit में truncate करके calculation की जाती थी, जिससे गलत result निकलता था
  • 128-bit popcount को emulate करने के लिए lower 64 bits और upper 64 bits के set bits अलग-अलग गिने जाते हैं और फिर जोड़े जाते हैं
  • 128-bit multiplication के overflow check के लिए efficient तरीका नहीं मिला, इसलिए इसे simple तरीके से handle किया गया
    • अगर b 0 नहीं है और (a * b) / b == a है, तो माना जाता है कि overflow नहीं हुआ
    • यह कोई revolutionary तरीका नहीं है, लेकिन कुछ और tests pass कराने के लिए काफी है

Subslicing bug और fallback intrinsics

  • subslicing bug sizeof छूट जाने की वजह से था, जिसके कारण slice के data pointer को element unit के बजाय byte unit में offset किया जा रहा था
  • यह bug slice की शुरुआत से नहीं, बल्कि अंत से subslicing करने पर ही टूटता था, और pattern matching में मुख्य रूप से इस्तेमाल होने वाला pattern होने के कारण लंबे समय तक नहीं पकड़ा गया
  • byte slice और string slice में byte और UTF-8 code unit का size 1 byte होता है, इसलिए अपने tests pass हो गए, और issue पूरे Rust compiler test suite में सामने आया
  • कुछ intrinsics को सीधे implement किए बिना Rust compiler की fallback implementation इस्तेमाल की जा सकती है
  • carrying_mul_add में input से 2 गुना बड़े integer पर multiplication करनी होती है
    • 64-bit तक इसे handle किया जा सकता है, लेकिन 128-bit input के लिए 256-bit integer चाहिए
    • LLVM 256-bit integers support करता है, लेकिन C और .NET support नहीं करते
  • Rust compiler की fallback implementation 128-bit integers से 256-bit multiplication और addition करती है, इसलिए 64-bit integers से 128-bit operations emulate करने में इसे reference के तौर पर इस्तेमाल किया जा सकता है

अधिक C compilers का support

  • project अधिक specialized C compilers पर Rust code चलने की संभावना बढ़ाना चाहता है
  • Rust code के Game Boy पर चलने, केवल move commands से compile होने, या Temple OS के Holly C से चलने के examples रहे हैं
  • जिन proprietary C compilers तक access नहीं है, उन्हें सीधे support नहीं किया जा सकता, लेकिन obscure C compiler support का दायरा बढ़ाने से ऐसे environments में Rust code चलने की संभावना बढ़ती है
  • कई platforms documentation की कमी और accessibility की कमी के कारण support नहीं होते
  • Git के कुछ हिस्से Rust में लिखने की चर्चा के संदर्भ में, NonStop जैसे proprietary platforms Rust, LLVM, GCC को support नहीं करते, जिससे Git support घटने या बंद होने की समस्या आ सकती है
  • Rust को C में compile करने पर theoretically जहाँ भी C है, वहाँ Rust चलाया जा सकता है
    • सभी platforms पर problems को bypass किया जा सकेगा या नहीं, यह अभी clear नहीं है
    • उस platform के लिए compiler कानूनी तरीके से पाने के लिए server खरीदना पड़ता था, जो budget से काफी बाहर था
    • ऐसे platforms पर Rust के जल्द चलने की संभावना कम दिखती है

मौजूदा C output strategy

  • मौजूदा plan जहाँ तक संभव हो standards-compliant C99 या ANSI C के करीब code generate करना है
  • thread-local initialization के लिए कुछ threading support चाहिए, इसलिए केवल standard POSIX API इस्तेमाल करने की दिशा चुनी गई है
  • कुछ specific intrinsics के लिए project के पास अपनी fallback implementations हैं, और उनकी list धीरे-धीरे बढ़ाई जा रही है
  • कुछ ANSI C compilers पर बहुत सरल Rust programs चलाने में सफलता मिली है
  • अभी support करना कठिन platforms को भी जरूरत पड़ने पर अपेक्षाकृत आसानी से add किया जा सके, यह target है

छोटी performance और file size improvements

  • integer literal output में यह बात reflect की गई है कि 2^32 से छोटे integers में decimal representation hexadecimal जितना या उससे छोटा होता है
    • 255, 0xFF से 1 byte छोटा है
    • 65536 भी 0xFFFF से छोटा है
    • 0x prefix की वजह से 2^32 तक hexadecimal representation छोटा नहीं होता
  • पूरे Rust compiler को C में convert करने जैसे extreme case में अधिकतम 1GB की C source file generate हुई थी, इसलिए file size में छोटी percentage reduction भी असर डालती है
  • debug info डालने के लिए इस्तेमाल होने वाला #line directive भी smarter बनाया गया है
    • source file name केवल बदलने पर ही include किया जाता है
    • debug info इस्तेमाल करते समय file size काफी घटाया जा सकता है

Internal refactoring और IR cleanup

  • rustc_codegen_clr के अंदर की कुछ functionality को अलग crate में split करके incremental build की speed बढ़ाई गई है
  • ज्यादा memory-efficient interned IR की ओर migration भी चल रहा है
  • पुराने IR में कुछ अजीब rvalue/lvalue थे जो C में अच्छे से map नहीं होते थे, और dynamically sized type जैसी Rust features में problem बढ़ जाती थी
  • उदाहरण के लिए MyStr जैसे custom dynamically sized type में &self.s simple दिखता है, लेकिन असल में fat pointer metadata handle करना पड़ता है
    • C99 के compound literal का इस्तेमाल करके struct FatPtr_str को एक line में बनाया जा सकता है
    • ANSI C में temporary variable में data और meta को अलग-अलग डालकर return करना पड़ता है
  • Rust और MIR की एक line कई C lines में expand होने पर old IR temporary local और sub-statement वाले internal scope approach से handle करता था
  • नया तरीका setup phase को ज्यादा complex बनाता है, लेकिन पूरे IR को ज्यादा simple करता है; आखिरी बचे हुए मुश्किल cases हल होने पर old IR की वह functionality हटाई जा सकेगी

आगे का काम

  • project पर काम करते हुए लगभग 1.5 साल हो चुके हैं, और bugs घटने के साथ बाकी bugs ढूँढने में ज्यादा समय लगने लगा है
  • “Rust panics under the hood” के part 2 पर काम चल रहा है, जिसमें Rust panic process को step-by-step समझाने की कोशिश है
  • सिर्फ panic message generation की explanation ही 10 minutes की हो चुकी है, इसलिए article को दो हिस्सों में बाँटने पर भी विचार हो रहा है
  • Rust के लिए एक छोटा और accurate memory profiler भी बन रहा है
    • code size लगभग 2K LOC है
    • schedule tight है, लेकिन कुछ हफ्तों में इससे जुड़ा article लिखना चाहते हैं

1 टिप्पणियां

 
GN⁺ 2025-04-14
Hacker News की राय
  • मैं अभी भी इंतज़ार कर रहा हूँ कि वैकल्पिक Rust frontend या backend में से कोई एक alpha, hppa, m68k, sh4 पर Rust को bootstrap करने लायक बना दे
    असल में rustc_codegen_gcc प्रोजेक्ट ने इसका वादा किया था, लेकिन आखिरकार उसे पूरा नहीं कर पाया
    • मुझे जानना है कि क्या वे सच में उन चारों platforms का इस्तेमाल करते हैं, या यह पूर्ण platform support मानने के लिए कोई मनमाना benchmark है
    • क्या m68k-unknown-linux-gnu Rust के Tier-3 target के रूप में merge नहीं हुआ था? [0]
      [0] https://github.com/rust-lang/compiler-team/issues/458
    • क्या उन्होंने वह लक्ष्य छोड़ दिया है? आखिरी बार जब सुना था, तब यह अभी development में था
    • Rust अभी भी OpenBSD on x86_64 को भी ठीक से support नहीं करता
  • fractalfir सचमुच प्रतिभाशाली व्यक्ति हैं। Rust Reddit पर उन्हें अक्सर देखता हूँ; compiler के बारे में मुझे बहुत जानकारी नहीं है, लेकिन लगता है दूसरों को उनका काम काफी पसंद है
    • मेरी जानकारी में वे काफी युवा हैं। उम्मीद है उनका भविष्य उज्ज्वल हो
  • “std के अधिकतर components .NET में लगभग 95%, C में 80% काम करते हैं” वाली बात में, HN title से यह बात छूट गई है कि 95% pass rate सिर्फ .NET पर लागू होता है
    GCC/Clang वाली तरफ यह “80%” ही है
    • README पुराना था। वे आंकड़े इस साल की शुरुआत के थे, और अब स्थिति यह है
      | .NET Core tests | 1764 | 48 | 20 | 96.29% |
      | C Core tests | 1712 | 71 | 8 | 95.59% |
  • इससे आज़माने लायक कई दिलचस्प use cases हैं। सबसे पहले दिमाग में Python जैसी दूसरी languages के साथ interoperability बेहतर करना आता है
    • PyO3 इस्तेमाल करने पर interoperability पहले से ही बेहतरीन है। बस अपवाद तब है जब लोग Rust वाले हिस्से को source से build करना चाहते हैं और Rust compiler install करना झंझट समझते हैं
      यह hack Rust compiler backend है। backend platform-specific instructions को input के रूप में लेते हैं, इसलिए generate हुआ non-trivial C code portable नहीं होगा
      users को पहले से generate किया हुआ platform-specific source लेना होगा, या Rust compiler और यह backend install करके खुद generate करना होगा
    • Rust के extern "c" functions से जो पहले से नहीं किया जा सकता, उसके मुकाबले यह नया क्या फायदा देता है?
  • क्या यह LLVM IR से C में जाता है? या Rust AST से C में?
    • प्रोजेक्ट README में जवाब मिला
      “मेरा .NET IR representation C पर अच्छी तरह map होता है, और इसी वजह से 2–3 हजार lines of code में Rust को C में compile करने का support जोड़ सका। codebase का लगभग पूरा हिस्सा reuse होता है, और C तथा .NET-specific code सिर्फ compilation के बिल्कुल आखिरी stage में मौजूद होता है”
    • यह rustc backend है, यानी LLVM, GCC, Cranelift backends का alternative
      शुरुआत में यह .NET backend के रूप में शुरू हुआ था, लेकिन पता चला कि यह approach C code generation को भी आसानी से support कर सकती है, इसलिए उसे जोड़ा गया। rustc जो पास करता है, उसे अपनी intermediate representation (IR) में बदलकर process करता है
  • Nim से C में जाने वाले compiler का test pass rate 100% है
  • लेकिन क्या यह Rust जैसी guarantees भी बनाए रखता है?
    • अगर transformation में खुद bug नहीं है, तो न होने की कोई वजह नहीं। static guarantees इस premise पर कि यह सामान्य Rust compiler में पहले से compile होने वाले Rust code को transform कर रहा है, पहले ही check होकर मौजूद होती हैं
      bounds checking जैसी dynamic guarantees भी C runtime में बिना दिक्कत implement की जा सकती हैं
    • न होने की कोई वजह है क्या?
  • बहुत शानदार। C से Rust की दिशा भी बढ़िया होगी
    • अगर program non-trivial है, तो शायद पूरे को एक बड़े unsafe block में डालना पड़ेगा
      C वह सारी जानकारी carry नहीं करता जिसे Rust में compile कराने के लिए explicit रूप से जानना ज़रूरी होता है
    • Mark Russinovich ने हाल ही में UK Rust conference में Microsoft के अंदर बड़े पैमाने पर C→Rust conversion की कोशिशों का ज़िक्र करते हुए talk दी थी
      https://www.youtube.com/watch?v=1VgptLwP588
    • ऐसे tools पहले से हैं। समस्या यह है कि वे बहुत सारे unsafe blocks इस्तेमाल करते हैं, और आम तौर पर result code Rust जैसा नहीं लगता
      उदाहरण के लिए, global variable-based state machine को named enum जैसी चीज़ों का इस्तेमाल करने वाली अधिक Rust-idiomatic state machine में बदलना बहुत मुश्किल होगा
      पर्याप्त शक्तिशाली AI की मदद से शायद संभव हो, लेकिन AI अभी intended काम सच में कराने में काफी पीछे है, इसलिए उसे तैयार मानना मुश्किल है। पूरी C और Rust codebase को context window में रखने जितनी memory भी चाहिए होगी; code एक निश्चित scale से ऊपर जाते ही बहुत महंगा hardware चाहिए होगा। वरना कई code-assist LLMs की तरह वह आपस में incompatible code को स्वतंत्र रूप से generate करेगा
      फिर भी अगर आप किसी C project को Rust में extend करना या धीरे-धीरे rewrite करना चाहते हैं, तो https://c2rust.com/ तुरंत इस्तेमाल किया जा सकता है
    • https://github.com/immunant/c2rust देखें
    • इससे आप किस तरह के फायदे की उम्मीद कर रहे हैं?
  • Rust को C में? आखिर ऐसा क्यों करें। सीधे C ही इस्तेमाल कर लें। अगर आप Rust समझ सकते हैं तो C भी ज़रूर समझ सकते हैं और कुशलता से इस्तेमाल कर सकते हैं
    • Rust के फायदे और gcc/C compilers की व्यापक compatibility और architecture support—दोनों पाने के लिए
      Rust एक modern language है जिसमें package management, सरल integrated build/test tools, काफी कम legacy baggage, और high-level features व syntax हैं जिन्हें लोग सचमुच पसंद करते हैं
      C भी साफ-सुथरी है, लेकिन complex codebases को ऐसी modern language के फायदे मिलते हैं जो C की speed बनाए रखते हुए robust abstractions बनाने में मदद करती है। बेशक borrow checker और memory safety भी अहम हैं
    • उन platforms पर Rust के फायदे पाने के लिए जिन्हें rustc support नहीं करता। यह काफी सीधा है
    • इसमें “क्योंकि कर सकते हैं, इसलिए करके देखते हैं” वाली बात भी काफी लगती है, लेकिन वजह यह भी है कि Rust कई platforms को support नहीं करता
      अगर पर्याप्त standard C code generate करने वाला Rust→C converter हो, तो वह यह gap भर सकता है