| FILECHECK(1) | LLVM | FILECHECK(1) |
نام (NAME)
FileCheck - ابزار اعتبارسنجی فایل با تطبیق انعطافپذیر الگوها
خلاصه دستور (SYNOPSIS)
FileCheck match-filename [--check-prefix=XXX] [--strict-whitespace]
توضیحات (DESCRIPTION)
دستور FileCheck دو فایل را میخواند (یکی از ورودی استاندارد و دیگری مشخصشده در خط فرمان) و از یکی برای اعتبارسنجی دیگری استفاده میکند. این رفتار بهویژه برای مجموعه آزمونها مفید است، که میخواهد بررسی کند آیا خروجی یک ابزار (مانند llc) حاوی اطلاعات مورد انتظار است یا خیر (برای نمونه، یک دستور movsd از esp یا هر مورد مد نظر دیگری). این سازوکار مشابه استفاده از grep است، اما برای تطبیق چندین ورودی مختلف در یک فایل با ترتیبی مشخص بهینهسازی شده است.
فایل match-filename فایلی را مشخص میکند که حاوی الگوهای مورد نظر برای تطبیق است. فایلی که باید اعتبارسنجی شود از ورودی استاندارد خوانده میشود، مگر اینکه از گزینه --input-file استفاده شده باشد.
گزینهها (OPTIONS)
گزینهها از متغیر محیطی FILECHECK_OPTS و از خط فرمان پردازش میشوند.
- -help
- چاپ خلاصهای از گزینههای خط فرمان.
- --check-prefix prefix
- دستور FileCheck
محتویات
match-filename را برای
یافتن
الگوهای
تطبیق
جستجو
میکند.
بهطور
پیشفرض،
پیشوند این
الگوها "CHECK:"
است. اگر
مایل به
استفاده از
پیشوند
متفاوتی
هستید
(مثلاً به
این دلیل که
همان فایل
ورودی در
حال بررسی
چندین
ابزار یا
گزینه
مختلف است)،
آرگومان
--check-prefix به شما
امکان
میدهد یک
یا چند
پیشوند را
برای تطبیق
(بدون ":"
انتهایی)
مشخص کنید.
استفاده از
چند پیشوند
برای
آزمونهایی
مفید است که
ممکن است
برای
گزینههای
مختلف اجرا
تغییر
کنند، اما
بیشتر خطوط
آنها
یکسان باقی
میماند.
دستور FileCheck اجازه استفاده از پیشوندهای تکراری را نمیدهد، حتی اگر یکی از آنها پیشوند بررسی و دیگری پیشوند توضیح باشد (بخش --comment-prefixes در زیر را ببینید).
- --check-prefixes prefix1,prefix2,...
- نام مستعاری برای --check-prefix که امکان مشخص کردن چندین پیشوند را بهصورت فهرستی جداشده با کاما فراهم میکند.
- --comment-prefixes prefix1,prefix2,...
- بهطور
پیشفرض، FileCheck
هرگونه
وقوع هر
پیشوند
بررسی را در
match-filename نادیده
میگیرد
اگر در همان
خط، پیش از
آن "COM:" یا
"RUN:" آمده
باشد. برای
جزئیات
نحوه
استفاده،
بخش
دستورالعمل
"COM:" را
ببینید.
در صورتی که این پیشوندهای توضیح پیشفرض برای محیط آزمون شما مناسب نباشند، میتوان آنها را با --comment-prefixes بازنویسی کرد. با این حال، انجام این کار در مجموعههای آزمون مبتنی بر LIT در LLVM توصیه نمیشود، زیرا اگر همگی از یک شیوه توضیحنویسی یکپارچه پیروی کنند نگهداری آنها آسانتر خواهد بود. در چنین حالتی، در عوض پیشنهاد تغییر پیشوندهای توضیح پیشفرض را مد نظر قرار دهید.
- --allow-unused-prefixes
- این گزینه رفتار برنامه را در هنگام استفاده از بیش از یک پیشوند (مشخصشده توسط --check-prefix یا --check-prefixes) که برخی از آنها در فایل آزمون وجود ندارند، کنترل میکند. اگر true باشد، این حالت مجاز است؛ اگر false باشد، FileCheck خطایی گزارش کرده و پیشوندهای ناموجود را فهرست میکند. مقدار پیشفرض false است.
- --input-file filename
- فایلی که باید بررسی شود (پیشفرض stdin است).
- --match-full-lines
- بهطور
پیشفرض، FileCheck
اجازه
تطبیق در هر
کجای خط را
میدهد. این
گزینه
ایجاب
میکند که
تمام
تطبیقهای
مثبت یک خط
کامل را
پوشش دهند.
فاصلههای
سفید ابتدا
و انتهای خط
نادیده
گرفته
میشوند،
مگر اینکه
--strict-whitespace نیز
مشخص شده
باشد. (توجه:
تطبیقهای
منفی حاصل
از CHECK-NOT تحت
تأثیر این
گزینه قرار
نمیگیرند!)
ارسال این گزینه معادل درج {{^ *}} یا {{^}} قبل از، و {{ *$}} یا {{$}} بعد از هر الگوی بررسی مثبت است.
- --strict-whitespace
- بهطور پیشفرض، FileCheck فاصلههای سفید افقی ورودی (فاصلهها و تبها) را استانداردسازی (canonicalize) میکند که باعث میشود تفاوتهای آنها نادیده گرفته شود (یک فاصله با یک تب تطبیق داده میشود). آرگومان --strict-whitespace این رفتار را غیرفعال میکند. توالیهای پایان خط در تمام حالتها به فرمت یونیکسی \n استانداردسازی میشوند.
- --ignore-case
- بهطور پیشفرض، FileCheck از تطبیق حساس به حروف کوچک و بزرگ استفاده میکند. این گزینه باعث میشود FileCheck از تطبیق غیرحساس به حروف کوچک و بزرگ استفاده کند.
- --implicit-check-not check-pattern
- بررسیهای
منفی ضمنی
را برای
الگوهای
مشخصشده
بین
بررسیهای
مثبت اضافه
میکند. این
گزینه
امکان
نوشتن
آزمونهای
سختگیرانهتر
را بدون
انباشتن
آنها با CHECK-NOT
فراهم
میسازد.
برای مثال، "--implicit-check-not warning:" میتواند هنگام آزمایش پیامهای تشخیصی ابزارهایی که گزینهای مشابه clang -verify ندارند، مفید باشد. با این گزینه FileCheck بررسی خواهد کرد که ورودی حاوی هشدارهایی نباشد که تحت پوشش هیچیک از الگوهای CHECK: قرار نگرفتهاند.
- --dump-input <value>
- تخلیه (dump) ورودی در stderr، به همراه یادداشتهایی که نشاندهنده تشخیصهای فعال فعلی هستند. هنگامی که این گزینه چند بار تکرار شود، مقداری از <value> که زودتر در فهرست زیر آمده است تقدم خواهد داشت. مقدار پیشفرض fail است.
- help - توضیح نحوه تخلیه ورودی و خروج
- always - تخلیه همیشگی ورودی
- fail - تخلیه ورودی فقط در صورت شکست
- never - عدم تخلیه ورودی در هر شرایطی
- --dump-input-context <N>
- در خروجی درخواستشده توسط --dump-input، تعداد <N> خط ورودی قبل و <N> خط ورودی بعد از هر خط مشخصشده توسط --dump-input-filter را چاپ میکند. هنگامی که این گزینه چند بار مشخص شده باشد، بزرگترین <N> تعیینشده اولویت دارد. مقدار پیشفرض ۵ است.
- --dump-input-filter <value>
- در خروجی درخواستشده توسط --dump-input، تنها خطوط ورودی از نوع <value> را به همراه زمینه مشخصشده توسط --dump-input-context چاپ میکند. در صورت تکرار چندباره این گزینه، مقداری از <value> که زودتر در فهرست زیر آمده است اولویت دارد. مقدار پیشفرض در صورت --dump-input=fail برابر با error، و در صورت --dump-input=always برابر با all است.
- all - تمام خطوط ورودی
- annotation-full - خطوط ورودی حاوی یادداشتها
- annotation - خطوط ورودی دارای نقطه شروع یادداشتها
- error - خطوط ورودی دارای نقطه شروع یادداشتهای خطا
- --enable-var-scope
- حوزه دید (scope)
را برای
متغیرهای
عبارت
باقاعده (regex)
فعال
میکند.
متغیرهایی که نام آنها با $ آغاز میشود، عمومی (global) تلقی شده و در سراسر فایل معتبر باقی میمانند.
تعریف تمام متغیرهای دیگر پس از برخورد با هر CHECK-LABEL لغو میشود.
- -D#<FMT>,<NUMVAR>=<NUMERIC EXPRESSION>
- یک متغیر عددی filecheck به نام NUMVAR با قالب تطبیق FMT را برابر با نتیجهٔ ارزیابی <NUMERIC EXPRESSION> قرار میدهد که میتواند در خطوط CHECK: استفاده شود. برای جزئیات در مورد عبارتهای عددی پشتیبانیشده، بخش FileCheck Numeric Variables and Expressions را ببینید.
- -version
- شماره نسخهٔ این برنامه را نمایش میدهد.
- -v
- تطبیقهای موفقیتآمیز الگوی دستورالعملها را چاپ میکند. با این حال، اگر -dump-input=fail یا -dump-input=always تنظیم شده باشد، این تطبیقها به عنوان حاشیهنویسیهای ورودی افزوده میشوند.
- -vv
- اطلاعات مفیدی را برای عیبیابی مسائل داخلی FileCheck چاپ میکند، مانند تطبیقهای همپوشان نادیدهگرفتهشدهٔ CHECK-DAG:، تطبیقهای الگوی ضمنی EOF، و الگوهای CHECK-NOT: که تطبیقی ندارند. مستلزم -v است. با این حال، اگر -dump-input=fail یا -dump-input=always تنظیم شده باشد، این اطلاعات را صرفاً به عنوان حاشیهنویسیهای ورودی اضافه میکند.
- --allow-deprecated-dag-overlap
- همپوشانی بین تطبیقها را در گروهی از دستورالعملهای متوالی CHECK-DAG: فعال میکند. این گزینه منسوخ شده است و صرفاً برای راحتی در حین انتقال آزمونهای قدیمی به پیادهسازی جدید غیرهمپوشان CHECK-DAG: ارائه شده است.
- --allow-empty
- بررسی ورودی خالی را مجاز میداند. بهطور پیشفرض، ورودی خالی رد میشود.
- --color
- استفاده از رنگها در خروجی (بهطور پیشفرض خودکار شناسایی میشود).
وضعیت خروج (EXIT STATUS)
اگر FileCheck تأیید کند که فایل با محتوای مورد انتظار مطابقت دارد، با وضعیت 0 خارج میشود. در غیر این صورت، یا در صورت وقوع یک خطا، با یک مقدار غیرصفر خارج خواهد شد.
آموزش (TUTORIAL)
ابزار FileCheck معمولاً در آزمونهای رگرسیون LLVM استفاده میشود و در خط RUN آزمون فراخوانی میگردد. یک مثال ساده از استفاده از FileCheck در یک خط RUN به این صورت است:
; RUN: llvm-as < %s | llc -march=x86-64 | FileCheck %s
این نحو بیان میکند که فایل جاری ("%s") به llvm-as هدایت (pipe) شود، آن به llc منتقل گردد، و سپس خروجی llc به FileCheck ارسال شود. این بدین معناست که FileCheck ورودی استاندارد خود (خروجی llc) را در برابر نام فایل مشخصشده به عنوان آرگومان (فایل اصلی .ll که با "%s" مشخص شده) بررسی خواهد کرد. برای درک نحوهٔ کارکرد آن، نگاهی به بقیهٔ فایل .ll (بعد از خط RUN) میاندازیم:
define void @sub1(i32* %p, i32 %v) {
entry:
; CHECK: sub1:
; CHECK: subl
%0 = tail call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %p, i32 %v)
ret void
}
define void @inc4(i64* %p) {
entry:
; CHECK: inc4:
; CHECK: incq
%0 = tail call i64 @llvm.atomic.load.add.i64.p0i64(i64* %p, i64 1)
ret void
}
در اینجا میتوانید خطوط "CHECK:" مشخصشده در کامنتها را مشاهده کنید. اکنون میبینید که چگونه فایل به llvm-as و سپس به llc هدایت میشود، و خروجی کد ماشین چیزی است که در حال بررسی آن هستیم. ابزار FileCheck خروجی کد ماشین را بررسی میکند تا مطمئن شود با آنچه خطوط "CHECK:" مشخص کردهاند، مطابقت دارد.
نحو خطوط "CHECK:" بسیار ساده است: آنها رشتههای ثابتی هستند که باید به ترتیب رخ دهند. FileCheck بهطور پیشفرض تفاوتهای فاصلههای خالی افقی را نادیده میگیرد (برای مثال یک فاصله میتواند با یک تب مطابقت داشته باشد) اما در غیر این صورت، محتوای خط "CHECK:" باید دقیقاً با چیزی در فایل آزمون مطابقت داشته باشد.
یک ویژگی خوب FileCheck (در مقایسه با grep) این است که امکان ادغام موارد آزمون را در گروههای منطقی فراهم میکند. به عنوان مثال، از آنجا که آزمون بالا برچسبهای "sub1:" و "inc4:" را بررسی میکند، تنها زمانی تطبیق مییابد که یک "subl" در بین این برچسبها وجود داشته باشد. اگر در جای دیگری از فایل وجود داشت، به حساب نمیآمد؛ در حالی که "grep subl" اگر "subl" در هر کجای فایل وجود داشته باشد مطابقت پیدا میکند.
گزینهٔ -check-prefix در FileCheck
گزینهٔ -check-prefix در FileCheck اجازه میدهد چندین پیکربندی آزمون از یک فایل .ll اجرا شوند. این در بسیاری از شرایط مفید است، برای مثال، آزمایش انواع معماریهای مختلف با llc. در اینجا یک مثال ساده آورده شده است:
; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
; RUN: | FileCheck %s -check-prefix=X32
; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 -mattr=sse41 \
; RUN: | FileCheck %s -check-prefix=X64
define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
%tmp1 = insertelement <4 x i32>; %tmp, i32 %s, i32 1
ret <4 x i32> %tmp1
; X32: pinsrd_1:
; X32: pinsrd $1, 4(%esp), %xmm0
; X64: pinsrd_1:
; X64: pinsrd $1, %edi, %xmm0
}
در این حالت، ما در حال آزمایش این هستیم که در هر دو تولید کد ۳۲ بیتی و ۶۴ بیتی، تولید کد مورد انتظار را به دست آوریم..SS دستورالعمل "COM:"
گاهی اوقات میخواهید بدون حذف کامل یک دستورالعمل FileCheck، آن را غیرفعال کنید یا میخواهید یادداشتهایی بنویسید که نام یک دستورالعمل در آنها ذکر شده است. دستورالعمل "COM:" انجام این کار را آسان میکند. برای مثال، ممکن است کدی مانند این داشته باشید:
; X32: pinsrd_1: ; X32: pinsrd $1, 4(%esp), %xmm0 ; COM: FIXME: X64 isn't working correctly yet for this part of codegen, but ; COM: X64 will have something similar to X32: ; COM: ; COM: X64: pinsrd_1: ; COM: X64: pinsrd $1, %edi, %xmm0
بدون "COM:"، لازم بود ترکیبی از تغییر عبارت و دستکاری نگارشی دستورالعمل را به کار ببرید تا از تشخیص موارد یادداشتشدهی "X32:" و "X64:" بالا به عنوان دستورالعمل توسط FileCheck جلوگیری کنید. علاوه بر این، پیامهای خطایابی FileCheck به گونهای پیشنهاد شدهاند که ممکن است به موارد بالا از "X64" که بدون دونقطه پایانی ":" هستند، به دلیل شباهت به غلط املایی در دستورالعمل اعتراض کنند. دور زدن همهی این مشکلات برای نویسنده آزمون میتواند خستهکننده باشد و دستکاری نگارشی دستورالعملها نیز میتواند هدف کد آزمون را نامشخص سازد. "COM:" از بروز تمام این مشکلات جلوگیری میکند.
چند نکته مهم درباره استفاده:
- •
- قرار گرفتن "COM:" درون الگوی یک دستورالعمل دیگر، ادامه الگو را تبدیل به یادداشت نمیکند. برای مثال:
; X32: pinsrd $1, 4(%esp), %xmm0 COM: This is part of the X32 pattern!
اگر نیاز دارید بخشی از الگوی یک دستورالعمل را موقتاً به یادداشت تبدیل کنید، آن را به خط دیگری منتقل کنید. دلیل این است که FileCheck دستورالعمل "COM:" را دقیقاً مشابه هر دستورالعمل دیگری تجزیه میکند: فقط اولین دستورالعمل موجود در خط به عنوان یک دستورالعمل شناخته میشود.
- به خاطر LIT، ابزار FileCheck با "RUN:" دقیقاً مانند "COM:" رفتار میکند. اگر این رفتار برای محیط آزمون شما مناسب نیست، --comment-prefixes را ببینید.
- ابزار FileCheck اگر "COM"، "RUN" یا هر پیشوند یادداشت تعریفشده توسط کاربر با یکی از پسوندهای معمول دستورالعمل بررسی، مانند "-NEXT:" یا "-NOT:" (که در ادامه شرح داده شدهاند) ترکیب شده باشد، آن را به عنوان یک دستورالعمل یادداشت تشخیص نمیدهد. در عوض FileCheck با چنین ترکیبی به عنوان متن ساده رفتار میکند. اگر لازم است برای محیط آزمون شما به عنوان دستورالعمل یادداشت عمل کند، آن را با استفاده از --comment-prefixes به عنوان چنین پیشوندی تعریف کنید.
دستورالعمل "CHECK-NEXT:"
گاهی اوقات میخواهید خطوط را تطبیق دهید و مایلید تأیید کنید که تطابقها دقیقاً در خطوط متوالی و بدون هیچ خط دیگری در میان آنها رخ میدهند. در این حالت، میتوانید از دستورالعملهای "CHECK:" و "CHECK-NEXT:" برای مشخص کردن این موضوع استفاده کنید. اگر یک پیشوند بررسی سفارشی تعیین کردهاید، کافی است از "<PREFIX>-NEXT:" استفاده کنید. برای مثال، موردی مانند این همانطور که انتظار دارید کار میکند:
define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) {
%tmp3 = load <2 x double>* %A, align 16
%tmp7 = insertelement <2 x double> undef, double %B, i32 0
%tmp9 = shufflevector <2 x double> %tmp3,
<2 x double> %tmp7,
<2 x i32> < i32 0, i32 2 >
store <2 x double> %tmp9, <2 x double>* %r, align 16
ret void
; CHECK: t2:
; CHECK: movl 8(%esp), %eax
; CHECK-NEXT: movapd (%eax), %xmm0
; CHECK-NEXT: movhpd 12(%esp), %xmm0
; CHECK-NEXT: movl 4(%esp), %eax
; CHECK-NEXT: movapd %xmm0, (%eax)
; CHECK-NEXT: ret
}
دستورالعملهای "CHECK-NEXT:" ورودی را رد میکنند مگر اینکه دقیقاً یک خط جدید بین آن و دستورالعمل قبلی وجود داشته باشد. یک "CHECK-NEXT:" نمیتواند اولین دستورالعمل در یک فایل باشد.
دستورالعمل "CHECK-SAME:"
گاهی اوقات میخواهید خطوط را تطبیق دهید و مایلید تأیید کنید که تطابقها در همان خط تطابق قبلی رخ میدهند. در این حالت، میتوانید از دستورالعملهای "CHECK:" و "CHECK-SAME:" برای مشخص کردن این موضوع استفاده کنید. اگر یک پیشوند بررسی سفارشی تعیین کردهاید، کافی است از "<PREFIX>-SAME:" استفاده کنید.
دستورالعمل "CHECK-SAME:" بهویژه در ترکیب با "CHECK-NOT:" (توضیح داده شده در زیر) بسیار قدرتمند است.
برای مثال، مورد زیر طبق انتظار عمل میکند:
!0 = !DILocation(line: 5, scope: !1, inlinedAt: !2) ; CHECK: !DILocation(line: 5, ; CHECK-NOT: column: ; CHECK-SAME: scope: ![[SCOPE:[0-9]+]]
دستورالعملهای "CHECK-SAME:" در صورتی که هرگونه خط جدیدی بین آن و دستورالعمل قبلی وجود داشته باشد، ورودی را رد میکنند.
دستورالعمل "CHECK-SAME:" همچنین برای اجتناب از نوشتن تطبیقدهندهها برای فیلدهای نامربوط کاربرد دارد. برای مثال، فرض کنید در حال نوشتن آزمونی هستید که ابزاری با خروجیای مانند این را تجزیه میکند:
Name: foo Field1: ... Field2: ... Field3: ... Value: 1 Name: bar Field1: ... Field2: ... Field3: ... Value: 2 Name: baz Field1: ... Field2: ... Field3: ... Value: 1
برای نوشتن آزمونی که تأیید کند foo مقدار 1 دارد، ممکن است ابتدا این را بنویسید:
CHECK: Name: foo
CHECK: Value: 1{{$}}
با این حال، این یک آزمون نامناسب خواهد بود: اگر مقدار مربوط به foo تغییر کند، آزمون همچنان موفق خواهد شد زیرا خط "CHECK: Value: 1" با مقدار مربوط به baz تطابق پیدا میکند. برای رفع این مشکل، میتوانید تطبیقدهندههای CHECK-NEXT را برای هر خط FieldN: اضافه کنید، اما این کار طولانی و پرگو خواهد بود و با اضافه شدن Field4 نیازمند بهروزرسانی است. روشی خلاصهتر برای نوشتن آزمون با استفاده از تطبیقدهنده "CHECK-SAME:" به شکل زیر خواهد بود:
CHECK: Name: foo
CHECK: Value:
CHECK-SAME: {{ 1$}}
این بررسی تأیید میکند که بار بعدی که عبارت "Value:" در خروجی ظاهر میشود، دارای مقدار 1 باشد.
نکته: یک "CHECK-SAME:" نمیتواند اولین دستورالعمل در یک فایل باشد..SS دستورالعمل "CHECK-EMPTY:"
اگر نیاز دارید بررسی کنید که خط بعدی کاملاً خالی است و حتی نویسه فاصله خالی (whitespace) نیز در آن وجود ندارد، میتوانید از دستورالعمل "CHECK-EMPTY:" استفاده کنید.
declare void @foo() declare void @bar() ; CHECK: foo ; CHECK-EMPTY: ; CHECK-NEXT: bar
درست مانند "CHECK-NEXT:"، این دستورالعمل نیز در صورتی که قبل از یافتن خط خالی بعدی بیش از یک خط جدید وجود داشته باشد شکست خواهد خورد، و نمیتواند اولین دستورالعمل درون یک فایل باشد.
دستورالعمل "CHECK-NOT:"
دستورالعمل "CHECK-NOT:" برای اطمینان از عدم وقوع یک رشته بین دو تطابق (یا پیش از نخستین تطابق، یا پس از آخرین تطابق) به کار میرود. برای مثال، جهت بررسی اینکه آیا یک بارگذاری (load) توسط یک تبدیل حذف شده است یا خیر، میتوان از آزمونی مانند این استفاده کرد:
define i8 @coerce_offset0(i32 %V, i32* %P) {
store i32 %V, i32* %P
%P2 = bitcast i32* %P to i8*
%P3 = getelementptr i8* %P2, i32 2
%A = load i8* %P3
ret i8 %A
; CHECK: @coerce_offset0
; CHECK-NOT: load
; CHECK: ret i8
}
دستورالعمل "CHECK-COUNT:"
اگر نیاز دارید چندین خط را بارها و بارها با یک الگوی یکسان مطابقت دهید، میتوانید یک CHECK: ساده را به تعداد دفعات مورد نیاز تکرار کنید. اگر این کار بیش از حد خستهکننده به نظر میرسد، میتوانید در عوض از یک بررسی شمارششده "CHECK-COUNT-<num>:" استفاده کنید، که در آن <num> یک عدد دهدهی مثبت است. این دستورالعمل الگو را دقیقاً <num> بار مطابقت میدهد، نه بیشتر و نه کمتر. اگر یک پیشوند بررسی سفارشی تعیین کردهاید، کافی است برای رسیدن به همان اثر از "<PREFIX>-COUNT-<num>:" استفاده کنید. در اینجا یک مثال ساده آورده شده است:
Loop at depth 1
Loop at depth 1
Loop at depth 1
Loop at depth 1
Loop at depth 2
Loop at depth 3
; CHECK-COUNT-6: Loop at depth {{[0-9]+}}
; CHECK-NOT: Loop at depth {{[0-9]+}}
دستورالعمل "CHECK-DAG:"
اگر تطبیق رشتههایی که در ترتیبی اکیداً متوالی رخ نمیدهند ضروری باشد، میتوان از "CHECK-DAG:" برای بررسی آنها بین دو تطابق (یا پیش از نخستین تطابق، یا پس از آخرین تطابق) استفاده کرد. برای نمونه، clang متغیرهای سراسری vtable را به ترتیب معکوس منتشر میکند. با استفاده از CHECK-DAG:، میتوانیم بررسیها را در ترتیب طبیعی نگه داریم:
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
struct Foo { virtual void method(); };
Foo f; // emit vtable
// CHECK-DAG: @_ZTV3Foo =
struct Bar { virtual void method(); };
Bar b;
// CHECK-DAG: @_ZTV3Bar =
دستورالعملهای CHECK-NOT: میتوانند با دستورالعملهای CHECK-DAG: ترکیب شوند تا رشتههای میان دستورالعملهای پیرامونی CHECK-DAG: را مستثنی سازند. در نتیجه، دستورالعملهای پیرامونی CHECK-DAG: نمیتوانند بازترتیب شوند؛ یعنی تمامی رخدادهای منطبق با CHECK-DAG: قبل از CHECK-NOT: نباید پس از رخدادهای منطبق با CHECK-DAG: بعد از CHECK-NOT: قرار گیرند. به عنوان مثال،
; CHECK-DAG: BEFORE ; CHECK-NOT: NOT ; CHECK-DAG: AFTER
این حالت، رشتههای ورودیای را که در آنها BEFORE بعد از AFTER رخ دهد، رد خواهد کرد.
با متغیرهای ثبتشده، CHECK-DAG: قادر است ترتیبهای توپولوژیکی معتبر یک DAG را با یالهایی از تعریف یک متغیر تا استفاده از آن تطبیق دهد. این قابلیت برای مثال هنگامی مفید است که نمونه آزمونهای شما باید با دنبالههای خروجی متفاوتی از زمانبند دستورالعملها (instruction scheduler) مطابقت داشته باشند. برای نمونه،
; CHECK-DAG: add [[REG1:r[0-9]+]], r1, r2 ; CHECK-DAG: add [[REG2:r[0-9]+]], r3, r4 ; CHECK: mul r5, [[REG1]], [[REG2]]
در این حالت، هر ترتیبی از آن دو دستورالعمل add مجاز خواهد بود.
اگر متغیرها را در یک بلوک CHECK-DAG: هم تعریف و هم استفاده میکنید، توجه داشته باشید که قاعده تعریف میتواند پس از استفاده از آن تطبیق یابد.
بنابراین، برای مثال، کد زیر موفق خواهد شد:
; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] ; CHECK-DAG: vmov.32 [[REG2]][1] vmov.32 d0[1] vmov.32 d0[0]
در حالی که این کد دیگر، موفق نخواهد شد:
; CHECK-DAG: vmov.32 [[REG2:d[0-9]+]][0] ; CHECK-DAG: vmov.32 [[REG2]][1] vmov.32 d1[1] vmov.32 d0[0]
هرچند این قابلیت میتواند بسیار سودمند باشد، اما خطرناک نیز هست؛ زیرا در خصوص توالی ثباتها، شما باید ترتیبی اکید داشته باشید (خواندن قبل از نوشتن، رونوشت قبل از استفاده و غیره). اگر تعریفی که آزمون شما به دنبال آن است مطابقت پیدا نکند (به دلیل وجود باگ در کامپایلر)، ممکن است در جایی بسیار دورتر از محل استفاده تطبیق یابد و باگهای واقعی را پنهان کند.
در این موارد، برای تحمیل ترتیب، از یک دستورالعمل غیر DAG بین بلوکهای DAG استفاده کنید.
یک دستورالعمل CHECK-DAG: از تطابقهایی که با تطابقهای هر یک از دستورالعملهای پیشین CHECK-DAG: در همان بلوک CHECK-DAG: همپوشانی داشته باشند صرفنظر میکند. این رفتار عدم همپوشانی نه تنها با سایر دستورالعملها سازگار است، بلکه برای مدیریت مجموعههایی از رشتهها یا الگوهای غیریکتا نیز ضروری است. به عنوان مثال، دستورالعملهای زیر به دنبال ورودیهای لاگ بدون ترتیب برای دو وظیفه در یک برنامه موازی، مانند محیط زمان اجرای OpenMP هستند:
// CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin // CHECK-DAG: [[THREAD_ID]]: task_end // // CHECK-DAG: [[THREAD_ID:[0-9]+]]: task_begin // CHECK-DAG: [[THREAD_ID]]: task_end
تضمین میشود که جفت دوم دستورالعملها با همان ورودیهای لاگ منطبق با جفت اول مطابقت پیدا نکنند، حتی با اینکه الگوها یکسان هستند و حتی اگر متن ورودیهای لاگ به دلیل استفاده مجدد از شناسه thread کاملاً یکسان باشد..SS دستورالعمل "CHECK-LABEL:"
گاهی در فایلی که شامل چندین آزمون تقسیمشده به بلوکهای منطقی است، یک یا چند دستورالعمل CHECK: ممکن است بهطور ناخواسته با تطبیق خطوط در یک بلوک بعدی با موفقیت انجام شوند. در حالی که معمولاً در نهایت خطایی ایجاد خواهد شد، بررسی نشانهگذاریشده بهعنوان عامل خطا ممکن است در عمل هیچ ارتباطی با منبع واقعی مشکل نداشته باشد.
برای ایجاد پیامهای خطای بهتر در این موارد، میتوان از دستورالعمل "CHECK-LABEL:" استفاده کرد. با این دستورالعمل دقیقاً مانند یک دستورالعمل معمولی CHECK رفتار میشود، با این تفاوت که FileCheck این فرض اضافی را در نظر میگیرد که خط تطبیقیافته توسط این دستورالعمل نمیتواند با هیچ بررسی دیگری موجود در match-filename نیز تطبیق یابد؛ این قابلیت برای خطوط حاوی برچسبها یا سایر شناسههای منحصربهفرد در نظر گرفته شده است. از نظر مفهومی، وجود CHECK-LABEL جریان ورودی را به بلوکهای مجزایی تقسیم میکند که هر کدام بهطور مستقل پردازش میشوند و از تطبیق یک دستورالعمل CHECK: در یک بلوک با خطی در بلوک دیگر جلوگیری مینماید. اگر --enable-var-scope فعال باشد، تمام متغیرهای محلی در ابتدای بلوک پاک میشوند.
به عنوان مثال،
define %struct.C* @C_ctor_base(%struct.C* %this, i32 %x) {
entry:
; CHECK-LABEL: C_ctor_base:
; CHECK: mov [[SAVETHIS:r[0-9]+]], r0
; CHECK: bl A_ctor_base
; CHECK: mov r0, [[SAVETHIS]]
%0 = bitcast %struct.C* %this to %struct.A*
%call = tail call %struct.A* @A_ctor_base(%struct.A* %0)
%1 = bitcast %struct.C* %this to %struct.B*
%call2 = tail call %struct.B* @B_ctor_base(%struct.B* %1, i32 %x)
ret %struct.C* %this
}
define %struct.D* @D_ctor_base(%struct.D* %this, i32 %x) {
entry:
; CHECK-LABEL: D_ctor_base:
استفاده از دستورالعملهای CHECK-LABEL: در این حالت تضمین میکند که سه دستورالعمل CHECK: تنها خطوط مربوط به بدنهٔ تابع @C_ctor_base را میپذیرند، حتی اگر الگوها با خطوطی که بعداً در فایل یافت میشوند مطابقت داشته باشند. علاوه بر این، اگر یکی از این سه دستورالعمل CHECK: ناموفق باشد، FileCheck با رفتن به بلوک بعدی بازیابی میشود و این امکان را میدهد که چندین شکست آزمون در یک بار اجرا شناسایی شوند.
هیچ الزامی وجود ندارد که دستورالعملهای CHECK-LABEL: حاوی رشتههایی باشند که با برچسبهای نحوی واقعی در یک زبان مبدأ یا خروجی مطابقت دارند: آنها تنها باید بهطور منحصربهفرد با یک خط منفرد در فایلِ در حال اعتبارسنجی تطبیق یابند.
دستورالعملهای CHECK-LABEL: نمیتوانند حاوی تعریف یا استفاده از متغیرها باشند.
اصلاحکنندههای دستورالعمل
یک اصلاحکنندهٔ دستورالعمل را میتوان با قرار دادن {<modifier>} به دنبال دستورالعمل اضافه کرد، که در آن تنها مقدار پشتیبانیشده برای <modifier> مقدار LITERAL است.
اصلاحکنندهٔ دستورالعمل LITERAL میتواند برای انجام یک تطبیق تحتاللفظی (literal) استفاده شود. این اصلاحکننده باعث میشود دستورالعمل هیچ نحوی را برای انجام تطبیق با عبارت باقاعده (regex)، ضبط متغیر یا هرگونه جایگزینی تشخیص ندهد. این قابلیت زمانی مفید است که در غیر این صورت، متن مورد نظر برای تطبیق نیازمند کاراکترهای گریز (escaping) بیش از حد باشد. برای مثال، موارد زیر به جای در نظر گرفتن عبارات به عنوان عبارات باقاعده، تطبیقهای تحتاللفظی انجام میدهند:
Input: [[[10, 20]], [[30, 40]]]
Output %r10: [[10, 20]]
Output %r10: [[30, 40]]
; CHECK{LITERAL}: [[[10, 20]], [[30, 40]]]
; CHECK-DAG{LITERAL}: [[30, 40]]
; CHECK-DAG{LITERAL}: [[10, 20]]
نحو تطبیق عبارت باقاعده در FileCheck
تمام دستورالعملهای FileCheck الگویی را برای تطبیق میپذیرند. برای بیشتر استفادههای FileCheck، تطبیق رشتهٔ ثابت کاملاً کافی است. برای برخی موارد، شکل انعطافپذیرتری از تطبیق مورد نظر است. برای پشتیبانی از این موضوع، FileCheck به شما امکان میدهد عبارات باقاعده را در رشتههای تطبیق مشخص کنید، که توسط دو جفتآکولاد محصور میشوند: {{yourregex}}. برنامه FileCheck یک تطبیقدهندهٔ عبارت باقاعده POSIX را پیادهسازی میکند؛ این برنامه از عبارات باقاعده توسعهیافته POSIX (ERE) پشتیبانی مینماید. از آنجا که میخواهیم برای بیشتر کارهایمان از تطبیق رشتهٔ ثابت استفاده کنیم، FileCheck طوری طراحی شده است که از ترکیب و انطباقِ تطبیق رشتهٔ ثابت با عبارات باقاعده پشتیبانی کند. این ویژگی به شما اجازه میدهد مواردی مانند این را بنویسید:
; CHECK: movhpd {{[0-9]+}}(%esp), {{%xmm[0-7]}}
در این حالت، هر آفستی از ثبات ESP مجاز خواهد بود و هر ثبات xmm نیز پذیرفته میشود.
از آنجا که عبارات باقاعده درون دو جفتآکولاد قرار میگیرند، از نظر بصری متمایز هستند و نیازی نیست مانند زبان C از کاراکترهای گریز درون دو آکولاد استفاده کنید. در موارد نادری که میخواهید دو آکولاد را صریحاً از ورودی مطابقت دهید، میتوانید از چیزی مانند {{[}][}]}} به عنوان الگوی خود استفاده کنید. یا اگر از نحو شمارش تکرار استفاده میکنید، برای مثال [[:xdigit:]]{8} برای تطبیق دقیقاً ۸ رقم هگزادسیمال، لازم است پرانتزهایی مانند این اضافه کنید: {{([[:xdigit:]]{8})}} تا از تداخل با آکولاد پایانی FileCheck جلوگیری شود.
بلوکهای جایگزینی رشته در FileCheck
اغلب مفید است که یک الگو مطابقت داده شود و سپس بررسی شود که آیا دوباره بعداً در فایل تکرار میشود یا خیر. برای آزمونهای تولید کد (codegen)، این کار میتواند برای مجاز دانستن هر ثباتی و سپس اطمینان از استفادهٔ یکپارچه از همان ثبات در ادامه مفید باشد. برای انجام این کار، FileCheck از بلوکهای جایگزینی رشته پشتیبانی میکند که امکان تعریف متغیرهای رشتهای و جایگزینی آنها در الگوها را فراهم میسازد. در اینجا یک مثال ساده آورده شده است:
; CHECK: test5:
; CHECK: notw [[REGISTER:%[a-z]+]]
; CHECK: andw {{.*}}[[REGISTER]]
خط بررسی اول با عبارت باقاعدهٔ %[a-z]+ مطابقت پیدا میکند و آن را در متغیر رشتهای REGISTER ضبط مینماید. خط دوم بررسی میکند که هر مقداری که در REGISTER قرار دارد، بعداً در فایل پس از یک "andw" ظاهر شود. بلوکهای جایگزینی رشتهٔ FileCheck همیشه در جفتهای [[ ]] قرار میگیرند، و نام متغیرهای رشتهای میتوانند با عبارت باقاعدهٔ \$[a-zA-Z_][a-zA-Z0-9_]* تشکیل شوند. اگر بعد از نام دو نقطه بیاید، این یک تعریف متغیر است؛ در غیر این صورت، یک جایگزینی به حساب میآید.
متغیرهای FileCheck میتوانند چندین بار تعریف شوند و جایگزینیها همیشه آخرین مقدار را دریافت میکنند. همچنین متغیرها میتوانند بعداً در همان خطی که تعریف شدهاند جایگزین شوند. به عنوان مثال:
; CHECK: op [[REG:r[0-9]+]], [[REG]]
این ساختار میتواند زمانی مفید باشد که بخواهید عملوندهای op ثباتی یکسان باشند، و اهمیتی ندهید که دقیقاً کدام ثبات است.
اگر --enable-var-scope اعمال شده باشد، متغیرهایی که نام آنها با $ شروع میشود، متغیر سراسری (global) در نظر گرفته میشوند. تمام متغیرهای دیگر محلی (local) هستند. تمام متغیرهای محلی در ابتدای هر بلوک CHECK-LABEL نامعین (undefined) میشوند. متغیرهای سراسری تحت تأثیر CHECK-LABEL قرار نمیگیرند. این امر اطمینان حاصل کردن از اینکه آزمونهای مجزا تحت تأثیر متغیرهای تنظیمشده در آزمونهای قبلی قرار نگیرند را سادهتر میسازد..SS بلوکهای جایگزینی عددی FileCheck
ابزار FileCheck همچنین از بلوکهای جایگزینی عددی پشتیبانی میکند که امکان تعریف متغیرهای عددی و تطبیق با مقادیر عددی که قید یک عبارت عددی را بر پایه آن متغیرها ارضا میکنند، از طریق یک جایگزینی عددی فراهم میسازد. این امر به دستورالعملهای CHECK: اجازه میدهد تا یک رابطه عددی میان دو عدد را راستیآزمایی کنند، مانند نیاز به استفاده از ثباتهای متوالی.
نحو ثبت و دریافت یک مقدار عددی به صورت [[#%<fmtspec>,<NUMVAR>:]] است که در آن:
- %<fmtspec>, یک مشخصکننده اختیاری قالب است که قالب عددی برای تطبیق و حداقل تعداد ارقام مورد انتظار را تعیین میکند.
- <NUMVAR>: تعریفی اختیاری برای متغیر <NUMVAR> از روی مقدار ثبتشده است.
نحو <fmtspec> به صورت #.<precision><conversion specifier> است که در آن:
- # پرچمی اختیاری برای مقادیر هگزادسیمال (hex) است (بخش <conversion specifier> در ادامه را ببینید) که نیازمند پیشوند 0x برای مقدار تطبیقیافته است.
- .<precision> یک مشخصکننده دقت اختیاری به سبک printf است که در آن <precision> حداقل تعداد ارقامی را که مقدار تطبیقیافته باید داشته باشد نشان میدهد، و در صورت لزوم صفرهای ابتدایی را انتظار دارد.
- <conversion specifier> یک مشخصکننده تبدیل اختیاری به سبک scanf است تا مشخص کند چه قالبی از عدد باید تطبیق داده شود (مانند یک عدد هگز). در حال حاضر مشخصکنندههای قالب پذیرفتهشده %u، %d، %x و %X هستند. در صورت عدم ذکر، مشخصکننده قالب به طور پیشفرض %u خواهد بود.
به عنوان مثال:
; CHECK: mov r[[#REG:]], 0x[[#%.8X,ADDR:]]
با mov r5, 0x0000FEFE تطبیق مییابد و مقدار REG را برابر 5 و ADDR را برابر 0xFEFE قرار میدهد. توجه داشته باشید که به علت مشخصکننده دقت، این الگو با mov r5, 0xFEFE مطابقت نخواهد داشت.
به عنوان نتیجهای از اختیاری بودن تعریف متغیر عددی، این امکان وجود دارد که صرفاً حضور یک مقدار عددی در یک قالب معین بررسی شود. این ویژگی زمانی که خود مقدار اهمیتی ندارد میتواند مفید باشد، برای مثال:
; CHECK-NOT: mov r0, r[[#]]
برای بررسی اینکه یک مقدار به جای انتقال یافتن، ساخته (تولید) شده است.
نحو یک جایگزینی عددی به صورت [[#%<fmtspec>, <constraint> <expr>]] است که در آن:
- <fmtspec> همان مشخصکننده قالب مورد استفاده برای تعریف متغیر است، اما در این زمینه نشان میدهد که مقدار عبارت عددی چگونه باید تطبیق داده شود. در صورت عدم ذکر، هر دو مؤلفه مشخصکننده قالب از قالب تطبیق متغیر(های) عددی استفادهشده در قید عبارت (در صورت وجود) استنتاج میشوند، و در صورت عدم استفاده از متغیرهای عددی به طور پیشفرض %u در نظر گرفته میشود که نشاندهنده بدون علامت بودن مقدار و بدون صفرهای ابتدایی است. در صورت بروز تعارض میان مشخصکنندههای قالب چند متغیر عددی، مشخصکننده تبدیل اجباری میشود اما مشخصکننده دقت اختیاری باقی میماند.
- <constraint> قیدی است که نحوه ارتباط مقدار مورد تطبیق با مقدار عبارت عددی را بیان میکند. تنها قید پذیرفتهشده کنونی == برای تطبیق دقیق است که در صورت مشخص نشدن <constraint> پیشفرض خواهد بود. در صورتی که <expr> خالی باشد، نباید هیچ قید تطبیقی مشخص شود.
- <expr> یک عبارت است. یک عبارت نیز به نوبه خود به صورت بازگشتی به این شکل تعریف میشود:
- یک عملوند عددی، یا
- یک عبارت به همراه یک عملگر و یک عملوند عددی پس از آن.
یک عملوند عددی میتواند یک متغیر عددی از پیش تعریفشده، یک لیترال عدد صحیح یا یک تابع باشد. فاصلهها قبل، بعد و میان هر یک از این عناصر پذیرفته میشوند. عملوندهای عددی دارای دقت ۶۴ بیتی هستند. سرریز و زیرریز رد میشوند. هیچ اولویتی برای عملگرها وجود ندارد، اما برای تغییر ترتیب ارزیابی میتوان از پرانتزها استفاده کرد.
عملگرهای پشتیبانیشده عبارتند از:
- + - حاصل جمع دو عملوند خود را برمیگرداند.
- - - تفاضل دو عملوند خود را برمیگرداند.
نحو فراخوانی تابع به صورت <name>(<arguments>) است که در آن:
- •
- name یک رشته لیترال از پیش تعریفشده است. مقادیر مجاز عبارتند از:
- add - حاصل جمع دو عملوند خود را برمیگرداند.
- div - خارجقسمت تقسیم دو عملوند خود را برمیگرداند.
- max - بزرگترین مقدار از میان دو عملوند خود را برمیگرداند.
- min - کوچکترین مقدار از میان دو عملوند خود را برمیگرداند.
- mul - حاصلضرب دو عملوند خود را برمیگرداند.
- sub - تفاضل دو عملوند خود را برمیگرداند.
- •
- <arguments> فهرستی از عبارتهاست که با کاما از هم جدا شدهاند.
به عنوان مثال:
; CHECK: load r[[#REG:]], [r0] ; CHECK: load r[[#REG+1]], [r1] ; CHECK: Loading from 0x[[#%x,ADDR:]] ; CHECK-SAME: to 0x[[#ADDR + 7]]
مثال بالا با متن زیر مطابقت دارد:
load r5, [r0] load r6, [r1] Loading from 0xa0463440 to 0xa0463447
اما با این متن مطابقت نخواهد داشت:
load r5, [r0] load r7, [r1] Loading from 0xa0463440 to 0xa0463443
به این دلیل که مقدار 7 با 5 + 1 برابر نیست و مقدار a0463443 نیز با a0463440 + 7 برابری نمیکند.
یک متغیر عددی همچنین میتواند با نتیجه یک عبارت عددی مقداردهی شود، که در این حالت قید عبارت عددی بررسی شده و در صورت تأیید، مقدار به متغیر تخصیص مییابد. بنابراین نحو یکپارچه برای بررسی یک عبارت عددی و ثبت مقدار آن در یک متغیر عددی به صورت [[#%<fmtspec>,<NUMVAR>: <constraint> <expr>]] با اجزایی همانگونه که قبلاً شرح داده شد خواهد بود. میتوان با استفاده از متغیرها به جای مقادیر، این نحو را برای خودتوصیفتر کردن یک مورد آزمون (testcase) به کار برد:
; CHECK: mov r[[#REG_OFFSET:]], 0x[[#%X,FIELD_OFFSET:12]] ; CHECK-NEXT: load r[[#]], [r[[#REG_BASE:]], r[[#REG_OFFSET]]]
که با این متن تطبیق پیدا میکند:
mov r4, 0xC load r6, [r5, r4]
گزینه --enable-var-scope همان تأثیری را بر متغیرهای عددی دارد که بر روی متغیرهای رشتهای میگذارد.
نکته مهم: در پیادهسازی کنونی، یک عبارت نمیتواند از متغیر عددی که پیشتر در همان دستورالعمل CHECK تعریف شده است استفاده کند..SS متغیرهای شبهعددی FileCheck
گاهی نیاز است خروجیای که شامل شماره خطوط فایل تطابق است بررسی و تأیید شود؛ برای نمونه هنگام آزمایش پیامهای تشخیصی کامپایلر (compiler diagnostics). این امر نوعی شکنندگی در ساختار فایل تطابق ایجاد میکند، چرا که خطوط "CHECK:" حاوی شماره خطوط مطلق در همان فایل هستند که باید با هر بار تغییر شماره خطوط در پی افزودن یا حذف متن، بهروزرسانی شوند.
برای پشتیبانی از این حالت، عبارات FileCheck متغیر شبهعددی @LINE را درک میکنند که به شماره خطِ الگوی CHECK که در آن قرار دارد ارزیابی میشود.
بدین ترتیب، الگوهای تطابق میتوانند در نزدیکی خطوط آزمون مربوطه قرار گیرند و شامل ارجاعات نسبی به شماره خطوط باشند؛ برای مثال:
// CHECK: test.cpp:[[# @LINE + 4]]:6: error: expected ';' after top level declarator
// CHECK-NEXT: {{^int a}}
// CHECK-NEXT: {{^ \^}}
// CHECK-NEXT: {{^ ;}}
int a
برای پشتیبانی از کاربردهای قدیمی @LINE به عنوان یک متغیر رشتهای ویژه، FileCheck همچنین استفادههای زیر از @LINE را با نحو بلوک جایگزینی رشته میپذیرد: [[@LINE]]، [[@LINE+<offset>]] و [[@LINE-<offset>]] بدون هیچ فاصلهای درون براکتها، جایی که offset یک عدد صحیح است.
تطبیق نویسههای خط جدید
برای تطبیق نویسههای خط جدید در عبارتهای منظم، میتوان از ردهٔ نویسهای [[:space:]] استفاده کرد. برای نمونه، الگوی زیر:
// CHECK: DW_AT_location [DW_FORM_sec_offset] ([[DLOC:0x[0-9a-f]+]]){{[[:space:]].*}}"intd"
با خروجیای به شکل زیر (از llvm-dwarfdump) مطابقت دارد:
DW_AT_location [DW_FORM_sec_offset] (0x00000233) DW_AT_name [DW_FORM_strp] ( .debug_str[0x000000c9] = "intd")
و به ما امکان میدهد متغیر DLOC در FileCheck را برابر با مقدار دلخواه 0x00000233 که از خط بلافاصله پیش از "intd" استخراج شده است، مقداردهی کنیم.
نویسندگان (AUTHORS)
توسط تیم LLVM نگهداری میشود (https://llvm.org).
کپیرایت و تکثیر (COPYRIGHT)
2003-2026, LLVM Project
| 2026-07-15 | 22 |